<commit_before>
/**
 * Module dependencies.
 */

const mongoose = require('mongoose')
    , express = require('express')
    , assert = require('assert')
    , should = require('should')
    , Promise = mongoose.Promise
    , Schema = mongoose.Schema

require('../');

/**
 * Schema definition.
 */

var DrumsetSchema = new Schema({
    brand: String
  , color: String
  , type:  String
  , model: String
});

/**
 * Schema methods.
 */

DrumsetSchema.statics.useQuery = function () {
  // return a Query
  return this.find({ color: 'black' });
}

DrumsetSchema.statics.usePromise = function () {
  var promise = new Promise();
  this.find({ type: 'Acoustic' }, promise.resolve.bind(promise));
  return promise;
}

DrumsetSchema.statics.queryError = function () {
  // should produce an invalid query error
  return this.find({ color: { $fake: { $boom: [] }} });
}

DrumsetSchema.statics.promiseError = function () {
  var promise = new Promise;
  promise.error(new Error('splat!'));
  return promise;
}

mongoose.model('Drumset', DrumsetSchema);

/**
 * Mongoose connection helper.
 */

function connect () {
  return mongoose.createConnection('mongodb://localhost/express_goose_test');
}

/**
 * Dummy data.
 */

var db = connect();
var collection = 'drumsets_' + (Math.random() * 100000 | 0);
var Drumset = db.model('Drumset', collection);
var pending = 4;

Drumset.create({
    brand: 'Roland'
  , color: 'black'
  , type: 'electronic'
  , _id: '4da8b662057a83596c000001'
}, added);

Drumset.create({
    brand: 'GMS'
  , color: 'Silver Sparkle'
  , type: 'Acoustic'
  , _id: '4da8b662057a83596c000002'
}, added);

Drumset.create({
    brand: 'DW'
  , color: 'Broken Glass'
  , type: 'Acoustic'
  , _id: '4da8b662057a83596c000003'
}, added);

Drumset.create({
    brand: 'Meinl'
  , color: 'black'
  , type: 'Acoustic'
  , _id: '4da8b662057a83596c000004'
}, added);

function added (err) {
  if (err) return console.error(err);
  if (--pending) return;
  db.close();
  assignExports();
}

/**
 * Creates a test server.
 */

function makeapp () {
  var app = express.createServer();
  app.set('views', __dirname + '/fixtures');
  app.set('view engine', 'jade');
  return app;
}

/**
 * DB is ready, export our expresso tests.
 */

function assignExports () {

  exports['test render'] = function () {
    var app = makeapp();
    var db = connect();
    var Drumset = db.model('Drumset', collection);

    app.get('/renderquery', function (req, res) {
      res.render('query', {
        query: Drumset.useQuery()
      });
    });

    app.get('/renderpromise', function (req, res) {
      res.render('promise', {
        promise: Drumset.usePromise()
      });
    });

    app.get('/renderboth', function (req, res) {
      res.render('both', {
          query: Drumset.useQuery()
        , promise: Drumset.usePromise()
      });
    });

    app.get('/renderqueryerror', function (req, res) {
      res.render('query', {
        query: Drumset.queryError()
      });
    });

    app.get('/renderpromiseerror', function (req, res) {
      res.render('promise', {
        promise: Drumset.promiseError()
      });
    });

    app.get('/renderbotherror', function (req, res) {
      res.render('both', {
          query: Drumset.queryError()
        , promise: Drumset.promiseError()
      });
    });

    app.get('/renderbothnest', function (req, res) {
      res.render('both', {
          locals: {
            promise: Drumset.usePromise()
          }
        , query: Drumset.useQuery()
      });
    });

    app.get('/renderlocalsonly', function (req, res) {
      res.render('promise', {
        locals: {
          promise: Drumset.usePromise()
        }
      });
    });

    app.get('/renderbothnesterror', function (req, res) {
      res.render('both', {
          locals: {
            query: Drumset.queryError()
          }
        , promise: Drumset.usePromise()
      });
    });

    // test

    var pending = 6;
    function done () {
      --pending || db.close();
    }

    assert.response(app,
      { url: '/renderquery' }
    , { status: 200
      , body: '

Roland

'
      }
    , done
    );

    assert.response(app,
      { url: '/renderpromise' }
    , { status: 200
      , body: '

Silver Sparkle

'
      }
    , done
    );

    assert.response(app,
      { url: '/renderboth' }
    , { status: 200
      , body: '

Roland

Meinl

'
      }
    , done
    );

    assert.response(app,
      { url: '/renderbothnest' }
    , { status: 200
      , body: '

Roland

Meinl

'
      }
    , done
    );

    assert.response(app,
      { url: '/renderlocalsonly' }
    , { status: 200
      , body: '

Silver Sparkle

'
      }
    , done
    );

    assert.response(app,
      { url: '/renderqueryerror' }
    , function (res) {
        assert.equal(res.statusCode, 500);
        assert.ok(~res.body.indexOf("Error: Can't use $fake with String."));
        done();
      }
    );

    assert.response(app,
      { url: '/renderpromiseerror' }
    , function (res) {
        assert.equal(res.statusCode, 500);
        assert.ok(~res.body.indexOf("Error: splat!"));
        done();
      }
    );

    assert.response(app,
      { url: '/renderbotherror' }
    , function (res) {
        assert.equal(res.statusCode, 500);
        assert.ok(~res.body.indexOf("Error: splat!"));
        done();
      }
    );

    assert.response(app,
      { url: '/renderbothnesterror' }
    , function (res) {
        assert.equal(res.statusCode, 500);
        assert.ok(~res.body.indexOf("Error: Can't use $fake with String."));
        done();
      }
    );
  };

  exports['test partial'] = function () {
    var app = makeapp();
    var db = connect();
    var Drumset = db.model('Drumset', collection);

    app.get('/partialquery', function (req, res) {
      res.partial('query', {
        query: Drumset.useQuery()
      });
    });

    app.get('/partiallocalsonly', function (req, res) {
      res.partial('promise', {
        locals: {
          promise: Drumset.usePromise()
        }
      });
    });

    app.get('/partialpromise', function (req, res) {
      res.partial('promise', {
        promise: Drumset.usePromise()
      });
    });

    app.get('/partialboth', function (req, res) {
      res.partial('both', {
          query: Drumset.useQuery()
        , promise: Drumset.usePromise()
      });
    });

    app.get('/partialqueryerror', function (req, res) {
      res.partial('query', {
        query: Drumset.queryError()
      });
    });

    app.get('/partialpromiseerror', function (req, res) {
      res.partial('promise', {
        promise: Drumset.promiseError()
      });
    });

    app.get('/partialbotherror', function (req, res) {
      res.partial('both', {
          query: Drumset.queryError()
        , promise: Drumset.promiseError()
      });
    });

    // test

    var pending = 6;
    function done () {
      --pending || db.close();
    }

    assert.response(app,
      { url: '/partialquery' }
    , { status: 200
      , body: '

Roland

'
      }
    , done
    );

    assert.response(app,
      { url: '/partialpromise' }
    , { status: 200
      , body: '

Silver Sparkle

'
      }
    , done
    );

    assert.response(app,
      { url: '/partialboth' }
    , { status: 200
      , body: '

Roland

Meinl

'
      }
    , done
    );

    assert.response(app,
      { url: '/partiallocalsonly' }
    , { status: 200
      , body: '

Silver Sparkle

'
      }
    , done
    );

    assert.response(app,
      { url: '/partialqueryerror' }
    , function (res) {
        assert.equal(res.statusCode, 500);
        assert.ok(~res.body.indexOf("Error: Can't use $fake with String."));
        done();
      }
    );

    assert.response(app,
      { url: '/partialpromiseerror' }
    , function (res) {
        assert.equal(res.statusCode, 500);
        assert.ok(~res.body.indexOf("Error: splat!"));
        done();
      }
    );

    assert.response(app,
      { url: '/partialbotherror' }
    , function (res) {
        assert.equal(res.statusCode, 500);
        assert.ok(~res.body.indexOf("Error: splat!"));
        done();
      }
    );
  };

  exports['test send'] = function () {
    var app = makeapp();
    var db = connect();
    var Drumset = db.model('Drumset', collection);

    app.get('/sendquery', function (req, res) {
      res.send(Drumset.useQuery());
    });

    app.get('/sendpromise', function (req, res) {
      res.send(Drumset.usePromise());
    });

    app.get('/sendboth', function (req, res) {
      res.send({
          query: Drumset.useQuery()
        , promise: Drumset.usePromise()
      });
    });

    app.get('/sendqueryerror', function (req, res) {
      res.send(Drumset.queryError());
    });

    app.get('/sendpromiseerror', function (req, res) {
      res.send(Drumset.promiseError());
    });

    app.get('/sendbotherror', function (req, res) {
      res.send({
          query: Drumset.queryError()
        , promise: Drumset.promiseError()
      });
    });

    // test

    var pending = 6;
    function done () {
      --pending || db.close();
    }

    assert.response(app,
      { url: '/sendquery' }
    , { status: 200
      , body: '[{"_id":"4da8b662057a83596c000001","type":"electronic","color":"black","brand":"Roland"},{"_id":"4da8b662057a83596c000004","type":"Acoustic","color":"black","brand":"Meinl"}]'
      , headers: { 'Content-Type': 'application/json' }
      }
    , done
    );

    assert.response(app,
      { url: '/sendpromise' }
    , { status: 200
      , body: '[{"_id":"4da8b662057a83596c000002","type":"Acoustic","color":"Silver Sparkle","brand":"GMS"},{"_id":"4da8b662057a83596c000003","type":"Acoustic","color":"Broken Glass","brand":"DW"},{"_id":"4da8b662057a83596c000004","type":"Acoustic","color":"black","brand":"Meinl"}]'
      , headers: { 'Content-Type': 'application/json' }
      }
    , done
    );

    assert.response(app,
      { url: '/sendboth' }
    , { status: 200
      , body: '{"query":[{"_id":"4da8b662057a83596c000001","type":"electronic","color":"black","brand":"Roland"},{"_id":"4da8b662057a83596c000004","type":"Acoustic","color":"black","brand":"Meinl"}],"promise":[{"_id":"4da8b662057a83596c000002","type":"Acoustic","color":"Silver Sparkle","brand":"GMS"},{"_id":"4da8b662057a83596c000003","type":"Acoustic","color":"Broken Glass","brand":"DW"},{"_id":"4da8b662057a83596c000004","type":"Acoustic","color":"black","brand":"Meinl"}]}'
      , headers: { 'Content-Type': 'application/json' }
      }
    , done
    );

    assert.response(app,
      { url: '/sendqueryerror' }
    , function (res) {
        assert.equal(res.statusCode, 500);
        assert.ok(~res.body.indexOf("Error: Can't use $fake with String."));
        done();
      }
    );

    assert.response(app,
      { url: '/sendpromiseerror' }
    , function (res) {
        assert.equal(res.statusCode, 500);
        assert.ok(~res.body.indexOf("Error: splat!"));
        done();
      }
    );

    assert.response(app,
      { url: '/sendbotherror' }
    , function (res) {
        assert.equal(res.statusCode, 500);
        assert.ok(~res.body.indexOf("Error: splat!"));
        done();
      }
    );
  }

}
<commit_msg>delete test db after tests complete<commit_after>
/**
 * Module dependencies.
 */

const mongoose = require('mongoose')
    , express = require('express')
    , assert = require('assert')
    , should = require('should')
    , Promise = mongoose.Promise
    , Schema = mongoose.Schema

require('../');

/**
 * Schema definition.
 */

var DrumsetSchema = new Schema({
    brand: String
  , color: String
  , type:  String
  , model: String
});

/**
 * Schema methods.
 */

DrumsetSchema.statics.useQuery = function () {
  // return a Query
  return this.find({ color: 'black' });
}

DrumsetSchema.statics.usePromise = function () {
  var promise = new Promise();
  this.find({ type: 'Acoustic' }, promise.resolve.bind(promise));
  return promise;
}

DrumsetSchema.statics.queryError = function () {
  // should produce an invalid query error
  return this.find({ color: { $fake: { $boom: [] }} });
}

