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

var hitSchema = mongoose.Schema({
    name: String,
    condition: {
        // i.e. basic, training, fast
        firstTask: String,
        // Note that 'feedback' is extra decoration on top of
        // a task, so specifying this condition will pair it based on
        // the firstTask. If firstTask is 'fast', the feedback will be
        // paired with the fast design; otherwise, it is paired with
        // the basic design
        laterTasks:String  // i.e. basic, feedback, training, fast
    },
    // Base payment
    payment: {type: Number, default: 0},
    // Bonus, in dollars
    bonus: {
        task:{type:Number, default:0},
        laterTask:{type:Number, default:0},
        // Nth array value corresponds to Nth task item. Last value will
        // repeat if there are more items (so a constant bonus would be
        // an array of length 1
        items:[{type: Number, default: 0}]
    },
    type: String, // e.g. Image tagging
    // The name of the model for items, e.g. 'pin'.
    // Should correspond to a model in models/{{itemModel}}.js
    itemModel: String,
    // The items to choose from.
    // If facets.length !== 0, the items will be sampled from
    // a facet in facets[]
    items: [Number],
    // A subsample. E.g. a query, which for meta has a name,
    facets: [{
        meta:mongoose.Schema.Types.Mixed,
        items: [Number],
    }],
    trainingset_id: String,
    // An explanation of what kind of facet is used, if any.
    // Optional, because this information should be gleamed
    // from the hit.type. If type === 'Relevance judgments", we
    // know that the faceting is queries. For now, facetType
    // is meant as a human-friendly annotation.
    facetType: String,
    setsPerItem: Number,
    maxSetSize: Number,
    // Used for estimating how long the task will take
    // Not used for the 'fast' condition, because the timer
    // time is the best estimate
    itemTimeEstimate: Number,
    // Specifies the task-completion timer in 'fast' condition
    timer: { type: Number, default: null },
    // Workers to exclude
    exclude: {
        // Workers that have done any tasks with this tasktype before
        pastInTaskType: Boolean,
        // All past workers (NOT IMPLEMENTED)
        pastAll: Boolean,
        // Array of hit_ids to exclude (NOT IMPLEMENTED)
        pastInHits: [String],
        // Array of userids to exclude (NOT IMPLEMENTED)
        users: [String]
    }
});

/* Get an array of all the hits with the same type.*/
hitSchema.statics.listAllByType = function(type, callback) {
    return this.aggregate([
      {$match:{"type": type}},
      {$group:{_id:null, "hits":{$addToSet:'$_id'}}}
    ]).exec(function(err, results){
        if (err) { return callback(err); }
        // Return just the array of IDs (and convert to String from ObjectId)
        var arr = results[0].hits.map(function(hit){return hit.toString();});
        return callback(null, arr);
    });
};

var Hit = mongoose.connection.model('Hit', hitSchema);

module.exports = Hit;
<commit_msg>Alow first task bonuses<commit_after>var mongoose = require('mongoose');

var hitSchema = mongoose.Schema({
    name: String,
    condition: {
        // i.e. basic, training, fast
        firstTask: String,
        // Note that 'feedback' is extra decoration on top of
        // a task, so specifying this condition will pair it based on
        // the firstTask. If firstTask is 'fast', the feedback will be
        // paired with the fast design; otherwise, it is paired with
        // the basic design
        laterTasks:String  // i.e. basic, feedback, training, fast
    },
    // Base payment
    payment: {type: Number, default: 0},
    // Bonus, in dollars
    bonus: {
        task:{type:Number, default:0},
        firstTask:{type:Number, default:0},
        laterTask:{type:Number, default:0},
        // Nth array value corresponds to Nth task item. Last value will
        // repeat if there are more items (so a constant bonus would be
        // an array of length 1
        items:[{type: Number, default: 0}]
    },
    type: String, // e.g. Image tagging
    // The name of the model for items, e.g. 'pin'.
    // Should correspond to a model in models/{{itemModel}}.js
    itemModel: String,
    // The items to choose from.
    // If facets.length !== 0, the items will be sampled from
    // a facet in facets[]
    items: [Number],
    // A subsample. E.g. a query, which for meta has a name,
    facets: [{
        meta:mongoose.Schema.Types.Mixed,
        items: [Number],
    }],
    trainingset_id: String,
    // An explanation of what kind of facet is used, if any.
    // Optional, because this information should be gleamed
    // from the hit.type. If type === 'Relevance judgments", we
    // know that the faceting is queries. For now, facetType
    // is meant as a human-friendly annotation.
    facetType: String,
    setsPerItem: Number,
    maxSetSize: Number,
    // Used for estimating how long the task will take
    // Not used for the 'fast' condition, because the timer
    // time is the best estimate
    itemTimeEstimate: Number,
    // Specifies the task-completion timer in 'fast' condition
    timer: { type: Number, default: null },
    // Workers to exclude
    exclude: {
        // Workers that have done any tasks with this tasktype before
        pastInTaskType: Boolean,
        // All past workers (NOT IMPLEMENTED)
        pastAll: Boolean,
        // Array of hit_ids to exclude (NOT IMPLEMENTED)
        pastInHits: [String],
        // Array of userids to exclude (NOT IMPLEMENTED)
        users: [String]
    }
});

/* Get an array of all the hits with the same type.*/
hitSchema.statics.listAllByType = function(type, callback) {
    return this.aggregate([
      {$match:{"type": type}},
      {$group:{_id:null, "hits":{$addToSet:'$_id'}}}
    ]).exec(function(err, results){
        if (err) { return callback(err); }
        // Return just the array of IDs (and convert to String from ObjectId)
        var arr = results[0].hits.map(function(hit){return hit.toString();});
        return callback(null, arr);
    });
};

var Hit = mongoose.connection.model('Hit', hitSchema);

module.exports = Hit;
<|endoftext|>


<commit_before>var striptIndent = require('./indentStrip')
var indentString = require('./indent')

function redent (str, num, char) {
  return indentString(striptIndent(str), char || ' ', num || 0)
}

module.exports = redent
<commit_msg>update text/redent -- update requires<commit_after>var undent = require('./undent')
var indent = require('./indent')

function redent (str, num, char) {
  return indent(undent(str), char || ' ', num || 0)
}

module.exports = redent
<|endoftext|>


<commit_before>#! /usr/bin/env node
const wetty = require('./wetty.js');
const fs = require('fs-extra');
const path = require('path');
const optimist = require('optimist');

const opts = optimist
  .options({
    sslkey: {
      demand: false,
      description: 'path to SSL key',
    },
    sslcert: {
      demand: false,
      description: 'path to SSL certificate',
    },
    sshhost: {
      demand: false,
      description: 'ssh server host',
    },
    sshport: {
      demand: false,
      description: 'ssh server port',
    },
    sshuser: {
      demand: false,
      description: 'ssh user',
    },
    sshauth: {
      demand: false,
      description: 'defaults to "password", you can use "publickey,password" instead',
    },
    port: {
      demand: false,
      alias: 'p',
      description: 'wetty listen port',
    },
    help: {
      demand: false,
      alias: 'h',
      description: 'Print help message',
    },
  })
  .boolean('allow_discovery').argv;

if (opts.help) {
  optimist.showHelp();
  process.exit(0);
}

const sshuser = opts.sshuser || process.env.SSHUSER || '';
const sshhost = opts.sshhost || process.env.SSHHOST || 'localhost';
const sshauth = opts.sshauth || process.env.SSHAUTH || 'password,keyboard-interactive';
const sshport = opts.sshport || process.env.SSHPOST || 22;
const port = opts.port || process.env.PORT || 3000;

loadSSL(opts).then(ssl => {
  opts.ssl = ssl;
});

process.on('uncaughtException', err => {
  console.error(`Error: ${err}`);
});

const tty = wetty.serve(port, sshuser, sshhost, sshport, sshauth, opts.ssl);

tty.on('exit', code => {
  console.log(`exit with code: ${code}`);
});

tty.on('disconnect', () => {
  console.log('disconnect');
});

async function loadSSL({ sslkey, sslcert }) {
  try {
    return sslkey && sslcert
      ? {
          key: await fs.readFile(path.resolve(sslkey)),
          cert: await fs.readFile(path.resolve(sslcert)),
        }
      : {};
  } catch (err) {
    console.err(err);
    process.exit(1);
  }
}
<commit_msg>preserve lts support<commit_after>#! /usr/bin/env node
const wetty = require('./wetty.js');
const fs = require('fs-extra');
const path = require('path');
const optimist = require('optimist');

const opts = optimist
  .options({
    sslkey: {
      demand     : false,
      description: 'path to SSL key',
    },
    sslcert: {
      demand     : false,
      description: 'path to SSL certificate',
    },
    sshhost: {
      demand     : false,
      description: 'ssh server host',
    },
    sshport: {
      demand     : false,
      description: 'ssh server port',
    },
    sshuser: {
      demand     : false,
      description: 'ssh user',
    },
    sshauth: {
      demand     : false,
      description: 'defaults to "password", you can use "publickey,password" instead',
    },
    port: {
      demand     : false,
      alias      : 'p',
      description: 'wetty listen port',
    },
    help: {
      demand     : false,
      alias      : 'h',
      description: 'Print help message',
    },
  })
  .boolean('allow_discovery').argv;

if (opts.help) {
  optimist.showHelp();
  process.exit(0);
}

const sshuser = opts.sshuser || process.env.SSHUSER || '';
const sshhost = opts.sshhost || process.env.SSHHOST || 'localhost';
const sshauth = opts.sshauth || process.env.SSHAUTH || 'password,keyboard-interactive';
const sshport = opts.sshport || process.env.SSHPOST || 22;
const port = opts.port || process.env.PORT || 3000;

