<commit_before>/*jslint node: true, vars:true */
"use strict";

var ctx ;

var SHAPES_VGA='U7/STATIC/SHAPES.VGA';
var FACES_VGA='U7/STATIC/FACES.VGA';
var PALETTES_FLX='U7/STATIC/PALETTES.FLX';

//-----------------------------------------------------------------------------------------------------------------
// Make a hex string out of value
function hex(value) {
    return '0x' + value.toString(16);
}

//-----------------------------------------------------------------------------------------------------------------
// FLX is the basic container file format of U7. FlxParser is a base class that reads the table of contents
// File format from here:
// http://wiki.ultimacodex.com/wiki/Ultima_VII_Internal_Formats
function  FlxParser() {
    // SomeSuperClass.apply(this, Array.prototype.slice.call(arguments));
}
FlxParser.prototype.parse= function(recordNum)
{
    var TFlxHdr = Struct.create(
                                Struct.string("comment",80),
                                Struct.uint32("magic1"),
                                Struct.uint32("numRecords"),
                                Struct.array("magic2", Struct.uint32(),10)
                                );
    var TFlxRecordIndex = Struct.create(
                                        Struct.uint32("byteOffset"), // relative to beginning of flx file
                                        Struct.uint32("byteLength")
                                        );
    var hdr= TFlxHdr.readStructs(this.buffer, 0, 1)[0];
    if (hdr.magic1!=0xffff1a00) {
        console.log('Magic1 is not 0xffff 1a00. Found: ' + hex(hdr.magic1));
        return;
    }
//    console.log('Num records in file: '+hdr.numRecords);
    // Read all record indices
    var recordIndex = TFlxRecordIndex.readStructs(this.buffer, 0x80, hdr.numRecords);
    this.onRecordRead(recordIndex[recordNum].byteOffset,recordIndex[recordNum].byteLength);
}

FlxParser.prototype.sendRequest= function (filename, recordNum) {
    // do we need to read the file first?
    if (this.buffer===undefined)
    {
        var request = new XMLHttpRequest();

        request.open( 'GET', filename, true );
        request.responseType = 'arraybuffer';

        var self=this;
        request.onload = function() {
//            console.log("file loaded: "+filename);
            self.buffer= request.response;
            self.parse( recordNum  );
        }
        request.send();
    } else {
        // file is already loaded. reuse buffer
        this.parse( recordNum  );
    }
}

// Load file and then call onRecordRead(arrayBuffer, byteOffset) once recordNum has been read
FlxParser.prototype.readFile= function (filename, recordNum, onRecordRead ) {
    this.onRecordRead = onRecordRead;
    this.sendRequest(filename, recordNum);
}

//-----------------------------------------------------------------------------------------------------------------
// A simple image object that can be blitted later. Uses gPalette to map from indexed to RGBA
function  RGBAImage(left,top,right,bottom) {
    // SomeSuperClass.apply(this, Array.prototype.slice.call(arguments));
    // this.memberVar= "abc";
    this.imgLeft=left;
    this.imgRight=right;
    this.imgTop=top;
    this.imgBottom=bottom;

    var imageWidth = right -left + 1;
    var imageHeight =bottom - top +1;

    this.currImg =    ctx.createImageData(imageWidth, imageHeight);
    this.currImgData= this.currImg.data;
    this.indexedData= new Array(imageWidth*imageHeight);
}
// store span in indexed data buffer
RGBAImage.prototype.setSpan= function(x, y, data) {
    x+= -this.imgLeft; y+= -this.imgTop;
    var indexPtr= (x+y*this.currImg.width);
    for (var i=0; i<data.length; ++i) {
        var color= data[i];
        if (color==0xff) { // 0xff is transparent
            indexPtr++;
            continue;
        } else {
            this.indexedData[indexPtr++]= data[i];
        }
    }
}
// convert indexed data to RGBA buffer
RGBAImage.prototype.applyPalette= function(palette) {
    var len= this.indexedData.length;
    var pixelPtr=0;
    for (var i=0; i<len; ++i) {
        // read from indexed data and get rgb values
        var color= palette[this.indexedData[i]];
        if (color===undefined) {
            //alpha=0
            this.currImgData[pixelPtr+3]= 0;
            pixelPtr+=4;
            continue;
        }
        this.currImgData[pixelPtr++]= color.r;
        this.currImgData[pixelPtr++]= color.g;
        this.currImgData[pixelPtr++]= color.b;
        this.currImgData[pixelPtr++]= 0xff;
    }
}
RGBAImage.prototype.blitImage= function(x,y) {
    ctx.putImageData(this.currImg, x,y);
}

//-----------------------------------------------------------------------------------------------------------------
// Palette parsing
function  PaletteParser() {
    FlxParser.apply(this, Array.prototype.slice.call(arguments));
    this.onload= function(palette) {}
    this.onRecordRead = this.parsePalette;
}
PaletteParser.prototype= new FlxParser();

// Load file and set palette to palette stored in recordnum
PaletteParser.prototype.readFile= function (filename, recordNum ) {
    this.sendRequest(filename, recordNum);
}

PaletteParser.prototype.parsePalette= function (fileOffset,byteLength) {
    var TColorEntry = Struct.create(
        Struct.uint8("r"),
        Struct.uint8("g"),
        Struct.uint8("b")
    );
    var pal = TColorEntry.readStructs(this.buffer, fileOffset, 256);
    for (var c=0; c<pal.length; ++c)
    {
        pal[c].r <<= 2;
        pal[c].g <<= 2;
        pal[c].b <<= 2;
    }
    // there should be 11 more palettes here..
    this.onload(pal);
}

//-----------------------------------------------------------------------------------------------------------------
// Shape frame parsing
function  ShapeParser() {
    FlxParser.apply(this, Array.prototype.slice.call(arguments));
    this.onload= function(rgbaImage) {}
}
ShapeParser.prototype= new FlxParser();

// Load file and then call onRecordRead(arrayBuffer, byteOffset) once recordNum has been read
ShapeParser.prototype.readFile= function (filename, recordNum, frameNum) {
    this.onRecordRead = function(fileOffset,byteLength){ this.parseFrameIndex(fileOffset, byteLength, frameNum); }
    this.sendRequest(filename, recordNum);
}

ShapeParser.prototype.parseFrameIndex= function (fileOffset, byteLength, frameNum) {
    var TShpStart = Struct.create(
        Struct.uint32("totalLength"), // relative to beginning of flx file
        Struct.uint32("firstFrameOffset")
    );

    var shpStart = TShpStart.readStructs(this.buffer, fileOffset, 1)[0];
    // A default shaper header has the expected length. extended headers will have a different length listed here
    if (shpStart.totalLength==byteLength) {
        var firstFrameOffset    = shpStart.firstFrameOffset;
        var numFrames = (firstFrameOffset - 4) / 4;
        var TShpHdr = Struct.create(
                                    Struct.uint32("totalLength"),
                                    Struct.array("offsetFrames", Struct.uint32(), numFrames) // relative to fileOffset
                                    );
        var frameIndex = TShpHdr.readStructs(this.buffer, fileOffset, 1)[0].offsetFrames;
//        console.log('numFrames: '+ numFrames);
        if (frameNum>=numFrames) {
            console.log('frame request exceeded numFrames');
            frameNum= numFrames-1;
        }
        this.parseShapeFrame(fileOffset+frameIndex[frameNum]);
    } else {
        // extended header found
        console.log('extended header found');
        this.onload(null); // null == error
    }
}

ShapeParser.prototype.parseShapeFrame= function (fileOffset)
{
    var TFrameDesc = Struct.create(
        Struct.uint16("maxX"),
        Struct.uint16("minXinverted"),
        Struct.uint16("minYinverted"),
        Struct.uint16("maxY")
    );
    var frameDesc = TFrameDesc.readStructs(this.buffer, fileOffset, 1)[0];
    var rgbaImage= new RGBAImage(-frameDesc.minXinverted, -frameDesc.minYinverted, frameDesc.maxX, frameDesc.maxY);

//    console.log( 'Frame ' + (frameDesc.minXinverted*-1) + ',' + (frameDesc.minYinverted*-1)  +' / '+ (frameDesc.maxX) + ',' + frameDesc.maxY);

    var TSpan = Struct.create(
        Struct.uint16("blockData"),
        Struct.int16("x"),
        Struct.int16("y")
    );
    var readPointer=fileOffset+8;
    while (true) {
        var currSpan = TSpan.readStructs(this.buffer, readPointer, 1)[0]; readPointer += 6;
        if (currSpan.blockData==0)
            break;
        var blockLen = currSpan.blockData >> 1;
        var isUncompressed = (currSpan.blockData & 1) == 0;
        if (isUncompressed) {
            var data = new Uint8Array(this.buffer, readPointer, blockLen); readPointer += blockLen;
            rgbaImage.setSpan(currSpan.x, currSpan.y, data);
        } else {
            // Run Length Encoded
            var offsetX= currSpan.x;
            var endX = offsetX + blockLen;

            while (offsetX < endX) {
                var RLEHeader = new Uint8Array(this.buffer, readPointer, 1)[0]; readPointer += 1;
                var RLELength = RLEHeader >> 1;
                var RLEuncompressed = (RLEHeader & 1)==0;

                if(RLEuncompressed) {
                    var data = new Uint8Array(this.buffer, readPointer, RLELength); readPointer += RLELength;
                    rgbaImage.setSpan(offsetX, currSpan.y, data);
                } else {
                    var color = new Uint8Array(this.buffer, readPointer, 1)[0]; readPointer += 1;
                    var data = new Uint8Array(RLELength);
                    for (var c=0; c<RLELength; ++c) {
                        data[c]=color;
                    }
                    rgbaImage.setSpan(offsetX, currSpan.y, data);
                }

                offsetX += RLELength;
            }
        }
    }

    this.onload(rgbaImage);
}

//-----------------------------------------------------------------------------------------------------------------
// current shape record to read. There are 300 in faces.vga
var currFace= 0;
var MAX_FACE= 5;
var intervalId;

// We just need one flx parser here
var palParser = new PaletteParser();
var shpParser = new ShapeParser();

var arrFaceImages = new Array(MAX_FACE);

function drawFaces() {
    currFace=0;
    intervalId=setInterval( function(){
                           if (currFace<MAX_FACE)
                           {
                           var img= arrFaceImages[currFace++];
                           if (img)
                           img.blitImage(0,0);
                           } else {
                           clearInterval(intervalId);
                           }
                           },500);
}

function loadFaces(palette) {
    var filename= FACES_VGA;
    var frame=0; // some shapes have multiple frames/expressions
    currFace=0;

    shpParser.onload= function(rgbaImage) {
        if (rgbaImage) {
            rgbaImage.applyPalette(palette);
            arrFaceImages[currFace]=rgbaImage;
        }
        if (++currFace>=MAX_FACE)
            drawFaces();
        else
            shpParser.readFile(filename, currFace, frame);
    }

    shpParser.readFile(filename, currFace, frame);
}

function loadShapes(palette) {
    var filename= SHAPES_VGA;
    var frame=0; // some shapes have multiple frames/expressions
    currFace=0;

    shpParser.onload= function(rgbaImage) {
        if (rgbaImage) {
            rgbaImage.applyPalette(palette);
            arrFaceImages[currFace]=rgbaImage;
        }
        if (++currFace>=MAX_FACE)
            drawFaces();
        else
            shpParser.readFile(filename, currFace, frame);
    }

    shpParser.readFile(filename, currFace, frame);
}

window.onload=function(){
    var canvas = document.getElementById("mycanvas");
    ctx = canvas.getContext("2d");

    // Load Palette #0 first
    var palette; // has rg,b, fields
    palParser.onload= function(pal) {
        palette=pal;
        loadFaces(palette);
//        loadShapes(palette);
    }
    palParser.readFile(PALETTES_FLX, 0);
};

<commit_msg>use secondary canvas entries<commit_after>/*jslint node: true, vars:true */
"use strict";

var ctx ;

var SHAPES_VGA='U7/STATIC/SHAPES.VGA';
var FACES_VGA='U7/STATIC/FACES.VGA';
var PALETTES_FLX='U7/STATIC/PALETTES.FLX';

//-----------------------------------------------------------------------------------------------------------------
// Make a hex string out of value
function hex(value) {
    return '0x' + value.toString(16);
}