DrumsetSchema.statics.promiseError = function () {
  var promise = new Promise;
  promise.error(new Error('splat!'));
  return promise;
}

mongoose.model('Drumset', DrumsetSchema);

/**
 * Mongoose connection helper.
 */

function connect () {
  return mongoose.createConnection('mongodb://localhost/express_goose_test');
}

/**
 * Dummy data.
 */

var db = connect();
var collection = 'drumsets_' + (Math.random() * 100000 | 0);
var Drumset = db.model('Drumset', collection);
var pending = 4;

Drumset.create({
    brand: 'Roland'
  , color: 'black'
  , type: 'electronic'
  , _id: '4da8b662057a83596c000001'
}, added);

Drumset.create({
    brand: 'GMS'
  , color: 'Silver Sparkle'
  , type: 'Acoustic'
  , _id: '4da8b662057a83596c000002'
}, added);

Drumset.create({
    brand: 'DW'
  , color: 'Broken Glass'
  , type: 'Acoustic'
  , _id: '4da8b662057a83596c000003'
}, added);

Drumset.create({
    brand: 'Meinl'
  , color: 'black'
  , type: 'Acoustic'
  , _id: '4da8b662057a83596c000004'
}, added);

function added (err) {
  if (err) return console.error(err);
  if (--pending) return;
  db.close();
  assignExports();
}

/**
 * Creates a test server.
 */

function makeapp () {
  var app = express.createServer();
  app.set('views', __dirname + '/fixtures');
  app.set('view engine', 'jade');
  return app;
}

/**
 * DB is ready, export our expresso tests.
 */

function assignExports () {

  /**
   * Clean up the test db when finished.
   */

  var testsrunning = 3;
  function finishTest () {
    if (--testsrunning) return;
    var db = connect();
    db.db.dropDatabase(function () {
      db.close();
    });
  }

  exports['test render'] = function () {
    var app = makeapp();
    var db = connect();
    var Drumset = db.model('Drumset', collection);

    app.get('/renderquery', function (req, res) {
      res.render('query', {
        query: Drumset.useQuery()
      });
    });

    app.get('/renderpromise', function (req, res) {
      res.render('promise', {
        promise: Drumset.usePromise()
      });
    });

    app.get('/renderboth', function (req, res) {
      res.render('both', {
          query: Drumset.useQuery()
        , promise: Drumset.usePromise()
      });
    });

    app.get('/renderqueryerror', function (req, res) {
      res.render('query', {
        query: Drumset.queryError()
      });
    });

    app.get('/renderpromiseerror', function (req, res) {
      res.render('promise', {
        promise: Drumset.promiseError()
      });
    });

    app.get('/renderbotherror', function (req, res) {
      res.render('both', {
          query: Drumset.queryError()
        , promise: Drumset.promiseError()
      });
    });

    app.get('/renderbothnest', function (req, res) {
      res.render('both', {
          locals: {
            promise: Drumset.usePromise()
          }
        , query: Drumset.useQuery()
      });
    });

    app.get('/renderlocalsonly', function (req, res) {
      res.render('promise', {
        locals: {
          promise: Drumset.usePromise()
        }
      });
    });

    app.get('/renderbothnesterror', function (req, res) {
      res.render('both', {
          locals: {
            query: Drumset.queryError()
          }
        , promise: Drumset.usePromise()
      });
    });

    // test

    var pending = 6;
    function done () {
      if (--pending) return;
      db.close();
      finishTest();
    }

    assert.response(app,
      { url: '/renderquery' }
    , { status: 200
      , body: '

Roland

'
      }
    , done
    );

    assert.response(app,
      { url: '/renderpromise' }
    , { status: 200
      , body: '

Silver Sparkle

'
      }
    , done
    );

    assert.response(app,
      { url: '/renderboth' }
    , { status: 200
      , body: '

Roland

Meinl

'
      }
    , done
    );

    assert.response(app,
      { url: '/renderbothnest' }
    , { status: 200
      , body: '

Roland

Meinl

'
      }
    , done
    );

    assert.response(app,
      { url: '/renderlocalsonly' }
    , { status: 200
      , body: '

Silver Sparkle

'
      }
    , done
    );

    assert.response(app,
      { url: '/renderqueryerror' }
    , function (res) {
        assert.equal(res.statusCode, 500);
        assert.ok(~res.body.indexOf("Error: Can't use $fake with String."));
        done();
      }
    );

    assert.response(app,
      { url: '/renderpromiseerror' }
    , function (res) {
        assert.equal(res.statusCode, 500);
        assert.ok(~res.body.indexOf("Error: splat!"));
        done();
      }
    );

    assert.response(app,
      { url: '/renderbotherror' }
    , function (res) {
        assert.equal(res.statusCode, 500);
        assert.ok(~res.body.indexOf("Error: splat!"));
        done();
      }
    );

    assert.response(app,
      { url: '/renderbothnesterror' }
    , function (res) {
        assert.equal(res.statusCode, 500);
        assert.ok(~res.body.indexOf("Error: Can't use $fake with String."));
        done();
      }
    );
  };

  exports['test partial'] = function () {
    var app = makeapp();
    var db = connect();
    var Drumset = db.model('Drumset', collection);

    app.get('/partialquery', function (req, res) {
      res.partial('query', {
        query: Drumset.useQuery()
      });
    });

    app.get('/partiallocalsonly', function (req, res) {
      res.partial('promise', {
        locals: {
          promise: Drumset.usePromise()
        }
      });
    });

    app.get('/partialpromise', function (req, res) {
      res.partial('promise', {
        promise: Drumset.usePromise()
      });
    });

    app.get('/partialboth', function (req, res) {
      res.partial('both', {
          query: Drumset.useQuery()
        , promise: Drumset.usePromise()
      });
    });

    app.get('/partialqueryerror', function (req, res) {
      res.partial('query', {
        query: Drumset.queryError()
      });
    });

    app.get('/partialpromiseerror', function (req, res) {
      res.partial('promise', {
        promise: Drumset.promiseError()
      });
    });

    app.get('/partialbotherror', function (req, res) {
      res.partial('both', {
          query: Drumset.queryError()
        , promise: Drumset.promiseError()
      });
    });

    // test

    var pending = 6;
    function done () {
      if (--pending) return;
      db.close();
      finishTest();
    }

    assert.response(app,
      { url: '/partialquery' }
    , { status: 200
      , body: '

Roland

'
      }
    , done
    );

    assert.response(app,
      { url: '/partialpromise' }
    , { status: 200
      , body: '

Silver Sparkle

'
      }
    , done
    );

    assert.response(app,
      { url: '/partialboth' }
    , { status: 200
      , body: '

Roland

Meinl

'
      }
    , done
    );

    assert.response(app,
      { url: '/partiallocalsonly' }
    , { status: 200
      , body: '

Silver Sparkle

'
      }
    , done
    );

    assert.response(app,
      { url: '/partialqueryerror' }
    , function (res) {
        assert.equal(res.statusCode, 500);
        assert.ok(~res.body.indexOf("Error: Can't use $fake with String."));
        done();
      }
    );

    assert.response(app,
      { url: '/partialpromiseerror' }
    , function (res) {
        assert.equal(res.statusCode, 500);
        assert.ok(~res.body.indexOf("Error: splat!"));
        done();
      }
    );

    assert.response(app,
      { url: '/partialbotherror' }
    , function (res) {
        assert.equal(res.statusCode, 500);
        assert.ok(~res.body.indexOf("Error: splat!"));
        done();
      }
    );
  };

  exports['test send'] = function () {
    var app = makeapp();
    var db = connect();
    var Drumset = db.model('Drumset', collection);

    app.get('/sendquery', function (req, res) {
      res.send(Drumset.useQuery());
    });

    app.get('/sendpromise', function (req, res) {
      res.send(Drumset.usePromise());
    });

    app.get('/sendboth', function (req, res) {
      res.send({
          query: Drumset.useQuery()
        , promise: Drumset.usePromise()
      });
    });

    app.get('/sendqueryerror', function (req, res) {
      res.send(Drumset.queryError());
    });

    app.get('/sendpromiseerror', function (req, res) {
      res.send(Drumset.promiseError());
    });

    app.get('/sendbotherror', function (req, res) {
      res.send({
          query: Drumset.queryError()
        , promise: Drumset.promiseError()
      });
    });

    // test

    var pending = 6;
    function done () {
      if (--pending) return;
      db.close();
      finishTest();
    }

    assert.response(app,
      { url: '/sendquery' }
    , { status: 200
      , body: '[{"_id":"4da8b662057a83596c000001","type":"electronic","color":"black","brand":"Roland"},{"_id":"4da8b662057a83596c000004","type":"Acoustic","color":"black","brand":"Meinl"}]'
      , headers: { 'Content-Type': 'application/json' }
      }
    , done
    );

    assert.response(app,
      { url: '/sendpromise' }
    , { status: 200
      , body: '[{"_id":"4da8b662057a83596c000002","type":"Acoustic","color":"Silver Sparkle","brand":"GMS"},{"_id":"4da8b662057a83596c000003","type":"Acoustic","color":"Broken Glass","brand":"DW"},{"_id":"4da8b662057a83596c000004","type":"Acoustic","color":"black","brand":"Meinl"}]'
      , headers: { 'Content-Type': 'application/json' }
      }
    , done
    );

    assert.response(app,
      { url: '/sendboth' }
    , { status: 200
      , body: '{"query":[{"_id":"4da8b662057a83596c000001","type":"electronic","color":"black","brand":"Roland"},{"_id":"4da8b662057a83596c000004","type":"Acoustic","color":"black","brand":"Meinl"}],"promise":[{"_id":"4da8b662057a83596c000002","type":"Acoustic","color":"Silver Sparkle","brand":"GMS"},{"_id":"4da8b662057a83596c000003","type":"Acoustic","color":"Broken Glass","brand":"DW"},{"_id":"4da8b662057a83596c000004","type":"Acoustic","color":"black","brand":"Meinl"}]}'
      , headers: { 'Content-Type': 'application/json' }
      }
    , done
    );

    assert.response(app,
      { url: '/sendqueryerror' }
    , function (res) {
        assert.equal(res.statusCode, 500);
        assert.ok(~res.body.indexOf("Error: Can't use $fake with String."));
        done();
      }
    );

    assert.response(app,
      { url: '/sendpromiseerror' }
    , function (res) {
        assert.equal(res.statusCode, 500);
        assert.ok(~res.body.indexOf("Error: splat!"));
        done();
      }
    );

    assert.response(app,
      { url: '/sendbotherror' }
    , function (res) {
        assert.equal(res.statusCode, 500);
        assert.ok(~res.body.indexOf("Error: splat!"));
        done();
      }
    );
  }

}
<|endoftext|>


<commit_before>'use strict';