loadSSL(opts).then(ssl => {
  opts.ssl = ssl;
});

process.on('uncaughtException', err => {
  console.error(`Error: ${err}`);
});

const tty = wetty.serve(port, sshuser, sshhost, sshport, sshauth, opts.ssl);

tty.on('exit', code => {
  console.log(`exit with code: ${code}`);
});

tty.on('disconnect', () => {
  console.log('disconnect');
});

function loadSSL({ sslkey, sslcert }) {
  return new Promise((resolve, reject) => {
    if (sslkey && sslcert) {
      const ssl = {};
      fs
        .readFile(path.resolve(sslkey))
        .then(key => {
          ssl.key = key;
        })
        .then(fs.readFile(path.resolve(sslcert)))
        .then(cert => {
          ssl.cert = cert;
        })
        .then(resolve(ssl))
        .catch(reject);
    }
    resolve({});
  });
}
<|endoftext|>


<commit_before>var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var OAuth = require('oauth').OAuth;

var index = require('./routes/index');
var twitter = require('./routes/twitter');
var manager = require('./routes/manager');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false,
  cookie: {
    maxAge: 30 * 60 * 1000  // 30 min
  }
}));
app.use(express.static(path.join(__dirname, 'public')));

app.use('/js', express.static(__dirname + '/node_modules/bootstrap/dist/js'));
app.use('/js', express.static(__dirname + '/node_modules/jquery/dist'));
app.use('/css', express.static(__dirname + '/public/stylesheets'))
app.use('/css', express.static(__dirname + '/node_modules/bootstrap/dist/css'));
app.use('/css', express.static(__dirname + '/node_modules/bootstrap-social'));
app.use('/fonts', express.static(__dirname + '/node_modules/bootstrap/dist/fonts'))

app.use('/', index);
app.use('/auth/twitter', twitter)
app.use('/manager', manager);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;
<commit_msg>express.staticを一部まとめた<commit_after>var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var OAuth = require('oauth').OAuth;

var index = require('./routes/index');
var twitter = require('./routes/twitter');
var manager = require('./routes/manager');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false,
  cookie: {
    maxAge: 30 * 60 * 1000  // 30 min
  }
}));
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', express.static(__dirname + '/node_modules/bootstrap/dist/'));
app.use('/js', express.static(__dirname + '/node_modules/jquery/dist'));
app.use('/css', express.static(__dirname + '/public/stylesheets'))
app.use('/css', express.static(__dirname + '/node_modules/bootstrap-social'));

app.use('/', index);
app.use('/auth/twitter', twitter)
app.use('/manager', manager);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;
<|endoftext|>


<commit_before>'use strict'

const SPOTIFY_PLAYPAUSE = 'dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause'
const SPOTIFY_NEXT = 'dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Next'
const SPOTIFY_PREVIOUS = 'dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Previous'
const SPOTIFY_INFO = 'dbus-send --print-reply --session --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get string:\'org.mpris.MediaPlayer2.Player\' string:\'Metadata\''

// const net = require('net')
const http = require('http')
const ip = require('ip')
const shelljs = require('shelljs')
const robot = require('robotjs')

robot.setMouseDelay(2)

const IP_ADDRESS = ip.address()

const server = http.createServer()
const io = require('socket.io')(server)

io.on('connection', function (client) {

    console.log('client connected', client.id)
    let spotifyInterval = null

    client.on('disconnect', () => {
        console.log('client disconnected', client.id)
        clearInterval(spotifyInterval)
    })

    client.on('get_commands_list', () => {
        console.log('get_commands_list')
        client.emit('commands_list', {
            data: [
                'mouseMoveCenter',
                'mouseMoveZero',
                'mouseMoveSin',
                'volumeup',
                'volumedown',
                'spotify',
                'spotifyPlayPause',
                'spotifyNext',
                'spotifyPrevious',
                'spotifyClose',
            ]
        })
    })

    client.on('mouseMoveCenter', () => {
        const screenSize = robot.getScreenSize()
        robot.moveMouse(screenSize.width / 2, screenSize.height / 2)
    })

    client.on('mouseMoveZero', () => {
        robot.moveMouse(0, 0)
    })

    client.on('mouseMoveSin', () => {
        const twoPI = Math.PI * 2.0
        const screenSize = robot.getScreenSize()
        const height = (screenSize.height / 2) - 10
        const width = screenSize.width

        for (let x = 0; x < width; x++) {
            let y = height * Math.sin((twoPI * x) / width) + height
            robot.moveMouse(x, y)
        }
    })

    client.on('volumeup', () => {
        shelljs.exec('amixer -D pulse sset Master 5%+', { silent: true })
    })

    client.on('volumedown', () => {
        shelljs.exec('amixer -D pulse sset Master 5%-', { silent: true })
    })

    client.on('spotify', () => {
        spotifyInterval = setInterval(() => {
            sendSpotifyInfo().then((data) => {
                client.emit('spotifyInfo', parseDbusData(data))
            })
        }, 5000)

        shelljs.exec('spotify&', { silent: true }, () => { })
    })
    client.on('spotifyPlayPause', () => {

        const cmd = shelljs.exec(SPOTIFY_PLAYPAUSE , { async: true, silent: true })
        cmd.stdout.on('data', (data) => {
            sendSpotifyInfo().then((data) => {
                client.emit('spotifyInfo', parseDbusData(data))
            })
        })

    })

    client.on('spotifyNext', () => {

        const cmd = shelljs.exec(SPOTIFY_NEXT, { async: true, silent: true })
        cmd.stdout.on('data', (data) => {
            sendSpotifyInfo().then((data) => {
                client.emit('spotifyInfo', parseDbusData(data))
            })
        })
    })

    client.on('spotifyPrevious', () => {

        const cmd = shelljs.exec(SPOTIFY_PREVIOUS, { async: true, silent: true })
        cmd.stdout.on('data', (data) => {
            sendSpotifyInfo().then((data) => {
                client.emit('spotifyInfo', parseDbusData(data))
            })
        })

    })

    client.on('spotifyClose', () => {
        shelljs.exec('kill $(ps aux | grep spotify | awk \'{print $2}\')')
        clearInterval(spotifyInterval)
    })

    client.on('openUrl', (data) => {
        shelljs.exec(`google-chrome ${data.url}`)
    })

    // client.emit('test_connection', { data: 'witaj!' })
})
server.listen(1337, IP_ADDRESS)

console.log(`Address: ${IP_ADDRESS}:1337`)

function sendSpotifyInfo() {
    return new Promise((resolve, reject) => {
        const cmd = shelljs.exec(SPOTIFY_INFO, { async: true, silent: true })

        cmd.stdout.on('data', (data) => { resolve(data) })
    })
}