//-----------------------------------------------------------------------------------------------------------------
// FLX is the basic container file format of U7. FlxParser is a base class that reads the table of contents
// File format from here:
// http://wiki.ultimacodex.com/wiki/Ultima_VII_Internal_Formats
function  FlxParser() {
    // SomeSuperClass.apply(this, Array.prototype.slice.call(arguments));
}
FlxParser.prototype.parse= function(recordNum)
{
    var TFlxHdr = Struct.create(
                                Struct.string("comment",80),
                                Struct.uint32("magic1"),
                                Struct.uint32("numRecords"),
                                Struct.array("magic2", Struct.uint32(),10)
                                );
    var TFlxRecordIndex = Struct.create(
                                        Struct.uint32("byteOffset"), // relative to beginning of flx file
                                        Struct.uint32("byteLength")
                                        );
    var hdr= TFlxHdr.readStructs(this.buffer, 0, 1)[0];
    if (hdr.magic1!=0xffff1a00) {
        console.log('Magic1 is not 0xffff 1a00. Found: ' + hex(hdr.magic1));
        return;
    }
//    console.log('Num records in file: '+hdr.numRecords);
    // Read all record indices
    var recordIndex = TFlxRecordIndex.readStructs(this.buffer, 0x80, hdr.numRecords);
    this.onRecordRead(recordIndex[recordNum].byteOffset,recordIndex[recordNum].byteLength);
}

FlxParser.prototype.sendRequest= function (filename, recordNum) {
    // do we need to read the file first?
    if (this.buffer===undefined)
    {
        var request = new XMLHttpRequest();

        request.open( 'GET', filename, true );
        request.responseType = 'arraybuffer';

        var self=this;
        request.onload = function() {
//            console.log("file loaded: "+filename);
            self.buffer= request.response;
            self.parse( recordNum  );
        }
        request.send();
    } else {
        // file is already loaded. reuse buffer
        this.parse( recordNum  );
    }
}

// Load file and then call onRecordRead(arrayBuffer, byteOffset) once recordNum has been read
FlxParser.prototype.readFile= function (filename, recordNum, onRecordRead ) {
    this.onRecordRead = onRecordRead;
    this.sendRequest(filename, recordNum);
}

//-----------------------------------------------------------------------------------------------------------------
// A simple image object that can be blitted later. Uses gPalette to map from indexed to RGBA
function  RGBAImage(left,top,right,bottom) {
    // SomeSuperClass.apply(this, Array.prototype.slice.call(arguments));
    // this.memberVar= "abc";
    this.imgLeft=left;
    this.imgRight=right;
    this.imgTop=top;
    this.imgBottom=bottom;

    var imageWidth = right -left + 1;
    var imageHeight =bottom - top +1;

    this.buffer= this.createBuffer(imageWidth,imageHeight);
    this.indexedData= new Array(imageWidth*imageHeight);
}

// putImageData does not support blending/transparency, and has terrible perf on Chrome. apparently it is faster
// to create secondary canvas elements and blit them to the primary using drawImage
RGBAImage.prototype.createBuffer= function(width,height) {
    var buffer = new Object();
    buffer.canvas = document.createElement("canvas");
    buffer.canvas.width = width;
    buffer.canvas.height = height;
    buffer.context = buffer.canvas.getContext("2d");
    buffer.imageData = buffer.context.createImageData(width, height);

    return buffer;
}

// store span in indexed data buffer
RGBAImage.prototype.setSpan= function(x, y, data) {
    x+= -this.imgLeft; y+= -this.imgTop;
    var indexPtr= (x+y*this.buffer.canvas.width);
    for (var i=0; i<data.length; ++i) {
        var color= data[i];
        if (color==0xff) { // 0xff is transparent
            indexPtr++;
            continue;
        } else {
            this.indexedData[indexPtr++]= data[i];
        }
    }
}
// convert indexed data to RGBA buffer
RGBAImage.prototype.applyPalette= function(palette) {
    // first write to imagedata.data, then copy that to canvas
    // in blitImage we then draw our private canvas to the main canvas..phew
    var data = this.buffer.imageData.data;
    var len= this.indexedData.length;
    var pixelPtr=0;
    for (var i=0; i<len; ++i) {
        // read from indexed data and get rgb values
        var color= palette[this.indexedData[i]];
        if (color===undefined) {
            //alpha=0
            pixelPtr+=4;
            continue;
        }
        data[pixelPtr++]= color.r;
        data[pixelPtr++]= color.g;
        data[pixelPtr++]= color.b;
        data[pixelPtr++]= 0xff;
    }
    this.buffer.context.putImageData(this.buffer.imageData, 0, 0);
}

RGBAImage.prototype.blitImage= function(x,y) {
    ctx.drawImage(this.buffer.canvas, x,y);
}

//-----------------------------------------------------------------------------------------------------------------
// Palette parsing
function  PaletteParser() {
    FlxParser.apply(this, Array.prototype.slice.call(arguments));
    this.onload= function(palette) {}
    this.onRecordRead = this.parsePalette;
}
PaletteParser.prototype= new FlxParser();

// Load file and set palette to palette stored in recordnum
PaletteParser.prototype.readFile= function (filename, recordNum ) {
    this.sendRequest(filename, recordNum);
}

PaletteParser.prototype.parsePalette= function (fileOffset,byteLength) {
    var TColorEntry = Struct.create(
        Struct.uint8("r"),
        Struct.uint8("g"),
        Struct.uint8("b")
    );
    var pal = TColorEntry.readStructs(this.buffer, fileOffset, 256);
    for (var c=0; c<pal.length; ++c)
    {
        pal[c].r <<= 2;
        pal[c].g <<= 2;
        pal[c].b <<= 2;
    }
    // there should be 11 more palettes here..
    this.onload(pal);
}

//-----------------------------------------------------------------------------------------------------------------
// Shape frame parsing
function  ShapeParser() {
    FlxParser.apply(this, Array.prototype.slice.call(arguments));
    this.onload= function(rgbaImage) {}
}
ShapeParser.prototype= new FlxParser();

// Load file and then call onRecordRead(arrayBuffer, byteOffset) once recordNum has been read
ShapeParser.prototype.readFile= function (filename, recordNum, frameNum) {
    this.onRecordRead = function(fileOffset,byteLength){ this.parseFrameIndex(fileOffset, byteLength, frameNum); }
    this.sendRequest(filename, recordNum);
}

ShapeParser.prototype.parseFrameIndex= function (fileOffset, byteLength, frameNum) {
    var TShpStart = Struct.create(
        Struct.uint32("totalLength"), // relative to beginning of flx file
        Struct.uint32("firstFrameOffset")
    );

    var shpStart = TShpStart.readStructs(this.buffer, fileOffset, 1)[0];
    // A default shaper header has the expected length. extended headers will have a different length listed here
    if (shpStart.totalLength==byteLength) {
        var firstFrameOffset    = shpStart.firstFrameOffset;
        var numFrames = (firstFrameOffset - 4) / 4;
        var TShpHdr = Struct.create(
                                    Struct.uint32("totalLength"),
                                    Struct.array("offsetFrames", Struct.uint32(), numFrames) // relative to fileOffset
                                    );
        var frameIndex = TShpHdr.readStructs(this.buffer, fileOffset, 1)[0].offsetFrames;
//        console.log('numFrames: '+ numFrames);
        if (frameNum>=numFrames) {
            console.log('frame request exceeded numFrames');
            frameNum= numFrames-1;
        }
        this.parseShapeFrame(fileOffset+frameIndex[frameNum]);
    } else {
        // extended header found
        console.log('extended header found');
        this.onload(null); // null == error
    }
}

ShapeParser.prototype.parseShapeFrame= function (fileOffset)
{
    var TFrameDesc = Struct.create(
        Struct.uint16("maxX"),
        Struct.uint16("minXinverted"),
        Struct.uint16("minYinverted"),
        Struct.uint16("maxY")
    );
    var frameDesc = TFrameDesc.readStructs(this.buffer, fileOffset, 1)[0];
    var rgbaImage= new RGBAImage(-frameDesc.minXinverted, -frameDesc.minYinverted, frameDesc.maxX, frameDesc.maxY);

//    console.log( 'Frame ' + (frameDesc.minXinverted*-1) + ',' + (frameDesc.minYinverted*-1)  +' / '+ (frameDesc.maxX) + ',' + frameDesc.maxY);

    var TSpan = Struct.create(
        Struct.uint16("blockData"),
        Struct.int16("x"),
        Struct.int16("y")
    );
    var readPointer=fileOffset+8;
    while (true) {
        var currSpan = TSpan.readStructs(this.buffer, readPointer, 1)[0]; readPointer += 6;
        if (currSpan.blockData==0)
            break;
        var blockLen = currSpan.blockData >> 1;
        var isUncompressed = (currSpan.blockData & 1) == 0;
        if (isUncompressed) {
            var data = new Uint8Array(this.buffer, readPointer, blockLen); readPointer += blockLen;
            rgbaImage.setSpan(currSpan.x, currSpan.y, data);
        } else {
            // Run Length Encoded
            var offsetX= currSpan.x;
            var endX = offsetX + blockLen;

            while (offsetX < endX) {
                var RLEHeader = new Uint8Array(this.buffer, readPointer, 1)[0]; readPointer += 1;
                var RLELength = RLEHeader >> 1;
                var RLEuncompressed = (RLEHeader & 1)==0;

                if(RLEuncompressed) {
                    var data = new Uint8Array(this.buffer, readPointer, RLELength); readPointer += RLELength;
                    rgbaImage.setSpan(offsetX, currSpan.y, data);
                } else {
                    var color = new Uint8Array(this.buffer, readPointer, 1)[0]; readPointer += 1;
                    var data = new Uint8Array(RLELength);
                    for (var c=0; c<RLELength; ++c) {
                        data[c]=color;
                    }
                    rgbaImage.setSpan(offsetX, currSpan.y, data);
                }

                offsetX += RLELength;
            }
        }
    }

    this.onload(rgbaImage);
}

//-----------------------------------------------------------------------------------------------------------------
// current shape record to read. There are 300 in faces.vga
var currFace= 0;
var MAX_FACE= 5;
var intervalId;

// We just need one flx parser here
var palParser = new PaletteParser();
var shpParser = new ShapeParser();

var arrFaceImages = new Array(MAX_FACE);

function drawFaces() {
    currFace=0;
    intervalId=setInterval( function(){
                           if (currFace<MAX_FACE)
                           {
                           var img= arrFaceImages[currFace++];
                           if (img)
                           img.blitImage(0,0);
                           } else {
                           clearInterval(intervalId);
                           }
                           },500);
}

function loadFaces(palette) {
    var filename= FACES_VGA;
    var frame=0; // some shapes have multiple frames/expressions
    currFace=0;

    shpParser.onload= function(rgbaImage) {
        if (rgbaImage) {
            rgbaImage.applyPalette(palette);
            arrFaceImages[currFace]=rgbaImage;
        }
        if (++currFace>=MAX_FACE)
            drawFaces();
        else
            shpParser.readFile(filename, currFace, frame);
    }

    shpParser.readFile(filename, currFace, frame);
}

function loadShapes(palette) {
    var filename= SHAPES_VGA;
    var frame=0; // some shapes have multiple frames/expressions
    currFace=0;

    shpParser.onload= function(rgbaImage) {
        if (rgbaImage) {
            rgbaImage.applyPalette(palette);
            arrFaceImages[currFace]=rgbaImage;
        }
        if (++currFace>=MAX_FACE)
            drawFaces();
        else
            shpParser.readFile(filename, currFace, frame);
    }

    shpParser.readFile(filename, currFace, frame);
}

window.onload=function(){
    var canvas = document.getElementById("mycanvas");
    ctx = canvas.getContext("2d");

    // Load Palette #0 first
    var palette; // has rg,b, fields
    palParser.onload= function(pal) {
        palette=pal;
        loadFaces(palette);
//        loadShapes(palette);
    }
    palParser.readFile(PALETTES_FLX, 0);
};

<|endoftext|>


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

"use strict";

ASS.debugMode = (location.search === "?debug");