/* Controllers */
function DirectoriesList($scope, $http) {
    $scope.currentSongIndex = 0;
    $scope.playlistsongs = [];

    $scope.selectAlbum = function(dir){
        $http({
            url : 'public/app/directories/songs.php',
            params : {
                dir : dir
            },
            method : 'get'
        }).success(function(data) {
            $scope.directorysongs = data.songs;
            $scope.directorycover = data.cover;
            player.trackEnded = songFinished;
        });
    };

    $scope.deleteAllSongs = function(){
        $scope.playlistsongs.length = 0;
        $scope.playlistsongs = [];
        if(player.playing){
            player.pause();
        }
    };

    $scope.addAllSongs = function(songs){
        var cnt = 0,
            numCnt = songs.length;

        for(; cnt < numCnt; cnt++){
            songs[cnt].playing = false;
            $scope.playlistsongs.push(songs[cnt]);
        }

        if (! ($scope.playlistsongs.length - numCnt))
        {
            runPlaylist();
        }

    };

    $scope.addSong = function(song){

        $scope.playlistsongs.push(song);

        if (! ($scope.playlistsongs.length - 1))
        {
            runPlaylist();
        }
    };

    $scope.deleteSong = function(index){
        var cloneArray = [];
        angular.forEach($scope.playlistsongs, function(item, cnt){
            if(cnt != index){
                cloneArray.push(item);
            }
        })
        $scope.playlistsongs.length = 0;
        $scope.playlistsongs = cloneArray;
        if(this.$root.$$phase != "$apply"){
            $scope.$digest();
        }
    };

    $scope.prevSong = function ()
    {
        if ($scope.currentSongIndex !== 0)
        {
            $scope.playSong($scope.currentSongIndex - 1);
        }
    };

    $scope.nextSong = function ()
    {
        if ($scope.currentSongIndex !== $scope.playlistsongs.length - 1)
        {
            $scope.playSong($scope.currentSongIndex + 1);
        }
    }

    function runPlaylist(){
        if(player.playing == false){
            $scope.playSong($scope.currentSongIndex);
        }
    }

    function songFinished ()
    {
        $scope.next ();
    }

    $scope.playSong = function(index){
        player.load($scope.playlistsongs[index].path);
        player.play();
        $scope.currentSongIndex = index;
        // force ng-repeat
        var cloneArray = [];
        angular.forEach($scope.playlistsongs, function(item){
           cloneArray.push(item);
        })
        $scope.playlistsongs.length = 0;
        $scope.playlistsongs = cloneArray;
        if(this.$root.$$phase != "$apply"){
            $scope.$digest();
        }
        // end force ng-repeat
    };

    $http({
        url : 'public/app/directories/directories.php',
        method : "get"
    }).success(function(data) {
        $scope.directories = data;
    });
}

function ReadAlbum(){
    console.log("DA", arguments);
}
<commit_msg>Clearing the playlist is now resetting the current song index to 0. Fixed #11.<commit_after>'use strict';

/* Controllers */
function DirectoriesList($scope, $http) {
    $scope.currentSongIndex = 0;
    $scope.playlistsongs = [];

    $scope.selectAlbum = function(dir){
        $http({
            url : 'public/app/directories/songs.php',
            params : {
                dir : dir
            },
            method : 'get'
        }).success(function(data) {
            $scope.directorysongs = data.songs;
            $scope.directorycover = data.cover;
            player.trackEnded = songFinished;
        });
    };

    $scope.deleteAllSongs = function ()
    {
        $scope.playlistsongs = [];
        $scope.currentSongIndex = 0;
        if (player.playing)
        {
            player.pause();
        }
    };

    $scope.addAllSongs = function(songs){
        var cnt = 0,
            numCnt = songs.length;

        for(; cnt < numCnt; cnt++){
            songs[cnt].playing = false;
            $scope.playlistsongs.push(songs[cnt]);
        }

        if (! ($scope.playlistsongs.length - numCnt))
        {
            runPlaylist();
        }

    };

    $scope.addSong = function(song){

        $scope.playlistsongs.push(song);

        if (! ($scope.playlistsongs.length - 1))
        {
            runPlaylist();
        }
    };

    $scope.deleteSong = function(index){
        var cloneArray = [];
        angular.forEach($scope.playlistsongs, function(item, cnt){
            if(cnt != index){
                cloneArray.push(item);
            }
        })
        $scope.playlistsongs.length = 0;
        $scope.playlistsongs = cloneArray;
        if(this.$root.$$phase != "$apply"){
            $scope.$digest();
        }
    };

    $scope.prevSong = function ()
    {
        if ($scope.currentSongIndex !== 0)
        {
            $scope.playSong($scope.currentSongIndex - 1);
        }
    };

    $scope.nextSong = function ()
    {
        if ($scope.currentSongIndex !== $scope.playlistsongs.length - 1)
        {
            $scope.playSong($scope.currentSongIndex + 1);
        }
    }

    function runPlaylist(){
        if(player.playing == false){
            $scope.playSong($scope.currentSongIndex);
        }
    }

    function songFinished ()
    {
        $scope.next ();
    }

    $scope.playSong = function(index){
        player.load($scope.playlistsongs[index].path);
        player.play();
        $scope.currentSongIndex = index;
        // force ng-repeat
        var cloneArray = [];
        angular.forEach($scope.playlistsongs, function(item){
           cloneArray.push(item);
        })
        $scope.playlistsongs.length = 0;
        $scope.playlistsongs = cloneArray;
        if(this.$root.$$phase != "$apply"){
            $scope.$digest();
        }
        // end force ng-repeat
    };

    $http({
        url : 'public/app/directories/directories.php',
        method : "get"
    }).success(function(data) {
        $scope.directories = data;
    });
}

function ReadAlbum(){
    console.log("DA", arguments);
}
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright The Closure Library Authors.
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview Contains the attribute whitelists for use in the Html
 * sanitizer.
 */

goog.provide('goog.html.sanitizer.AttributeSanitizedWhitelist');
goog.provide('goog.html.sanitizer.AttributeWhitelist');

/**
 * A whitelist for attributes that are always safe and allowed by default.
 * The sanitizer only applies whitespace trimming to these.
 * @const @dict {boolean}
 */
goog.html.sanitizer.AttributeWhitelist = {
  '* ARIA-CHECKED': true,
  '* ARIA-COLCOUNT': true,
  '* ARIA-COLINDEX': true,
  '* ARIA-DESCRIBEDBY': true,
  '* ARIA-DISABLED': true,
  '* ARIA-GOOG-EDITABLE': true,
  '* ARIA-LABEL': true,
  '* ARIA-LABELLEDBY': true,
  '* ARIA-MULTILINE': true,
  '* ARIA-MULTISELECTABLE': true,
  '* ARIA-ORIENTATION': true,
  '* ARIA-PLACEHOLDER': true,
  '* ARIA-READONLY': true,
  '* ARIA-REQUIRED': true,
  '* ARIA-ROLEDESCRIPTION': true,
  '* ARIA-ROWCOUNT': true,
  '* ARIA-ROWINDEX': true,
  '* ARIA-SELECTED': true,
  '* ABBR': true,
  '* ACCEPT': true,
  '* ACCESSKEY': true,
  '* ALIGN': true,
  '* ALT': true,
  '* AUTOCOMPLETE': true,
  '* AXIS': true,
  '* BGCOLOR': true,
  '* BORDER': true,
  '* CELLPADDING': true,
  '* CELLSPACING': true,
  '* CHAROFF': true,
  '* CHAR': true,
  '* CHECKED': true,
  '* CLEAR': true,
  '* COLOR': true,
  '* COLSPAN': true,
  '* COLS': true,
  '* COMPACT': true,
  '* COORDS': true,
  '* DATETIME': true,
  '* DIR': true,
  '* DISABLED': true,
  '* ENCTYPE': true,
  '* FACE': true,
  '* FRAME': true,
  '* HEIGHT': true,
  '* HREFLANG': true,
  '* HSPACE': true,
  '* ISMAP': true,
  '* LABEL': true,
  '* LANG': true,
  '* MAX': true,
  '* MAXLENGTH': true,
  '* METHOD': true,
  '* MULTIPLE': true,
  '* NOHREF': true,
  '* NOSHADE': true,
  '* NOWRAP': true,
  '* OPEN': true,
  '* READONLY': true,
  '* REQUIRED': true,
  '* REL': true,
  '* REV': true,
  '* ROLE': true,
  '* ROWSPAN': true,
  '* ROWS': true,
  '* RULES': true,
  '* SCOPE': true,
  '* SELECTED': true,
  '* SHAPE': true,
  '* SIZE': true,
  '* SPAN': true,
  '* START': true,
  '* SUMMARY': true,
  '* TABINDEX': true,
  '* TITLE': true,
  '* TYPE': true,
  '* VALIGN': true,
  '* VALUE': true,
  '* VSPACE': true,
  '* WIDTH': true
};

/**
 * A whitelist for attributes that are not safe to allow unrestricted, but are
 * made safe by default policies installed by the sanitizer in
 * goog.html.sanitizer.HtmlSanitizer.Builder.prototype.build, and thus allowed
 * by default under these policies.
 * @const @dict {boolean}
 */
goog.html.sanitizer.AttributeSanitizedWhitelist = {

  // Attributes which can contain URL fragments
  '* USEMAP': true,
  // Attributes which can contain URLs
  '* ACTION': true,
  '* CITE': true,
  '* HREF': true,
  // Attributes which can cause network requests
  '* LONGDESC': true,
  '* SRC': true,
  'LINK HREF': true,
  // Prevents clobbering
  '* FOR': true,
  '* HEADERS': true,
  '* NAME': true,
  // Controls where a window is opened. Prevents tab-nabbing
  'A TARGET': true,

  // Attributes which could cause UI redressing.
  '* CLASS': true,
  '* ID': true,

  // CSS style can cause network requests and XSSs
  '* STYLE': true
};
<commit_msg>RELNOTES[NEW]: Whitelist additional ARIA attributes in the HtmlSanitizer.<commit_after>/**
 * @license
 * Copyright The Closure Library Authors.
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview Contains the attribute whitelists for use in the Html
 * sanitizer.
 */

goog.provide('goog.html.sanitizer.AttributeSanitizedWhitelist');
goog.provide('goog.html.sanitizer.AttributeWhitelist');

/**
 * A whitelist for attributes that are always safe and allowed by default.
 * The sanitizer only applies whitespace trimming to these.
 * @const @dict {boolean}
 */
goog.html.sanitizer.AttributeWhitelist = {
  '* ARIA-CHECKED': true,
  '* ARIA-COLCOUNT': true,
  '* ARIA-COLINDEX': true,
  '* ARIA-CONTROLS': true,
  '* ARIA-DESCRIBEDBY': true,
  '* ARIA-DISABLED': true,
  '* ARIA-EXPANDED': true,
  '* ARIA-GOOG-EDITABLE': true,
  '* ARIA-HASPOPUP': true,
  '* ARIA-HIDDEN': true,
  '* ARIA-LABEL': true,
  '* ARIA-LABELLEDBY': true,
  '* ARIA-MULTILINE': true,
  '* ARIA-MULTISELECTABLE': true,
  '* ARIA-ORIENTATION': true,
  '* ARIA-PLACEHOLDER': true,
  '* ARIA-READONLY': true,
  '* ARIA-REQUIRED': true,
  '* ARIA-ROLEDESCRIPTION': true,
  '* ARIA-ROWCOUNT': true,
  '* ARIA-ROWINDEX': true,
  '* ARIA-SELECTED': true,
  '* ABBR': true,
  '* ACCEPT': true,
  '* ACCESSKEY': true,
  '* ALIGN': true,
  '* ALT': true,
  '* AUTOCOMPLETE': true,
  '* AXIS': true,
  '* BGCOLOR': true,
  '* BORDER': true,
  '* CELLPADDING': true,
  '* CELLSPACING': true,
  '* CHAROFF': true,
  '* CHAR': true,
  '* CHECKED': true,
  '* CLEAR': true,
  '* COLOR': true,
  '* COLSPAN': true,
  '* COLS': true,
  '* COMPACT': true,
  '* COORDS': true,
  '* DATETIME': true,
  '* DIR': true,
  '* DISABLED': true,
  '* ENCTYPE': true,
  '* FACE': true,
  '* FRAME': true,
  '* HEIGHT': true,
  '* HREFLANG': true,
  '* HSPACE': true,
  '* ISMAP': true,
  '* LABEL': true,
  '* LANG': true,
  '* MAX': true,
  '* MAXLENGTH': true,
  '* METHOD': true,
  '* MULTIPLE': true,
  '* NOHREF': true,
  '* NOSHADE': true,
  '* NOWRAP': true,
  '* OPEN': true,
  '* READONLY': true,
  '* REQUIRED': true,
  '* REL': true,
  '* REV': true,
  '* ROLE': true,
  '* ROWSPAN': true,
  '* ROWS': true,
  '* RULES': true,
  '* SCOPE': true,
  '* SELECTED': true,
  '* SHAPE': true,
  '* SIZE': true,
  '* SPAN': true,
  '* START': true,
  '* SUMMARY': true,
  '* TABINDEX': true,
  '* TITLE': true,
  '* TYPE': true,
  '* VALIGN': true,
  '* VALUE': true,
  '* VSPACE': true,
  '* WIDTH': true
};