function parseDbusData(data) {
    data = data.replace(/( )+/g, ' ')
    data = data.replace(/\n/g, '')
    data = data.replace(/dict entry\(/g, '\ndict entry(')

    data = data.match(/dict entry\(.*\)/g).join('\n')
    data = data.replace(/dict entry\( string /g, '')
    data = data.replace(/ variant \w+ /g, ':')
    data = data.replace(/ \)/g, '')
    data = data.replace(/ string /g, '')

    return JSON.parse(`{${data.replace(/\n/g, ',')}}`)
}
<commit_msg>Added detect if spotify is open<commit_after>'use strict'

const SPOTIFY_PLAYPAUSE = 'dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause'
const SPOTIFY_NEXT = 'dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Next'
const SPOTIFY_PREVIOUS = 'dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Previous'
const SPOTIFY_INFO = 'dbus-send --print-reply --session --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get string:\'org.mpris.MediaPlayer2.Player\' string:\'Metadata\''

// const net = require('net')
const http = require('http')
const ip = require('ip')
const shelljs = require('shelljs')
const robot = require('robotjs')

robot.setMouseDelay(2)

const IP_ADDRESS = ip.address()

const server = http.createServer()
const io = require('socket.io')(server)

io.on('connection', function (client) {

    console.log('client connected', client.id)
    let spotifyInterval = null

    client.on('disconnect', () => {
        console.log('client disconnected', client.id)
        clearInterval(spotifyInterval)
    })

    client.on('get_commands_list', () => {
        console.log('get_commands_list')
        client.emit('commands_list', {
            data: [
                'mouseMoveCenter',
                'mouseMoveZero',
                'mouseMoveSin',
                'volumeup',
                'volumedown',
                'spotify',
                'spotifyPlayPause',
                'spotifyNext',
                'spotifyPrevious',
                'spotifyClose',
            ]
        })
    })

    client.on('mouseMoveCenter', () => {
        const screenSize = robot.getScreenSize()
        robot.moveMouse(screenSize.width / 2, screenSize.height / 2)
    })

    client.on('mouseMoveZero', () => {
        robot.moveMouse(0, 0)
    })

    client.on('mouseMoveSin', () => {
        const twoPI = Math.PI * 2.0
        const screenSize = robot.getScreenSize()
        const height = (screenSize.height / 2) - 10
        const width = screenSize.width

        for (let x = 0; x < width; x++) {
            let y = height * Math.sin((twoPI * x) / width) + height
            robot.moveMouse(x, y)
        }
    })

    client.on('volumeup', () => {
        shelljs.exec('amixer -D pulse sset Master 5%+', { silent: true })
    })

    client.on('volumedown', () => {
        shelljs.exec('amixer -D pulse sset Master 5%-', { silent: true })
    })

    client.on('spotify', () => {
        spotifyInterval = setInterval(() => {
            getSpotifyInfo().then((data) => {
                client.emit('spotifyInfo', parseDbusData(data))
            })
        }, 2000)

        // shelljs.exec('spotify&', { silent: true }, () => { })

        const isSpotify = shelljs.exec('ps aux | grep spotify | awk \'{print $11}\'', { async: true, silent: true })

        isSpotify.stdout.on('data', (data) => {
            console.log(data)
            if (data.match('/usr/share/spotify/spotify'))
                sendSpotifyInfo(client)
            else{
                const cmd = shelljs.exec('spotify&', { async: true, silent: true })
                cmd.stdout.on('data', (data) => {
                    console.log('spotify started')
                    sendSpotifyInfo(client)
                })

            }
        })
    })
    client.on('spotifyPlayPause', () => {

        const cmd = shelljs.exec(SPOTIFY_PLAYPAUSE, { async: true, silent: true })
        cmd.stdout.on('data', (data) => {
            sendSpotifyInfo(client)
        })

    })

    client.on('spotifyNext', () => {

        const cmd = shelljs.exec(SPOTIFY_NEXT, { async: true, silent: true })
        cmd.stdout.on('data', (data) => {
            sendSpotifyInfo(client)
        })
    })

    client.on('spotifyPrevious', () => {

        const cmd = shelljs.exec(SPOTIFY_PREVIOUS, { async: true, silent: true })
        cmd.stdout.on('data', (data) => {
            sendSpotifyInfo(client)
        })

    })

    client.on('spotifyClose', () => {
        shelljs.exec('kill $(ps aux | grep spotify | awk \'{print $2}\')')
        clearInterval(spotifyInterval)
    })

    client.on('openUrl', (data) => {
        shelljs.exec(`google-chrome ${data.url}`)
    })

    // client.emit('test_connection', { data: 'witaj!' })
})
server.listen(1337, IP_ADDRESS)

console.log(`Address: ${IP_ADDRESS}:1337`)

function getSpotifyInfo() {
    return new Promise((resolve, reject) => {
        const cmd = shelljs.exec(SPOTIFY_INFO, { async: true, silent: true })

        cmd.stdout.on('data', (data) => { resolve(data) })
    })
}

function parseDbusData(data) {
    data = data.replace(/( )+/g, ' ')
    data = data.replace(/\n/g, '')
    data = data.replace(/dict entry\(/g, '\ndict entry(')

    data = data.match(/dict entry\(.*\)/g).join('\n')
    data = data.replace(/dict entry\( string /g, '')
    data = data.replace(/ variant \w+ /g, ':')
    data = data.replace(/ \)/g, '')
    data = data.replace(/ string /g, '')

    return JSON.parse(`{${data.replace(/\n/g, ',')}}`)
}

function sendSpotifyInfo(client){
    setTimeout(() => { getSpotifyInfo().then((data) => { client.emit('spotifyInfo', parseDbusData(data)) }) }, 100)
}<|endoftext|>


<commit_before>ZBase.registerView((function() {

  var load = function(url) {
    var qparams = {
      with_categories: true,
      type: "all",
      author: "all"
    };

    var owner_param = UrlUtil.getParamValue(url, "owner");
    if (owner_param) {
      qparams.owner = owner_param;
    }

    var author_param = UrlUtil.getParamValue(url, "author");
    if (author_param) {
      qparams.author = author_param;
    }

    var category_param = UrlUtil.getParamValue(url, "category");
    if (category_param) {
      qparams.category_prefix = category_param;
    }

    var pstatus_param = UrlUtil.getParamValue(url, "publishing_status");
    if (pstatus_param) {
      qparams.publishing_status = pstatus_param;
    }

    $.showLoader();

    $.httpGet("/api/v1/documents?" + $.buildQueryString(qparams), function(r) {
      if (r.status == 200) {
        render(JSON.parse(r.response), qparams, url);
      } else {
        $.fatalError();
      }
    });
  }

  var render = function(data, qparams, path) {
    var reports = data.documents;
    var categories = data.categories;

    var page = $.getTemplate(
        "views/datastore_queries",
        "zbase_datastore_queries_main_tpl");

    renderTable(
        page.querySelector(".zbase_datastore_queries tbody"),
        reports);

    $("z-dropdown.create_new_doc", page).addEventListener("change", function(e) {
      $.createNewDocument(this.getValue());
      this.setValue([]);
    });

    var search = $("z-search.search_queries", page);
    search.addEventListener("z-search-autocomplete", searchAutocomplete);
    search.addEventListener("z-search-submit", searchSubmit);

    $.handleLinks(page);
    $.replaceViewport(page)
    $.hideLoader();
  };

  var renderTable = function(tbody_elem, reports) {
    var doc_types = {
      report: true,
      sql_query: true
    };

    reports.forEach(function(doc) {
      if (!doc_types[doc.type]) {
        return;
      }
      var url = getPathPrefixForDocType(doc.type) + doc.uuid;

      var tr = document.createElement("tr");
      tr.innerHTML =
          "" + $.escapeHTML(doc.name) + "	" +
          "" + $.escapeHTML(doc.type) + "	" +
          "" + DateUtil.printTimeAgo(doc.mtime) + "	";

      tbody_elem.appendChild(tr);
    });
  };

  var getPathPrefixForDocType = function(doctype) {
    switch (doctype) {
      case "report":
        return "/a/reports/";
      case "sql_query":
        return "/a/sql/";
    }
  };

  var searchAutocomplete = function(e) {
    var term = e.detail.value;
    var search_widget = this;

    searchDocuments(term, function(r) {
      var documents = JSON.parse(r.response).documents;
      var items = [];

      for (var i = 0; i < documents.length; i++) {
        if (i > 10) {
          break;
        }

        items.push({
          query: documents[i].name,
          data_value: documents[i].name});
      }

      search_widget.autocomplete(term, items);
    });
  };

  var searchSubmit = function(e) {
    console.log("search submit");
    var term = e.detail.value;
    var search_widget = this;

    searchDocuments(term, function(r) {
      console.log(r);
      var documents = JSON.parse(r.response).documents;
      console.log(documents);
      if (documents.length == 1) {
        var path;
        switch (documents[0].type) {
          case "sql_query":
            path = "/a/sql/" + documents[0].uuid;
            break;

          case "report":
            path = "/a/reports/" + documents[0].uuid;
            break;
        }

        var input = $("input", search_widget);
        input.value = "";
        input.blur();

        $.navigateTo(path);
        return;
      } else {
        //TODO navigate to search view?
      }
    });
  };

  var searchDocuments = function(term, callback) {
    $.httpGet("/api/v1/documents?search=" + term, function(r) {
      if (r.status == 200) {
        callback(r);
      }
    });
  };

  return {
    name: "datastore_queries",
    loadView: function(params) { load(params.path); },
    unloadView: function() {},
    handleNavigationChange: load
  };

})());
<commit_msg>queries list search view<commit_after>ZBase.registerView((function() {
  var load = function(url) {
    var qparams = {
      with_categories: true,
      type: "all",
      author: "all",
    };

    var owner_param = UrlUtil.getParamValue(url, "owner");
    if (owner_param) {
      qparams.owner = owner_param;
    }

    var author_param = UrlUtil.getParamValue(url, "author");
    if (author_param) {
      qparams.author = author_param;
    }

    var category_param = UrlUtil.getParamValue(url, "category");
    if (category_param) {
      qparams.category_prefix = category_param;
    }

    var pstatus_param = UrlUtil.getParamValue(url, "publishing_status");
    if (pstatus_param) {
      qparams.publishing_status = pstatus_param;
    }

    var search_param = UrlUtil.getParamValue(url, "q");
    if (search_param) {
      qparams.search = search_param;
    }

    $.showLoader();

    searchDocuments(qparams, function(r) {
      if (r.status == 200) {
        render(JSON.parse(r.response), qparams, url);
      } else {
        $.fatalError();
      }
    });
  };

  var searchDocuments = function(qparams, callback) {
    $.httpGet("/api/v1/documents?" + $.buildQueryString(qparams), callback);
  };

  var render = function(data, qparams, path) {
    var reports = data.documents;
    var categories = data.categories;

    var page = $.getTemplate(
        "views/datastore_queries",
        "zbase_datastore_queries_main_tpl");

    renderTable(
        page.querySelector(".zbase_datastore_queries tbody"),
        reports);

    $("z-dropdown.create_new_doc", page).addEventListener("change", function(e) {
      $.createNewDocument(this.getValue());
      this.setValue([]);
    });

    var search = $("z-search.search_queries", page);
    search.addEventListener("z-search-autocomplete", searchAutocomplete);
    search.addEventListener("z-search-submit", searchSubmit);

    if (qparams.search) {
      $("z-input", search).setAttribute("data-value", qparams.search);
      var query_bc = $("zbase-breadcrumbs .query_breadcrumb", page);
      query_bc.href = getSearchUrl(qparams.search);
      query_bc.innerHTML = "Search results for '" + qparams.search + "'";
    }

    $.handleLinks(page);
    $.replaceViewport(page)
    $.hideLoader();
  };

  var renderTable = function(tbody_elem, reports) {
    var doc_types = {
      report: true,
      sql_query: true
    };

    reports.forEach(function(doc) {
      if (!doc_types[doc.type]) {
        return;
      }
      var url = getPathPrefixForDocType(doc.type) + doc.uuid;

      var tr = document.createElement("tr");
      tr.innerHTML =
          "" + $.escapeHTML(doc.name) + "	" +
          "" + $.escapeHTML(doc.type) + "	" +
          "" + DateUtil.printTimeAgo(doc.mtime) + "	";

      tbody_elem.appendChild(tr);
    });

    $.handleLinks(tbody_elem);
  };

  var getPathPrefixForDocType = function(doctype) {
    switch (doctype) {
      case "report":
        return "/a/reports/";
      case "sql_query":
        return "/a/sql/";
    }
  };

  var searchAutocomplete = function(e) {
    var term = e.detail.value;
    var search_widget = this;

    searchDocuments({search: term}, function(r) {
      if (r.status == 200) {
        var documents = JSON.parse(r.response).documents;
        var items = [];

        for (var i = 0; i < documents.length; i++) {
          if (i > 10) {
            break;
          }

          items.push({
            query: documents[i].name,
            data_value: documents[i].name});
        }

        search_widget.autocomplete(term, items);
      }
    });
  };

  var searchSubmit = function(e) {
    var term = e.detail.value;
    var search_widget = this;

    searchDocuments({search: term}, function(r) {
      if (r.status == 200) {
        var documents = JSON.parse(r.response).documents;
        if (documents.length == 1) {
          var path;
          switch (documents[0].type) {
            case "sql_query":
              path = "/a/sql/" + documents[0].uuid;
              break;

            case "report":
              path = "/a/reports/" + documents[0].uuid;
              break;
          }

          var input = $("input", search_widget);
          input.value = "";
          input.blur();

          $.navigateTo(path);
          return;
        } else {
          $.navigateTo(getSearchUrl(term));
        }
      }
    });
  };

  var getSearchUrl = function(search_term) {
    var path = "/a/datastore/queries"
    if (search_term.length > 0) {
      path += "?q=" + search_term;
    }

    return path;
  };

  return {
    name: "datastore_queries",
    loadView: function(params) { load(params.path); },
    unloadView: function() {},
    handleNavigationChange: load
  };

})());
<|endoftext|>


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

var assert = require("assert"),
    xml2js = require("xml2js"),
    vows = require("vows"),
    Step = require("step"),
    _ = require("underscore"),
    querystring = require("querystring"),
    http = require("http"),
    httputil = require("./lib/http"),
    oauthutil = require("./lib/oauth"),
    xrdutil = require("./lib/xrd"),
    actutil = require("./lib/activity"),
    setupApp = oauthutil.setupApp;

var suite = vows.describe("webfinger endpoint test");

var webfinger = {
    links: [
        {
            rel: "http://webfinger.net/rel/profile-page",
            type: "text/html",
            href: "http://localhost:4815/alice"
        },
        {
            rel: "activity-inbox",
            href: "http://localhost:4815/api/user/alice/inbox"
        },
        {
            rel: "activity-outbox",
            href: "http://localhost:4815/api/user/alice/feed"
        },
        {
            rel: "dialback",
            href: "http://localhost:4815/api/dialback"
        }
    ]
};

// A batch to test endpoints

suite.addBatch({
    "When we set up the app": {
        topic: function() {
            setupApp(this.callback);
        },
        teardown: function(app) {
            if (app && app.close) {
                app.close();
            }
        },
        "it works": function(err, app) {
            assert.ifError(err);
        },
        "and we check the webfinger endpoint":
        httputil.endpoint("/.well-known/webfinger", ["GET"]),
         "and we get the webfinger endpoint with no uri":
        httputil.getfail("/.well-known/webfinger", 400),
        "and we get the webfinger endpoint with an empty uri":
        httputil.getfail("/.well-known/webfinger?resource=", 404),
        "and we get the webfinger endpoint with an HTTP URI at some other domain":
        httputil.getfail("/.well-known/webfinger?resource=http://photo.example/evan", 404),
        "and we get the webfinger endpoint with a Webfinger at some other domain":
        httputil.getfail("/.well-known/webfinger?resource=evan@photo.example", 404),
        "and we get the webfinger endpoint with a Webfinger of a non-existent user":
        httputil.getfail("/.well-known/webfinger?resource=evan@localhost", 404)
    }
});

suite.addBatch({
    "When we set up the app": {
        topic: function() {
            setupApp(this.callback);
        },
        teardown: function(app) {
            if (app && app.close) {
                app.close();
            }
        },
        "it works": function(err, app) {
            assert.ifError(err);
        },
        "and we register a client and user": {
            topic: function() {
                oauthutil.newCredentials("alice", "test+pass", this.callback);
            },
            "it works": function(err, cred) {
                assert.ifError(err);
            },
            "and we test the webfinger endpoint":
            xrdutil.jrdContext("http://localhost:4815/.well-known/webfinger?resource=alice@localhost",
                               webfinger),
            "and we test the webfinger endpoint with an acct: URI":
            xrdutil.jrdContext("http://localhost:4815/.well-known/webfinger?resource=acct:alice@localhost",
                               webfinger)
        }
    }
});

suite["export"](module);
<commit_msg>Test a group webfinger<commit_after>// webfinger.js
//
// Tests the Webfinger JRD endpoints
//
// Copyright 2012 E14N https://e14n.com/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

var assert = require("assert"),
    xml2js = require("xml2js"),
    vows = require("vows"),
    Step = require("step"),
    _ = require("underscore"),
    querystring = require("querystring"),
    http = require("http"),
    httputil = require("./lib/http"),
    oauthutil = require("./lib/oauth"),
    xrdutil = require("./lib/xrd"),
    actutil = require("./lib/activity"),
    pj = httputil.postJSON,
    gj = httputil.getJSON,
    validActivity = actutil.validActivity,
    setupApp = oauthutil.setupApp;

var suite = vows.describe("webfinger endpoint test");

var webfinger = {
    links: [
        {
            rel: "http://webfinger.net/rel/profile-page",
            type: "text/html",
            href: "http://localhost:4815/alice"
        },
        {
            rel: "activity-inbox",
            href: "http://localhost:4815/api/user/alice/inbox"
        },
        {
            rel: "activity-outbox",
            href: "http://localhost:4815/api/user/alice/feed"
        },
        {
            rel: "dialback",
            href: "http://localhost:4815/api/dialback"
        }
    ]
};

// A batch to test endpoints

suite.addBatch({
    "When we set up the app": {
        topic: function() {
            setupApp(this.callback);
        },
        teardown: function(app) {
            if (app && app.close) {
                app.close();
            }
        },
        "it works": function(err, app) {
            assert.ifError(err);
        },
        "and we check the webfinger endpoint":
        httputil.endpoint("/.well-known/webfinger", ["GET"]),
         "and we get the webfinger endpoint with no uri":
        httputil.getfail("/.well-known/webfinger", 400),
        "and we get the webfinger endpoint with an empty uri":
        httputil.getfail("/.well-known/webfinger?resource=", 404),
        "and we get the webfinger endpoint with an HTTP URI at some other domain":
        httputil.getfail("/.well-known/webfinger?resource=http://photo.example/evan", 404),
        "and we get the webfinger endpoint with a Webfinger at some other domain":
        httputil.getfail("/.well-known/webfinger?resource=evan@photo.example", 404),
        "and we get the webfinger endpoint with a Webfinger of a non-existent user":
        httputil.getfail("/.well-known/webfinger?resource=evan@localhost", 404)
    }
});

suite.addBatch({
    "When we set up the app": {
        topic: function() {
            setupApp(this.callback);
        },
        teardown: function(app) {
            if (app && app.close) {
                app.close();
            }
        },
        "it works": function(err, app) {
            assert.ifError(err);
        },
        "and we register a client and user": {
            topic: function() {
                oauthutil.newCredentials("alice", "test+pass", this.callback);
            },
            "it works": function(err, cred) {
                assert.ifError(err);
            },
            "and we test the webfinger endpoint":
            xrdutil.jrdContext("http://localhost:4815/.well-known/webfinger?resource=alice@localhost",
                               webfinger),
            "and we test the webfinger endpoint with an acct: URI":
            xrdutil.jrdContext("http://localhost:4815/.well-known/webfinger?resource=acct:alice@localhost",
                               webfinger),
            "and they create a group": {
                topic: function(cred) {
                    var url = "http://localhost:4815/api/user/alice/feed",
                        callback = this.callback,
                        act = {
                            verb: "create",
                            object: {
                                displayName: "Caterpillars",
                                objectType: "group"
                            }
                        };

                    pj(url, cred, act, function(err, body, resp) {
                        callback(err, body);
                    });
                },
                "it works": function(err, act) {
                    assert.ifError(err);
                    validActivity(act);
                },
                "and we test the webfinger endpoint with the group ID": {
                    topic: function(act, cred) {
                        var url = "http://localhost:4815/.well-known/webfinger?resource="+act.object.id,
                            callback = this.callback,
                            req;

                        req = http.request(url, function(res) {
                            var body = "";
                            res.setEncoding("utf8");
                            res.on("data", function(chunk) {
                                body = body + chunk;
                            });
                            res.on("error", function(err) {
                                callback(err, null);
                            });
                            res.on("end", function() {
                                var obj = JSON.parse(body);
                                callback(null, obj);
                            });
                        });

                        req.on("error", function(err) {
                            callback(err, null);
                        });

                        req.end();
                    },
                    "it works": function(err, obj) {
                        assert.ifError(err);
                        assert.isObject(obj);
                    }
                }
            }
        }
    }
});

suite["export"](module);
<|endoftext|>


<commit_before>function BufferLoader(context, soundList, callback) {
    this.context = context;
    this.soundList = soundList;
    this.onload = callback;
    this.bufferList = new Array();
    this.loadCount = 0;
}

// loadBuffer also loads sound metadata into the bufferList array.
BufferLoader.prototype.loadBuffer = function(sound, index) {
    // Load buffer asynchronously
    var request = new XMLHttpRequest();
    request.open("GET", sound.url, true);
    request.responseType = "arraybuffer";

    var loader = this;

    request.onload = function() {
    // Asynchronously decode the audio file data in request.response
    loader.context.decodeAudioData(
        request.response,
        function(buffer) {
        if (!buffer) {
            alert('error decoding file data: ' + url);
            return;
        }
        // buffer is the main purpose, but metadata offset and url are also part of the object.
        // thus bufferList is more the update of soundList.
        loader.bufferList.push({"buffer": buffer, "offset": Number(sound.offset), "url": sound.url});
        console.log('loaded buffer ' + index + ": " + sound.url);
        if (++loader.loadCount == loader.soundList.length)
            loader.onload(loader.bufferList);
        },
        function(error) {
            console.error('decodeAudioData error', error);
        }
    );
    }

    request.onerror = function() {
        alert('BufferLoader: XHR error');
    }

    request.send();
}

BufferLoader.prototype.load = function() {
    for (var i = 0; i < this.soundList.length; ++i) {
        this.loadBuffer(this.soundList[i], i);
    }
}

function AudioHandler(soundList, context, clock) {
    this.soundList = soundList;
    //this.source; //??
    this.context = context;
    this.totalDuration;
    this.clock = clock;
    this.playingSounds = new Array();
    this.WAAQueue = new Array();

    this.offset_global = 0; // needed as a member for pauseManager's use.

    this.totalDuration = 0;
    for (var i = 0; i < this.soundList.length; i++) {
        this.totalDuration += this.soundList[i].buffer.duration;
    }

    this.playing = false;
    this.recent_start = 0, this.recent_pause = 0;

    this.initialize_soundCreation();
    // cannot have this.player.playing because one-time assignment isn't practical for a dynamic variable
}

AudioHandler.prototype.initialize_soundCreation = function(callback) {
    this.soundList.sort(function(a, b) {
            return a.offset - b.offset;
    });

    for (var i = 0; i < this.soundList.length; i++) {
        this.soundList[i] = new Sound(i, this.soundList[i], this);
        // reconstruct soundList
        // need to initialize index (i) here for sound because BufferLoader's soundlist had to be sorted in main first.
    }

    this.handleClick();
}

AudioHandler.prototype.play_onClick = function(offset_global) { // offset format, specified in handleClick, is necessary to handle clicks on elements that overlap: element clicked can have later start time than the element that it overlaps.
    this.offset_global = offset_global;

    var soundList = this.soundList; // for convenience
    this.recent_start = this.context.currentTime;// + offset_global;
    var i; // first valid sound's index

    for (i = 0; i < soundList.length; i++) {
        soundList[i].player.render("ALL");
        if (soundList[i].offset + soundList[i].buffer.duration >= this.offset_global) break;
    } // aka first valid. start from here, but don't do anything yet.

    this.playing = true;
    // start by playing the first valid (first conditional passes for sure)
    for (i; i < soundList.length && this.playing; i++) {
        if (soundList[i].offset <= this.offset_global && soundList[i].buffer.duration + soundList[i].offset >= this.offset_global) {
            //console.log("playing " + i + ": " + soundList[i].url + " lies between " + soundList[i].offset + " and " + Number(soundList[i].buffer.duration + soundList[i].offset));
            soundList[i].play();
        }
        else {
            //console.log(soundList[i].url + " is the first to start after the clicked position. waiting to play it.")
            this.play_Chrono(i); //asynchronous
            break;
        }
    }
}

AudioHandler.prototype.play_Chrono = function(i) {
    var queued_event;
    var self = this; // again, not proper. unless i discover proper way to deal with anonymous func and context
    function recursivePlay(index) {
        queued_event = this.clock.callbackAtTime(function() {
                if (self.playing && index < self.soundList.length) {
                    self.soundList[index].play();
                    recursivePlay(++index);
                    return index;
                }
            }, Number(self.recent_start + self.soundList[index].offset - self.offset_global));
        self.WAAQueue.push(queued_event);
    }

    recursivePlay(i);
}

AudioHandler.prototype.pauseManager = function() {
    // happens upon click
    var self = this;
    var context = this.context;

    self.recent_pause = context.currentTime - self.recent_start + self.offset_global;
    self.playing = false;
    $(self.playingSounds).each(function(index, sound) {
        sound.pause();
    });
    self.playingSounds = [];

    $(self.WAAQueue).each(function(index, WAA_event) {
        WAA_event.clear();
    });
}

AudioHandler.prototype.handleClick = function() {
    var self = this; // for convenience of anonymous functions

    $(document).keyup(function(e) {
        if (e.keyCode === 32) {
            if (self.playing) self.pauseManager();
            else self.play_onClick(self.recent_pause);
        }
    });

    // control from middle of player.
    $(self.soundList).each(function(index, sound) {
        // the player clicked will callback the parameter.
        sound.player.handleClick(function(new_offset_global) {
            self.pauseManager();
            $(self.soundList).each(function(index, sound) {
                sound.player.resetWidth();
                //$(player.textProgress).html("");
            });
            window.setTimeout(function(){self.play_onClick(new_offset_global);}, 50);
        });
    });
}

function Sound(index, sound, parent) {
    this.index = index;

    this.buffer = sound.buffer;
    this.url = sound.url;
    this.offset = sound.offset;
    this.playing = false; // * USE!!!!
    this.parent = parent; // AudioHandler
    /*
        of importance:
        - totalDuration
        - recent_start
        - recent_pause
        - offset_global
     */
    this.player = new Player(this);
}

Sound.prototype.play = function() { // CAN I FREAKING GET RID OF THE SELF??? INHERITANCE FREAKING PROBLEMS WOW
    var playheadTime = this.parent.context.currentTime - this.parent.recent_start + this.parent.offset_global;
    if (playheadTime >= this.offset) playheadTime -= this.offset; // now turns into relative offset.
    //if (self.offset_global > sound.offset) relative_offset += self.offset_global - sound.offset;
    //else /*self.offset_global < sound.offset*/ relative_offset =
    //var relative_offset = self.offset_global + (self.context.currentTime - self.recent_start) - sound.offset;

    // call to refresh correct div, id'd by index.
    this.source = this.parent.context.createBufferSource();
    this.source.buffer = this.buffer;
    this.source.connect(this.parent.context.destination);

    this.source.start(0, playheadTime);
    this.playing = true;
    // console.log("playing " + sound.index + ": " + sound.url + " from " + playheadTime + " / " + sound.buffer.duration);

    this.parent.playingSounds.push(this);

    //console.log(playheadTime + "/" + sound.buffer.duration);

    this.player.render(playheadTime);

    // BAADDD
    var source = this.source;
    var sound = this;
    source.onended = (function() {
        //console.log('finished ' + sound.url + ": " + sound.index);
        source.stop();
        sound.playing = false;
    })

}

Sound.prototype.pause = function() {
    this.source.stop();
    this.playing = false;
}

function Player(parentSound) {
    //this.player.player, this.player.progress, this.player.textProgress;
    this.sound = parentSound; // of course, this.player.sound.buffer, etc, is available in Sound class but never used.

    this.initialize();
    this.movePlayhead();
}

var topOffset = 0;

Player.prototype.initialize = function() {
    // to incorporate Handlebars
    var scale = 1000;

    this.textProgress = document.createElement('div');
    $(this.textProgress).addClass('textProgress')
                .html("");

    this.progress = document.createElement('div');
    $(this.progress).addClass('progress');

    this.player = document.createElement('div');
    $(this.player).addClass('player')
        .width( (this.sound.buffer.duration / this.sound.parent.totalDuration) * scale)
        .css({
                'left': (this.sound.offset / this.sound.parent.totalDuration) * scale ,
                'top': topOffset
            })
        .data('id', "sound_" + this.index);

    $(this.player).append(this.progress);

    $(this.player).append(this.textProgress);

    topOffset += 65;

    $(this.player).appendTo($('.soundContainer'));

    // have yet to tidy up centering of all sound elements (after each add, adjust margins)

    this.overPlayer = document.createElement('div');
    $(this.overPlayer).addClass('overPlayer');
    $(this.player).append(this.overPlayer);

    // initialize playhead
    this.playhead = document.createElement('div');
    $(this.playhead).addClass('playhead');
    $(this.player).append(this.playhead);
}

Player.prototype.render = function(relative_offset) {
    // console.log("playhead at " + relative_offset);
    var time_startRender = this.sound.parent.context.currentTime; // window object.
    var self = this;
    //for animation
    function _render() {
        if (self.sound.playing) {
            var soundProgress = self.sound.parent.context.currentTime - time_startRender + relative_offset;
            var soundPercent = (soundProgress / self.sound.buffer.duration) * 100;

            $(self.progress).width(soundPercent + "%");

            //and refresh number text
            //$(player_self.player).children($('.textProgress')).html(soundProgress.toFixed(2) + " / " + sound.buffer.duration.toFixed() + " secs.");

            window.requestAnimationFrame(function() {
                _render();
            });
        }
        else {
            return;
        }
    }

    if (relative_offset === "ALL")
        $(this.progress).width("100%");
    else
        _render();
}

Player.prototype.resetWidth = function() {$(this.progress).width(0);}

Player.prototype.handleClick = function(callback) {
    var self = this;
    $(this.player).click(function(e) {
        var newXpos = (e.clientX - $(this).offset().left);
        var new_offset_global = (newXpos / $(this).width()) * self.sound.buffer.duration + self.sound.offset;

        callback(new_offset_global);
    });
}

Player.prototype.movePlayhead = function() {
    var playhead = this.playhead;

    $(this.overPlayer).mousemove(function(event) {
        $(playhead).css({'left':event.offsetX});
    });
}

window.onload = init;

var context, bufferloader, audioHandler, clock;

function init() {
  // Fix up prefixing
    window.AudioContext = window.AudioContext || window.webkitAudioContext;

    context = new AudioContext();
    clock = new WAAClock(context);
    bufferloader = new BufferLoader(
        context,
        [
            {"url": "/../sample_songs/tsi.mp3", "offset": 0},
            {"url": "/../sample_songs/pakabaka.mp3", "offset": 4},
            {"url": "/../sample_songs/mmmmm.mp3", "offset": 9}
        ],
        finishedLoading
        );

    bufferloader.load();

    function finishedLoading(retrieved_soundList) {
        clock.start();
        var soundList = retrieved_soundList;

        audioHandler = new AudioHandler(soundList, context, clock);
    }
}<commit_msg>rough abstraction of createSound, for testing of new sound organization model<commit_after>function BufferLoader(context, soundList, callback) {
    this.context = context;
    this.soundList = soundList;
    this.onload = callback;
    this.bufferList = new Array();
    this.loadCount = 0;
}

// loadBuffer also loads sound metadata into the bufferList array.
BufferLoader.prototype.loadBuffer = function(sound, index) {
    // Load buffer asynchronously
    var request = new XMLHttpRequest();
    request.open("GET", sound.url, true);
    request.responseType = "arraybuffer";

    var loader = this;

    request.onload = function() {
    // Asynchronously decode the audio file data in request.response
    loader.context.decodeAudioData(
        request.response,
        function(buffer) {
        if (!buffer) {
            alert('error decoding file data: ' + url);
            return;
        }
        // buffer is the main purpose, but metadata offset and url are also part of the object.
        // thus bufferList is more the update of soundList.
        loader.bufferList.push({"buffer": buffer, "offset": Number(sound.offset), "url": sound.url});
        console.log('loaded buffer ' + index + ": " + sound.url);
        if (++loader.loadCount == loader.soundList.length)
            loader.onload(loader.bufferList);
        },
        function(error) {
            console.error('decodeAudioData error', error);
        }
    );
    }

    request.onerror = function() {
        alert('BufferLoader: XHR error');
    }

    request.send();
}

BufferLoader.prototype.load = function() {
    for (var i = 0; i < this.soundList.length; ++i) {
        this.loadBuffer(this.soundList[i], i);
    }
}

function AudioHandler(soundList, context, clock) {
    this.soundList = soundList;
    //this.source; //??
    this.context = context;
    this.totalDuration;
    this.clock = clock;
    this.playingSounds = new Array();
    this.WAAQueue = new Array();

    this.offset_global = 0; // needed as a member for pauseManager's use.

    // intialize totalDuration
    this.totalDuration = 0;
    for (var i = 0; i < this.soundList.length; i++) {
        this.totalDuration += this.soundList[i].buffer.duration;
    }

    this.playing = false;
    this.recent_start = 0, this.recent_pause = 0;

    // initialize soundList (including initial sort by offset)
    // by converting the format of soundList (swap).
    // TO IMPROVE: partition-based conversion.
    this.temp = new Array();
    for (var i = 0; i < this.soundList.length; i++) {
        //this.soundList[i] = new Sound(i, this.soundList[i], this);
        this.temp.push(new Sound(this.soundList[i], this));
        // reconstruct soundList
        // need to initialize index (i) here for sound because BufferLoader's soundlist had to be sorted in main first.
    }
    this.soundList = this.temp;
    this.soundList.sort(function(a, b) {
            return a.offset - b.offset;
    });

    this.handleClick();
}

AudioHandler.prototype.createSound = function(sound) {
    this.soundList.push(new Sound(this.soundList[i], this));
    this.soundList.sort(function(a, b) {
            return a.offset - b.offset;
    });
}

AudioHandler.prototype.play_onClick = function(offset_global) { // offset format, specified in handleClick, is necessary to handle clicks on elements that overlap: element clicked can have later start time than the element that it overlaps.
    this.offset_global = offset_global;

    var soundList = this.soundList; // for convenience
    this.recent_start = this.context.currentTime;// + offset_global;
    var i; // first valid sound's index

    for (i = 0; i < soundList.length; i++) {
        soundList[i].player.render("ALL");
        if (soundList[i].offset + soundList[i].buffer.duration >= this.offset_global) break;
    } // aka first valid. start from here, but don't do anything yet.

    this.playing = true;
    // start by playing the first valid (first conditional passes for sure)
    for (i; i < soundList.length && this.playing; i++) {
        if (soundList[i].offset <= this.offset_global && soundList[i].buffer.duration + soundList[i].offset >= this.offset_global) {
            //console.log("playing " + i + ": " + soundList[i].url + " lies between " + soundList[i].offset + " and " + Number(soundList[i].buffer.duration + soundList[i].offset));
            soundList[i].play();
        }
        else {
            //console.log(soundList[i].url + " is the first to start after the clicked position. waiting to play it.")
            this.play_Chrono(i); //asynchronous
            break;
        }
    }
}

AudioHandler.prototype.play_Chrono = function(i) {
    var queued_event;
    var self = this; // again, not proper. unless i discover proper way to deal with anonymous func and context
    function recursivePlay(index) {
        queued_event = this.clock.callbackAtTime(function() {
                if (self.playing && index < self.soundList.length) {
                    self.soundList[index].play();
                    recursivePlay(++index);
                    return index;
                }
            }, Number(self.recent_start + self.soundList[index].offset - self.offset_global));
        self.WAAQueue.push(queued_event);
    }

    recursivePlay(i);
}

AudioHandler.prototype.pauseManager = function() {
    // happens upon click
    var self = this;
    var context = this.context;

    self.recent_pause = context.currentTime - self.recent_start + self.offset_global;
    self.playing = false;
    $(self.playingSounds).each(function(index, sound) {
        sound.pause();
    });
    self.playingSounds = [];

    $(self.WAAQueue).each(function(index, WAA_event) {
        WAA_event.clear();
    });
}

AudioHandler.prototype.handleClick = function() {
    var self = this; // for convenience of anonymous functions

    $(document).keyup(function(e) {
        if (e.keyCode === 32) {
            if (self.playing) self.pauseManager();
            else self.play_onClick(self.recent_pause);
        }
    });

    // control from middle of player.
    $(self.soundList).each(function(index, sound) {
        // the player clicked will callback the parameter.
        sound.player.handleClick(function(new_offset_global) {
            self.pauseManager();
            $(self.soundList).each(function(index, sound) {
                sound.player.resetWidth();
                //$(player.textProgress).html("");
            });
            window.setTimeout(function(){self.play_onClick(new_offset_global);}, 50);
        });
    });
}

function Sound(sound, parent) {

    this.buffer = sound.buffer;
    this.url = sound.url;
    this.offset = sound.offset;
    this.playing = false; // * USE!!!!
    this.parent = parent; // AudioHandler
    /*
        of importance:
        - totalDuration
        - recent_start
        - recent_pause
        - offset_global
     */
    this.player = new Player(this);
}

Sound.prototype.play = function() { // CAN I FREAKING GET RID OF THE SELF??? INHERITANCE FREAKING PROBLEMS WOW
    var playheadTime = this.parent.context.currentTime - this.parent.recent_start + this.parent.offset_global;
    if (playheadTime >= this.offset) playheadTime -= this.offset; // now turns into relative offset.
    //if (self.offset_global > sound.offset) relative_offset += self.offset_global - sound.offset;
    //else /*self.offset_global < sound.offset*/ relative_offset =
    //var relative_offset = self.offset_global + (self.context.currentTime - self.recent_start) - sound.offset;

    // call to refresh correct div, id'd by index.
    this.source = this.parent.context.createBufferSource();
    this.source.buffer = this.buffer;
    this.source.connect(this.parent.context.destination);

    this.source.start(0, playheadTime);
    this.playing = true;
    // console.log("playing " + sound.index + ": " + sound.url + " from " + playheadTime + " / " + sound.buffer.duration);

    this.parent.playingSounds.push(this);

    //console.log(playheadTime + "/" + sound.buffer.duration);

    this.player.render(playheadTime);

    // BAADDD
    var source = this.source;
    var sound = this;
    source.onended = (function() {
        //console.log('finished ' + sound.url + ": " + sound.index);
        source.stop();
        sound.playing = false;
    })

}

Sound.prototype.pause = function() {
    this.source.stop();
    this.playing = false;
}

function Player(parentSound) {
    //this.player.player, this.player.progress, this.player.textProgress;
    this.sound = parentSound; // of course, this.player.sound.buffer, etc, is available in Sound class but never used.

    this.initialize();
    this.movePlayhead();
}

var topOffset = 0;

Player.prototype.initialize = function() {
    // to incorporate Handlebars
    var scale = 1000;

    this.textProgress = document.createElement('div');
    $(this.textProgress).addClass('textProgress')
                .html("");

    this.progress = document.createElement('div');
    $(this.progress).addClass('progress');

    this.player = document.createElement('div');
    $(this.player).addClass('player')
        .width( (this.sound.buffer.duration / this.sound.parent.totalDuration) * scale)
        .css({
                'left': (this.sound.offset / this.sound.parent.totalDuration) * scale ,
                'top': topOffset
            });

    $(this.player).append(this.progress);

    $(this.player).append(this.textProgress);

    topOffset += 65;

    $(this.player).appendTo($('.soundContainer'));

    // have yet to tidy up centering of all sound elements (after each add, adjust margins)

    this.overPlayer = document.createElement('div');
    $(this.overPlayer).addClass('overPlayer');
    $(this.player).append(this.overPlayer);

    // initialize playhead
    this.playhead = document.createElement('div');
    $(this.playhead).addClass('playhead');
    $(this.player).append(this.playhead);
}

Player.prototype.render = function(relative_offset) {
    // console.log("playhead at " + relative_offset);
    var time_startRender = this.sound.parent.context.currentTime; // window object.
    var self = this;
    //for animation
    function _render() {
        if (self.sound.playing) {
            var soundProgress = self.sound.parent.context.currentTime - time_startRender + relative_offset;
            var soundPercent = (soundProgress / self.sound.buffer.duration) * 100;

            $(self.progress).width(soundPercent + "%");

            //and refresh number text
            //$(player_self.player).children($('.textProgress')).html(soundProgress.toFixed(2) + " / " + sound.buffer.duration.toFixed() + " secs.");

            window.requestAnimationFrame(function() {
                _render();
            });
        }
        else {
            return;
        }
    }

    if (relative_offset === "ALL")
        $(this.progress).width("100%");
    else
        _render();
}

Player.prototype.resetWidth = function() {$(this.progress).width(0);}

Player.prototype.handleClick = function(callback) {
    var self = this;
    $(this.player).click(function(e) {
        var newXpos = (e.clientX - $(this).offset().left);
        var new_offset_global = (newXpos / $(this).width()) * self.sound.buffer.duration + self.sound.offset;

        callback(new_offset_global);
    });
}

Player.prototype.movePlayhead = function() {
    var playhead = this.playhead;

    $(this.overPlayer).mousemove(function(event) {
        $(playhead).css({'left':event.offsetX});
    });
}

window.onload = init;

var context, bufferloader, audioHandler, clock;

function init() {
  // Fix up prefixing
    window.AudioContext = window.AudioContext || window.webkitAudioContext;

    context = new AudioContext();
    clock = new WAAClock(context);
    bufferloader = new BufferLoader(
        context,
        [
            {"url": "/../sample_songs/tsi.mp3", "offset": 0},
            {"url": "/../sample_songs/pakabaka.mp3", "offset": 4},
            {"url": "/../sample_songs/mmmmm.mp3", "offset": 9}
        ],
        finishedLoading
        );

    bufferloader.load();

    function finishedLoading(retrieved_soundList) {
        clock.start();
        var soundList = retrieved_soundList;

        audioHandler = new AudioHandler(soundList, context, clock);
    }
}<|endoftext|>


<commit_before>/*
 * Provides a medium implementation of a computer agent for Starfighter Squadrons.
 */
define([ "Maneuver", "PlanningAction", "Position", "RangeRuler", "ShipBase", "SimpleAgent" ], function(Maneuver,
        PlanningAction, Position, RangeRuler, ShipBase, SimpleAgent)
{
    function MediumAgent(name, team, squadBuilder)
    {
        InputValidator.validateNotEmpty("name", name);
        InputValidator.validateNotNull("team", team);
        InputValidator.validateNotNull("squadBuilder", squadBuilder);

        this.getName = function()
        {
            return name;
        }

        this.getSquadBuilder = function()
        {
            return squadBuilder;
        }

        this.getTeam = function()
        {
            return team;
        }
    }

    MediumAgent.prototype = Object.create(SimpleAgent.prototype);

    /*
     * @param environment Environment.
     *
     * @param adjudicator Adjudicator.
     *
     * @return a new action.
     */
    MediumAgent.prototype.getPlanningAction = function(environment, adjudicator, callback)
    {
        InputValidator.validateNotNull("environment", environment);
        InputValidator.validateNotNull("adjudicator", adjudicator);
        InputValidator.validateNotNull("callback", callback);

        var team = this.getTeam();
        var tokens = environment.getTokensForTeam(team);
        var defenders = environment.getDefenders(team);
        var tokenToManeuver = {};

        tokens.forEach(function(token)
        {
            var fromPosition = environment.getPositionFor(token);
            var shipBase = token.getShipBase();
            var maneuvers = token.getManeuvers();
            LOGGER.trace("maneuvers.length = " + maneuvers.length + " for " + token);

            // Find the maneuvers which keep the ship on the battlefield.
            var validManeuvers = [];

            // Find the maneuvers which take the ship within range of a defender.
            var validManeuversR1 = [];
            var validManeuversR2 = [];
            var validManeuversR3 = [];

            maneuvers.forEach(function(maneuver)
            {
                var toPosition = Maneuver.computeToPosition(maneuver, fromPosition, shipBase);

                if (toPosition
                        && Position.isPathInPlayArea(Maneuver.computePolygon(shipBase, toPosition.getX(), toPosition
                                .getY(), toPosition.getHeading())))
                {
                    validManeuvers.push(maneuver);
                    var weapon = token.getPrimaryWeapon();

                    for (var i = 0; i < defenders.length; i++)
                    {
                        var defender = defenders[i];
                        var defenderPosition = environment.getPositionFor(defender);

                        if (weapon.isDefenderTargetable(token, toPosition, defender, defenderPosition))
                        {
                            var range = RangeRuler.getRange(token, toPosition, defender, defenderPosition);

                            if (range === Range.ONE)
                            {
                                validManeuversR1.push(maneuver);
                            }
                            else if (range === Range.TWO)
                            {
                                validManeuversR2.push(maneuver);
                            }
                            else if (range === Range.THREE)
                            {
                                validManeuversR3.push(maneuver);
                            }
                        }
                    }
                }
            });

            LOGGER.trace("validManeuversR1.length = " + validManeuversR1.length + " for " + token);

            var maneuver = validManeuversR1.vizziniRandomElement();

            if (!maneuver)
            {
                LOGGER.trace("validManeuversR2.length = " + validManeuversR2.length + " for " + token);
                maneuver = validManeuversR2.vizziniRandomElement();
            }

            if (!maneuver)
            {
                LOGGER.trace("validManeuversR3.length = " + validManeuversR3.length + " for " + token);
                maneuver = validManeuversR3.vizziniRandomElement();
            }

            if (!maneuver)
            {
                LOGGER.trace("validManeuvers.length = " + validManeuvers.length + " for " + token);
                maneuver = validManeuvers.vizziniRandomElement();
            }

            LOGGER.trace("0 maneuver = " + maneuver + " for " + token);

            if (!maneuver)
            {
                // Ship fled the battlefield.
                maneuver = maneuvers.vizziniRandomElement();
                LOGGER.trace("1 maneuver = " + maneuver + " for " + token);
            }

            tokenToManeuver[token] = maneuver;
        });

        var answer = new PlanningAction(environment, this, tokenToManeuver);

        callback(answer);
    }

    MediumAgent.prototype.toString = function()
    {
        return this.getName() + ", MediumAgent, " + this.getTeam() + ", " + this.getSquadBuilder().getName();
    }

    return MediumAgent;
});
<commit_msg>Changed to pick the maneuver which gets closest to a defender.<commit_after>/*
 * Provides a medium implementation of a computer agent for Starfighter Squadrons.
 */
define([ "Maneuver", "PlanningAction", "Position", "RangeRuler", "ShipBase", "SimpleAgent" ], function(Maneuver,
        PlanningAction, Position, RangeRuler, ShipBase, SimpleAgent)
{
    function MediumAgent(name, team, squadBuilder)
    {
        InputValidator.validateNotEmpty("name", name);
        InputValidator.validateNotNull("team", team);
        InputValidator.validateNotNull("squadBuilder", squadBuilder);

        this.getName = function()
        {
            return name;
        }

        this.getSquadBuilder = function()
        {
            return squadBuilder;
        }

        this.getTeam = function()
        {
            return team;
        }
    }

    MediumAgent.prototype = Object.create(SimpleAgent.prototype);

    /*
     * @param environment Environment.
     *
     * @param adjudicator Adjudicator.
     *
     * @return a new action.
     */
    MediumAgent.prototype.getPlanningAction = function(environment, adjudicator, callback)
    {
        InputValidator.validateNotNull("environment", environment);
        InputValidator.validateNotNull("adjudicator", adjudicator);
        InputValidator.validateNotNull("callback", callback);

        var team = this.getTeam();
        var tokens = environment.getTokensForTeam(team);
        var defenders = environment.getDefenders(team);
        var tokenToManeuver = {};

        tokens.forEach(function(token)
        {
            var fromPosition = environment.getPositionFor(token);
            var shipBase = token.getShipBase();
            var maneuvers = token.getManeuvers();
            LOGGER.trace("maneuvers.length = " + maneuvers.length + " for " + token);

            // Find the maneuvers which keep the ship on the battlefield.
            var validManeuvers = [];
            var closestManeuver;
            var minDistance;

            // Find the maneuvers which take the ship within range of a defender.
            var validManeuversR1 = [];
            var validManeuversR2 = [];
            var validManeuversR3 = [];

            maneuvers.forEach(function(maneuver)
            {
                var toPosition = Maneuver.computeToPosition(maneuver, fromPosition, shipBase);

                if (toPosition
                        && Position.isPathInPlayArea(Maneuver.computePolygon(shipBase, toPosition.getX(), toPosition
                                .getY(), toPosition.getHeading())))
                {
                    validManeuvers.push(maneuver);
                    var weapon = token.getPrimaryWeapon();

                    for (var i = 0; i < defenders.length; i++)
                    {
                        var defender = defenders[i];
                        var defenderPosition = environment.getPositionFor(defender);

                        // Save the maneuver which has the minimum distance.
                        var distance = toPosition.computeDistance(defenderPosition);

                        if (!minDistance || distance < minDistance)
                        {
                            closestManeuver = maneuver;
                            minDistance = distance;
                        }

                        if (weapon.isDefenderTargetable(token, toPosition, defender, defenderPosition))
                        {
                            var range = RangeRuler.getRange(token, toPosition, defender, defenderPosition);

                            if (range === Range.ONE)
                            {
                                validManeuversR1.push(maneuver);
                            }
                            else if (range === Range.TWO)
                            {
                                validManeuversR2.push(maneuver);
                            }
                            else if (range === Range.THREE)
                            {
                                validManeuversR3.push(maneuver);
                            }
                        }
                    }
                }
            });

            LOGGER.trace("validManeuversR1.length = " + validManeuversR1.length + " for " + token);

            var maneuver = validManeuversR1.vizziniRandomElement();

            if (!maneuver)
            {
                LOGGER.trace("validManeuversR2.length = " + validManeuversR2.length + " for " + token);
                maneuver = validManeuversR2.vizziniRandomElement();
            }

            if (!maneuver)
            {
                LOGGER.trace("validManeuversR3.length = " + validManeuversR3.length + " for " + token);
                maneuver = validManeuversR3.vizziniRandomElement();
            }

            if (!maneuver && closestManeuver)
            {
                LOGGER.trace("closestManeuver = " + closestManeuver + " for " + token);
                maneuver = closestManeuver;
            }

            if (!maneuver)
            {
                LOGGER.trace("validManeuvers.length = " + validManeuvers.length + " for " + token);
                maneuver = validManeuvers.vizziniRandomElement();
            }

            LOGGER.trace("0 maneuver = " + maneuver + " for " + token);

            if (!maneuver)
            {
                // Ship fled the battlefield.
                maneuver = maneuvers.vizziniRandomElement();
                LOGGER.trace("1 maneuver = " + maneuver + " for " + token);
            }

            tokenToManeuver[token] = maneuver;
        });

        var answer = new PlanningAction(environment, this, tokenToManeuver);

        callback(answer);
    }

    MediumAgent.prototype.toString = function()
    {
        return this.getName() + ", MediumAgent, " + this.getTeam() + ", " + this.getSquadBuilder().getName();
    }

    return MediumAgent;
});
<|endoftext|>


<commit_before>/* @flow */
import React, { PureComponent } from 'react';

import connectWithActions from '../connectWithActions';
import {
  isHomeNarrow,
  isPrivateNarrow,
  isGroupNarrow,
  isSpecialNarrow,
  isStreamNarrow,
  isTopicNarrow,
} from '../utils/narrow';
import { getSession } from '../selectors';

import type { Message, Narrow } from '../types';
import TitleHome from './TitleHome';
import TitlePrivate from './TitlePrivate';
import TitleGroup from './TitleGroup';
import TitleSpecial from './TitleSpecial';
import TitleStream from './TitleStream';
import TitlePlain from './TitlePlain';

const titles = [
  { isFunc: isHomeNarrow, component: TitleHome },
  { isFunc: isSpecialNarrow, component: TitleSpecial },
  { isFunc: isStreamNarrow, component: TitleStream },
  { isFunc: isTopicNarrow, component: TitleStream },
  { isFunc: isPrivateNarrow, component: TitlePrivate },
  { isFunc: isGroupNarrow, component: TitleGroup },
];

type Props = {
  narrow: Narrow,
  editMessage: Message,
  color: string,
};

class Title extends PureComponent<Props> {
  props: Props;

  render() {
    const { narrow, editMessage, color } = this.props;

    if (editMessage != null) {
      return <TitlePlain text="Edit message" color={color} />;
    }

    const titleType = narrow && titles.find(x => x.isFunc(narrow));

    if (!titleType) {
      return null;
    }

    return <titleType.component color={color} narrow={narrow} />;
  }
}

export default connectWithActions(state => ({
  editMessage: getSession(state).editMessage,
}))(Title);
<commit_msg>title: Use standard Redux Dispatch.<commit_after>/* @flow */
import { connect } from 'react-redux';

import React, { PureComponent } from 'react';

import {
  isHomeNarrow,
  isPrivateNarrow,
  isGroupNarrow,
  isSpecialNarrow,
  isStreamNarrow,
  isTopicNarrow,
} from '../utils/narrow';
import { getSession } from '../selectors';

import type { Message, Narrow } from '../types';
import TitleHome from './TitleHome';
import TitlePrivate from './TitlePrivate';
import TitleGroup from './TitleGroup';
import TitleSpecial from './TitleSpecial';
import TitleStream from './TitleStream';
import TitlePlain from './TitlePlain';

const titles = [
  { isFunc: isHomeNarrow, component: TitleHome },
  { isFunc: isSpecialNarrow, component: TitleSpecial },
  { isFunc: isStreamNarrow, component: TitleStream },
  { isFunc: isTopicNarrow, component: TitleStream },
  { isFunc: isPrivateNarrow, component: TitlePrivate },
  { isFunc: isGroupNarrow, component: TitleGroup },
];

type Props = {
  narrow: Narrow,
  editMessage: Message,
  color: string,
};

class Title extends PureComponent<Props> {
  props: Props;

  render() {
    const { narrow, editMessage, color } = this.props;

    if (editMessage != null) {
      return <TitlePlain text="Edit message" color={color} />;
    }

    const titleType = narrow && titles.find(x => x.isFunc(narrow));

    if (!titleType) {
      return null;
    }

    return <titleType.component color={color} narrow={narrow} />;
  }
}

export default connect(state => ({
  editMessage: getSession(state).editMessage,
}))(Title);
<|endoftext|>


<commit_before>import chai from 'chai'
var assert = chai.assert

import * as simulator from '../lib/metis/simulator.js'
import * as reproduction from '../lib/metis/operators/reproduction.js'
import * as utils from './test_utils.js'

describe('Basic simulation', () => {
    it('No Ops simulation', () => {
        let individuals = utils.generate_n_basic_individuals(10)
        let orig_individuals = individuals.slice()
        let state = {
            individuals, operators: [],
            cycle: 0,
            global_parameters: {}
        }
        simulator.cycle(state)
        assert.equal(state.cycle, 1)
        assert.equal(state.individuals.length, orig_individuals.length)
    })
    it('Reproduction simulation', () => {
        let size = 10
        let rep_size = 20
        let individuals = utils.generate_n_basic_individuals(size)
        let operators = [new reproduction.NoGenomeSexualReproduction(
            utils.empty_species, rep_size)]
        let state = {
            individuals, operators,
            cycle: 0,
            global_parameters: {}
        }
        simulator.cycle(state)
        assert.equal(state.individuals.length, size + rep_size)
    })
})

describe('Several Cycles', () => {
    it('do_n_cycles - no ops', () => {
        let individuals = utils.generate_n_basic_individuals(10)
        let orig_individuals = individuals.slice()
        let state = simulator.do_n_cycles(2, individuals, [])
        assert.equal(state.cycle, 3)
        assert.equal(state.individuals.length, orig_individuals.length)
    })
})

describe('Async', () => {
    it('do_n_cycles - async', (done) => {
        let individuals = utils.generate_n_basic_individuals(10)
        let orig_individuals = individuals.slice()
        let reporter = (state, callback) => {
            if (callback) {
                callback()
            }
            else {
                assert.equal(state.cycle, 3)
                assert.equal(state.individuals.length, orig_individuals.length)
                done()
            }
        }
        let state = simulator.do_n_cycles(2, individuals, [], 0, reporter)
    })
})
<commit_msg>modules test: simulator<commit_after>const chai = require('chai')
const assert = chai.assert

const all = require('../../lib/metis/all.js')
const utlis = require('./test_utils.js')

describe('Basic simulation', () => {
    it('No Ops simulation', () => {
        let individuals = utils.generate_n_basic_individuals(10)
        let orig_individuals = individuals.slice()
        let state = {
            individuals, operators: [],
            cycle: 0,
            global_parameters: {}
        }
        all.sim_cycle(state)
        assert.equal(state.cycle, 1)
        assert.equal(state.individuals.length, orig_individuals.length)
    })
    it('Reproduction simulation', () => {
        let size = 10
        let rep_size = 20
        let individuals = utils.generate_n_basic_individuals(size)
        let operators = [new reproduction.NoGenomeSexualReproduction(
            utils.empty_species, rep_size)]
        let state = {
            individuals, operators,
            cycle: 0,
            global_parameters: {}
        }
        all.sim_cycle(state)
        assert.equal(state.individuals.length, size + rep_size)
    })
})

describe('Several Cycles', () => {
    it('do_n_cycles - no ops', () => {
        let individuals = utils.generate_n_basic_individuals(10)
        let orig_individuals = individuals.slice()
        let state = all.sim_do_n_cycles(2, individuals, [])
        assert.equal(state.cycle, 3)
        assert.equal(state.individuals.length, orig_individuals.length)
    })
})

describe('Async', () => {
    it('do_n_cycles - async', (done) => {
        let individuals = utils.generate_n_basic_individuals(10)
        let orig_individuals = individuals.slice()
        let reporter = (state, callback) => {
            if (callback) {
                callback()
            }
            else {
                assert.equal(state.cycle, 3)
                assert.equal(state.individuals.length, orig_individuals.length)
                done()
            }
        }
        let state = all.sim_do_n_cycles(2, individuals, [], 0, reporter)
    })
})
<|endoftext|>