addEventListener("DOMContentLoaded", function () {
	var createSubDiv;
	var wrappers = {};
	(function () {
		var defaultSubDiv = document.createElement("div");

		createSubDiv = function (dialogue, currentTime) {
			var result = defaultSubDiv.cloneNode(true);
			result.dialogue = dialogue;
			dialogue.drawTo(result, currentTime);
			wrappers[dialogue.layer][dialogue.alignment].appendChild(result);
			return result;
		};

		defaultSubDiv.constructor.prototype.remove = function () {
			if (this.parentElement !== null) {
				this.parentElement.removeChild(this);
				this.dialogue.erase();
			}
		};
	})();

	var video = document.querySelector("#video");

	var videoMetadataLoaded = false;
	var ass = null;

	var parser = null;
	var rawASS = null;

	var testVideoAndASSLoaded = function () {
		if (videoMetadataLoaded && ass) {
			var videoWidth = video.videoWidth;
			var videoHeight = video.videoHeight;
			document.body.style.width = video.style.width = videoWidth + "px";
			document.body.style.height = video.style.height = videoHeight + "px";
			document.body.style.marginLeft = video.style.marginLeft = (-videoWidth / 2) + "px";

			var subsWrapper = document.querySelector("#subs-wrapper");

			var info = ass.info;
			info.scaleTo(videoWidth, videoHeight);
			var zoom = (1 / info.scaleX);
			var zoomedDiv = document.querySelector(".zoomed");
			zoomedDiv.style.transform = "scale(" + zoom + ")";
			zoomedDiv.style.webkitTransform = "scale(" + zoom + ")";

			info.dpi = parseFloat(getComputedStyle(document.querySelector("#dpi-div")).height.match(/(\d+)px/)[1]);

			var layers = new Set();
			var dialogues = ass.dialogues;
			dialogues.forEach(function (dialogue) {
				layers.add(dialogue.layer);
			});
			layers.iterator().toArray().sort().forEach(function (layer) {
				var i;
				wrappers[layer] = {};
				for (i = 1; i <= 9; ++i) {
					var wrapperDiv = document.createElement("div");
					wrapperDiv.className = "an" + i + " layer" + layer;
					subsWrapper.appendChild(wrapperDiv);
					wrappers[layer][i] = wrapperDiv;
				}
			});

			var allFonts = new Set();
			ass.styles.forEach(function (style) {
				allFonts.add(style.fontName);
			});
			dialogues.forEach(function (dialogue) {
				dialogue.parts.forEach(function (part) {
					if (part instanceof ASS.Tags.FontName) {
						allFonts.add(part.value);
					}
				});
			});
			var numFonts = Array.prototype.filter.call(document.styleSheets, function (stylesheet) {
				return stylesheet.href && stylesheet.href.endsWith("/fonts.css");
			}).reduce(function (previousValue, currentValue) {
				return previousValue + Array.prototype.filter.call(currentValue.cssRules, function (rule) {
					return rule.type === CSSRule.FONT_FACE_RULE && allFonts.has(rule.style.getPropertyValue("font-family").match(/^['"]?(.*?)['"]?$/)[1]);
				}).map(function (fontFaceRule) {
					var xhr = new XMLHttpRequest();
					var fontSrc = fontFaceRule.style.src;
					if (fontSrc) {
						fontSrc = fontSrc.match(/url\((.+)\)$/)[1];
					}
					else {
						fontSrc = fontFaceRule.cssText.match(/url\("?(.+?)"?\)/)[1];
					}
					xhr.open("GET", fontSrc, true);
					xhr.addEventListener("readystatechange", function () {
						if (xhr.readyState === XMLHttpRequest.DONE) {
							--numFonts;
							if (numFonts === 0) {
								video.play();
							}
						}
					});
					xhr.send(null);
					return xhr;
				})
				.length;
			}, 0);
			if (numFonts === 0) {
				video.play();
			}

			var currentTime;
			var currentSubs = [];
			var newSubs = dialogues.toIterable().map(function (entry) {
				return entry[1];
			}).skipWhile(function (dialogue) {
				return dialogue.end < currentTime;
			}).takeWhile(function (dialogue) {
				return dialogue.start <= currentTime;
			}).filter(function (dialogue) {
				return dialogue.end >= currentTime && !dialogue.isDrawn();
			}).map(function (dialogue) {
				return createSubDiv(dialogue, currentTime);
			});
			video.addEventListener("timeupdate", function () {
				currentTime = video.currentTime;

				currentSubs = currentSubs.filter(function (sub) {
					if (sub.dialogue.start <= currentTime && sub.dialogue.end > currentTime) {
						return true;
					}
					else {
						sub.remove();
						return false;
					}
				}).concat(Iterator(newSubs).toArray());
			}, false);

			video.addEventListener("seeking", function () {
				currentSubs.forEach(function (sub) {
					sub.remove();
				});
				currentSubs = [];
			});

			video.addEventListener("pause", function () {
				subsWrapper.className = "paused";
			}, false);

			video.addEventListener("playing", function () {
				subsWrapper.className = "";
			}, false);
		};
	}

	if (video.readyState < HTMLMediaElement.HAVE_METADATA) {
		video.addEventListener("loadedmetadata", function () {
			videoMetadataLoaded = true;
			testVideoAndASSLoaded();
		}, false);
	}
	else {
		videoMetadataLoaded = true;
		testVideoAndASSLoaded();
	}

	var parserRequest = new XMLHttpRequest();
	parserRequest.open("GET", "ass.pegjs", true);
	parserRequest.addEventListener("readystatechange", function () {
		if (parserRequest.readyState === XMLHttpRequest.DONE) {
			parser = PEG.buildParser(parserRequest.responseText);

			if (rawASS) {
				ass = ASS.parse(rawASS, parser);
				if (ASS.debugMode) {
					window.ass = ass;
				}
				testVideoAndASSLoaded();
			}
		}
	}, false);
	parserRequest.send(null);

	var track = document.querySelector("#video > track[data-format='ass']");
	var subsRequest = new XMLHttpRequest();
	subsRequest.open("GET", track.src || track.getAttribute("src"), true);
	subsRequest.addEventListener("readystatechange", function () {
		if (subsRequest.readyState === XMLHttpRequest.DONE) {
			rawASS = subsRequest.responseText;

			if (parser) {
				ass = ASS.parse(rawASS, parser);
				if (ASS.debugMode) {
					window.ass = ass;
				}
				testVideoAndASSLoaded();
			}
		}
	}, false);
	subsRequest.send(null);
}, false);
<commit_msg>Added debug logging for video state changes.<commit_after>/**
 * libjass
 *
 * https://github.com/Arnavion/libjass
 *
 * Copyright 2013 Arnav Singh
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

"use strict";

ASS.debugMode = (location.search === "?debug");

addEventListener("DOMContentLoaded", function () {
	var createSubDiv;
	var wrappers = {};
	(function () {
		var defaultSubDiv = document.createElement("div");

		createSubDiv = function (dialogue, currentTime) {
			var result = defaultSubDiv.cloneNode(true);
			result.dialogue = dialogue;
			dialogue.drawTo(result, currentTime);
			wrappers[dialogue.layer][dialogue.alignment].appendChild(result);
			return result;
		};

		defaultSubDiv.constructor.prototype.remove = function () {
			if (this.parentElement !== null) {
				this.parentElement.removeChild(this);
				this.dialogue.erase();
			}
		};
	})();

	var video = document.querySelector("#video");

	var videoMetadataLoaded = false;
	var ass = null;

	var parser = null;
	var rawASS = null;

	var testVideoAndASSLoaded = function () {
		if (videoMetadataLoaded && ass) {
			var videoWidth = video.videoWidth;
			var videoHeight = video.videoHeight;
			document.body.style.width = video.style.width = videoWidth + "px";
			document.body.style.height = video.style.height = videoHeight + "px";
			document.body.style.marginLeft = video.style.marginLeft = (-videoWidth / 2) + "px";

			var subsWrapper = document.querySelector("#subs-wrapper");

			var info = ass.info;
			info.scaleTo(videoWidth, videoHeight);
			var zoom = (1 / info.scaleX);
			var zoomedDiv = document.querySelector(".zoomed");
			zoomedDiv.style.transform = "scale(" + zoom + ")";
			zoomedDiv.style.webkitTransform = "scale(" + zoom + ")";

			info.dpi = parseFloat(getComputedStyle(document.querySelector("#dpi-div")).height.match(/(\d+)px/)[1]);

			var layers = new Set();
			var dialogues = ass.dialogues;
			dialogues.forEach(function (dialogue) {
				layers.add(dialogue.layer);
			});
			layers.iterator().toArray().sort().forEach(function (layer) {
				var i;
				wrappers[layer] = {};
				for (i = 1; i <= 9; ++i) {
					var wrapperDiv = document.createElement("div");
					wrapperDiv.className = "an" + i + " layer" + layer;
					subsWrapper.appendChild(wrapperDiv);
					wrappers[layer][i] = wrapperDiv;
				}
			});

			var allFonts = new Set();
			ass.styles.forEach(function (style) {
				allFonts.add(style.fontName);
			});
			dialogues.forEach(function (dialogue) {
				dialogue.parts.forEach(function (part) {
					if (part instanceof ASS.Tags.FontName) {
						allFonts.add(part.value);
					}
				});
			});
			var numFonts = Array.prototype.filter.call(document.styleSheets, function (stylesheet) {
				return stylesheet.href && stylesheet.href.endsWith("/fonts.css");
			}).reduce(function (previousValue, currentValue) {
				return previousValue + Array.prototype.filter.call(currentValue.cssRules, function (rule) {
					return rule.type === CSSRule.FONT_FACE_RULE && allFonts.has(rule.style.getPropertyValue("font-family").match(/^['"]?(.*?)['"]?$/)[1]);
				}).map(function (fontFaceRule) {
					var xhr = new XMLHttpRequest();
					var fontSrc = fontFaceRule.style.src;
					if (fontSrc) {
						fontSrc = fontSrc.match(/url\((.+)\)$/)[1];
					}
					else {
						fontSrc = fontFaceRule.cssText.match(/url\("?(.+?)"?\)/)[1];
					}
					xhr.open("GET", fontSrc, true);
					xhr.addEventListener("readystatechange", function () {
						if (xhr.readyState === XMLHttpRequest.DONE) {
							--numFonts;
							if (numFonts === 0) {
								video.play();
							}
						}
					});
					xhr.send(null);
					return xhr;
				})
				.length;
			}, 0);
			if (numFonts === 0) {
				video.play();
			}

			var currentTime;
			var currentSubs = [];
			var newSubs = dialogues.toIterable().map(function (entry) {
				return entry[1];
			}).skipWhile(function (dialogue) {
				return dialogue.end < currentTime;
			}).takeWhile(function (dialogue) {
				return dialogue.start <= currentTime;
			}).filter(function (dialogue) {
				return dialogue.end >= currentTime && !dialogue.isDrawn();
			}).map(function (dialogue) {
				return createSubDiv(dialogue, currentTime);
			});
			video.addEventListener("timeupdate", function () {
				currentTime = video.currentTime;

				currentSubs = currentSubs.filter(function (sub) {
					if (sub.dialogue.start <= currentTime && sub.dialogue.end > currentTime) {
						return true;
					}
					else {
						sub.remove();
						return false;
					}
				}).concat(Iterator(newSubs).toArray());

				if (ASS.debugMode) {
					console.log("video.timeupdate: video.paused = " + video.paused + ", video.seeking = " + video.seeking);
				}
			}, false);

			video.addEventListener("seeking", function () {
				currentSubs.forEach(function (sub) {
					sub.remove();
				});

				currentSubs = [];

				if (ASS.debugMode) {
					console.log("video.seeking: video.paused = " + video.paused + ", video.seeking = " + video.seeking);
				}
			}, false);

			video.addEventListener("pause", function () {
				subsWrapper.className = "paused";

				if (ASS.debugMode) {
					console.log("video.pause: video.paused = " + video.paused + ", video.seeking = " + video.seeking);
				}
			}, false);

			video.addEventListener("playing", function () {
				subsWrapper.className = "";

				if (ASS.debugMode) {
					console.log("video.playing: video.paused = " + video.paused + ", video.seeking = " + video.seeking);
				}
			}, false);
		};
	}

	if (video.readyState < HTMLMediaElement.HAVE_METADATA) {
		video.addEventListener("loadedmetadata", function () {
			videoMetadataLoaded = true;
			testVideoAndASSLoaded();
		}, false);
	}
	else {
		videoMetadataLoaded = true;
		testVideoAndASSLoaded();
	}

	var parserRequest = new XMLHttpRequest();
	parserRequest.open("GET", "ass.pegjs", true);
	parserRequest.addEventListener("readystatechange", function () {
		if (parserRequest.readyState === XMLHttpRequest.DONE) {
			parser = PEG.buildParser(parserRequest.responseText);

			if (rawASS) {
				ass = ASS.parse(rawASS, parser);
				if (ASS.debugMode) {
					window.ass = ass;
				}
				testVideoAndASSLoaded();
			}
		}
	}, false);
	parserRequest.send(null);

	var track = document.querySelector("#video > track[data-format='ass']");
	var subsRequest = new XMLHttpRequest();
	subsRequest.open("GET", track.src || track.getAttribute("src"), true);
	subsRequest.addEventListener("readystatechange", function () {
		if (subsRequest.readyState === XMLHttpRequest.DONE) {
			rawASS = subsRequest.responseText;

			if (parser) {
				ass = ASS.parse(rawASS, parser);
				if (ASS.debugMode) {
					window.ass = ass;
				}
				testVideoAndASSLoaded();
			}
		}
	}, false);
	subsRequest.send(null);
}, false);
<|endoftext|>


<commit_before>var VoltronHooks = require('voltron-hooks');
var Q = require('q');

module.exports = Model;

function Model(document, schema) {
  if (!document) {
    document = {};
  }
  var virtuals = {};
  Object.defineProperty(this, '_attributes', {
    get: function () {
      return document;
    }
  });
  Object.defineProperty(this, '_virtuals', {
    get: function () {
      return virtuals;
    }
  });
  if (schema) {
    Model.applySchemaToModel(schema, this);
  }
}

Model.define = function (constructor, schema, options) {
  var Fn = function (document) {
    Model.call(this, document, schema);
    constructor.call(this, document);
  };

  Fn.build = Model.build;
  Fn.prototype = Object.create(Model.prototype, {
    constructor: {
      value: constructor,
      enumerable: false
    }
  });

  VoltronHooks.defineBeforeHook(Fn.prototype, 'update');

  if (options && options.hasOwnProperty('primaryKey')) {
    Object.defineProperty(Fn.prototype, '_primaryKey', {
        value: options.primaryKey,
        enumerable: false
    });
  }

  return Fn;
};

Model.applySchemaToModel = function (schema, model) {
  Object.keys(schema).forEach(function (key) {
    var schemaProp = schema[key];
    var property = {};
    var modelKey;

    if (schemaProp.fieldName) {
      modelKey = schemaProp.fieldName;
    }
    else {
      modelKey = key;
    }

    if (schemaProp.virtual) {
      var virtualField = schemaProp.virtual;
      property.get = function () {
        return model.getVirtual(virtualField);
      };
      property.set = function (value) {
        model.setVirtual(virtualField, value);
      };
    }
    else {
      if (!schemaProp.get) {
        property.get = function () {
          return model.get(modelKey);
        };
      }
      else {
        property.get = schemaProp.get;
      }

      if (!schemaProp.set) {
        property.set = function (val) {
          model.set(modelKey, val);
        };
      }
      else {
        property.set = schemaProp.set;
      }

      if (schemaProp.type) {
        var _set = property.set;
        property.set = function (value) {
          value = schemaProp.type.cast(value);
          _set.call(this, value);
        };
      }

      if (schemaProp.value) {
        model.set(modelKey, schemaProp.value);
      }

    }
    property.enumerable = true;
    Object.defineProperty(model, key, property);
  });
};

Model.build = function (documents) {
  var models = [];
  var count = documents.length;
  for (var i = 0; i < count; i++) {
    models.push(new this(documents[i]));
  }
  return models;
};

Object.defineProperties(Model.prototype, {
  id: {
    get: function () {
      var key;
      if (this._primaryKey) {
        key = this._primaryKey;
      }
      else if (this._primaryKey === false) {
        key = undefined;
      }
      else {
        key = 'id';
      }

      if (this._attributes) {
        return this._attributes[key];
      } else {
        return undefined;
      }
    }
  },
  get: {
    value: function (attr) {
      return this._attributes[attr];
    }
  },
  set: {
    value: function (attr, value) {
      this._attributes[attr] = value;
    }
  },
  getVirtual: {
    value: function (attr) {
      return this._virtuals[attr];
    }
  },
  setVirtual: {
    value: function (attr, value) {
      this._virtuals[attr] = value;
    }
  },
  update: {
    value: function (newAttrs) {
      var self = this;
      if (newAttrs) {
        Object.keys(this).map(function (key) {
          if (newAttrs.hasOwnProperty(key)) {
            self[key] = newAttrs[key];
          }
        });
      }
      return Q.when(this);
    }, writable: true
  },
  inspect: {
    value: function () {
      var self = this;
      var output = 'Instance of ' + this.constructor + '\n';
      Object.keys(this).map(function (key) {
        output += '' + key + ': ' + self[key] + '\n';
      });
      return output;
    }
  }
});

<commit_msg>adding toJSON method<commit_after>var VoltronHooks = require('voltron-hooks');
var Q = require('q');

module.exports = Model;

function Model(document, schema) {
  if (!document) {
    document = {};
  }
  var virtuals = {};
  Object.defineProperty(this, '_attributes', {
    get: function () {
      return document;
    }
  });
  Object.defineProperty(this, '_virtuals', {
    get: function () {
      return virtuals;
    }
  });
  if (schema) {
    Model.applySchemaToModel(schema, this);
  }
}

Model.define = function (constructor, schema, options) {
  var Fn = function (document) {
    Model.call(this, document, schema);
    constructor.call(this, document);
  };

  Fn.build = Model.build;
  Fn.prototype = Object.create(Model.prototype, {
    constructor: {
      value: constructor,
      enumerable: false
    }
  });

  VoltronHooks.defineBeforeHook(Fn.prototype, 'update');

  if (options && options.hasOwnProperty('primaryKey')) {
    Object.defineProperty(Fn.prototype, '_primaryKey', {
        value: options.primaryKey,
        enumerable: false
    });
  }

  return Fn;
};

Model.applySchemaToModel = function (schema, model) {
  Object.keys(schema).forEach(function (key) {
    var schemaProp = schema[key];
    var property = {};
    var modelKey;

    if (schemaProp.fieldName) {
      modelKey = schemaProp.fieldName;
    }
    else {
      modelKey = key;
    }

    if (schemaProp.virtual) {
      var virtualField = schemaProp.virtual;
      property.get = function () {
        return model.getVirtual(virtualField);
      };
      property.set = function (value) {
        model.setVirtual(virtualField, value);
      };
    }
    else {
      if (!schemaProp.get) {
        property.get = function () {
          return model.get(modelKey);
        };
      }
      else {
        property.get = schemaProp.get;
      }

      if (!schemaProp.set) {
        property.set = function (val) {
          model.set(modelKey, val);
        };
      }
      else {
        property.set = schemaProp.set;
      }

      if (schemaProp.type) {
        var _set = property.set;
        property.set = function (value) {
          value = schemaProp.type.cast(value);
          _set.call(this, value);
        };
      }

      if (schemaProp.value) {
        model.set(modelKey, schemaProp.value);
      }

    }
    property.enumerable = true;
    Object.defineProperty(model, key, property);
  });
};

Model.build = function (documents) {
  var models = [];
  var count = documents.length;
  for (var i = 0; i < count; i++) {
    models.push(new this(documents[i]));
  }
  return models;
};

Object.defineProperties(Model.prototype, {
  id: {
    get: function () {
      var key;
      if (this._primaryKey) {
        key = this._primaryKey;
      }
      else if (this._primaryKey === false) {
        key = undefined;
      }
      else {
        key = 'id';
      }

      if (this._attributes) {
        return this._attributes[key];
      } else {
        return undefined;
      }
    }
  },
  get: {
    value: function (attr) {
      return this._attributes[attr];
    }
  },
  set: {
    value: function (attr, value) {
      this._attributes[attr] = value;
    }
  },
  getVirtual: {
    value: function (attr) {
      return this._virtuals[attr];
    }
  },
  setVirtual: {
    value: function (attr, value) {
      this._virtuals[attr] = value;
    }
  },
  update: {
    value: function (newAttrs) {
      var self = this;
      if (newAttrs) {
        Object.keys(this).map(function (key) {
          if (newAttrs.hasOwnProperty(key)) {
            self[key] = newAttrs[key];
          }
        });
      }
      return Q.when(this);
    }, writable: true
  },
  inspect: {
    value: function () {
      var output = 'Instance of ' + this.constructor + '\n';
      Object.keys(this).map(function (key) {
        output += '' + key + ': ' + this[key] + '\n';
      }.bind(this));
      return output;
    }
  },
  toJSON: {
    value: function () {
      var output = { id: this.id };
      Object.keys(this).map(function (key) {
        output[key] = this[key];
      }.bind(this));
      return output;
    }
  }
});

<|endoftext|>


<commit_before>var browserify = require('browserify')
  , npmcss     = require('npm-css')
  , rework     = require('rework')
  , variables  = require('rework-vars')
  , path       = require('path')

function error (resp, e) {

  // Jaws-like router support
  if (typeof resp.error == 'function') return resp.error(e)

  resp.writeHead(500, {'Content-Type': 'text/plain'})
  resp.end(e.message)

}

module.exports = function (opts) {

  return {
    css: function (req, resp) {
      var file = npmcss(path.join(process.cwd(), opts.css.entry))
      var css = rework(file)
      css.use(variables(opts.css.variables))
      resp.setHeader('content-type', 'text/css')
      resp.end(css.toString())
    }

  , js: function (req, resp) {
      var bundle = browserify([opts.js.entry])
      bundle.transform('hbsfy')
      bundle.transform('brfs')
      bundle.bundle({debug: opts.debug || false}, function (e, src) {
        if (e) return error(resp, e);
        resp.setHeader('content-type', 'text/javascript')
        resp.end(src)
      })
    }

  }

}
<commit_msg>require hbsfy and brfs explicity<commit_after>var browserify = require('browserify')
  , hbsfy      = require('hbsfy')
  , brfs       = require('brfs')
  , npmcss     = require('npm-css')
  , rework     = require('rework')
  , variables  = require('rework-vars')
  , path       = require('path')

function error (resp, e) {

  // Jaws-like router support
  if (typeof resp.error == 'function') return resp.error(e)

  resp.writeHead(500, {'Content-Type': 'text/plain'})
  resp.end(e.message)

}

module.exports = function (opts) {

  return {
    css: function (req, resp) {
      var file = npmcss(path.join(process.cwd(), opts.css.entry))
      var css = rework(file)
      css.use(variables(opts.css.variables))
      resp.setHeader('content-type', 'text/css')
      resp.end(css.toString())
    }

  , js: function (req, resp) {
      var bundle = browserify([opts.js.entry])
      bundle.transform(hbsfy)
      bundle.transform(brfs)
      bundle.bundle({debug: opts.debug || false}, function (e, src) {
        if (e) return error(resp, e);
        resp.setHeader('content-type', 'text/javascript')
        resp.end(src)
      })
    }

  }

}
<|endoftext|>


<commit_before>var emitter = require('emitter');

var default_buttons = [

	['n1', 'n2', 'n3'],
	['n4', 'n5', 'n6'],
	['n7', 'n8', 'n9'],
	['__', 'n0', 'nd'],
	['_s', '_d', '_m'],
	['_a', '_c', '_e'],

]

var symbols = {

	n1:"symbol-0001.png",
	n2:"symbol-0002.png",
	n3:"symbol-0003.png",
	n4:"symbol-0004.png",
	n5:"symbol-0005.png",
	n6:"symbol-0006.png",
	n7:"symbol-0007.png",
	n8:"symbol-0008.png",
	n9:"symbol-0009.png",
	n0:"symbol-0010.png",
	nd:"symbol-0011.png", /* decimal */
	_a:"symbol-0012.png", /* add */
	_s:"symbol-0013.png", /* subtract */
	_c:"symbol-0014.png", /* clear */
	_m:"symbol-0015.png", /* multiply */
	_d:"symbol-0016.png", /* divide */
	_e:"symbol-0017.png", /* equals */
	_t:"symbol-0018.png", /* tick */
  __:null 							/* blank */

}

var chars = {

	n0:"0",
  n1:"1",
  n2:"2",
  n3:"3",
  n4:"4",
  n5:"5",
  n6:"6",
  n7:"7",
  n8:"8",
  n9:"9",
  nd:".",
  _a:"+", 			/* add */
	_s:"-", 			/* subtract */
	_m:"×",	/* multiply */
	_d:"÷" /* divide */

}

var class_names = {

	n1:"number1",
	n2:"number2",
	n3:"number3",
	n4:"number4",
	n5:"number5",
	n6:"number6",
	n7:"number7",
	n8:"number8",
	n9:"number9",
	n0:"number0",
	nd:"decimal",
	_a:"add",
	_s:"subtract",
	_c:"clear",
	_m:"multiply",
	_d:"divide",
	_e:"equals",
	_t:"tick",
	__:"blank"

}

var default_config = {

	display:true,
	decimals:2,
	integers:10,
	lib:'build/shennan-calculator/lib'

}

module.exports = function(buttons, config){

	config = config || {};

	for(var i in default_config){

		if(typeof config[i] === 'undefined')
			config[i] = default_config[i];

	}

	return new Calculator(buttons || default_buttons, config);

}

function Calculator(buttons, config){

	var n1 = '';
	var n2 = '';
	var operator;
	var operator_active;
	var btns = [];

	var calc = emitter( create_element('div', 'calculator') );

	var row_height = config.display ? 90 / (buttons.length + 1) : 90 / buttons.length;

	var display_row = create_element('div', 'row');

	display_row.style.height = row_height + '%';

	var display = display_row.appendChild( create_element('div', 'display') );

	var display_inner = display.appendChild( create_element('div', 'inner') );

	if(config.display){

		calc.appendChild( display_row );

	}

	for(var i in buttons){

		var cell_width = 100 / buttons[i].length

		var row = create_element('div', 'row');

		row.style.height = row_height + '%';

		calc.appendChild(row);

		for(var j in buttons[i]){

			var cell = create_element('div', 'cell');

			cell.style.width = cell_width + '%';
			cell.style.left = cell_width * parseInt(j) + '%';

			if(symbols[buttons[i][j]]){

				var symbol = buttons[i][j];

				var button = create_button( symbols[symbol], class_names[symbol] );

				button.setAttribute('data-symbol', symbol);

				btns.push(button);

				cell.appendChild(button);

				if(symbol === '_e' || symbol === '_t'){

					button.onclick = confirm_pressed;

				}else if(symbol === '_c'){

					button.onclick = clear_pressed;

				}else{

					button.onclick = button_pressed;

				}
			}

			row.appendChild(cell);

		}
	}

	calc.clear = function(emit){

		emit = typeof emit === 'boolean' ? emit : true;

		n1 = '';
		n2 = '';
		operator = undefined;
		operator_active = undefined;

		render();

		if(emit)
			calc.emit('clear');

	}

	function confirm_pressed(e){

		equals();

		render();

		calc.emit('confirm', get_current_number());

	}

	function clear_pressed(e){

		n1 = '';
		n2 = '';
		operator = undefined;
		operator_active = undefined;

		render();

		calc.emit('clear');

	}

	function button_pressed(e){

		var button = typeof e !== 'undefined' ? e.currentTarget : this;

		var symbol = button.getAttribute('data-symbol');

		var op = !/n./.test(symbol);

		if(op){

			if(!operator_active) equals(operator);

			operator = symbol;

		}else{

			if(operator){

				n2 += chars[symbol];

			}else{

				n1 += chars[symbol];

			}
		}

		operator_active = op ? button : undefined;

		render();

		calc.emit('button', get_current_number());

	}

	function equals(){

		var nn1 = Number(n1);
		var nn2 = Number(n2);

		switch(operator){

			case '_d':
				nn1 /= nn2;
				n2 = '';
				break;
			case '_s':
				nn1 -= nn2;
				n2 = '';
				break;
			case '_m':
				nn1 *= nn2;
				n2 = '';
				break;
			case '_a':
				nn1 += nn2;
				n2 = '';
				break;

		}

		n1 = String(round(nn1, config.decimals));

	}

	function render(){

		render_display();
		render_buttons();

	}

	function render_display(){

		display_inner.innerHTML = get_current_number_string();

	}

	function render_buttons(){

		var regex = /active/;

		for(var i in btns){

			if(btns[i] !== operator_active){

				btns[i].className = btns[i].className.replace(regex, '');

			}else{

				if(!regex.test(operator_active.className)){

					operator_active.className += ' active';

				}
			}
		}
	}

	function get_current_number_string(){

		var n = !n2.length ? n1 : n2;

		// add sign if we're dealing with negative number to start
		prepend = (operator === '_s' && n1 === '0') ? '-' : '';

		return n === '0' ? prepend : prepend + n;

	}

	function get_current_number(){

		return !n2.length ? Number(n1) : Number(n2);

	}

	function round(number, places) {

    return Math.round(number * Math.pow(10, places)) / Math.pow(10, places);

	}

	function create_element(tagname, classes, id){

		if(!document)
			throw new Error('There is no document object!');

		var el = document.createElement(tagname);

		if(typeof id === 'string')
			el.id = id;

		if(typeof classes === 'string')
			el.className = classes;

		if(classes instanceof Array)
			el.className = classes.join(' ');

		return el;

	}

	function create_button(icon, classes){

		if(classes instanceof Array)
			classes.push('button');

		if(typeof classes === 'string')
			classes += ' button';

		var button = create_element('img', classes);

		button.src = config.lib + '/imgs/' + icon;

		button.draggable = false;
		button.ondragstart = function(){ return false; }

		return button;

	}

	return calc;

}<commit_msg>added touch support<commit_after>var emitter = require('emitter');

var default_buttons = [

	['n1', 'n2', 'n3'],
	['n4', 'n5', 'n6'],
	['n7', 'n8', 'n9'],
	['__', 'n0', 'nd'],
	['_s', '_d', '_m'],
	['_a', '_c', '_e'],

]

var symbols = {

	n1:"symbol-0001.png",
	n2:"symbol-0002.png",
	n3:"symbol-0003.png",
	n4:"symbol-0004.png",
	n5:"symbol-0005.png",
	n6:"symbol-0006.png",
	n7:"symbol-0007.png",
	n8:"symbol-0008.png",
	n9:"symbol-0009.png",
	n0:"symbol-0010.png",
	nd:"symbol-0011.png", /* decimal */
	_a:"symbol-0012.png", /* add */
	_s:"symbol-0013.png", /* subtract */
	_c:"symbol-0014.png", /* clear */
	_m:"symbol-0015.png", /* multiply */
	_d:"symbol-0016.png", /* divide */
	_e:"symbol-0017.png", /* equals */
	_t:"symbol-0018.png", /* tick */
  __:null 							/* blank */

}

var chars = {

	n0:"0",
  n1:"1",
  n2:"2",
  n3:"3",
  n4:"4",
  n5:"5",
  n6:"6",
  n7:"7",
  n8:"8",
  n9:"9",
  nd:".",
  _a:"+", 			/* add */
	_s:"-", 			/* subtract */
	_m:"×",	/* multiply */
	_d:"÷" /* divide */

}

var class_names = {

	n1:"number1",
	n2:"number2",
	n3:"number3",
	n4:"number4",
	n5:"number5",
	n6:"number6",
	n7:"number7",
	n8:"number8",
	n9:"number9",
	n0:"number0",
	nd:"decimal",
	_a:"add",
	_s:"subtract",
	_c:"clear",
	_m:"multiply",
	_d:"divide",
	_e:"equals",
	_t:"tick",
	__:"blank"

}

var default_config = {

	display:true,
	decimals:2,
	integers:10,
	lib:'build/shennan-calculator/lib'

}

module.exports = function(buttons, config){

	config = config || {};

	for(var i in default_config){

		if(typeof config[i] === 'undefined')
			config[i] = default_config[i];

	}

	return new Calculator(buttons || default_buttons, config);

}

function Calculator(buttons, config){

	var n1 = '';
	var n2 = '';
	var operator;
	var operator_active;
	var btns = [];

	var calc = emitter( create_element('div', 'calculator') );

	var row_height = config.display ? 90 / (buttons.length + 1) : 90 / buttons.length;

	var display_row = create_element('div', 'row');

	display_row.style.height = row_height + '%';

	var display = display_row.appendChild( create_element('div', 'display') );

	var display_inner = display.appendChild( create_element('div', 'inner') );

	if(config.display){

		calc.appendChild( display_row );

	}

	for(var i in buttons){

		var cell_width = 100 / buttons[i].length

		var row = create_element('div', 'row');

		row.style.height = row_height + '%';

		calc.appendChild(row);

		for(var j in buttons[i]){

			var cell = create_element('div', 'cell');

			cell.style.width = cell_width + '%';
			cell.style.left = cell_width * parseInt(j) + '%';

			if(symbols[buttons[i][j]]){

				var symbol = buttons[i][j];

				var button = create_button( symbols[symbol], class_names[symbol] );

				button.setAttribute('data-symbol', symbol);

				btns.push(button);

				cell.appendChild(button);

				if(symbol === '_e' || symbol === '_t'){

					button.onclick = button.ontouchend = confirm_pressed;

				}else if(symbol === '_c'){

					button.onclick = button.ontouchend = clear_pressed;

				}else{

					button.onclick = button.ontouchend = button_pressed;

				}
			}

			row.appendChild(cell);

		}
	}

	calc.clear = function(emit){

		emit = typeof emit === 'boolean' ? emit : true;

		n1 = '';
		n2 = '';
		operator = undefined;
		operator_active = undefined;

		render();

		if(emit)
			calc.emit('clear');

	}

	function confirm_pressed(e){

		e.preventDefault ? e.preventDefault() : e.returnValue = false;

		equals();

		render();

		calc.emit('confirm', get_current_number());

	}

	function clear_pressed(e){

		e.preventDefault ? e.preventDefault() : e.returnValue = false;

		n1 = '';
		n2 = '';
		operator = undefined;
		operator_active = undefined;

		render();

		calc.emit('clear');

	}

	function button_pressed(e){

		e.preventDefault ? e.preventDefault() : e.returnValue = false;

		var button = typeof e !== 'undefined' ? e.currentTarget : this;

		var symbol = button.getAttribute('data-symbol');

		var op = !/n./.test(symbol);

		if(op){

			if(!operator_active) equals(operator);

			operator = symbol;

		}else{

			if(operator){

				n2 += chars[symbol];

			}else{

				n1 += chars[symbol];

			}
		}

		operator_active = op ? button : undefined;

		render();

		calc.emit('button', get_current_number());

	}

	function equals(){

		var nn1 = Number(n1);
		var nn2 = Number(n2);

		switch(operator){

			case '_d':
				nn1 /= nn2;
				n2 = '';
				break;
			case '_s':
				nn1 -= nn2;
				n2 = '';
				break;
			case '_m':
				nn1 *= nn2;
				n2 = '';
				break;
			case '_a':
				nn1 += nn2;
				n2 = '';
				break;

		}

		n1 = String(round(nn1, config.decimals));

	}

	function render(){

		render_display();
		render_buttons();

	}

	function render_display(){

		display_inner.innerHTML = get_current_number_string();

	}

	function render_buttons(){

		var regex = /active/;

		for(var i in btns){

			if(btns[i] !== operator_active){

				btns[i].className = btns[i].className.replace(regex, '');

			}else{

				if(!regex.test(operator_active.className)){

					operator_active.className += ' active';

				}
			}
		}
	}

	function get_current_number_string(){

		var n = !n2.length ? n1 : n2;

		// add sign if we're dealing with negative number to start
		prepend = (operator === '_s' && n1 === '0') ? '-' : '';

		return n === '0' ? prepend : prepend + n;

	}

	function get_current_number(){

		return !n2.length ? Number(n1) : Number(n2);

	}

	function round(number, places) {

    return Math.round(number * Math.pow(10, places)) / Math.pow(10, places);

	}

	function create_element(tagname, classes, id){

		if(!document)
			throw new Error('There is no document object!');

		var el = document.createElement(tagname);

		if(typeof id === 'string')
			el.id = id;

		if(typeof classes === 'string')
			el.className = classes;

		if(classes instanceof Array)
			el.className = classes.join(' ');

		return el;

	}

	function create_button(icon, classes){

		if(classes instanceof Array)
			classes.push('button');

		if(typeof classes === 'string')
			classes += ' button';

		var button = create_element('img', classes);

		button.src = config.lib + '/imgs/' + icon;

		button.draggable = false;
		button.ondragstart = function(){ return false; }

		return button;

	}

	return calc;

}<|endoftext|>


<commit_before>var level = require('level');
var multilevel = require('multilevel');
var levelProxy = require('level-proxy');
var net = require('net');
var fs = require('fs');
var path = require('path');
var has = require('has');
var manifest = require('level-manifest')({
    methods: {
        _iteratorCreate: { type: 'async' },
        _iteratorNext: { type: 'async' },
        _iteratorEnd: { type: 'async' }
    }
});

module.exports = function (dir, opts) {
    var proxy = levelProxy();
    withProxy(proxy, dir, opts);
    return proxy;
};

function withProxy (proxy, dir, opts) {
    var db = level(dir, opts);
    var sockfile = path.join(dir, 'level-party.sock');

    db.once('error', onerror);
    db.once('open', onopen);

    function onerror (err) {
        db.removeListener('open', onopen);
        if (err.type === 'OpenError') createStream();
    }

    function onopen (times) {
        db.removeListener('error', onerror);

        var server = net.createServer(function (stream) {
            var iterators = {};
            if (!db.methods) db.methods = {};

            db.methods._iteratorCreate = { type: 'async' };
            db._iteratorCreate = function (ix, opts) {
                iterators[ix] = (db.iterator && db.iterator(opts))
                    || (db.db && db.db.iterator && db.db.iterator(opts))
                ;
            };

            db.methods._iteratorNext = { type: 'async' };
            db._iteratorNext = function (ix, cb) {
                if (!has(iterators, ix)) cb(new Error('no such iterator'))
                else iterators[ix].next(function (err, key, value) {
                    cb(err, key, value);
                })
            };

            db.methods._iteratorEnd = { type: 'async' };
            db._iteratorEnd = function (ix, cb) {
                if (!has(iterators, ix)) cb(new Error('no such iterator'))
                else iterators[ix].end(cb)
            };

            stream.on('error', function (err) { cleanup() });
            stream.once('end', cleanup);
            stream.pipe(multilevel.server(db)).pipe(stream);

            function cleanup () {
                Object.keys(iterators).forEach(function (ix) {
                    iterators[ix].end(function () {});
                });
                iterators = null;
            }
        });
        server.listen(sockfile);

        server.once('error', onerror);
        server.once('listening', onlistening);

        function onerror (err) {
            server.removeListener('listening', onlistening);
            if (!times && err && err.code === 'EADDRINUSE') {
                fs.unlink(sockfile, function (err) {
                    if (err) db.emit('error', err)
                    else onopen(1)
                });
            }
            else db.emit('error', err);
        }

        function onlistening () {
            server.removeListener('error', onerror);
            db.close = function () {
                proxy.swap(null);
                server.close();
            };
            proxy.swap(db);
            proxy.emit('open');
        }
    }

    function createStream () {
        var xdb = multilevel.client(manifest);

        var iteratorIx = 0;
        xdb.iterator = function (opts) {
            var ix = iteratorIx ++;
            xdb._iteratorCreate(ix, opts);

            return { next: next, end: end };
            function next (cb) { xdb._iteratorNext(ix, cb) }
            function end (cb) { xdb._iteratorEnd(ix, cb) }
        };

        (function connect () {
            var stream = net.connect(sockfile);
            stream.on('connect', function () {
                xdb.open = function () {};
                xdb.close = function () {
                    proxy.swap(null);
                    stream.removeListener('end', onend);
                    stream.end();
                };
                proxy.swap(xdb);
                proxy.emit('open');
            });

            stream.on('error', function (err) {
                stream.removeListener('end', onend);
                setTimeout(connect, 50);
            });
            stream.on('end', onend);
            stream.pipe(xdb.createRpcStream()).pipe(stream);

            function onend () {
                proxy.swap(null);
                withProxy(proxy, dir, opts);
            }
        })();
    }
}
<commit_msg>all tests pass<commit_after>var level = require('level');
var multilevel = require('multilevel');
var levelProxy = require('level-proxy');
var net = require('net');
var fs = require('fs');
var path = require('path');
var has = require('has');
var manifest = require('level-manifest')({
    methods: {
        _iteratorCreate: { type: 'async' },
        _iteratorNext: { type: 'async' },
        _iteratorEnd: { type: 'async' }
    }
});

module.exports = function (dir, opts) {
    var proxy = levelProxy();
    withProxy(proxy, dir, opts);
    return proxy;
};

function withProxy (proxy, dir, opts) {
    var db = level(dir, opts);
    var sockfile = path.join(dir, 'level-party.sock');

    db.once('error', onerror);
    db.once('open', onopen);

    function onerror (err) {
        db.removeListener('open', onopen);
        if (err.type === 'OpenError') createStream();
    }

    function onopen (times) {
        db.removeListener('error', onerror);

        var server = net.createServer(function (stream) {
            var iterators = {};
            if (!db.methods) db.methods = {};

            db.methods._iteratorCreate = { type: 'async' };
            db._iteratorCreate = function (ix, opts) {
                iterators[ix] = (db.iterator && db.iterator(opts))
                    || (db.db && db.db.iterator && db.db.iterator(opts))
                ;
            };

            db.methods._iteratorNext = { type: 'async' };
            db._iteratorNext = function (ix, cb) {
                if (!has(iterators, ix)) cb(new Error('no such iterator'))
                else iterators[ix].next(cb);
            };

            db.methods._iteratorEnd = { type: 'async' };
            db._iteratorEnd = function (ix, cb) {
                if (!has(iterators, ix)) cb(new Error('no such iterator'))
                else iterators[ix].end(cb)
            };

            stream.on('error', function (err) { cleanup() });
            stream.once('end', cleanup);
            stream.pipe(multilevel.server(db)).pipe(stream);

            function cleanup () {
                Object.keys(iterators).forEach(function (ix) {
                    iterators[ix].end(function () {});
                });
                iterators = null;
            }
        });
        server.listen(sockfile);

        server.once('error', onerror);
        server.once('listening', onlistening);

        function onerror (err) {
            server.removeListener('listening', onlistening);
            if (!times && err && err.code === 'EADDRINUSE') {
                fs.unlink(sockfile, function (err) {
                    if (err) db.emit('error', err)
                    else onopen(1)
                });
            }
            else db.emit('error', err);
        }

        function onlistening () {
            server.removeListener('error', onerror);
            db.close = function () {
                proxy.swap(null);
                server.close();
            };
            proxy.swap(db);
            proxy.emit('open');
        }
    }

    function createStream () {
        var xdb = multilevel.client(manifest);

        var iteratorIx = 0;
        xdb.iterator = function (opts) {
            var ix = iteratorIx ++;
            xdb._iteratorCreate(ix, opts);

            return { next: next, end: end };
            function next (cb) { xdb._iteratorNext(ix, cb) }
            function end (cb) { xdb._iteratorEnd(ix, cb) }
        };

        (function connect () {
            var stream = net.connect(sockfile);
            stream.on('connect', function () {
                xdb.open = function () {};
                xdb.close = function () {
                    proxy.swap(null);
                    stream.removeListener('end', onend);
                    stream.end();
                };
                proxy.swap(xdb);
                proxy.emit('open');
            });

            stream.on('error', function (err) {
                stream.removeListener('end', onend);
                setTimeout(connect, 50);
            });
            stream.on('end', onend);
            stream.pipe(xdb.createRpcStream()).pipe(stream);

            function onend () {
                proxy.swap(null);
                withProxy(proxy, dir, opts);
            }
        })();
    }
}
<|endoftext|>


<commit_before>//Library of Array and Object sorting algorithms
var sort = require('./sorting');
//Library of Discrete Data Structures
var data = require('./data');

function objectsEqual(o1, o2) {
	if (typeof o1 !== typeof o2)
		return false

	if (typeof o1 === 'object') {
		var k1 = Object.keys(o1);
		var k2 = Object.keys(o2);
		if (k1.length !== k2.length)
			return false
    for (var i = 0; i < k1.length; i++) {
      if (k1[i] !== k2[i]) {
        return false
      }
    }
		for (var i = 0; i < k1.length; i++) {
			if (! objectsEqual(o1[k1[i]], o2[k2[i]]))
      	return false
		}
    return true
	}
	else
		return o1 === o2
}

function randomInt(min, max) {
  if (min <= max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  } else {
    throw new RangeError("Minimum must be less than or equal to Maximum")
  }
}

module.exports = {objectsEqual, randomInt, sort};
<commit_msg>added data to module exports<commit_after>//Library of Array and Object sorting algorithms
var sort = require('./sorting');
//Library of Discrete Data Structures
var data = require('./data');

function objectsEqual(o1, o2) {
	if (typeof o1 !== typeof o2)
		return false

	if (typeof o1 === 'object') {
		var k1 = Object.keys(o1);
		var k2 = Object.keys(o2);
		if (k1.length !== k2.length)
			return false
    for (var i = 0; i < k1.length; i++) {
      if (k1[i] !== k2[i]) {
        return false
      }
    }
		for (var i = 0; i < k1.length; i++) {
			if (! objectsEqual(o1[k1[i]], o2[k2[i]]))
      	return false
		}
    return true
	}
	else
		return o1 === o2
}

function randomInt(min, max) {
  if (min <= max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  } else {
    throw new RangeError("Minimum must be less than or equal to Maximum")
  }
}

module.exports = {objectsEqual, randomInt, sort, data};
<|endoftext|>


<commit_before>'use strict';
const fs = require('fs');
const Discord = require('discord.js');

const Nix = require('./lib/nix');
const cfg = require('./config.js');

const discordClient = new Discord.Client();

let nix = new Nix(discordClient, cfg);

// Load every command in the commands folder
fs.readdirSync('./lib/commands')
  .forEach(file => {
    nix.addCommand(require('./lib/commands/' + file));
  });

nix.listen()
  .subscribe(
    () => {},
    (error) => onNixError(error),
    () => onNixComplete()
);

function onNixError(error) {
  console.error(error);
  nix.messageOwner('Unhandled error: ' + error)
    .subscribe(
      () => {},
      () => {},
      () => process.exit(1)
    )
}

function onNixComplete() {
  console.log('Shutting down');
  nix.messageOwner('Nix shutting down')
    .subscribe(
      () => {},
      () => {},
      () => process.exit(0)
    );
}
<commit_msg>Update final catch error message for the owner<commit_after>'use strict';
const fs = require('fs');
const Discord = require('discord.js');

const Nix = require('./lib/nix');
const cfg = require('./config.js');

const discordClient = new Discord.Client();

let nix = new Nix(discordClient, cfg);

// Load every command in the commands folder
fs.readdirSync('./lib/commands')
  .forEach(file => {
    nix.addCommand(require('./lib/commands/' + file));
  });

nix.listen()
  .subscribe(
    () => {},
    (error) => onNixError(error),
    () => onNixComplete()
);

function onNixError(error) {
  console.error(error);
  nix.messageOwner('Shutting down due to unhandled error: ' + error)
    .subscribe(
      () => {},
      () => {},
      () => process.exit(1)
    );
}

function onNixComplete() {
  console.log('Shutting down');
  nix.messageOwner('Nix shutting down')
    .subscribe(
      () => {},
      () => {},
      () => process.exit(0)
    );
}
<|endoftext|>


<commit_before>// load all the things

require('fs').readdirSync(__dirname + '/lib/').forEach(function(file) {
  if (file.match(/.+\.js/g) !== null && file !== 'index.js') {
    var name = file.replace('.js', '');
    exports[name] = require('./lib/' + file).factory;
  }
});

exports.io = {};
require('fs').readdirSync(__dirname + '/lib/io/').forEach(function(file) {
  if (file.match(/.+\.js/g) !== null && file !== 'index.js') {
    var name = file.replace('.js', '');
    exports.io[name] = require('./lib/io/' + file).factory;
  }
});

<commit_msg>no need to avoid index.js in lib/io as it doesn't exist<commit_after>// load all the things

require('fs').readdirSync(__dirname + '/lib/').forEach(function(file) {
  if (file.match(/.+\.js/g) !== null && file !== 'index.js') {
    var name = file.replace('.js', '');
    exports[name] = require('./lib/' + file).factory;
  }
});

exports.io = {};
require('fs').readdirSync(__dirname + '/lib/io/').forEach(function(file) {
  if (file.match(/.+\.js/g) !== null) {
    var name = file.replace('.js', '');
    exports.io[name] = require('./lib/io/' + file).factory;
  }
});
<|endoftext|>


<commit_before>const firebase = require('firebase')
const config = require('./config')

firebase.initializeApp(config);

var ref = firebase.database().ref().child("room1")
var Gpio = require('onoff').Gpio;
var led = new Gpio(17, 'out');

ref.on('value', function (data) {
    if (data.val().Light == "1") {
        console.log('led on :-)')
        led.writeSync(1);
        // var iv = setInterval(function(){
        //     led.writeSync(led.readSync() === 0 ? 1 : 0)
        // }, 800)
        // var iv = setInterval(function(){
        //     led.writeSync(led.readSync() === 0 ? 1 : 0)
        // }, 100);
    } else {
        console.log('led off')
        led.writeSync(0);
    }
})
<commit_msg>update project<commit_after>const firebase = require('firebase')
const config = require('./config')

firebase.initializeApp(config);

var ref = firebase.database().ref().child("room1")
var Gpio = require('onoff').Gpio;
var led = new Gpio(17, 'out');

ref.on('value', function (data) {
    if (data.val().Light == "1") {
        console.log('led on :-)')
        // led.writeSync(1);
        var iv = setInterval(function(){
            led.writeSync(led.readSync() === 0 ? 1 : 0)
        }, 800)
        // var iv = setInterval(function(){
        //     led.writeSync(led.readSync() === 0 ? 1 : 0)
        // }, 100);
    } else {
        console.log('led off')
        led.writeSync(0);
    }
})
<|endoftext|>


<commit_before>
var hex2bin = {
  '0': '0000', '1': '0001', '2': '0010', '3': '0011',
  '4': '0100', '5': '0101', '6': '0110', '7': '0111',
  '8': '1000', '9': '1001', 'a': '1010', 'b': '1011',
  'c': '1100', 'd': '1101', 'e': '1110', 'f': '1111'
};

var map = [
  [1],
  [2],
  [4],
  [8],
  [1, 6],
  [3, 2],
  [6, 4],
  [1, 2, 8],
  [2, 5, 6],
  [5, 1, 2],
  [1, 0, 2, 4],
  [2, 0, 4, 8],
  [4, 0, 9, 6],
  [8, 1, 9, 2],
  [1, 6, 3, 8, 4],
  [3, 2, 7, 6, 8],
  [6, 5, 5, 3, 6],
  [1, 3, 1, 0, 7, 2],
  [2, 6, 2, 1, 4, 4],
  [5, 2, 4, 2, 8, 8],
  [1, 0, 4, 8, 5, 7, 6],
  [2, 0, 9, 7, 1, 5, 2],
  [4, 1, 9, 4, 3, 0, 4],
  [8, 3, 8, 8, 6, 0, 8],
  [1, 6, 7, 7, 7, 2, 1, 6],
  [3, 3, 5, 5, 4, 4, 3, 2],
  [6, 7, 1, 0, 8, 8, 6, 4],
  [1, 3, 4, 2, 1, 7, 7, 2, 8],
  [2, 6, 8, 4, 3, 5, 4, 5, 6],
  [5, 3, 6, 8, 7, 0, 9, 1, 2],
  [1, 0, 7, 3, 7, 4, 1, 8, 2, 4],
  [2, 1, 4, 7, 4, 8, 3, 6, 4, 8],
  [4, 2, 9, 4, 9, 6, 7, 2, 9, 6],
  [8, 5, 8, 9, 9, 3, 4, 5, 9, 2],
  [1, 7, 1, 7, 9, 8, 6, 9, 1, 8, 4],
  [3, 4, 3, 5, 9, 7, 3, 8, 3, 6, 8],
  [6, 8, 7, 1, 9, 4, 7, 6, 7, 3, 6],
  [1, 3, 7, 4, 3, 8, 9, 5, 3, 4, 7, 2],
  [2, 7, 4, 8, 7, 7, 9, 0, 6, 9, 4, 4],
  [5, 4, 9, 7, 5, 5, 8, 1, 3, 8, 8, 8],
  [1, 0, 9, 9, 5, 1, 1, 6, 2, 7, 7, 7, 6],
  [2, 1, 9, 9, 0, 2, 3, 2, 5, 5, 5, 5, 2],
  [4, 3, 9, 8, 0, 4, 6, 5, 1, 1, 1, 0, 4],
  [8, 7, 9, 6, 0, 9, 3, 0, 2, 2, 2, 0, 8],
  [1, 7, 5, 9, 2, 1, 8, 6, 0, 4, 4, 4, 1, 6],
  [3, 5, 1, 8, 4, 3, 7, 2, 0, 8, 8, 8, 3, 2],
  [7, 0, 3, 6, 8, 7, 4, 4, 1, 7, 7, 6, 6, 4],
  [1, 4, 0, 7, 3, 7, 4, 8, 8, 3, 5, 5, 3, 2, 8],
  [2, 8, 1, 4, 7, 4, 9, 7, 6, 7, 1, 0, 6, 5, 6],
  [5, 6, 2, 9, 4, 9, 9, 5, 3, 4, 2, 1, 3, 1, 2],
  [1, 1, 2, 5, 8, 9, 9, 9, 0, 6, 8, 4, 2, 6, 2, 4],
  [2, 2, 5, 1, 7, 9, 9, 8, 1, 3, 6, 8, 5, 2, 4, 8],
  [4, 5, 0, 3, 5, 9, 9, 6, 2, 7, 3, 7, 0, 4, 9, 6],
  [9, 0, 0, 7, 1, 9, 9, 2, 5, 4, 7, 4, 0, 9, 9, 2],
  [1, 8, 0, 1, 4, 3, 9, 8, 5, 0, 9, 4, 8, 1, 9, 8, 4],
  [3, 6, 0, 2, 8, 7, 9, 7, 0, 1, 8, 9, 6, 3, 9, 6, 8],
  [7, 2, 0, 5, 7, 5, 9, 4, 0, 3, 7, 9, 2, 7, 9, 3, 6],
  [1, 4, 4, 1, 1, 5, 1, 8, 8, 0, 7, 5, 8, 5, 5, 8, 7, 2],
  [2, 8, 8, 2, 3, 0, 3, 7, 6, 1, 5, 1, 7, 1, 1, 7, 4, 4],
  [5, 7, 6, 4, 6, 0, 7, 5, 2, 3, 0, 3, 4, 2, 3, 4, 8, 8],
  [1, 1, 5, 2, 9, 2, 1, 5, 0, 4, 6, 0, 6, 8, 4, 6, 9, 7, 6],
  [2, 3, 0, 5, 8, 4, 3, 0, 0, 9, 2, 1, 3, 6, 9, 3, 9, 5, 2],
  [4, 6, 1, 1, 6, 8, 6, 0, 1, 8, 4, 2, 7, 3, 8, 7, 9, 0, 4],
  [9, 2, 2, 3, 3, 7, 2, 0, 3, 6, 8, 5, 4, 7, 7, 5, 8, 0, 8],
  [1, 8, 4, 4, 6, 7, 4, 4, 0, 7, 3, 7, 0, 9, 5, 5, 1, 6, 1, 6],
  [3, 6, 8, 9, 3, 4, 8, 8, 1, 4, 7, 4, 1, 9, 1, 0, 3, 2, 3, 2]
];

var trimReg = /^0+/;

// node version check
var ver = process.version.substring(1).split('.');
var useTypedArray = ver[0] * 100000 + ver[1] * 1000 + ver[2] * 1 >= 11013

var arrayAdd = function(base, add) {
  var pos = 19, range = 20 - add.length;
  while (true) {
    if (pos >= range) {
      base[pos] += add[pos - range];
    }
    if (base[pos] > 9) {
      base[pos - 1]++;
      base[pos] -= 10;
    } else if (pos < range) {
      break;
    }
    pos--;
  }
};

module.exports = function(hex) {
  var output = btmp = binary = '', i = pos = 0, negative = false
    number = useTypedArray ? new Uint8Array(20) : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];

  hex = hex.substring(0, 16).toLowerCase();

  // to bin
  for (i = 15; i >= 0; i--) {
    binary = (hex[i] ? hex2bin[hex[i]] : '0000') + binary;
  }

  // negative flag
  negative = binary[0] === '1';
  binary = binary.substring(1);

  // negative flip
  if (negative) {
    for (i = 0; i < binary.length; i++) {
      btmp += (binary[i] === '1' ? '0' : '1');
    }
    binary = btmp;
  }

  // check map & calc
  for (i = binary.length - 1; i >= 0; i--) {
    binary[i] === '1' && arrayAdd(number, map[pos])
    pos++;
  }

  // negative flip back
  negative && arrayAdd(number, map[0]);

  // result tostring
  btmp = '';
  for (i = 0; i < number.length; i++) {
    btmp += number[i];
  }
  // trim left zeropad
  output = btmp.replace(trimReg, '');

  // add '-'
  return negative ? '-' + output : output;
};
<commit_msg>add more arguments type<commit_after>
var hex2bin = {
  '0': '0000', '1': '0001', '2': '0010', '3': '0011',
  '4': '0100', '5': '0101', '6': '0110', '7': '0111',
  '8': '1000', '9': '1001', 'a': '1010', 'b': '1011',
  'c': '1100', 'd': '1101', 'e': '1110', 'f': '1111'
};

var map = [
  [1],
  [2],
  [4],
  [8],
  [1, 6],
  [3, 2],
  [6, 4],
  [1, 2, 8],
  [2, 5, 6],
  [5, 1, 2],
  [1, 0, 2, 4],
  [2, 0, 4, 8],
  [4, 0, 9, 6],
  [8, 1, 9, 2],
  [1, 6, 3, 8, 4],
  [3, 2, 7, 6, 8],
  [6, 5, 5, 3, 6],
  [1, 3, 1, 0, 7, 2],
  [2, 6, 2, 1, 4, 4],
  [5, 2, 4, 2, 8, 8],
  [1, 0, 4, 8, 5, 7, 6],
  [2, 0, 9, 7, 1, 5, 2],
  [4, 1, 9, 4, 3, 0, 4],
  [8, 3, 8, 8, 6, 0, 8],
  [1, 6, 7, 7, 7, 2, 1, 6],
  [3, 3, 5, 5, 4, 4, 3, 2],
  [6, 7, 1, 0, 8, 8, 6, 4],
  [1, 3, 4, 2, 1, 7, 7, 2, 8],
  [2, 6, 8, 4, 3, 5, 4, 5, 6],
  [5, 3, 6, 8, 7, 0, 9, 1, 2],
  [1, 0, 7, 3, 7, 4, 1, 8, 2, 4],
  [2, 1, 4, 7, 4, 8, 3, 6, 4, 8],
  [4, 2, 9, 4, 9, 6, 7, 2, 9, 6],
  [8, 5, 8, 9, 9, 3, 4, 5, 9, 2],
  [1, 7, 1, 7, 9, 8, 6, 9, 1, 8, 4],
  [3, 4, 3, 5, 9, 7, 3, 8, 3, 6, 8],
  [6, 8, 7, 1, 9, 4, 7, 6, 7, 3, 6],
  [1, 3, 7, 4, 3, 8, 9, 5, 3, 4, 7, 2],
  [2, 7, 4, 8, 7, 7, 9, 0, 6, 9, 4, 4],
  [5, 4, 9, 7, 5, 5, 8, 1, 3, 8, 8, 8],
  [1, 0, 9, 9, 5, 1, 1, 6, 2, 7, 7, 7, 6],
  [2, 1, 9, 9, 0, 2, 3, 2, 5, 5, 5, 5, 2],
  [4, 3, 9, 8, 0, 4, 6, 5, 1, 1, 1, 0, 4],
  [8, 7, 9, 6, 0, 9, 3, 0, 2, 2, 2, 0, 8],
  [1, 7, 5, 9, 2, 1, 8, 6, 0, 4, 4, 4, 1, 6],
  [3, 5, 1, 8, 4, 3, 7, 2, 0, 8, 8, 8, 3, 2],
  [7, 0, 3, 6, 8, 7, 4, 4, 1, 7, 7, 6, 6, 4],
  [1, 4, 0, 7, 3, 7, 4, 8, 8, 3, 5, 5, 3, 2, 8],
  [2, 8, 1, 4, 7, 4, 9, 7, 6, 7, 1, 0, 6, 5, 6],
  [5, 6, 2, 9, 4, 9, 9, 5, 3, 4, 2, 1, 3, 1, 2],
  [1, 1, 2, 5, 8, 9, 9, 9, 0, 6, 8, 4, 2, 6, 2, 4],
  [2, 2, 5, 1, 7, 9, 9, 8, 1, 3, 6, 8, 5, 2, 4, 8],
  [4, 5, 0, 3, 5, 9, 9, 6, 2, 7, 3, 7, 0, 4, 9, 6],
  [9, 0, 0, 7, 1, 9, 9, 2, 5, 4, 7, 4, 0, 9, 9, 2],
  [1, 8, 0, 1, 4, 3, 9, 8, 5, 0, 9, 4, 8, 1, 9, 8, 4],
  [3, 6, 0, 2, 8, 7, 9, 7, 0, 1, 8, 9, 6, 3, 9, 6, 8],
  [7, 2, 0, 5, 7, 5, 9, 4, 0, 3, 7, 9, 2, 7, 9, 3, 6],
  [1, 4, 4, 1, 1, 5, 1, 8, 8, 0, 7, 5, 8, 5, 5, 8, 7, 2],
  [2, 8, 8, 2, 3, 0, 3, 7, 6, 1, 5, 1, 7, 1, 1, 7, 4, 4],
  [5, 7, 6, 4, 6, 0, 7, 5, 2, 3, 0, 3, 4, 2, 3, 4, 8, 8],
  [1, 1, 5, 2, 9, 2, 1, 5, 0, 4, 6, 0, 6, 8, 4, 6, 9, 7, 6],
  [2, 3, 0, 5, 8, 4, 3, 0, 0, 9, 2, 1, 3, 6, 9, 3, 9, 5, 2],
  [4, 6, 1, 1, 6, 8, 6, 0, 1, 8, 4, 2, 7, 3, 8, 7, 9, 0, 4],
  [9, 2, 2, 3, 3, 7, 2, 0, 3, 6, 8, 5, 4, 7, 7, 5, 8, 0, 8],
  [1, 8, 4, 4, 6, 7, 4, 4, 0, 7, 3, 7, 0, 9, 5, 5, 1, 6, 1, 6],
  [3, 6, 8, 9, 3, 4, 8, 8, 1, 4, 7, 4, 1, 9, 1, 0, 3, 2, 3, 2]
];

var trimReg = /^0+/;

// node version check
var ver = process.version.substring(1).split('.');
var useTypedArray = ver[0] * 100000 + ver[1] * 1000 + ver[2] * 1 >= 11013

var z32 = '00000000000000000000000000000000';
var z64 = z32+z32;

var arrayAdd = function(base, add) {
  var pos = 19, range = 20 - add.length;
  while (true) {
    if (pos >= range) {
      base[pos] += add[pos - range];
    }
    if (base[pos] > 9) {
      base[pos - 1]++;
      base[pos] -= 10;
    } else if (pos < range) {
      break;
    }
    pos--;
  }
};

module.exports = function(hex, low) {
  var ls = hs = output = btmp = binary = '', i = pos = 0, negative = false
    number = useTypedArray ?
      new Uint8Array(20) : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0];

  // high and low
  if (low !== undefined && low != null) {
    binary = hex.toString(2) + z32.substr(0, 32-ls.length) + ls;
  // hex string
  } else if (typeof hex === 'string') {
    hex = hex.toLowerCase();
    // trim left 0x
    hex.substring(0, 2) === '0x' && (hex = hex.substring(2));
    hex = hex.substring(0, 16);
    // to bin
    for (; i < hex.length; i++) {
      binary += hex2bin[hex[i]];
    }

  // number
  } else if (typeof hex === 'number') {
    binary = hex.toString(2);
  // error
  } else {
    throw new Error('argument type errpr');
  }
  // left zero padding
  if (binary.length < 64) {
    binary = z64.substr(0, 64 - binary.length) + binary;
  }

  // negative flag
  negative = binary[0] === '1';
  binary = binary.substring(1);

  // negative flip
  if (negative) {
    for (i = 0; i < binary.length; i++) {
      btmp += (binary[i] === '1' ? '0' : '1');
    }
    binary = btmp;
  }

  // check map & calc
  pos = 0
  for (i = binary.length - 1; i >= 0; i--) {
    binary[i] === '1' && arrayAdd(number, map[pos])
    pos++;
  }

  // negative flip back
  negative && arrayAdd(number, map[0]);

  // result tostring
  btmp = '';
  for (i = 0; i < number.length; i++) {
    btmp += number[i];
  }

  // trim left zeropad
  output = btmp.replace(trimReg, '');

  // add '-'
  return negative ? '-' + output : output;

};