/**
 * A whitelist for attributes that are not safe to allow unrestricted, but are
 * made safe by default policies installed by the sanitizer in
 * goog.html.sanitizer.HtmlSanitizer.Builder.prototype.build, and thus allowed
 * by default under these policies.
 * @const @dict {boolean}
 */
goog.html.sanitizer.AttributeSanitizedWhitelist = {

  // Attributes which can contain URL fragments
  '* USEMAP': true,
  // Attributes which can contain URLs
  '* ACTION': true,
  '* CITE': true,
  '* HREF': true,
  // Attributes which can cause network requests
  '* LONGDESC': true,
  '* SRC': true,
  'LINK HREF': true,
  // Prevents clobbering
  '* FOR': true,
  '* HEADERS': true,
  '* NAME': true,
  // Controls where a window is opened. Prevents tab-nabbing
  'A TARGET': true,

  // Attributes which could cause UI redressing.
  '* CLASS': true,
  '* ID': true,

  // CSS style can cause network requests and XSSs
  '* STYLE': true
};
<|endoftext|>


<commit_before>/* Copyright 2014 (c) SoFIE Studios.  All rights reserved.
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file.
 */

/**
 * @fileoverview  Implement the application for the Chicken and Egg Machine.
 * Requires Box2Dweb.min.js: http://box2dweb.googlecode.com/svn/trunk/Box2d.min.js
 */

/**
 * Constructor for the ChickenAndEgg class.  Use the run() method to populate
 * the object with controllers and wire up the events.
 * @param {Element} canvas The CANVAS element for drawing the simulation.
 * @constructor
 */
ChickenAndEgg = function(canvas) {
  /**
   * Nifty wrapper for requestAnimationFrame() courtesy Paul Irish:
   * http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
   * @type {Function}
   * @private
   */
  window.wrappedRequestAnimationFrame =
      window.requestAnimationFrame       ||
      window.webkitRequestAnimationFrame ||
      window.mozRequestAnimationFrame    ||
      window.oRequestAnimationFrame      ||
      window.msRequestAnimationFrame     ||
      function(/* function */ callback, /* DOMElement */ element) {
        window.setTimeout(callback, 1000 / 60);
      };

  /**
   * The DOM element that contains the application.
   * @type {Element}
   * @private
   */
  this._canvas = canvas;
  /**
   * The scale factor for canvas coordinates to the Box2D world. Not valid until
   * initWorld() is called.
   * @type {number}
   * @private
   */
  this._scale = 0.0;
  /**
   * The size in Box2D world coordinates of the canvas. Not valid until initWorld() is
   * called.
   * @type {Box2D.Common.Math.b2Vec2}
   * @private
   */
  this._worldSize = new Box2D.Common.Math.b2Vec2(0.0, 0.0);
  /**
   * The Box2D world associated with this simulation. Not valid until initWorld() is
   * called.
   * @type {Box2D.Dynamics.b2World}
   * @private
   */
  this._world = null;
}
ChickenAndEgg.prototype.constructor = ChickenAndEgg;

/**
 * Various constants used to set up and run the Box2D simulation.
 * @enum {Object}
 */
ChickenAndEgg.Box2DConsts = {
  GRAVITY: {x: 0, y: -9.81},
  FRAME_RATE: 1/60.0,
  VELOCITY_ITERATION_COUNT: 10,
  POSITION_ITERATION_COUNT: 10,
  DOUG_FIR_DENSITY: 5.3,  // Density of Douglas Fir in g/cm^3
  DOUG_FIR_FRICTION: 0.3,
  DOUG_FIR_RESTITUTION: 0.804
};

/**
 * Constants used to refer to the DOM.
 * @enum {string}
 */
ChickenAndEgg.DOMConsts = {
  BODY: 'body'
};

/**
 * Scale factor to transform CANVAS coordinates into Box2D world coordinates. Returns
 * 0 until initWorld() is called.
 * @return The scale factor.
 */
ChickenAndEgg.prototype.scale = function() {
  return this._scale;
}

/**
 * Scale factor to transform CANVAS coordinates into Box2D world coordinates. Returns
 * 0 until initWorld() is called.
 * @return The Box2D world.
 */
ChickenAndEgg.prototype.world = function() {
  return this._world;
}

/**
 * The size of the game board in Box2D world coordinates. Returns (0, 0) until
 * initWorld() is called.
 * @return The game board size.
 */
ChickenAndEgg.prototype.worldSize = function() {
  return this._worldSize;
}

/**
 * The run() method initializes and runs the simulation. It never returns.
 */
ChickenAndEgg.prototype.run = function() {
  // Bind the mouse-down event to the BODY element. This ensures that the conditionally-
  // bound mouse-up event will fire properly.
  $(this._canvas).mousedown(this._mouseDown.bind(this));
  this.initWorld(this._canvas);
  var heartbeat = function() {
    this.simulationTick();
    this.clearCanvas(this._canvas);
    this.drawWorld(this._canvas);
    window.wrappedRequestAnimationFrame(heartbeat.bind(this));
  };
  heartbeat.bind(this)();
}

/**
 * Initialize all the objects in the world and connect them all together in the
 * simulation.
 * @param {Element} canvas The CANVAS element for drawing the simulation.
 */
ChickenAndEgg.prototype.initWorld = function(canvas) {
  this._world = new Box2D.Dynamics.b2World(
      new Box2D.Common.Math.b2Vec2(ChickenAndEgg.Box2DConsts.GRAVITY.x,
                                   ChickenAndEgg.Box2DConsts.GRAVITY.y),
      true);  // Allow objects to sleep when inactive.
  this._scale = canvas.width / 4;  // 4m wide simulation.
  this._worldSize = new Box2D.Common.Math.b2Vec2(canvas.width / this._scale,
                                                 canvas.height / this._scale);
  var roost = new Roost();
  roost.addToSimulation(this);
  var ground = new Ground();
  ground.addToSimulation(this);
  this._sluice = new Sluice();
  this._sluice.addToSimulation(this);
  var coopDoor = new CoopDoor();
  coopDoor.addToSimulation(this);

  for (var e = 0; e < 20; e++) {
    var egg = new Egg(0.1 * e, this._worldSize.y - 0.02);
    egg.addToSimulation(this);
  }
}

/**
 * Clear the canvas.
 * @param {Element} canvas The CANVAS element for drawing the simulation.
 */
ChickenAndEgg.prototype.clearCanvas = function(canvas) {
  var ctx = canvas.getContext("2d");
  ctx.clearRect(0, 0, canvas.width, canvas.height);
}

/**
 * Draw all the elements in the world.
 * @param {Element} canvas The CANVAS element for drawing the simulation.
 */
ChickenAndEgg.prototype.drawWorld = function(canvas) {
  var ctx = canvas.getContext("2d");
  // Set up the root transform of the CANVAS such that origin is in the lower-left corner,
  // y is positive upwards and the scale is in meters.
  ctx.save();
  ctx.translate(0, canvas.height);
  ctx.scale(this._scale, -this._scale);
  // Hack to deal with weird fact that CANVAS scales the line width.
  ctx.lineWidth = ctx.lineWidth / this._scale;
  for (var b = this._world.GetBodyList(); b; b = b.m_next) {
    if (b.IsActive() &&
        typeof b.GetUserData() !== 'undefined' &&
        b.GetUserData() != null) {
        b.GetUserData().draw(ctx, b);
    }
  }
  ctx.restore();
}

/**
 * Run a simulation tick, then schedule the next one.
 */
ChickenAndEgg.prototype.simulationTick = function() {
  this._world.Step(ChickenAndEgg.Box2DConsts.FRAME_RATE,
                   ChickenAndEgg.Box2DConsts.VELOCITY_ITERATION_COUNT,
                   ChickenAndEgg.Box2DConsts.POSITION_ITERATION_COUNT);
  this._world.ClearForces();
}

/**
 * Convert a coordinate in the CANVAS element's coordinate system into a 2D coordinate in
 * the Box2D simulation's coordinate system.
 * @param {number} x The x-coordinate
 * @param {number} y The y-coordinate
 * @param {Canvas} canvas The canvas that defines the coordinate system.
 * @return {Box2D.Vec2} The converted coordinate.
 * @private
 */
ChickenAndEgg.prototype._convertToWorldCoordinates = function(x, y, canvas) {
  var offset = $(canvas).offset();
  if (offset) {
    x = x - offset.left;
    y = y - offset.top;
  }
  return new Box2D.Common.Math.b2Vec2(
    x / this._scale,
    (y - canvas.height) / -this._scale);
}

/**
 * Handle the mouse-down event. Convert the event into Box2D coordinates and issue a
 * hit-detection. If the sluice handle is hit, start the handle-drag sequence.
 * @param {Event} event The mouse-down event. page{X|Y} is normalized by jQuery.
 * @private
 */
ChickenAndEgg.prototype._mouseDown = function(event) {
  var worldMouse = this._convertToWorldCoordinates(
      event.pageX, event.pageY, this._canvas);
  /**
   * Callback for the QueryPoint() method. If the sluice handle was hit, bind the mouse-
   * drag and mouse-up event handlers and start dragging the sluice.
   * @param {Box2D.Dynamics.b2Fixture} fixture The fixture to test.
   * @return {boolean} Wether to continue with the query. Returns false if the sluice
   *     handle was hit.
   */
  var hitSluiceHandle = function(fixture) {
    if (this._sluice.isSluiceHandle(fixture)) {
      $(ChickenAndEgg.DOMConsts.BODY)
          .mousemove(this._mouseDrag.bind(this))
          .mouseup(this._mouseUp.bind(this));
      return false;  // Stop searching.
    }
    return true;
  };
  this._world.QueryPoint(hitSluiceHandle.bind(this), worldMouse);
}

/**
 * Handle the mouse-drag event. Compute the angle formed by the mouse point and the
 * origin of the sluice, and rotate the sluice by that angle.
 * @param {Event} event The mouse-down event. page{X|Y} is normalized by jQuery.
 * @private
 */
ChickenAndEgg.prototype._mouseDrag = function(event) {
  var worldMouse = this._convertToWorldCoordinates(
      event.pageX, event.pageY, this._canvas);
  var origin = Sluice.SLUICE_ORIGIN;
  this._sluice.body().SetAngle(Math.PI / 6.0);
  console.log('mousemove (' + worldMouse.x + ', ' + worldMouse.y + ')');
}

/**
 * Handle the mouse-up event. End the sluice drag sequence.
 * @param {Event} event The mouse-down event. page{X|Y} is normalized by jQuery.
 * @private
 */
ChickenAndEgg.prototype._mouseUp = function(event) {
  console.log('mouseup (' + event.pageX + ', ' + event.pageY + ')');
  $(ChickenAndEgg.DOMConsts.BODY).unbind('mousemove').unbind('mouseup');
}
<commit_msg>Rotate the sluice via the mouse.<commit_after>/* Copyright 2014 (c) SoFIE Studios.  All rights reserved.
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file.
 */

/**
 * @fileoverview  Implement the application for the Chicken and Egg Machine.
 * Requires Box2Dweb.min.js: http://box2dweb.googlecode.com/svn/trunk/Box2d.min.js
 */

/**
 * Constructor for the ChickenAndEgg class.  Use the run() method to populate
 * the object with controllers and wire up the events.
 * @param {Element} canvas The CANVAS element for drawing the simulation.
 * @constructor
 */
ChickenAndEgg = function(canvas) {
  /**
   * Nifty wrapper for requestAnimationFrame() courtesy Paul Irish:
   * http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
   * @type {Function}
   * @private
   */
  window.wrappedRequestAnimationFrame =
      window.requestAnimationFrame       ||
      window.webkitRequestAnimationFrame ||
      window.mozRequestAnimationFrame    ||
      window.oRequestAnimationFrame      ||
      window.msRequestAnimationFrame     ||
      function(/* function */ callback, /* DOMElement */ element) {
        window.setTimeout(callback, 1000 / 60);
      };

  /**
   * The DOM element that contains the application.
   * @type {Element}
   * @private
   */
  this._canvas = canvas;
  /**
   * The scale factor for canvas coordinates to the Box2D world. Not valid until
   * initWorld() is called.
   * @type {number}
   * @private
   */
  this._scale = 0.0;
  /**
   * The size in Box2D world coordinates of the canvas. Not valid until initWorld() is
   * called.
   * @type {Box2D.Common.Math.b2Vec2}
   * @private
   */
  this._worldSize = new Box2D.Common.Math.b2Vec2(0.0, 0.0);
  /**
   * The Box2D world associated with this simulation. Not valid until initWorld() is
   * called.
   * @type {Box2D.Dynamics.b2World}
   * @private
   */
  this._world = null;
}
ChickenAndEgg.prototype.constructor = ChickenAndEgg;

/**
 * Various constants used to set up and run the Box2D simulation.
 * @enum {Object}
 */
ChickenAndEgg.Box2DConsts = {
  GRAVITY: {x: 0, y: -9.81},
  FRAME_RATE: 1/60.0,
  VELOCITY_ITERATION_COUNT: 10,
  POSITION_ITERATION_COUNT: 10,
  DOUG_FIR_DENSITY: 5.3,  // Density of Douglas Fir in g/cm^3
  DOUG_FIR_FRICTION: 0.3,
  DOUG_FIR_RESTITUTION: 0.804
};

/**
 * Constants used to refer to the DOM.
 * @enum {string}
 * @private
 */
ChickenAndEgg._DOMConsts = {
  BODY: 'body'
};

/**
 * Limits for things like the sluice angle and other game objects.
 * @enum {Object}
 * @private
 */
ChickenAndEgg._Limits = {
  SLUICE_MAX_ANGLE: Math.PI / 12.0,
  SLUICE_MIN_ANGLE: -Math.PI / 12.0
};

/**
 * Scale factor to transform CANVAS coordinates into Box2D world coordinates. Returns
 * 0 until initWorld() is called.
 * @return The scale factor.
 */
ChickenAndEgg.prototype.scale = function() {
  return this._scale;
}

/**
 * Scale factor to transform CANVAS coordinates into Box2D world coordinates. Returns
 * 0 until initWorld() is called.
 * @return The Box2D world.
 */
ChickenAndEgg.prototype.world = function() {
  return this._world;
}

/**
 * The size of the game board in Box2D world coordinates. Returns (0, 0) until
 * initWorld() is called.
 * @return The game board size.
 */
ChickenAndEgg.prototype.worldSize = function() {
  return this._worldSize;
}

/**
 * The run() method initializes and runs the simulation. It never returns.
 */
ChickenAndEgg.prototype.run = function() {
  // Bind the mouse-down event to the BODY element. This ensures that the conditionally-
  // bound mouse-up event will fire properly.
  $(this._canvas).mousedown(this._mouseDown.bind(this));
  this.initWorld(this._canvas);
  var heartbeat = function() {
    this.simulationTick();
    this.clearCanvas(this._canvas);
    this.drawWorld(this._canvas);
    window.wrappedRequestAnimationFrame(heartbeat.bind(this));
  };
  heartbeat.bind(this)();
}

/**
 * Initialize all the objects in the world and connect them all together in the
 * simulation.
 * @param {Element} canvas The CANVAS element for drawing the simulation.
 */
ChickenAndEgg.prototype.initWorld = function(canvas) {
  this._world = new Box2D.Dynamics.b2World(
      new Box2D.Common.Math.b2Vec2(ChickenAndEgg.Box2DConsts.GRAVITY.x,
                                   ChickenAndEgg.Box2DConsts.GRAVITY.y),
      true);  // Allow objects to sleep when inactive.
  this._scale = canvas.width / 4;  // 4m wide simulation.
  this._worldSize = new Box2D.Common.Math.b2Vec2(canvas.width / this._scale,
                                                 canvas.height / this._scale);
  var roost = new Roost();
  roost.addToSimulation(this);
  var ground = new Ground();
  ground.addToSimulation(this);
  this._sluice = new Sluice();
  this._sluice.addToSimulation(this);
  var coopDoor = new CoopDoor();
  coopDoor.addToSimulation(this);

  for (var e = 0; e < 20; e++) {
    var egg = new Egg(0.1 * e, this._worldSize.y - 0.02);
    egg.addToSimulation(this);
  }
}

/**
 * Clear the canvas.
 * @param {Element} canvas The CANVAS element for drawing the simulation.
 */
ChickenAndEgg.prototype.clearCanvas = function(canvas) {
  var ctx = canvas.getContext("2d");
  ctx.clearRect(0, 0, canvas.width, canvas.height);
}

/**
 * Draw all the elements in the world.
 * @param {Element} canvas The CANVAS element for drawing the simulation.
 */
ChickenAndEgg.prototype.drawWorld = function(canvas) {
  var ctx = canvas.getContext("2d");
  // Set up the root transform of the CANVAS such that origin is in the lower-left corner,
  // y is positive upwards and the scale is in meters.
  ctx.save();
  ctx.translate(0, canvas.height);
  ctx.scale(this._scale, -this._scale);
  // Hack to deal with weird fact that CANVAS scales the line width.
  ctx.lineWidth = ctx.lineWidth / this._scale;
  for (var b = this._world.GetBodyList(); b; b = b.m_next) {
    if (b.IsActive() &&
        typeof b.GetUserData() !== 'undefined' &&
        b.GetUserData() != null) {
        b.GetUserData().draw(ctx, b);
    }
  }
  ctx.restore();
}

/**
 * Run a simulation tick, then schedule the next one.
 */
ChickenAndEgg.prototype.simulationTick = function() {
  this._world.Step(ChickenAndEgg.Box2DConsts.FRAME_RATE,
                   ChickenAndEgg.Box2DConsts.VELOCITY_ITERATION_COUNT,
                   ChickenAndEgg.Box2DConsts.POSITION_ITERATION_COUNT);
  this._world.ClearForces();
}

/**
 * Convert a coordinate in the CANVAS element's coordinate system into a 2D coordinate in
 * the Box2D simulation's coordinate system.
 * @param {number} x The x-coordinate
 * @param {number} y The y-coordinate
 * @param {Canvas} canvas The canvas that defines the coordinate system.
 * @return {Box2D.Vec2} The converted coordinate.
 * @private
 */
ChickenAndEgg.prototype._convertToWorldCoordinates = function(x, y, canvas) {
  var offset = $(canvas).offset();
  if (offset) {
    x = x - offset.left;
    y = y - offset.top;
  }
  return new Box2D.Common.Math.b2Vec2(
    x / this._scale,
    (y - canvas.height) / -this._scale);
}

/**
 * Handle the mouse-down event. Convert the event into Box2D coordinates and issue a
 * hit-detection. If the sluice handle is hit, start the handle-drag sequence.
 * @param {Event} event The mouse-down event. page{X|Y} is normalized by jQuery.
 * @private
 */
ChickenAndEgg.prototype._mouseDown = function(event) {
  var worldMouse = this._convertToWorldCoordinates(
      event.pageX, event.pageY, this._canvas);
  /**
   * Callback for the QueryPoint() method. If the sluice handle was hit, bind the mouse-
   * drag and mouse-up event handlers and start dragging the sluice.
   * @param {Box2D.Dynamics.b2Fixture} fixture The fixture to test.
   * @return {boolean} Wether to continue with the query. Returns false if the sluice
   *     handle was hit.
   */
  var hitSluiceHandle = function(fixture) {
    if (this._sluice.isSluiceHandle(fixture)) {
      $(ChickenAndEgg._DOMConsts.BODY)
          .mousemove(this._mouseDrag.bind(this))
          .mouseup(this._mouseUp.bind(this));
      return false;  // Stop searching.
    }
    return true;
  };
  this._world.QueryPoint(hitSluiceHandle.bind(this), worldMouse);
}

/**
 * Handle the mouse-drag event. Compute the angle formed by the mouse point and the
 * origin of the sluice, and rotate the sluice by that angle.
 * @param {Event} event The mouse-down event. page{X|Y} is normalized by jQuery.
 * @private
 */
ChickenAndEgg.prototype._mouseDrag = function(event) {
  var worldMouse = this._convertToWorldCoordinates(
      event.pageX, event.pageY, this._canvas);
  var origin = Sluice.SLUICE_ORIGIN;
  var angle = Math.atan2(worldMouse.y - origin.y, worldMouse.x - origin.x);
  angle = Math.min(
      Math.max(angle, ChickenAndEgg._Limits.SLUICE_MIN_ANGLE),
      ChickenAndEgg._Limits.SLUICE_MAX_ANGLE);
  this._sluice.body().SetAngle(angle);
}

/**
 * Handle the mouse-up event. End the sluice drag sequence.
 * @param {Event} event The mouse-down event. page{X|Y} is normalized by jQuery.
 * @private
 */
ChickenAndEgg.prototype._mouseUp = function(event) {
  $(ChickenAndEgg._DOMConsts.BODY).unbind('mousemove').unbind('mouseup');
}
<|endoftext|>