<|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 path = require('path'),
    mkdirp = require('mkdirp').sync,

    log = require('./lib/log'),
    util = require('./lib/utils'),
    create = require('./lib/create'),

    // todo: make user configurable
    SRCPATHS = [path.resolve(__dirname, 'archetypes'), './archetypes'];

function errorWithUsage(code, msg) {
    var err = util.error(code, msg);
    err.usage = module.exports.usage;
    return err;
}

function pathify(subpath) {
    return util.findInPaths(SRCPATHS, subpath); // full path if exists, or false
}

function makeDestinationDir(from, to) {
    var stat = util.exists(from),
        is_file = stat && stat.isFile(),
        dest = is_file ? path.dirname(to) : to,
        dstat = util.exists(dest),
        is_dir = dstat && dstat.isDirectory(),
        error = null;

    if (!dstat || !is_dir) {
        try {
            log.debug('mkdirp ', dest);
            mkdirp(dest);
        } catch(err) {
            error = util.error(9, 'Destination directory is invalid.');
        }
    }

    return error;
}

function getDestinationDir(type, destopt, name) {
    var parts = [destopt];

    if ('mojit' === type.toLowerCase()) {
        parts.push('mojits'); // BC - type "mojit" goes inside mojits dir
    }

    return path.resolve.apply(null, parts.concat(name));
}

function subtypePath(type, args) {
    var subtype = args.length > 1 ? args.shift() : 'default';
    return path.join(type, subtype).toLowerCase(); // i.e. 'app/full'
}

function getSourceDir(type, args) {
    var source, err;

    // get archetype source directory based on first one OR two arguments
    switch (type.toLowerCase()) {
    case 'app':
    case 'mojit':
        // 1. mojito create [options] <app|mojit> [full|simple|default] <name>
        source = pathify(subtypePath(type, args));
        err = 'Invalid subtype.';
        break;

    case 'custom':
        // 2. mojito create [options] custom <path/to/archetype> <name>
        source = pathify(args.shift());
        err = 'Custom archtype path is invalid.';
        break;

    default:
        // 3. mojito create [options] <path/to/archetype> <name>
        //    (this *should* be the only supported syntax)
        source = util.exists(type) && path.resolve(type);
        err = type + ' is not a valid archetype or path.';
    }

    return source || errorWithUsage(5, err);
}

function amMissingArgs(type, args) {
    var err = false;

    if (!type) {
        err = 'No parameters.';

    } else if (!args.length) {
        err = 'Missing subtype, name or path.';
    }

    return err && errorWithUsage(3, err);
}

function exec(source, dest, keyval, cb) {
    var dircheck = makeDestinationDir(source, dest);

    log.info('Name:', keyval.name);
    log.info('Source:', source);
    log.info('Destination:', dest);

    if (dircheck) {
        cb(dircheck);
        return;
    }

    create(source, dest, keyval, cb);
}