<commit_before>var wf = {
  init: function() {
    $('
').appendTo('body');
    $('

Benvenuti

 Qui troverai le nostre descrizioni per i wireframe

').appendTo($('.joyride-list'));
    /**

    If you've already set up a Wordpress instance, with JSON API plugin activated
    you just have to put in WF_URL you're complete address to reach it

    e.g.:

    var WF_URL = 'http://www.example.com/api/';

    **/
    var WF_URL = 'http://www.example.com/api/';

    /**

    The way the whole thing is managed right now is that in the wordpress instance
    we're managing more than one project for Wireframes, so we're using categories
    to address one particular project.

    This way I'm defining WF_PRJ as the category_slug for the project.

    e.g.:

    var WF_URL = 'project_wf'

    **/
    var WF_PRJ = 'project_wf';

    $.ajax({
        type: 'GET',
        url: WF_URL,
        dataType: 'json',
        crossDomain: true,
        success: function (data) {
          console.log('the API is working good.');

        },
        error: function (error) {
          // TODO
          //$('.toobad').reveal();
          console.log('you appear to be offline, or your API is not working at all.');
        }
      })
  },

  error: function() {
    $('#error').html('that\'s terrible :(');
  },

  getCategoryPosts: function(callback, type, slug) {
    $.ajax({
      type: 'GET',
      url: WF_URL + 'get_category_posts' + '/?post_type=' + type + '&slug=' + slug + '&count=-1',
      dataType: 'json',
      crossDomain: true,
      success: callback,
      error: function(error) {
        $('body').html('something was really wrong, please refresh or check internet connection');
      }
    })

  },

  parseJoyride: function(data) {
    if(!data.posts) {
      return;
    }

    for(var i = 0; i < data.posts.length; ++i) {
      var k = i+1;
      var content = '
#' + k + ': ' + data.posts[i].title + '
' + data.posts[i].content;
      $('
').html(content).appendTo($('.joyride-list'));
    }
    $(document).foundation('joyride', 'start');
  },

  error: function(error) {
    var error_data = {
      "type": error,
      "message" : "sorry we're getting back soon, just experiencing some hiccups"
    }
  }
}

wf.getCategoryPosts(
  function (data) {
    wf.parseJoyride(data);
  },
  'joyride',
  WF_PRJ
);

<commit_msg>more scalable<commit_after>var wf = {
  init: function() {
    $('
').appendTo('body');
    $('

Benvenuti

 Qui troverai le nostre descrizioni per i wireframe

').appendTo($('.joyride-list'));
    /**

    If you've already set up a Wordpress instance, with JSON API plugin activated
    you just have to put in WF_URL you're complete address to reach it

    e.g.:

    var WF_URL = 'http://www.example.com/api/';

    **/
    var WF_URL = 'http://www.example.com/api/';
    /**
    Define your own custom post type name
    **/

    var WF_CPT = 'joyride';
    /**

    The way the whole thing is managed right now is that in the wordpress instance
    we're managing more than one project for Wireframes, so we're using categories
    to address one particular project.

    This way I'm defining WF_PRJ as the category_slug for the project.

    e.g.:

    var WF_URL = 'project_wf'

    **/
    var WF_PRJ = 'project_wf';

    $.ajax({
        type: 'GET',
        url: WF_URL,
        dataType: 'json',
        crossDomain: true,
        success: function (data) {
          console.log('the API is working good.');

        },
        error: function (error) {
          // TODO
          //$('.toobad').reveal();
          console.log('you appear to be offline, or your API is not working at all.');
        }
      })
  },

  error: function() {
    $('#error').html('that\'s terrible :(');
  },

  getCategoryPosts: function(callback, type, slug) {
    $.ajax({
      type: 'GET',
      url: WF_URL + 'get_category_posts' + '/?post_type=' + type + '&slug=' + slug + '&count=-1',
      dataType: 'json',
      crossDomain: true,
      success: callback,
      error: function(error) {
        $('body').html('something was really wrong, please refresh or check internet connection');
      }
    })

  },

  parseJoyride: function(data) {
    if(!data.posts) {
      return;
    }

    for(var i = 0; i < data.posts.length; ++i) {
      var k = i+1;
      var content = '
#' + k + ': ' + data.posts[i].title + '
' + data.posts[i].content;
      $('
').html(content).appendTo($('.joyride-list'));
    }
    $(document).foundation('joyride', 'start');
  },

  error: function(error) {
    var error_data = {
      "type": error,
      "message" : "sorry we're getting back soon, just experiencing some hiccups"
    }
  }
}

wf.getCategoryPosts(
  function (data) {
    wf.parseJoyride(data);
  },
  WF_CPT,
  WF_PRJ
);

<|endoftext|>


<commit_before>var express = require('express'),
    path    = require('path'),
    exec    = require('child_process').exec,
    i18n    = require('i18n-abide'),
    _       = require('underscore'),
    backboneio = require('backbone.io'),
    mbc = require('mbc-common'),
    conf = mbc.config.Caspa,
    search_options = mbc.config.Search,
    collections = mbc.config.Common.Collections,
    moment = require('moment'),
    App = require("mbc-common/models/App"),
    maxage = 365 * 24 * 60 * 60 * 1000,
    uuid = require('node-uuid'),
    logger = mbc.logger().addLogger('caspa_server')
 ;

var loggerStream = {
    write: function(message, encoding) {
        logger.info(message);
    }
};

/* make sure at runtime that we atempt to get the dirs we need */
for (d in conf.Dirs) {
    /* HACK: but I'm not going to waist time writing mkdir -p */
    exec ('mkdir -p ' + conf.Dirs[d], function (error, stdout, stderr) {
        if (error !== null) {
            logger.error('exec error: ' + error);
        }
    });
}

var app = express();

app.configure(function () {
    app.use(i18n.abide({
        supported_languages: ['en-US', 'es', 'db-LB', 'it-CH'],
        default_lang: 'es',
        debug_lang: 'it-CH',
        translation_directory: 'locale'
    }));
    app.set('port', process.env.PORT || 3000);
    app.set('views', conf.Dirs.views);
    app.set('view engine', 'jade');
    app.use(express.logger({ stream: loggerStream, format: 'dev' }));
    app.use(express.compress());
/*    app.use('/uploads', upload({
        tmpDir:    conf.Dirs.uploads + '/incoming',
        uploadDir: conf.Dirs.upolads,
        uploadUrl: '/uploads/',
        safeFileTypes: /\.(webm|mkv|mov|mp4|avi|ogg)$/i,
    }));*/
    app.use(express.bodyParser({
            uploadDir: conf.Dirs.uploads,
            maxFieldsSize: 10 * 1024 * 1024
    }));
    app.use(express.methodOverride());
    app.use(express.cookieParser());
    app.use(express.cookieSession({ secret: 'your secret here', cookie: { maxAge: maxage }}));
    app.use(require('less-middleware')({
        src:  conf.Dirs.styles,
        dest: conf.Dirs.pub,
        compress: true}
    ));
    app.use(express.static(conf.Dirs.pub, {maxAge: maxage}));
    app.use('/models', express.static(conf.Dirs.models, {maxAge: maxage}));
    app.use('/lib',    express.static(conf.Dirs.vendor, {maxAge: maxage}));
    app.use(app.router);
});

app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
  app.set('io.loglevel', 100);
  app.set('minify', false);
});

app.configure('production', function(){
  app.use(express.errorHandler());
  app.set('io.loglevel', 1);
  app.set('minify', true);
});

var appModel = require('./routes')(app);
//var media = require('./routes/media')(app);

function debug_backend (backend) {
    backend.use(function(req, res, next) {
        logger.debug('Backend: ', req.backend);
        logger.debug('Method: ', req.method);
        logger.debug('Model: ', JSON.stringify(req.model));
        next();
    });
}

var db = mbc.db();

var publisher = mbc.pubsub();
var listener = mbc.pubsub();

// Override mongoStore read method with custom
var searchWrapper = require('./searchWrapper.js');

function id_middleware(req, res, next) {
    if( req.method == 'create' && req.model._id === undefined) {
        req.model._id = uuid.v1();
    }
    next();
}

var mediabackend = backboneio.createBackend();
mediabackend.use(searchWrapper(backboneio.middleware.mongoStore(db, collections.Medias, { search: search_options.Medias })));

var piecebackend = backboneio.createBackend();
piecebackend.use(id_middleware);
piecebackend.use(searchWrapper(backboneio.middleware.mongoStore(db, collections.Pieces, { search: search_options.Pieces })));

var transformbackend = backboneio.createBackend();
transformbackend.use(id_middleware);
transformbackend.use(searchWrapper(backboneio.middleware.mongoStore(db, collections.Transforms, { search: search_options.Transforms })));

var listbackend = backboneio.createBackend();
listbackend.use(id_middleware);
listbackend.use(searchWrapper(backboneio.middleware.mongoStore (db, collections.Lists, { search: search_options.Lists })));

var schedbackend = backboneio.createBackend();
schedbackend.use(id_middleware);
schedbackend.use(function (req, res, next) {
    publisher.publishJSON([req.backend, req.method].join('.'), { model: req.model });
    next();
});
schedbackend.use(searchWrapper(backboneio.middleware.mongoStore(db, collections.Scheds, { search: search_options.Scheds })));

var statusbackend = backboneio.createBackend();
listener.on('JSONmessage', function(chan, status) {

    if( chan != "mostoStatus" ) // we can ignore this message
        return;

    // This receives messages from mosto and propagates the message through
    //  backbone.io
    var emit = _.after(6, function() {
        logger.info('emitting', status);
        statusbackend.emit('updated', status)
    });
    ['previous', 'current', 'next'].forEach(function(pos) {
        db.collection(collections.Scheds).findEach({ _id: status.show[pos]._id }, function(err, res) {
            if( res ) {
                status.show[pos] = {
                    name: res.title,
                    _id: res._id,
                };
            }
            emit();
        });
        //db.collection('lists').findEach({ "models._id": status.piece[pos]._id }, function(err, res) {
        db.collection(collections.Pieces).findById(status.piece[pos]._id, function(err, piece) {
            if( err ) {
                // we still want to call emit() even if there was a DB error
                logger.error(err);
            }

            if( piece ) {
                /*
                var piece = _.chain(res.models).filter(function(p) {
                    return p._id == status.piece[pos]._id;
                }).value();
                console.log("[mosto status] filtered pieces", piece)
                if( !piece ) {
                    var message = "[mosto status] error: this shouldn't be empty";
                    console.log(message);
                    return new Error(message);
                }
                if( piece.length != 1 ) {
                    var message = "[mosto status] error: there must only be one!";
                    console.log(message)
                    return new Error(message);
                }

                piece = piece[0];
                */
                status.piece[pos] = piece;
                // default name to id
                if( !status.piece[pos].name ) {
                    var file = piece.file;
                    status.piece[pos].name = path.basename(file).replace(path.extname(file), '');
                }
            }
            emit();
        });
    });
});
listener.subscribe('mostoStatus');
statusbackend.use(backboneio.middleware.mongoStore(db, collections.Status, { search: search_options.Status }));

var framebackend = backboneio.createBackend();
listener.on('JSONmessage', function(chan, msg) {
    if( !(chan == 'mostoStatus.progress' ) )
        return;

    var status = new App.ProgressStatus(msg);
    framebackend.emit('updated', status);
});
listener.subscribe('mostoStatus.progress');
framebackend.use(backboneio.middleware.memoryStore(db, 'progress', {}));

var appbackend = backboneio.createBackend();
appbackend.use(backboneio.middleware.configStore());

// there should probably be two backends or two collections or both, or something, one for
// one-time momentary messages like warnings and such to be dismissed by the frontend,
// and another one for "sticky" messages like long-lived status problems, like if melted died
// or the DB has a problem
var mostomessagesbackend = backboneio.createBackend();
listener.on('JSONpmessage', function(pattern, chan, msg) {
    switch( chan ) {
        case "mostoMessage.emit":
            return mostomessagesbackend.emit('created', msg.model);
        case "mostoMessage.create":
            return mostomessagesbackend.emit('created', msg.model);
        case "mostoMessage.delete":
            return mostomessagesbackend.emit('deleted', msg.model);
    }
});
listener.psubscribe('mostoMessage*');
mostomessagesbackend.use(backboneio.middleware.mongoStore(db, collections.Mostomessages, { search: search_options.Mostomessages }));

_([mediabackend, listbackend, appbackend, piecebackend, transformbackend]).each (debug_backend);

var io = backboneio.listen(app.listen(app.get('port'), function(){
    logger.info("Express server listening on port " + app.get('port') + " in mode " + app.settings.env);
}), { mediabackend: mediabackend,
      piecebackend: piecebackend,
      transformbackend: transformbackend,
      listbackend:  listbackend,
      schedbackend: schedbackend,
      statusbackend: statusbackend,
      framebackend: framebackend,
      appbackend: appbackend
    });

io.configure('production', function(){
    io.enable('browser client minification');  // send minified client
    io.enable('browser client etag');          // apply etag caching logic based on version number
    io.enable('browser client gzip');          // gzip the file
});

io.set('logger', logger); // Log socket.io with custom logger

var utils = require('./utils');

if (process.env.MBC_SCRAPE) {
    setTimeout(function () {
        utils.scrape_files (conf.Dirs.scrape, function (model) {
            db.collection(collections.Medias).insert(model, {safe:true}, function(err, result) {
                if (err) {
                    logger.error('error','An error has occurred' + err);
                } else {
                    mediabackend.emit('created', model);
                }
            });
        });
    }, 300);
} else {
    logger.info ("not scrapping");
}
<commit_msg>Adding options and channel to debug backends<commit_after>var express = require('express'),
    path    = require('path'),
    exec    = require('child_process').exec,
    i18n    = require('i18n-abide'),
    _       = require('underscore'),
    backboneio = require('backbone.io'),
    mbc = require('mbc-common'),
    conf = mbc.config.Caspa,
    search_options = mbc.config.Search,
    collections = mbc.config.Common.Collections,
    moment = require('moment'),
    App = require("mbc-common/models/App"),
    maxage = 365 * 24 * 60 * 60 * 1000,
    uuid = require('node-uuid'),
    logger = mbc.logger().addLogger('caspa_server')
 ;

var loggerStream = {
    write: function(message, encoding) {
        logger.info(message);
    }
};

/* make sure at runtime that we atempt to get the dirs we need */
for (d in conf.Dirs) {
    /* HACK: but I'm not going to waist time writing mkdir -p */
    exec ('mkdir -p ' + conf.Dirs[d], function (error, stdout, stderr) {
        if (error !== null) {
            logger.error('exec error: ' + error);
        }
    });
}

var app = express();

app.configure(function () {
    app.use(i18n.abide({
        supported_languages: ['en-US', 'es', 'db-LB', 'it-CH'],
        default_lang: 'es',
        debug_lang: 'it-CH',
        translation_directory: 'locale'
    }));
    app.set('port', process.env.PORT || 3000);
    app.set('views', conf.Dirs.views);
    app.set('view engine', 'jade');
    app.use(express.logger({ stream: loggerStream, format: 'dev' }));
    app.use(express.compress());
/*    app.use('/uploads', upload({
        tmpDir:    conf.Dirs.uploads + '/incoming',
        uploadDir: conf.Dirs.upolads,
        uploadUrl: '/uploads/',
        safeFileTypes: /\.(webm|mkv|mov|mp4|avi|ogg)$/i,
    }));*/
    app.use(express.bodyParser({
            uploadDir: conf.Dirs.uploads,
            maxFieldsSize: 10 * 1024 * 1024
    }));
    app.use(express.methodOverride());
    app.use(express.cookieParser());
    app.use(express.cookieSession({ secret: 'your secret here', cookie: { maxAge: maxage }}));
    app.use(require('less-middleware')({
        src:  conf.Dirs.styles,
        dest: conf.Dirs.pub,
        compress: true}
    ));
    app.use(express.static(conf.Dirs.pub, {maxAge: maxage}));
    app.use('/models', express.static(conf.Dirs.models, {maxAge: maxage}));
    app.use('/lib',    express.static(conf.Dirs.vendor, {maxAge: maxage}));
    app.use(app.router);
});

app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
  app.set('io.loglevel', 100);
  app.set('minify', false);
});

app.configure('production', function(){
  app.use(express.errorHandler());
  app.set('io.loglevel', 1);
  app.set('minify', true);
});

var appModel = require('./routes')(app);
//var media = require('./routes/media')(app);

function debug_backend (backend) {
    backend.use(function(req, res, next) {
        logger.debug('Backend: ', req.backend);
        logger.debug('Method: ', req.method);
        logger.debug('Channel: ', req.channel);
        logger.debug('Options: ', JSON.stringify(req.options));
        logger.debug('Model: ', JSON.stringify(req.model));
        next();
    });
}

var db = mbc.db();

var publisher = mbc.pubsub();
var listener = mbc.pubsub();

// Override mongoStore read method with custom
var searchWrapper = require('./searchWrapper.js');

function id_middleware(req, res, next) {
    if( req.method == 'create' && req.model._id === undefined) {
        req.model._id = uuid.v1();
    }
    next();
}

var mediabackend = backboneio.createBackend();
mediabackend.use(searchWrapper(backboneio.middleware.mongoStore(db, collections.Medias, { search: search_options.Medias })));

var piecebackend = backboneio.createBackend();
piecebackend.use(id_middleware);
piecebackend.use(searchWrapper(backboneio.middleware.mongoStore(db, collections.Pieces, { search: search_options.Pieces })));

var transformbackend = backboneio.createBackend();
transformbackend.use(id_middleware);
transformbackend.use(searchWrapper(backboneio.middleware.mongoStore(db, collections.Transforms, { search: search_options.Transforms })));

var listbackend = backboneio.createBackend();
listbackend.use(id_middleware);
listbackend.use(searchWrapper(backboneio.middleware.mongoStore (db, collections.Lists, { search: search_options.Lists })));

var schedbackend = backboneio.createBackend();
schedbackend.use(id_middleware);
schedbackend.use(function (req, res, next) {
    publisher.publishJSON([req.backend, req.method].join('.'), { model: req.model });
    next();
});
schedbackend.use(searchWrapper(backboneio.middleware.mongoStore(db, collections.Scheds, { search: search_options.Scheds })));

var statusbackend = backboneio.createBackend();
listener.on('JSONmessage', function(chan, status) {

    if( chan != "mostoStatus" ) // we can ignore this message
        return;

    // This receives messages from mosto and propagates the message through
    //  backbone.io
    var emit = _.after(6, function() {
        logger.info('emitting', status);
        statusbackend.emit('updated', status)
    });
    ['previous', 'current', 'next'].forEach(function(pos) {
        db.collection(collections.Scheds).findEach({ _id: status.show[pos]._id }, function(err, res) {
            if( res ) {
                status.show[pos] = {
                    name: res.title,
                    _id: res._id,
                };
            }
            emit();
        });
        //db.collection('lists').findEach({ "models._id": status.piece[pos]._id }, function(err, res) {
        db.collection(collections.Pieces).findById(status.piece[pos]._id, function(err, piece) {
            if( err ) {
                // we still want to call emit() even if there was a DB error
                logger.error(err);
            }

            if( piece ) {
                /*
                var piece = _.chain(res.models).filter(function(p) {
                    return p._id == status.piece[pos]._id;
                }).value();
                console.log("[mosto status] filtered pieces", piece)
                if( !piece ) {
                    var message = "[mosto status] error: this shouldn't be empty";
                    console.log(message);
                    return new Error(message);
                }
                if( piece.length != 1 ) {
                    var message = "[mosto status] error: there must only be one!";
                    console.log(message)
                    return new Error(message);
                }

                piece = piece[0];
                */
                status.piece[pos] = piece;
                // default name to id
                if( !status.piece[pos].name ) {
                    var file = piece.file;
                    status.piece[pos].name = path.basename(file).replace(path.extname(file), '');
                }
            }
            emit();
        });
    });
});
listener.subscribe('mostoStatus');
statusbackend.use(backboneio.middleware.mongoStore(db, collections.Status, { search: search_options.Status }));

var framebackend = backboneio.createBackend();
listener.on('JSONmessage', function(chan, msg) {
    if( !(chan == 'mostoStatus.progress' ) )
        return;

    var status = new App.ProgressStatus(msg);
    framebackend.emit('updated', status);
});
listener.subscribe('mostoStatus.progress');
framebackend.use(backboneio.middleware.memoryStore(db, 'progress', {}));

var appbackend = backboneio.createBackend();
appbackend.use(backboneio.middleware.configStore());

// there should probably be two backends or two collections or both, or something, one for
// one-time momentary messages like warnings and such to be dismissed by the frontend,
// and another one for "sticky" messages like long-lived status problems, like if melted died
// or the DB has a problem
var mostomessagesbackend = backboneio.createBackend();
listener.on('JSONpmessage', function(pattern, chan, msg) {
    switch( chan ) {
        case "mostoMessage.emit":
            return mostomessagesbackend.emit('created', msg.model);
        case "mostoMessage.create":
            return mostomessagesbackend.emit('created', msg.model);
        case "mostoMessage.delete":
            return mostomessagesbackend.emit('deleted', msg.model);
    }
});
listener.psubscribe('mostoMessage*');
mostomessagesbackend.use(backboneio.middleware.mongoStore(db, collections.Mostomessages, { search: search_options.Mostomessages }));

_([mediabackend, listbackend, appbackend, piecebackend, transformbackend]).each (debug_backend);

var io = backboneio.listen(app.listen(app.get('port'), function(){
    logger.info("Express server listening on port " + app.get('port') + " in mode " + app.settings.env);
}), { mediabackend: mediabackend,
      piecebackend: piecebackend,
      transformbackend: transformbackend,
      listbackend:  listbackend,
      schedbackend: schedbackend,
      statusbackend: statusbackend,
      framebackend: framebackend,
      appbackend: appbackend
    });

io.configure('production', function(){
    io.enable('browser client minification');  // send minified client
    io.enable('browser client etag');          // apply etag caching logic based on version number
    io.enable('browser client gzip');          // gzip the file
});

io.set('logger', logger); // Log socket.io with custom logger

var utils = require('./utils');

if (process.env.MBC_SCRAPE) {
    setTimeout(function () {
        utils.scrape_files (conf.Dirs.scrape, function (model) {
            db.collection(collections.Medias).insert(model, {safe:true}, function(err, result) {
                if (err) {
                    logger.error('error','An error has occurred' + err);
                } else {
                    mediabackend.emit('created', model);
                }
            });
        });
    }, 300);
} else {
    logger.info ("not scrapping");
}
<|endoftext|>


<commit_before>angular.module('private.trainer.sessions.directives', [
])
.directive('trainerSessionsIndex', function(){
  return {
    templateUrl: 'app/private/trainer/sessions/sessions-directives.tmpl/sessions-index.tmpl.html',
    controller : "TrainerSessionsController as trainerSessionsCtrl"
  };
})
.controller("TrainerSessionsController", function TrainerSessionsController(SessionsModel, Flash){
    var ctrl = this;
        ctrl.search = "";
        ctrl.sessions = [];
    SessionsModel.getSessions("managed").then(function(response){
        ctrl.sessions = response.data || [];
    });
    ctrl.updateSessions = function(){
        SessionsModel.getSessions("managed").then(function(response){
            ctrl.sessions = response.data || [];
        });
    };
    ctrl.editName = function(sessionToSet){
        SessionsModel.updateNameSession(sessionToSet).then(function(response){
            response.flash();
            if(!response.isErroneous()){
                ctrl.updateSessions();
            }
        });
    };
    ctrl.editComments = function(sessionToSet){
        SessionsModel.updateCommentsSession(sessionToSet).then(function(response){
            response.flash();
            if(!response.isErroneous()){
                ctrl.updateSessions();
            }
        });
    };
    ctrl.archiveSession = function(sessionToArchive){
        if(sessionToArchive){
            SessionsModel.archiveSession(sessionToArchive).then(function(response){
                response.flash();
                if(!response.isErroneous()){
                    ctrl.updateSessions();
                }
            });
        }else{
            Flash.danger("No scenario choosed");
        }
    };
})
.directive('trainerSessionsAdd', function(ScenariosModel, SessionsModel, Flash) {
  return {
    templateUrl: 'app/private/trainer/sessions/sessions-directives.tmpl/sessions-add-form.tmpl.html',
    scope: false,
    require: "^trainerSessionsIndex",
    link : function(scope, element, attrs, parentCtrl){
        ScenariosModel.getScenarios().then(function(scenarios){
            scope.scenarios = scenarios;
        });
        scope.newSession = {
            name : "",
            scenarioId : 0
        };
        scope.addSession = function(){
            if(scope.newSession.scenarioId != 0){
                SessionsModel.createSession(scope.newSession.name, scope.newSession.scenarioId).then(function(response){
                    response.flash();
                    if(!response.isErroneous()){
                        scope.newSession = {
                            name : "",
                            scenarioId : 0
                        };
                        parentCtrl.updateSessions();
                    }
                });
            }else{
                Flash.warning("No scenario choosed");
            }
        };
    }
  };
})
.directive('trainerSessionsList', function() {
  return {
    templateUrl: 'app/private/trainer/sessions/sessions-directives.tmpl/sessions-list.tmpl.html',
    scope: {
        sessions : "=",
        search : "=",
        archive : "="
    }
  };
})
.directive('trainerSession', function(Flash) {
    return {
        templateUrl: 'app/private/trainer/sessions/sessions-directives.tmpl/session-card.tmpl.html',
        restrict: 'A',
        require: "^trainerSessionsIndex",
        scope: {
           session: '=',
           archive: "="
        },
        link : function(scope, element, attrs, parentCtrl){
            // Private function
            var resetSessionToSet = function(){
                scope.sessionToSet = {
                    id: scope.session.id,
                    name: scope.session.name,
                    comments: scope.session.gameModel.comments
                };
            }

            // Public parameters
            scope.editingName = false;
            scope.editingComments = false;
            resetSessionToSet();

            // Public function
            scope.toogleEditingName = function(){
                if(scope.editingComments){
                    scope.toogleEditingComments();
                }
                scope.editingName = (!scope.editingName);
                resetSessionToSet();
            };

            // Public function
            scope.editName = function(){
                parentCtrl.editName(scope.sessionToSet);
                scope.toogleEditingName();
            };

            // Public function
            scope.toogleEditingComments = function(){
                if(scope.editingName){
                    scope.toogleEditingName();
                }
                scope.editingComments = (!scope.editingComments);
                resetSessionToSet();
            };

            // Public function
            scope.editComments = function(){
                parentCtrl.editComments(scope.sessionToSet);
                scope.toogleEditingComments();
            };
        }
    }
});<commit_msg>Correction scenario response<commit_after>angular.module('private.trainer.sessions.directives', [
])
.directive('trainerSessionsIndex', function(){
  return {
    templateUrl: 'app/private/trainer/sessions/sessions-directives.tmpl/sessions-index.tmpl.html',
    controller : "TrainerSessionsController as trainerSessionsCtrl"
  };
})
.controller("TrainerSessionsController", function TrainerSessionsController(SessionsModel, Flash){
    var ctrl = this;
        ctrl.search = "";
        ctrl.sessions = [];
    SessionsModel.getSessions("managed").then(function(response){
        ctrl.sessions = response.data || [];
    });
    ctrl.updateSessions = function(){
        SessionsModel.getSessions("managed").then(function(response){
            ctrl.sessions = response.data || [];
        });
    };
    ctrl.editName = function(sessionToSet){
        SessionsModel.updateNameSession(sessionToSet).then(function(response){
            response.flash();
            if(!response.isErroneous()){
                ctrl.updateSessions();
            }
        });
    };
    ctrl.editComments = function(sessionToSet){
        SessionsModel.updateCommentsSession(sessionToSet).then(function(response){
            response.flash();
            if(!response.isErroneous()){
                ctrl.updateSessions();
            }
        });
    };
    ctrl.archiveSession = function(sessionToArchive){
        if(sessionToArchive){
            SessionsModel.archiveSession(sessionToArchive).then(function(response){
                response.flash();
                if(!response.isErroneous()){
                    ctrl.updateSessions();
                }
            });
        }else{
            Flash.danger("No scenario choosed");
        }
    };
})
.directive('trainerSessionsAdd', function(ScenariosModel, SessionsModel, Flash) {
  return {
    templateUrl: 'app/private/trainer/sessions/sessions-directives.tmpl/sessions-add-form.tmpl.html',
    scope: false,
    require: "^trainerSessionsIndex",
    link : function(scope, element, attrs, parentCtrl){
        ScenariosModel.getScenarios().then(function(response){
            if(!response.isErroneous()){
                scope.scenarios = response.data;
            }else{
                Flash.danger("Error loading scenarios")
            }
        });
        scope.newSession = {
            name : "",
            scenarioId : 0
        };
        scope.addSession = function(){
            if(scope.newSession.scenarioId != 0){
                SessionsModel.createSession(scope.newSession.name, scope.newSession.scenarioId).then(function(response){
                    response.flash();
                    if(!response.isErroneous()){
                        scope.newSession = {
                            name : "",
                            scenarioId : 0
                        };
                        parentCtrl.updateSessions();
                    }
                });
            }else{
                Flash.warning("No scenario choosed");
            }
        };
    }
  };
})
.directive('trainerSessionsList', function() {
  return {
    templateUrl: 'app/private/trainer/sessions/sessions-directives.tmpl/sessions-list.tmpl.html',
    scope: {
        sessions : "=",
        search : "=",
        archive : "="
    }
  };
})
.directive('trainerSession', function(Flash) {
    return {
        templateUrl: 'app/private/trainer/sessions/sessions-directives.tmpl/session-card.tmpl.html',
        restrict: 'A',
        require: "^trainerSessionsIndex",
        scope: {
           session: '=',
           archive: "="
        },
        link : function(scope, element, attrs, parentCtrl){
            // Private function
            var resetSessionToSet = function(){
                scope.sessionToSet = {
                    id: scope.session.id,
                    name: scope.session.name,
                    comments: scope.session.gameModel.comments
                };
            }

            // Public parameters
            scope.editingName = false;
            scope.editingComments = false;
            resetSessionToSet();

            // Public function
            scope.toogleEditingName = function(){
                if(scope.editingComments){
                    scope.toogleEditingComments();
                }
                scope.editingName = (!scope.editingName);
                resetSessionToSet();
            };

            // Public function
            scope.editName = function(){
                parentCtrl.editName(scope.sessionToSet);
                scope.toogleEditingName();
            };

            // Public function
            scope.toogleEditingComments = function(){
                if(scope.editingName){
                    scope.toogleEditingName();
                }
                scope.editingComments = (!scope.editingComments);
                resetSessionToSet();
            };

            // Public function
            scope.editComments = function(){
                parentCtrl.editComments(scope.sessionToSet);
                scope.toogleEditingComments();
            };
        }
    }
});<|endoftext|>


<commit_before>/*
 * Copyright 2015 Björn Ricks <bjoern.ricks@gmail.com>
 *
 */

var angTutApp = angular.module('angTutApp', ['ngRoute', 'ngMaterial']);

angTutApp.config(['$routeProvider',
    function($routeProvider) {
        $routeProvider.
            when('/', {
                templateUrl: 'home.html'
            }).
            when('/examples/:exampleNumber', {
                templateUrl: 'example-view.html',
                controller: 'ExampleDetailCtrl'
            }).
            when('/sections/:sectionNumber', {
                templateUrl: 'section-view.html',
                controller: 'SectionCtrl'
            }).
            otherwise({
                redirectTo: '/'
            });
    }]
);

angTutApp.factory('conf', function() {
    var service = {
        examplesPath: 'examples/',
    };
    return service;
});

angTutApp.factory('examples', function($http) {
    function getData(callback) {
        $http({
            method: 'GET',
            url: 'examples.json',
            cache: true
        }).success(callback);
    }
    return {
        list: getData,
        find: function(exampleNumber, callback) {
            getData(function(data) {
                var index = parseInt(exampleNumber);
                angular.forEach(data, function(section, key) {
                    angular.forEach(section.examples, function(example, key) {
                        if (example.id == index) {
                            callback(example);
                        }
                    });
                });
            });
        },
        findSection: function(sectionNumber, callback) {
            getData(function(data) {
                var index = parseInt(sectionNumber);
                angular.forEach(data, function(section, key) {
                    if (section.id == index) {
                        callback(section);
                    }
                });
            });
        }
    };
});

angTutApp.factory('menu', function() {
    return self = {
        selectSection: function(section) {
            self.openedSection = section;
        },
        toggleSelectSection: function(section) {
            self.openedSection = (self.openedSection === section ?
                    null : section);
        },
        isSectionSelected: function(section) {
            return self.openedSection === section;
        },
        getSectionName: function() {
            if (!self.openedSection) {
                return "";
            }
            return self.openedSection.name;
        }
    };
});

angTutApp.controller('HomeCtrl', function($scope, examples, menu) {
    $scope.menu = menu;
    examples.list(function(examples) {
        $scope.examples = examples;
    });
});

angTutApp.controller('ExampleDetailCtrl', ['$scope', '$routeParams', '$http', '$sce', 'conf',
        'examples', 'menu',
    function($scope, $routeParams, $http, $sce, conf, examples, menu) {
        $scope.menu = menu;
        examples.find($routeParams.exampleNumber, function(example) {
            $scope.example = example;
            var examplePath = conf.examplesPath + example.id + '/';
            $scope.runUrl = examplePath + 'index.html';
            $scope.readme = examplePath + 'readme.html';
        });
}]);

angTutApp.controller('SectionCtrl', ['$scope', '$routeParams', '$http', '$sce', 'conf', 'examples',
        'menu',
    function($scope, $routeParams, $http, $sce, conf, examples, menu) {
        $scope.menu = menu;
        examples.findSection($routeParams.sectionNumber, function(section) {
            $scope.section = section;
            $scope.readme = conf.examplesPath + 'section' + section.id + '.html';
        });
    }
]);

angTutApp.directive('atHljs', ['conf', function(conf) {
    return {
        scope: { file: '=', example: '=' },
        restrict: 'A',
        controller: function($scope, $http) {
            var path = [
                conf.examplesPath,
                $scope.example.id,
                $scope.file
            ].join('/');
            $http.get(path).success(function(data) {
                if (typeof(data) === 'object') {
                    // un-parse auto-parsed JSON files for presentation as text
                    data = JSON.stringify(data, null, 2);
                } else {
                    // Remove trailing newlines from code presentation
                    data = data.trim();
                }
                $scope.content = data;
            });
        },
        link: function(scope, element, attrs) {
            var contentParent = angular.element(
                '

'
            );
            element.append(contentParent);
            scope.$watch('content', function(data) {
                if (data) {
                    var codeElement = contentParent.find('code');
                    var highlightedCode = hljs.highlightAuto(data);
                    codeElement.append(
                        highlightedCode.value).addClass('highlight');
                }
            });
        }
    };
}]);
<commit_msg>Use self invoking anonymous function to seperate namespaces<commit_after>/*
 * Copyright 2015 Björn Ricks <bjoern.ricks@gmail.com>
 *
 */
(function() {
    'use strict';

    var angTutApp = angular.module('angTutApp', ['ngRoute', 'ngMaterial']);

    angTutApp.config(['$routeProvider',
        function($routeProvider) {
            $routeProvider.
                when('/', {
                    templateUrl: 'home.html'
                }).
                when('/examples/:exampleNumber', {
                    templateUrl: 'example-view.html',
                    controller: 'ExampleDetailCtrl'
                }).
                when('/sections/:sectionNumber', {
                    templateUrl: 'section-view.html',
                    controller: 'SectionCtrl'
                }).
                otherwise({
                    redirectTo: '/'
                });
        }]
    );

    angTutApp.factory('conf', function() {
        var service = {
            examplesPath: 'examples/',
        };
        return service;
    });

    angTutApp.factory('examples', function($http) {
        function getData(callback) {
            $http({
                method: 'GET',
                url: 'examples.json',
                cache: true
            }).success(callback);
        }
        return {
            list: getData,
            find: function(exampleNumber, callback) {
                getData(function(data) {
                    var index = parseInt(exampleNumber);
                    angular.forEach(data, function(section, key) {
                        angular.forEach(section.examples, function(example, key) {
                            if (example.id == index) {
                                callback(example);
                            }
                        });
                    });
                });
            },
            findSection: function(sectionNumber, callback) {
                getData(function(data) {
                    var index = parseInt(sectionNumber);
                    angular.forEach(data, function(section, key) {
                        if (section.id == index) {
                            callback(section);
                        }
                    });
                });
            }
        };
    });

    angTutApp.factory('menu', function() {
        return self = {
            selectSection: function(section) {
                self.openedSection = section;
            },
            toggleSelectSection: function(section) {
                self.openedSection = (self.openedSection === section ?
                        null : section);
            },
            isSectionSelected: function(section) {
                return self.openedSection === section;
            },
            getSectionName: function() {
                if (!self.openedSection) {
                    return "";
                }
                return self.openedSection.name;
            }
        };
    });

    angTutApp.controller('HomeCtrl', function($scope, examples, menu) {
        $scope.menu = menu;
        examples.list(function(examples) {
            $scope.examples = examples;
        });
    });

    angTutApp.controller('ExampleDetailCtrl', ['$scope', '$routeParams', '$http', '$sce', 'conf',
            'examples', 'menu',
        function($scope, $routeParams, $http, $sce, conf, examples, menu) {
            $scope.menu = menu;
            examples.find($routeParams.exampleNumber, function(example) {
                $scope.example = example;
                var examplePath = conf.examplesPath + example.id + '/';
                $scope.runUrl = examplePath + 'index.html';
                $scope.readme = examplePath + 'readme.html';
            });
    }]);

    angTutApp.controller('SectionCtrl', ['$scope', '$routeParams', '$http', '$sce', 'conf', 'examples',
            'menu',
        function($scope, $routeParams, $http, $sce, conf, examples, menu) {
            $scope.menu = menu;
            examples.findSection($routeParams.sectionNumber, function(section) {
                $scope.section = section;
                $scope.readme = conf.examplesPath + 'section' + section.id + '.html';
            });
        }
    ]);

    angTutApp.directive('atHljs', ['conf', function(conf) {
        return {
            scope: { file: '=', example: '=' },
            restrict: 'A',
            controller: function($scope, $http) {
                var path = [
                    conf.examplesPath,
                    $scope.example.id,
                    $scope.file
                ].join('/');
                $http.get(path).success(function(data) {
                    if (typeof(data) === 'object') {
                        // un-parse auto-parsed JSON files for presentation as text
                        data = JSON.stringify(data, null, 2);
                    } else {
                        // Remove trailing newlines from code presentation
                        data = data.trim();
                    }
                    $scope.content = data;
                });
            },
            link: function(scope, element, attrs) {
                var contentParent = angular.element(
                    '

'
                );
                element.append(contentParent);
                scope.$watch('content', function(data) {
                    if (data) {
                        var codeElement = contentParent.find('code');
                        var highlightedCode = hljs.highlightAuto(data);
                        codeElement.append(
                            highlightedCode.value).addClass('highlight');
                    }
                });
            }
        };
    }]);
})();
<|endoftext|>