function main(env, cb) {
    var type = env.args.shift() || '',
        source = amMissingArgs(type, env.args) || getSourceDir(type, env.args),
        name = env.args.shift(),
        keyval = util.parseCsvObj(env.opts.keyval),
        dest = env.opts.directory || '.';

    if (env.opts.loglevel) {
        log.level = env.opts.loglevel;
        log.silly('logging level set to', env.opts.loglevel);
    }

    if (source instanceof Error) {
        cb(source);
        return;
    }

    if (!name) {
        cb(errorWithUsage(3, 'Missing name.'));
        return;
    }

    if (name.indexOf(path.sep) !== -1) {
        // assume a name like foo/bar/baz is like --dir foo/bar & name baz
        // if --dir is already specified, use it too
        dest = path.resolve(dest, path.dirname(name));
        name = path.basename(name);
    }

    // enable shortcut for destination file/dir name
    if ('.' === name) {
        name = path.basename(source).replace(create.TEMPLATE_RE, '');
    }

    dest = getDestinationDir(type, dest, name);
    keyval.name = keyval.name || name;
    keyval.port = env.opts.port || 8666;

    function npmCb(err) {
        log.info('Installing mojito application "' + dest + '’s" dependencies with npm.');
        module.exports.npmi(err, dest, cb);
    }

    exec(source, dest, keyval, 'app' === type ? npmCb : cb);
}

module.exports = main;

module.exports.usage = [
    'Usage: mojito create [options] <app|mojit> [full|simple|default] <name>',
    'Usage: mojito create [options] custom <path/to/archetype> <name>',
    'Usage: mojito create [options] <path/to/archetype> <name>',
    '',
    'Example: mojito create app Foo',
    '  (creates directory "Foo" containing a new Mojito application named "Foo")',
    '',
    'Example: mojito create mojit Bar',
    '  (creates directory "Bar" containing new Mojit named "Bar")',
    '',
    'Options: ',
    '  --directory <path> Optional destination directory',
    '  -d <path>          Short for --directory',
    '  --port <number>    Specifies default port for your Mojito app to run on.',
    '  -p [number]        Short for --port.',
    '  --keyval <string>  key value pairs to pass to a custom archetype template',
    '                     a key/value is separated by colons, key/value pairs by',
    '                     commas: "key1:val1,key2:val2',
    '  -k <string>        Short for --keyval'].join('\n');

module.exports.options = [
    {shortName: 'd', hasValue: true, longName: 'directory'},
    {shortName: 'k', hasValue: true, longName: 'keyval'},
    {shortName: 'p', hasValue: true, longName: 'port'}
];

module.exports.getSourceDir = getSourceDir;
module.exports.npmi = require('./lib/npmi');
<commit_msg>change SRCPATH[1] from ./archetypes to ../archetypes<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 path = require('path'),
    mkdirp = require('mkdirp').sync,

    log = require('./lib/log'),
    util = require('./lib/utils'),
    create = require('./lib/create'),

    // todo: make user configurable
    SRCPATHS = [path.resolve(__dirname, 'archetypes'), '../archetypes'];

function errorWithUsage(code, msg) {
    var err = util.error(code, msg);
    err.usage = module.exports.usage;
    return err;
}

function pathify(subpath) {
    return util.findInPaths(SRCPATHS, subpath); // full path if exists, or false
}

function makeDestinationDir(from, to) {
    var stat = util.exists(from),
        is_file = stat && stat.isFile(),
        dest = is_file ? path.dirname(to) : to,
        dstat = util.exists(dest),
        is_dir = dstat && dstat.isDirectory(),
        error = null;

    if (!dstat || !is_dir) {
        try {
            log.debug('mkdirp ', dest);
            mkdirp(dest);
        } catch(err) {
            error = util.error(9, 'Destination directory is invalid.');
        }
    }

    return error;
}

function getDestinationDir(type, destopt, name) {
    var parts = [destopt];

    if ('mojit' === type.toLowerCase()) {
        parts.push('mojits'); // BC - type "mojit" goes inside mojits dir
    }

    return path.resolve.apply(null, parts.concat(name));
}

function subtypePath(type, args) {
    var subtype = args.length > 1 ? args.shift() : 'default';
    return path.join(type, subtype).toLowerCase(); // i.e. 'app/full'
}

function getSourceDir(type, args) {
    var source, err;

    // get archetype source directory based on first one OR two arguments
    switch (type.toLowerCase()) {
    case 'app':
    case 'mojit':
        // 1. mojito create [options] <app|mojit> [full|simple|default] <name>
        source = pathify(subtypePath(type, args));
        err = 'Invalid subtype.';
        break;

    case 'custom':
        // 2. mojito create [options] custom <path/to/archetype> <name>
        source = pathify(args.shift());
        err = 'Custom archtype path is invalid.';
        break;

    default:
        // 3. mojito create [options] <path/to/archetype> <name>
        //    (this *should* be the only supported syntax)
        source = util.exists(type) && path.resolve(type);
        err = type + ' is not a valid archetype or path.';
    }

    return source || errorWithUsage(5, err);
}

function amMissingArgs(type, args) {
    var err = false;

    if (!type) {
        err = 'No parameters.';

    } else if (!args.length) {
        err = 'Missing subtype, name or path.';
    }

    return err && errorWithUsage(3, err);
}

function exec(source, dest, keyval, cb) {
    var dircheck = makeDestinationDir(source, dest);

    log.info('Name:', keyval.name);
    log.info('Source:', source);
    log.info('Destination:', dest);

    if (dircheck) {
        cb(dircheck);
        return;
    }

    create(source, dest, keyval, cb);
}

function main(env, cb) {
    var type = env.args.shift() || '',
        source = amMissingArgs(type, env.args) || getSourceDir(type, env.args),
        name = env.args.shift(),
        keyval = util.parseCsvObj(env.opts.keyval),
        dest = env.opts.directory || '.';

    if (env.opts.loglevel) {
        log.level = env.opts.loglevel;
        log.silly('logging level set to', env.opts.loglevel);
    }

    if (source instanceof Error) {
        cb(source);
        return;
    }

    if (!name) {
        cb(errorWithUsage(3, 'Missing name.'));
        return;
    }

    if (name.indexOf(path.sep) !== -1) {
        // assume a name like foo/bar/baz is like --dir foo/bar & name baz
        // if --dir is already specified, use it too
        dest = path.resolve(dest, path.dirname(name));
        name = path.basename(name);
    }

    // enable shortcut for destination file/dir name
    if ('.' === name) {
        name = path.basename(source).replace(create.TEMPLATE_RE, '');
    }

    dest = getDestinationDir(type, dest, name);
    keyval.name = keyval.name || name;
    keyval.port = env.opts.port || 8666;

    function npmCb(err) {
        log.info('Installing mojito application "' + dest + '’s" dependencies with npm.');
        module.exports.npmi(err, dest, cb);
    }

    exec(source, dest, keyval, 'app' === type ? npmCb : cb);
}

module.exports = main;

module.exports.usage = [
    'Usage: mojito create [options] <app|mojit> [full|simple|default] <name>',
    'Usage: mojito create [options] custom <path/to/archetype> <name>',
    'Usage: mojito create [options] <path/to/archetype> <name>',
    '',
    'Example: mojito create app Foo',
    '  (creates directory "Foo" containing a new Mojito application named "Foo")',
    '',
    'Example: mojito create mojit Bar',
    '  (creates directory "Bar" containing new Mojit named "Bar")',
    '',
    'Options: ',
    '  --directory <path> Optional destination directory',
    '  -d <path>          Short for --directory',
    '  --port <number>    Specifies default port for your Mojito app to run on.',
    '  -p [number]        Short for --port.',
    '  --keyval <string>  key value pairs to pass to a custom archetype template',
    '                     a key/value is separated by colons, key/value pairs by',
    '                     commas: "key1:val1,key2:val2',
    '  -k <string>        Short for --keyval'].join('\n');

module.exports.options = [
    {shortName: 'd', hasValue: true, longName: 'directory'},
    {shortName: 'k', hasValue: true, longName: 'keyval'},
    {shortName: 'p', hasValue: true, longName: 'port'}
];

module.exports.getSourceDir = getSourceDir;
module.exports.npmi = require('./lib/npmi');
<|endoftext|>