<commit_before>// Transforms a stream of TAP into a stream of result objects
// and string comments.  Emits "results" event with summary.
var Writable = require('stream').Writable
var yaml = require('js-yaml')
var util = require('util')

util.inherits(Consumer, Writable)

module.exports = Consumer

function Consumer (options) {
  options = options || {}
  this.indent = options.indent || ''
  this.level = options.level || 0
  Writable.call(this, { objectMode: true })
  this.buffer = ''
  this.bailedOut = false
  this.ending = false
  this.plan = -1
  this.yamlish = ''
  this.yind = ''
  this.child = null
  this.current = null

  this.count = 0
  this.pass = 0
  this.fail = 0
  this.todo = 0
  this.skip = 0
  this.ok = true

  this.postPlan = false
  this.bailedOut = false

  if (options.debug)
    this.debug = debug
}

Consumer.prototype.processYamlish = function () {
  var yamlish = this.yamlish
  this.yamlish = ''
  this.yind = ''

  if (!this.current) {
    this.emit('garbage', yamlish)
    return
  }

  try {
    var diags = yaml.safeLoad(yamlish)
  } catch (er) {
    this.emit('garbage', yamlish)
    return
  }

  this.current.diag = diags
  this.emitResult()
}

Consumer.prototype.debug = function () {}

function debug () {
  var m = util.format.apply(util, arguments)
  console.error(this.indent + m)
}

Consumer.prototype.write = function (chunk, encoding, cb) {
  if (typeof encoding === 'string' && encoding !== 'utf8')
    chunk = new Buffer(chunk, encoding)

  if (Buffer.isBuffer(chunk))
    chunk += ''

  if (typeof encoding === 'function') {
    cb = encoding
    encoding = null
  }

  if (this.bailedOut) {
    if (cb)
      process.nextTick(cb)
    return true
  }

  this.buffer += chunk
  do {
    var match = this.buffer.match(/^.*\r?\n/)
    if (!match || this.bailedOut)
      break

    this.buffer = this.buffer.substr(match[0].length)
    this._parse(match[0])
  } while (this.buffer.length)

  if (cb)
    process.nextTick(cb)
  return true
}

Consumer.prototype.end = function (chunk, encoding, cb) {
  if (chunk) {
    if (typeof encoding === 'function') {
      cb = encoding
      encoding = null
    }
    this.write(chunk, encoding)
  }

  this.ending = true
  if (this.buffer)
    this.write('\n')

  // if we have yamlish, means we didn't finish with a ...
  if (this.yamlish)
    this.emit('garbage', this.yamlish)

  this.emitResult()

  if (this.count !== this.plan)
    this.ok = false

  var final = {
    plan: this.plan,
    count: this.count,
    pass: this.pass,
    ok: this.ok
  }

  if (this.fail)
    final.fail = this.fail

  if (this.bailedOut)
    final.bailout = true

  if (this.todo)
    final.todo = this.todo

  if (this.skip)
    final.skip = this.skip

  this.emit('complete', final)

  Writable.prototype.end.call(this, null, null, cb)
}

Consumer.prototype.bailout = function (reason) {
  this.bailedOut = true
  this.ok = false
  this.emit('bailout', reason)
}

Consumer.prototype.emitResult = function () {
  if (this.child) {
    this.child.end()
    this.child = null
  }

  this.yamlish = ''
  this.yind = ''

  if (!this.current)
    return

  var res = this.current
  this.current = null

  this.count++
  if (res.ok) {
    this.pass++
  } else {
    this.fail++
    if (!res.todo)
      this.ok = false
  }
  if (res.skip)
    this.skip++
  if (res.todo)
    this.todo++

  this.emit('result', res)
}

Consumer.prototype.startChild = function (indent, line) {
  this.emitResult()

  this.child = new Consumer({
    indent: indent,
    parent: this,
    level: this.level + 1
  })

  this.emit('child', this.child)
  this.child.on('bailout', this.bailout.bind(this))
  var self = this
  this.child.on('complete', function (results) {
    if (!results.ok)
      self.ok = false
  })
  this.child.write(line.substr(indent.length))
}

Consumer.prototype._parse = function (line) {
  this.debug('      > %j', line)

  // normalize line endings
  line = line.replace(/\r\n$/, '\n')

  // ignore empty lines
  if (line === '\n')
    return

  // After a bailout, everything is ignored
  if (this.bailedOut)
    return

  // comment
  if (line.match(/^\s*#/)) {
    this.emit('comment', line)
    return
  }

  var bailout = line.match(/^bail out!(.*)\n$/i)
  if (bailout) {
    var reason = bailout[1].trim()
    this.bailout(reason)
    return
  }

  // If version is specified, must be at the very beginning.
  var version = line.match(/^TAP Version ([0-9]+)\n$/i)
  if (version) {
    if (this.plan === -1 && this.count === 0)
      this.emit('version', version[1])
    else
      this.emit('garbage', line)
    return
  }

  // if we got a plan at the end, or a 1..0 plan, then we can't
  // have any more results, yamlish, or child sets.
  if (this.postPlan) {
    this.emit('garbage', line)
    return
  }

  // still belongs to the child.
  if (this.child && line.indexOf(this.child.indent) === 0) {
    line = line.substr(this.child.indent.length)
    this.debug('child line %j', line)
    this.child.write(line)
    return
  }

  var indent = line.match(/^[ \t]+/)
  if (indent) {
    indent = indent[0]

    this.debug('indent %j', indent)

    // if we don't have a current res, then it can't be yamlish,
    // must be a child result set
    if (!this.current) {
      this.debug('no current, start child', line)
      this.startChild(indent, line)
      return
    }

    // if we are not currently processing yamlish, then it has to
    // be either the start of a child, or the start of yamlish.
    if (!this.yind) {
      this.debug('no yind yet')
      // either this starts yamlish, or it is a child.
      if (line === indent + '---\n') {
        this.debug('yamlish start %j', line)
        this.yind = indent
      } else {
        this.debug('not yamlish start %j', line)
        this.startChild(indent, line)
      }
      return
    }

    // now we know it is yamlish

    // if it's not as indented, then it's broken.
    // The whole yamlish chunk is garbage.
    if (indent.indexOf(this.yind) !== 0) {
      // oops!  was not actually yamlish, I guess.
      // treat as garbage
      this.debug('garbage! %j %j', this.yind, indent)
      this.emit('garbage', this.yamlish + line)
      this.emitResult()
      return
    }

    // yamlish ends with "...\n"
    if (line === this.yind + '...\n') {
      this.processYamlish()
      return
    }

    // ok!  it is valid yamlish indentation, and not the ...
    // save it to parse later.
    this.yamlish += line
    return
  }

  // not indented.  if we were doing yamlish, then it didn't go good
  if (this.yind) {
    this.emit('garbage', this.yamlish)
    this.yamlish = ''
    this.yind = ''
  }

  this.emitResult()

  var plan = line.match(/^([0-9]+)\.\.([0-9]+)(?:\s+(#.*))?\n$/)
  if (plan) {
    if (this.plan !== -1) {
      // this is not valid tap, just garbage
      this.emit('garbage', line)
      return
    }

    var start = +(plan[1])
    var end = +(plan[2])
    var comment = plan[3]
    this.debug('    > plan', start, end, comment)
    this.plan = end
    this.emit('plan', this.plan)
    if (comment)
      this.emit('comment', comment + '\n')

    // This means that the plan is coming at the END of all the tests
    // Plans MUST be either at the beginning or the very end.  We treat
    // plans like '1..0' the same, since they indicate that no tests
    // will be coming.
    if (this.count !== 0 || this.plan === 0)
      this.postPlan = true

    return
  }

  var parsed = line.match(/^(not )?ok(?: ([0-9]+))?(?:(?: - )?(.*))?\n$/)
  this.debug('parsed', parsed)
  if (!parsed) {
    this.debug('  not a tap line, I guess %j', line)
    this.emit('garbage', line)
    return
  }

  var ok = !parsed[1]
  var id = +(parsed[2] || this.count)
  var res = { id: id, ok: ok }

  var rest = parsed[3] || ''
  var name
  rest = rest.replace(/([^\\]|^)((?:\\\\)*)#/g, '$1\n$2').split('\n')
  name = rest.shift()
  rest = rest.filter(function (r) { return r.trim() }).join('#')

  // now, let's see if there's a directive in there.
  var dir = this._parseDirective(rest.trim())
  if (!dir) {
    name += rest ? '#' + rest : ''
  } else {
    res.ok = true
    res[dir[0]] = dir[1]
  }

  if (name)
    res.name = name.trim()

  // hold onto it, because we might get yamlish diagnostics
  this.current = res
  this.debug('current', res)
}

Consumer.prototype._parseDirective = function (line) {
  line = line.trim()
  var re = /^(todo|skip)\b/i
  var type = line.match(re)
  if (!type)
    return false

  return [ type[0].toLowerCase(), line.replace(re, '').trim() || true ]
}

if (require.main === module) {
  var etoa = require('events-to-array')
  var consumer = new Consumer()
  var events = etoa(consumer, [ 'pipe', 'unpipe', 'prefinish', 'finish' ])

  process.stdin.pipe(consumer)
  process.on('exit', function () {
    console.log(util.inspect(events, null, Infinity))
  })
}
<commit_msg>consumer: remove unused 'ending' var<commit_after>// Transforms a stream of TAP into a stream of result objects
// and string comments.  Emits "results" event with summary.
var Writable = require('stream').Writable
var yaml = require('js-yaml')
var util = require('util')

util.inherits(Consumer, Writable)

module.exports = Consumer

function Consumer (options) {
  options = options || {}
  this.indent = options.indent || ''
  this.level = options.level || 0
  Writable.call(this, { objectMode: true })
  this.buffer = ''
  this.bailedOut = false
  this.plan = -1
  this.yamlish = ''
  this.yind = ''
  this.child = null
  this.current = null

  this.count = 0
  this.pass = 0
  this.fail = 0
  this.todo = 0
  this.skip = 0
  this.ok = true

  this.postPlan = false
  this.bailedOut = false

  if (options.debug)
    this.debug = debug
}

Consumer.prototype.processYamlish = function () {
  var yamlish = this.yamlish
  this.yamlish = ''
  this.yind = ''

  if (!this.current) {
    this.emit('garbage', yamlish)
    return
  }

  try {
    var diags = yaml.safeLoad(yamlish)
  } catch (er) {
    this.emit('garbage', yamlish)
    return
  }

  this.current.diag = diags
  this.emitResult()
}

Consumer.prototype.debug = function () {}

function debug () {
  var m = util.format.apply(util, arguments)
  console.error(this.indent + m)
}

Consumer.prototype.write = function (chunk, encoding, cb) {
  if (typeof encoding === 'string' && encoding !== 'utf8')
    chunk = new Buffer(chunk, encoding)

  if (Buffer.isBuffer(chunk))
    chunk += ''

  if (typeof encoding === 'function') {
    cb = encoding
    encoding = null
  }

  if (this.bailedOut) {
    if (cb)
      process.nextTick(cb)
    return true
  }

  this.buffer += chunk
  do {
    var match = this.buffer.match(/^.*\r?\n/)
    if (!match || this.bailedOut)
      break

    this.buffer = this.buffer.substr(match[0].length)
    this._parse(match[0])
  } while (this.buffer.length)

  if (cb)
    process.nextTick(cb)
  return true
}

Consumer.prototype.end = function (chunk, encoding, cb) {
  if (chunk) {
    if (typeof encoding === 'function') {
      cb = encoding
      encoding = null
    }
    this.write(chunk, encoding)
  }

  if (this.buffer)
    this.write('\n')

  // if we have yamlish, means we didn't finish with a ...
  if (this.yamlish)
    this.emit('garbage', this.yamlish)

  this.emitResult()

  if (this.count !== this.plan)
    this.ok = false

  var final = {
    plan: this.plan,
    count: this.count,
    pass: this.pass,
    ok: this.ok
  }

  if (this.fail)
    final.fail = this.fail

  if (this.bailedOut)
    final.bailout = true

  if (this.todo)
    final.todo = this.todo

  if (this.skip)
    final.skip = this.skip

  this.emit('complete', final)

  Writable.prototype.end.call(this, null, null, cb)
}

Consumer.prototype.bailout = function (reason) {
  this.bailedOut = true
  this.ok = false
  this.emit('bailout', reason)
}

Consumer.prototype.emitResult = function () {
  if (this.child) {
    this.child.end()
    this.child = null
  }

  this.yamlish = ''
  this.yind = ''

  if (!this.current)
    return

  var res = this.current
  this.current = null

  this.count++
  if (res.ok) {
    this.pass++
  } else {
    this.fail++
    if (!res.todo)
      this.ok = false
  }
  if (res.skip)
    this.skip++
  if (res.todo)
    this.todo++

  this.emit('result', res)
}

Consumer.prototype.startChild = function (indent, line) {
  this.emitResult()

  this.child = new Consumer({
    indent: indent,
    parent: this,
    level: this.level + 1
  })

  this.emit('child', this.child)
  this.child.on('bailout', this.bailout.bind(this))
  var self = this
  this.child.on('complete', function (results) {
    if (!results.ok)
      self.ok = false
  })
  this.child.write(line.substr(indent.length))
}

Consumer.prototype._parse = function (line) {
  this.debug('      > %j', line)

  // normalize line endings
  line = line.replace(/\r\n$/, '\n')

  // ignore empty lines
  if (line === '\n')
    return

  // After a bailout, everything is ignored
  if (this.bailedOut)
    return

  // comment
  if (line.match(/^\s*#/)) {
    this.emit('comment', line)
    return
  }

  var bailout = line.match(/^bail out!(.*)\n$/i)
  if (bailout) {
    var reason = bailout[1].trim()
    this.bailout(reason)
    return
  }

  // If version is specified, must be at the very beginning.
  var version = line.match(/^TAP Version ([0-9]+)\n$/i)
  if (version) {
    if (this.plan === -1 && this.count === 0)
      this.emit('version', version[1])
    else
      this.emit('garbage', line)
    return
  }

  // if we got a plan at the end, or a 1..0 plan, then we can't
  // have any more results, yamlish, or child sets.
  if (this.postPlan) {
    this.emit('garbage', line)
    return
  }

  // still belongs to the child.
  if (this.child && line.indexOf(this.child.indent) === 0) {
    line = line.substr(this.child.indent.length)
    this.debug('child line %j', line)
    this.child.write(line)
    return
  }

  var indent = line.match(/^[ \t]+/)
  if (indent) {
    indent = indent[0]

    this.debug('indent %j', indent)

    // if we don't have a current res, then it can't be yamlish,
    // must be a child result set
    if (!this.current) {
      this.debug('no current, start child', line)
      this.startChild(indent, line)
      return
    }

    // if we are not currently processing yamlish, then it has to
    // be either the start of a child, or the start of yamlish.
    if (!this.yind) {
      this.debug('no yind yet')
      // either this starts yamlish, or it is a child.
      if (line === indent + '---\n') {
        this.debug('yamlish start %j', line)
        this.yind = indent
      } else {
        this.debug('not yamlish start %j', line)
        this.startChild(indent, line)
      }
      return
    }

    // now we know it is yamlish

    // if it's not as indented, then it's broken.
    // The whole yamlish chunk is garbage.
    if (indent.indexOf(this.yind) !== 0) {
      // oops!  was not actually yamlish, I guess.
      // treat as garbage
      this.debug('garbage! %j %j', this.yind, indent)
      this.emit('garbage', this.yamlish + line)
      this.emitResult()
      return
    }

    // yamlish ends with "...\n"
    if (line === this.yind + '...\n') {
      this.processYamlish()
      return
    }

    // ok!  it is valid yamlish indentation, and not the ...
    // save it to parse later.
    this.yamlish += line
    return
  }

  // not indented.  if we were doing yamlish, then it didn't go good
  if (this.yind) {
    this.emit('garbage', this.yamlish)
    this.yamlish = ''
    this.yind = ''
  }

  this.emitResult()

  var plan = line.match(/^([0-9]+)\.\.([0-9]+)(?:\s+(#.*))?\n$/)
  if (plan) {
    if (this.plan !== -1) {
      // this is not valid tap, just garbage
      this.emit('garbage', line)
      return
    }

    var start = +(plan[1])
    var end = +(plan[2])
    var comment = plan[3]
    this.debug('    > plan', start, end, comment)
    this.plan = end
    this.emit('plan', this.plan)
    if (comment)
      this.emit('comment', comment + '\n')

    // This means that the plan is coming at the END of all the tests
    // Plans MUST be either at the beginning or the very end.  We treat
    // plans like '1..0' the same, since they indicate that no tests
    // will be coming.
    if (this.count !== 0 || this.plan === 0)
      this.postPlan = true

    return
  }

  var parsed = line.match(/^(not )?ok(?: ([0-9]+))?(?:(?: - )?(.*))?\n$/)
  this.debug('parsed', parsed)
  if (!parsed) {
    this.debug('  not a tap line, I guess %j', line)
    this.emit('garbage', line)
    return
  }

  var ok = !parsed[1]
  var id = +(parsed[2] || this.count)
  var res = { id: id, ok: ok }

  var rest = parsed[3] || ''
  var name
  rest = rest.replace(/([^\\]|^)((?:\\\\)*)#/g, '$1\n$2').split('\n')
  name = rest.shift()
  rest = rest.filter(function (r) { return r.trim() }).join('#')

  // now, let's see if there's a directive in there.
  var dir = this._parseDirective(rest.trim())
  if (!dir) {
    name += rest ? '#' + rest : ''
  } else {
    res.ok = true
    res[dir[0]] = dir[1]
  }

  if (name)
    res.name = name.trim()

  // hold onto it, because we might get yamlish diagnostics
  this.current = res
  this.debug('current', res)
}

Consumer.prototype._parseDirective = function (line) {
  line = line.trim()
  var re = /^(todo|skip)\b/i
  var type = line.match(re)
  if (!type)
    return false

  return [ type[0].toLowerCase(), line.replace(re, '').trim() || true ]
}

if (require.main === module) {
  var etoa = require('events-to-array')
  var consumer = new Consumer()
  var events = etoa(consumer, [ 'pipe', 'unpipe', 'prefinish', 'finish' ])

  process.stdin.pipe(consumer)
  process.on('exit', function () {
    console.log(util.inspect(events, null, Infinity))
  })
}
<|endoftext|>


<commit_before>/**
 * Created by Spadon on 11/09/2015.
 */

var Logics = require('./Logics/Logics'),
    Solver = require('./Logics/Solver'),
    Utils = require('./Utils');

/**
 * Reasoning engine containing incremental algorithms
 * and heuristics for KB view maintaining.
 */

ReasoningEngine = {
    /**
     * A naive reasoner that recalculates the entire knowledge base.
     * @deprecated
     * @param triplesIns
     * @param triplesDel
     * @param rules
     * @returns {{fi: *, fe: *}}
     */
    naive: function(FeAdd, FeDel, F, R) {
        var FiAdd = [], FiAddNew = [], additions, deletions,
            Fe = Logics.getOnlyExplicitFacts(F), FiAddNew = [];

        // Deletion
        if(FeDel && FeDel.length) {
            Fe = Logics.minus(Fe, FeDel);
        }

        // Insertion
        if(FeAdd && FeAdd.length) {
            Fe = Utils.uniques(Fe, FeAdd);
        }

        // Recalculation
        do {
            FiAdd = Utils.uniques(FiAdd, FiAddNew);
            FiAddNew = Solver.evaluateRuleSet(R, Utils.uniques(Fe, FiAdd));
        } while (!Logics.containsFacts(FiAdd, FiAddNew));

        additions = Utils.uniques(FeAdd, FiAdd);
        deletions = Logics.minus(F, Utils.uniques(Fe, FiAdd));

        F = Utils.uniques(Fe, FiAdd);

        return {
            additions: additions,
            deletions: deletions,
            updatedF: F
        };
    },

    /**
     * Incremental reasoning which avoids complete recalculation of facts.
     * Concat is preferred over merge for evaluation purposes.
     * @param R set of rules
     * @param F set of assertions
     * @param FeAdd set of assertions to be added
     * @param FeDel set of assertions to be deleted
     */
    incremental: function (FeAdd, FeDel, F, R) {
        var Rdel = [], Rred, Rins = [],
            FiDel = [], FiAdd = [],
            FiDelNew = [], FiAddNew = [],
            superSet = [],

            additions, deletions,

            Fe = Logics.getOnlyExplicitFacts(F),
            Fi = Logics.getOnlyImplicitFacts(F);

        if(FeDel && FeDel.length) {
            // Overdeletion
            do {
                FiDel = Utils.uniques(FiDel, FiDelNew);
                Rdel = Logics.restrictRuleSet(R, Utils.uniques(FeDel, FiDel));
                FiDelNew = Solver.evaluateRuleSet(Rdel, Utils.uniques(Utils.uniques(Fi, Fe), FeDel));
            } while (Utils.uniques(FiDel, FiDelNew).length > FiDel.length);
            Fe = Logics.minus(Fe, FeDel);
            Fi = Logics.minus(Fi, FiDel);

            // Rederivation
            do {
                FiAdd = Utils.uniques(FiAdd, FiAddNew);
                Rred = Logics.restrictRuleSet(R, FiDel);
                FiAddNew = Solver.evaluateRuleSet(Rred, Utils.uniques(Fe, Fi));
            } while(Utils.uniques(FiAdd, FiAddNew).length > FiAdd.length);

        }

        // Insertion
        if(FeAdd && FeAdd.length) {
            do {
                FiAdd = Utils.uniques(FiAdd, FiAddNew);
                superSet = Utils.uniques(Utils.uniques(Utils.uniques(Fe, Fi), FeAdd), FiAdd);
                Rins = Logics.restrictRuleSet(R, superSet);
                FiAddNew = Solver.evaluateRuleSet(Rins, superSet);
            } while (!Utils.containsSubset(FiAdd, FiAddNew));
        }

        additions = Utils.uniques(FeAdd, FiAdd);
        deletions = Utils.uniques(FeDel, FiDel);

        return {
            additions: additions,
            deletions: deletions
        };
    },

    incrementalBf: function (FeAdd, FeDel, F, R) {

        R = Logics.decomposeRuleHeadsIntoSeveralRules(R);

        var backwardForwardDelete = function(E, I, FeDel, R) {
            var C = new Utils.IterableStructure(), D = new Utils.IterableStructure(), P = new Utils.IterableStructure(),
                Y = [], O = new Utils.IterableStructure(), S = [],
                V = new Utils.IterableStructure(), IWithoutO, DWithoutP, IWithoutS,
                fact, tuples, evalRes;

            var checkProvability = function(fact) {
                var tuples, smallestSubstitutions, substitutedRuleFacts;

                if (!C.add(fact)) {
                    return;
                }

                saturate();

                if (P.contains(fact)) {
                    return;
                }

                tuples = Solver.matchHead(R, fact);

                for (var i = 0; i < tuples.length; i++) {
                    smallestSubstitutions = Solver.eval(IWithoutS, tuples[i].annotatedQuery, [], tuples[i].mapping, tuples[i].rule.constants);
                    for (var j = 0; j < tuples[i].rule.causes.length; j++) {
                        substitutedRuleFacts = Solver.substitute(tuples[i].rule.causes[j], smallestSubstitutions);
                        for (var k = 0; k < substitutedRuleFacts.length; k++) {
                            checkProvability(substitutedRuleFacts[k]);
                        }
                    }
                    if (fact.appearsIn(P)) {
                        return;
                    }
                }
            };

            var saturate = function() {
                var tuplesMatchBody, fact, evalRes, H;

                while (fact = C.next()) {
                    if (fact.appearsIn(E) || fact.appearsIn(Y)) {
                        P.add(fact);
                    }
                }

                while (fact = P.next()) {
                    if (V.add(fact)) {
                        tuplesMatchBody = Solver.matchBody(R, fact);
                        for (var i = 0; i < tuplesMatchBody.length; i++) {
                            evalRes = Solver.eval(V.toArray(), tuplesMatchBody[i].annotatedQuery, [fact], tuplesMatchBody[i].mapping);
                            H = Solver.substitute(tuplesMatchBody[i].rule.consequences[0], evalRes);
                            for (var j = 0; j < H.length; j++) {
                                if(C.contains(H[j])) {
                                    P.add(H);
                                } else {
                                    Y.add(H);
                                }
                            }
                        }
                    }
                }

                return;
            };

            E = Logics.minus(E, FeDel);
            D.add(FeDel);

            while (fact = D.next()) {
                IWithoutS = Logics.minus(I, S);
                checkProvability(fact);
                S = Logics.minus(C.toArray(), P.toArray());

                if (!P.contains(fact)) {
                    IWithoutO = Logics.minus(I, O.toArray());
                    tuples = Solver.matchBody(R, fact);
                    for (var i = 0; i < tuples.length; i++) {
                        evalRes = Solver.eval(IWithoutO, tuples[i].annotatedQuery, [fact], tuples[i].mapping, tuples[i].rule.constants);
                        D.add(Solver.substitute(tuples[i].rule.consequences[0], evalRes));
                    }
                    O.add(fact);
                }
            }

            DWithoutP = Logics.minus(D.toArray(), P.toArray());
            I = Logics.minus(I, DWithoutP[i]);

            return I;
        };

        var Rins = [],
            FiDel = [], FiAdd = [],
            FiAddNew = [], superSet = [],

            additions, deletions,

            Fe = Logics.getOnlyExplicitFacts(F),
            Fi = Logics.getOnlyImplicitFacts(F);

        if(FeDel && FeDel.length) {
            FiDel = backwardForwardDelete(Fe, Fi, FeDel, R);
        }

        // Insertion
        if(FeAdd && FeAdd.length) {
            do {
                FiAdd = Utils.uniques(FiAdd, FiAddNew);
                superSet = Utils.uniques(Utils.uniques(Utils.uniques(Fe, Fi), FeAdd), FiAdd);
                Rins = Logics.restrictRuleSet(R, superSet);
                FiAddNew = Solver.evaluateRuleSet(Rins, superSet);
            } while (Utils.uniques(FiAdd, FiAddNew).length > FiAdd.length);
        }

        additions = Utils.uniques(FeAdd, FiAdd);
        deletions = Utils.uniques(FeDel, FiDel);

        F = Utils.uniques(F, additions);
        F = Logics.minus(F, deletions);

        return {
            additions: additions,
            deletions: deletions,
            updatedF: F
        };
    },

    /**
     * Returns valid facts using explicit facts' validity tags.
     * @param F
     * @param refs
     * @returns {Array}
     */
    tagFilter: function(F, refs) {
        var validSet = [];
        for (var i = 0; i < F.length; i++) {
            if (F[i].isValid()) {
                validSet.push(F[i]);
            }
        }
        return validSet;
    },

    /**
     * Tags newly inferred facts, and (un)validates updated ones.
     * Explicit facts are 'validity'-tagged, while
     * implicit ones are 'causedBy'-tagged.
     * @param FeAdd
     * @param FeDel
     * @param F
     * @param R
     * @returns {{additions: *, deletions: Array}}
     */
    tagging: function(FeAdd, FeDel, F, R) {
        var newExplicitFacts, resolvedExplicitFacts, validUpdateResults,
            FiAdd = [], Rins = [],
            Fi = Logics.getOnlyImplicitFacts(F);

        // Returns new explicit facts to be added
        validUpdateResults = Logics.updateValidTags(F, FeAdd, FeDel);
        newExplicitFacts = validUpdateResults.__new__;
        resolvedExplicitFacts = validUpdateResults.__resolved__;

        if(newExplicitFacts.length > 0) {
            do {
                Logics.unify(FiAdd, Fi);
                F = Utils.uniques(F, Fi);
                Rins = Logics.restrictRuleSet(R, F);
                FiAdd = Solver.evaluateRuleSet(Rins, F, true);
            } while (!Utils.containsSubset(Fi, FiAdd));
            Logics.unify(FiAdd, Fi);
        }

        return {
            additions: Utils.uniques(newExplicitFacts.concat(resolvedExplicitFacts), Fi),
            deletions: []
        };
    }
};

module.exports = {
    naive: ReasoningEngine.naive,
    incrementalBf: ReasoningEngine.incrementalBf,
    incremental: ReasoningEngine.incremental,
    tagging: ReasoningEngine.tagging,
    tagFilter: ReasoningEngine.tagFilter
};<commit_msg>Using length comparison + unify for tb reasoning<commit_after>/**
 * Created by Spadon on 11/09/2015.
 */

var Logics = require('./Logics/Logics'),
    Solver = require('./Logics/Solver'),
    Utils = require('./Utils');

/**
 * Reasoning engine containing incremental algorithms
 * and heuristics for KB view maintaining.
 */

ReasoningEngine = {
    /**
     * A naive reasoner that recalculates the entire knowledge base.
     * @deprecated
     * @param triplesIns
     * @param triplesDel
     * @param rules
     * @returns {{fi: *, fe: *}}
     */
    naive: function(FeAdd, FeDel, F, R) {
        var FiAdd = [], FiAddNew = [], additions, deletions,
            Fe = Logics.getOnlyExplicitFacts(F), FiAddNew = [];

        // Deletion
        if(FeDel && FeDel.length) {
            Fe = Logics.minus(Fe, FeDel);
        }

        // Insertion
        if(FeAdd && FeAdd.length) {
            Fe = Utils.uniques(Fe, FeAdd);
        }

        // Recalculation
        do {
            FiAdd = Utils.uniques(FiAdd, FiAddNew);
            FiAddNew = Solver.evaluateRuleSet(R, Utils.uniques(Fe, FiAdd));
        } while (!Logics.containsFacts(FiAdd, FiAddNew));

        additions = Utils.uniques(FeAdd, FiAdd);
        deletions = Logics.minus(F, Utils.uniques(Fe, FiAdd));

        F = Utils.uniques(Fe, FiAdd);

        return {
            additions: additions,
            deletions: deletions,
            updatedF: F
        };
    },

    /**
     * Incremental reasoning which avoids complete recalculation of facts.
     * Concat is preferred over merge for evaluation purposes.
     * @param R set of rules
     * @param F set of assertions
     * @param FeAdd set of assertions to be added
     * @param FeDel set of assertions to be deleted
     */
    incremental: function (FeAdd, FeDel, F, R) {
        var Rdel = [], Rred, Rins = [],
            FiDel = [], FiAdd = [],
            FiDelNew = [], FiAddNew = [],
            superSet = [],

            additions, deletions,

            Fe = Logics.getOnlyExplicitFacts(F),
            Fi = Logics.getOnlyImplicitFacts(F);

        if(FeDel && FeDel.length) {
            // Overdeletion
            do {
                FiDel = Utils.uniques(FiDel, FiDelNew);
                Rdel = Logics.restrictRuleSet(R, Utils.uniques(FeDel, FiDel));
                FiDelNew = Solver.evaluateRuleSet(Rdel, Utils.uniques(Utils.uniques(Fi, Fe), FeDel));
            } while (Utils.uniques(FiDel, FiDelNew).length > FiDel.length);
            Fe = Logics.minus(Fe, FeDel);
            Fi = Logics.minus(Fi, FiDel);

            // Rederivation
            do {
                FiAdd = Utils.uniques(FiAdd, FiAddNew);
                Rred = Logics.restrictRuleSet(R, FiDel);
                FiAddNew = Solver.evaluateRuleSet(Rred, Utils.uniques(Fe, Fi));
            } while(Utils.uniques(FiAdd, FiAddNew).length > FiAdd.length);

        }

        // Insertion
        if(FeAdd && FeAdd.length) {
            do {
                FiAdd = Utils.uniques(FiAdd, FiAddNew);
                superSet = Utils.uniques(Utils.uniques(Utils.uniques(Fe, Fi), FeAdd), FiAdd);
                Rins = Logics.restrictRuleSet(R, superSet);
                FiAddNew = Solver.evaluateRuleSet(Rins, superSet);
            } while (!Utils.containsSubset(FiAdd, FiAddNew));
        }

        additions = Utils.uniques(FeAdd, FiAdd);
        deletions = Utils.uniques(FeDel, FiDel);

        return {
            additions: additions,
            deletions: deletions
        };
    },

    incrementalBf: function (FeAdd, FeDel, F, R) {

        R = Logics.decomposeRuleHeadsIntoSeveralRules(R);

        var backwardForwardDelete = function(E, I, FeDel, R) {
            var C = new Utils.IterableStructure(), D = new Utils.IterableStructure(), P = new Utils.IterableStructure(),
                Y = [], O = new Utils.IterableStructure(), S = [],
                V = new Utils.IterableStructure(), IWithoutO, DWithoutP, IWithoutS,
                fact, tuples, evalRes;

            var checkProvability = function(fact) {
                var tuples, smallestSubstitutions, substitutedRuleFacts;

                if (!C.add(fact)) {
                    return;
                }

                saturate();

                if (P.contains(fact)) {
                    return;
                }

                tuples = Solver.matchHead(R, fact);

                for (var i = 0; i < tuples.length; i++) {
                    smallestSubstitutions = Solver.eval(IWithoutS, tuples[i].annotatedQuery, [], tuples[i].mapping, tuples[i].rule.constants);
                    for (var j = 0; j < tuples[i].rule.causes.length; j++) {
                        substitutedRuleFacts = Solver.substitute(tuples[i].rule.causes[j], smallestSubstitutions);
                        for (var k = 0; k < substitutedRuleFacts.length; k++) {
                            checkProvability(substitutedRuleFacts[k]);
                        }
                    }
                    if (fact.appearsIn(P)) {
                        return;
                    }
                }
            };

            var saturate = function() {
                var tuplesMatchBody, fact, evalRes, H;

                while (fact = C.next()) {
                    if (fact.appearsIn(E) || fact.appearsIn(Y)) {
                        P.add(fact);
                    }
                }

                while (fact = P.next()) {
                    if (V.add(fact)) {
                        tuplesMatchBody = Solver.matchBody(R, fact);
                        for (var i = 0; i < tuplesMatchBody.length; i++) {
                            evalRes = Solver.eval(V.toArray(), tuplesMatchBody[i].annotatedQuery, [fact], tuplesMatchBody[i].mapping);
                            H = Solver.substitute(tuplesMatchBody[i].rule.consequences[0], evalRes);
                            for (var j = 0; j < H.length; j++) {
                                if(C.contains(H[j])) {
                                    P.add(H);
                                } else {
                                    Y.add(H);
                                }
                            }
                        }
                    }
                }

                return;
            };

            E = Logics.minus(E, FeDel);
            D.add(FeDel);

            while (fact = D.next()) {
                IWithoutS = Logics.minus(I, S);
                checkProvability(fact);
                S = Logics.minus(C.toArray(), P.toArray());

                if (!P.contains(fact)) {
                    IWithoutO = Logics.minus(I, O.toArray());
                    tuples = Solver.matchBody(R, fact);
                    for (var i = 0; i < tuples.length; i++) {
                        evalRes = Solver.eval(IWithoutO, tuples[i].annotatedQuery, [fact], tuples[i].mapping, tuples[i].rule.constants);
                        D.add(Solver.substitute(tuples[i].rule.consequences[0], evalRes));
                    }
                    O.add(fact);
                }
            }

            DWithoutP = Logics.minus(D.toArray(), P.toArray());
            I = Logics.minus(I, DWithoutP[i]);

            return I;
        };

        var Rins = [],
            FiDel = [], FiAdd = [],
            FiAddNew = [], superSet = [],

            additions, deletions,

            Fe = Logics.getOnlyExplicitFacts(F),
            Fi = Logics.getOnlyImplicitFacts(F);

        if(FeDel && FeDel.length) {
            FiDel = backwardForwardDelete(Fe, Fi, FeDel, R);
        }

        // Insertion
        if(FeAdd && FeAdd.length) {
            do {
                FiAdd = Utils.uniques(FiAdd, FiAddNew);
                superSet = Utils.uniques(Utils.uniques(Utils.uniques(Fe, Fi), FeAdd), FiAdd);
                Rins = Logics.restrictRuleSet(R, superSet);
                FiAddNew = Solver.evaluateRuleSet(Rins, superSet);
            } while (Utils.uniques(FiAdd, FiAddNew).length > FiAdd.length);
        }

        additions = Utils.uniques(FeAdd, FiAdd);
        deletions = Utils.uniques(FeDel, FiDel);

        F = Utils.uniques(F, additions);
        F = Logics.minus(F, deletions);

        return {
            additions: additions,
            deletions: deletions,
            updatedF: F
        };
    },

    /**
     * Returns valid facts using explicit facts' validity tags.
     * @param F
     * @param refs
     * @returns {Array}
     */
    tagFilter: function(F, refs) {
        var validSet = [];
        for (var i = 0; i < F.length; i++) {
            if (F[i].isValid()) {
                validSet.push(F[i]);
            }
        }
        return validSet;
    },

    /**
     * Tags newly inferred facts, and (un)validates updated ones.
     * Explicit facts are 'validity'-tagged, while
     * implicit ones are 'causedBy'-tagged.
     * @param FeAdd
     * @param FeDel
     * @param F
     * @param R
     * @returns {{additions: *, deletions: Array}}
     */
    tagging: function(FeAdd, FeDel, F, R) {
        var newExplicitFacts, resolvedExplicitFacts, validUpdateResults,
            FiAdd = [], Rins = [],
            Fi = Logics.getOnlyImplicitFacts(F);

        // Returns new explicit facts to be added
        validUpdateResults = Logics.updateValidTags(F, FeAdd, FeDel);
        newExplicitFacts = validUpdateResults.__new__;
        resolvedExplicitFacts = validUpdateResults.__resolved__;

        if(newExplicitFacts.length > 0) {
            do {
                F = Utils.uniques(F, Fi);
                Rins = Logics.restrictRuleSet(R, F);
                FiAdd = Solver.evaluateRuleSet(Rins, F, true);
            } while (Fi.length < Logics.unify(FiAdd, Fi));
        }

        return {
            additions: Utils.uniques(newExplicitFacts.concat(resolvedExplicitFacts), Fi),
            deletions: []
        };
    }
};

module.exports = {
    naive: ReasoningEngine.naive,
    incrementalBf: ReasoningEngine.incrementalBf,
    incremental: ReasoningEngine.incremental,
    tagging: ReasoningEngine.tagging,
    tagFilter: ReasoningEngine.tagFilter
};<|endoftext|>


<commit_before>var nroonga = require('nroonga');
var Deferred = require('jsdeferred').Deferred;

var ShortText =
      exports.ShortText =
      Database.ShortText = 'ShortText';

var TABLE_HASH_KEY =
      exports.TABLE_HASH_KEY =
      Database.TABLE_HASH_KEY = 'TABLE_HASH_KEY';
var TABLE_PAT_KEY =
      exports.TABLE_PAT_KEY =
      Database.TABLE_PAT_KEY = 'TABLE_PAT_KEY';
var KEY_NORMALIZE =
      exports.KEY_NORMALIZE =
      Database.KEY_NORMALIZE = 'KEY_NORMALIZE';

var COLUMN_SCALAR =
      exports.COLUMN_SCALAR =
      Database.COLUMN_SCALAR = 'COLUMN_SCALAR';
var COLUMN_INDEX =
      exports.COLUMN_INDEX =
      Database.COLUMN_INDEX = 'COLUMN_INDEX';
var WITH_POSITION =
      exports.WITH_POSITION =
      Database.WITH_POSITION = 'WITH_POSITION';

var TokenBigram =
      exports.TokenBigram =
      Database.TokenBigram = 'TokenBigram';

function Database(source) {
  if (typeof source == 'string') // path
    this._database = new nroonga.Database(source);
  else if (source instanceof nroonga.Database)
    this._database = source;
  else
    return source;
}

Database.prototype = {
  command: function() {
    return this._database.command.apply(this._database, arguments);
  },
  commandSync: function() {
    return this._database.commandSync.apply(this._database, arguments);
  },
  commandString: function() {
    return this._database.commandString.apply(this._database, arguments);
  },
  commandSyncString: function() {
    return this._database.commandSyncString.apply(this._database, arguments);
  },
  commandDeferred: function(command, options) {
    var deferred = new Deferred();
    var callback = function(error, data) {
          if (error)
            deferred.fail(error);
          else
            deferred.call(data);
        };

    if (options)
      this._database.command(command, options, callback);
    else
      this._database.command(command, callback);

    return deferred;
  },
  commandDeferredString: function(command) {
    var deferred = new Deferred();
    this._database.commandString(command, function(error, data) {
      if (error)
        deferred.fail(error);
      else
        deferred.call(data);
    });
    return deferred;
  },

  columnListSync: function(tableName) {
    var result =  this.commandSync('column_list', { table: tableName });
    return Database.formatResults(result);
  },
  columnNamesSync: function(tableName) {
    var columns = this.columnListSync(tableName);
    var ordinalColumns = columns.filter(function(column) {
      return column.name.charAt(0) !== '_';
    });
    var names = ordinalColumns.map(function(column) {
      return column.name;
    });
    return names;
  }
};

exports.Database = Database;

exports.formatResults = Database.formatResults = function(results) {
  var columns = {};
  results[0].forEach(function(column, index) {
    columns[index] = column[0];
  });

  var hashResults = [];
  results.slice(1).forEach(function(result) {
    var hashResult = {};
    result.forEach(function(column, index) {
      hashResult[columns[index]] = column;
    });
    hashResults.push(hashResult);
  });
  return hashResults;
};
<commit_msg>Create database directory if not exists<commit_after>var nroonga = require('nroonga');
var Deferred = require('jsdeferred').Deferred;
var path = require('path');
var mkdirp = require('mkdirp');

var ShortText =
      exports.ShortText =
      Database.ShortText = 'ShortText';

var TABLE_HASH_KEY =
      exports.TABLE_HASH_KEY =
      Database.TABLE_HASH_KEY = 'TABLE_HASH_KEY';
var TABLE_PAT_KEY =
      exports.TABLE_PAT_KEY =
      Database.TABLE_PAT_KEY = 'TABLE_PAT_KEY';
var KEY_NORMALIZE =
      exports.KEY_NORMALIZE =
      Database.KEY_NORMALIZE = 'KEY_NORMALIZE';

var COLUMN_SCALAR =
      exports.COLUMN_SCALAR =
      Database.COLUMN_SCALAR = 'COLUMN_SCALAR';
var COLUMN_INDEX =
      exports.COLUMN_INDEX =
      Database.COLUMN_INDEX = 'COLUMN_INDEX';
var WITH_POSITION =
      exports.WITH_POSITION =
      Database.WITH_POSITION = 'WITH_POSITION';

var TokenBigram =
      exports.TokenBigram =
      Database.TokenBigram = 'TokenBigram';

function Database(source) {
  if (typeof source == 'string') { // path
    mkdirp.sync(path.dirname(source));
    this._database = new nroonga.Database(source);
  } else if (source instanceof nroonga.Database)
    this._database = source;
  else
    return source;
}

Database.prototype = {
  command: function() {
    return this._database.command.apply(this._database, arguments);
  },
  commandSync: function() {
    return this._database.commandSync.apply(this._database, arguments);
  },
  commandString: function() {
    return this._database.commandString.apply(this._database, arguments);
  },
  commandSyncString: function() {
    return this._database.commandSyncString.apply(this._database, arguments);
  },
  commandDeferred: function(command, options) {
    var deferred = new Deferred();
    var callback = function(error, data) {
          if (error)
            deferred.fail(error);
          else
            deferred.call(data);
        };

    if (options)
      this._database.command(command, options, callback);
    else
      this._database.command(command, callback);

    return deferred;
  },
  commandDeferredString: function(command) {
    var deferred = new Deferred();
    this._database.commandString(command, function(error, data) {
      if (error)
        deferred.fail(error);
      else
        deferred.call(data);
    });
    return deferred;
  },

  columnListSync: function(tableName) {
    var result =  this.commandSync('column_list', { table: tableName });
    return Database.formatResults(result);
  },
  columnNamesSync: function(tableName) {
    var columns = this.columnListSync(tableName);
    var ordinalColumns = columns.filter(function(column) {
      return column.name.charAt(0) !== '_';
    });
    var names = ordinalColumns.map(function(column) {
      return column.name;
    });
    return names;
  }
};

exports.Database = Database;

exports.formatResults = Database.formatResults = function(results) {
  var columns = {};
  results[0].forEach(function(column, index) {
    columns[index] = column[0];
  });

  var hashResults = [];
  results.slice(1).forEach(function(result) {
    var hashResult = {};
    result.forEach(function(column, index) {
      hashResult[columns[index]] = column;
    });
    hashResults.push(hashResult);
  });
  return hashResults;
};
<|endoftext|>


<commit_before>/**
 * Yii GridView widget.
 *
 * This is the JavaScript widget used by the yii\grid\GridView widget.
 *
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
(function ($) {
    $.fn.yiiGridView = function (method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === 'object' || !method) {
            return methods.init.apply(this, arguments);
        } else {
            $.error('Method ' + method + ' does not exist on jQuery.yiiGridView');
            return false;
        }
    };

    var defaults = {
        filterUrl: undefined,
        filterSelector: undefined
    };

    var gridData = {};

    var gridEvents = {
        /**
         * beforeFilter event is triggered before filtering the grid.
         * The signature of the event handler should be:
         *     function (event)
         * where
         *  - event: an Event object.
         *
         * If the handler returns a boolean false, it will stop filter form submission after this event. As
         * a result, afterFilter event will not be triggered.
         */
        beforeFilter: 'beforeFilter',
        /**
         * afterFilter event is triggered after filtering the grid and filtered results are fetched.
         * The signature of the event handler should be:
         *     function (event)
         * where
         *  - event: an Event object.
         */
        afterFilter: 'afterFilter'
    };

    var methods = {
        init: function (options) {
            return this.each(function () {
                var $e = $(this);
                var settings = $.extend({}, defaults, options || {});
                var id = $e.attr('id');
                if (gridData[id] === undefined) {
                    gridData[id] = {};
                }

                gridData[id] = $.extend(gridData[id], {settings: settings});

                var enterPressed = false;
                $(document).off('change.yiiGridView keydown.yiiGridView', settings.filterSelector)
                    .on('change.yiiGridView keydown.yiiGridView', settings.filterSelector, function (event) {
                        if (event.type === 'keydown') {
                            if (event.keyCode !== 13) {
                                return; // only react to enter key
                            } else {
                                enterPressed = true;
                            }
                        } else {
                            // prevent processing for both keydown and change events
                            if (enterPressed) {
                                enterPressed = false;
                                return;
                            }
                        }

                        methods.applyFilter.apply($e);

                        return false;
                    });
            });
        },

        applyFilter: function () {
            var $grid = $(this), event;
            var settings = gridData[$grid.attr('id')].settings;
            var data = {};
            $.each($(settings.filterSelector).serializeArray(), function () {
                if (!(this.name in data)) {
                    data[this.name] = [];
                }
                data[this.name].push(this.value);
            });

            var namesInFilter = Object.keys(data);

            $.each(yii.getQueryParams(settings.filterUrl), function (name, value) {
                if (namesInFilter.indexOf(name) === -1 && namesInFilter.indexOf(name.replace(/\[\]$/, '')) === -1) {
                    if (!$.isArray(value)) {
                        value = [value];
                    }
                    if (!(name in data)) {
                        data[name] = value;
                    } else {
                        $.each(value, function (i, val) {
                            if ($.inArray(val, data[name])) {
                                data[name].push(val);
                            }
                        });
                    }
                }
            });

            var pos = settings.filterUrl.indexOf('?');
            var url = pos < 0 ? settings.filterUrl : settings.filterUrl.substring(0, pos);
            var hashPos = settings.filterUrl.indexOf('#');
            if (hashPos >= 0) {
                url += settings.filterUrl.substring(pos);
            }

            $grid.find('form.gridview-filter-form').remove();
            var $form = $('<form/>', {
                action: url,
                method: 'get',
                'class': 'gridview-filter-form',
                style: 'display:none',
                'data-pjax': ''
            }).appendTo($grid);
            $.each(data, function (name, values) {
                $.each(values, function (index, value) {
                    $form.append($('<input/>').attr({type: 'hidden', name: name, value: value}));
                });
            });

            event = $.Event(gridEvents.beforeFilter);
            $grid.trigger(event);
            if (event.result === false) {
                return;
            }

            $form.submit();

            $grid.trigger(gridEvents.afterFilter);
        },

        setSelectionColumn: function (options) {
            var $grid = $(this);
            var id = $(this).attr('id');
            if (gridData[id] === undefined) {
                gridData[id] = {};
            }
            gridData[id].selectionColumn = options.name;
            if (!options.multiple || !options.checkAll) {
                return;
            }
            var checkAll = "#" + id + " input[name='" + options.checkAll + "']";
            var inputs = options.class ? "input." + options.class : "input[name='" + options.name + "']";
            var inputsEnabled = "#" + id + " " + inputs + ":enabled";
            $(document).off('click.yiiGridView', checkAll).on('click.yiiGridView', checkAll, function () {
                $grid.find(inputs + ":enabled").prop('checked', this.checked);
            });
            $(document).off('click.yiiGridView', inputsEnabled).on('click.yiiGridView', inputsEnabled, function () {
                var all = $grid.find(inputs).length == $grid.find(inputs + ":checked").length;
                $grid.find("input[name='" + options.checkAll + "']").prop('checked', all);
            });
        },

        getSelectedRows: function () {
            var $grid = $(this);
            var data = gridData[$grid.attr('id')];
            var keys = [];
            if (data.selectionColumn) {
                $grid.find("input[name='" + data.selectionColumn + "']:checked").each(function () {
                    keys.push($(this).parent().closest('tr').data('key'));
                });
            }
            return keys;
        },

        destroy: function () {
            return this.each(function () {
                $(window).unbind('.yiiGridView');
                $(this).removeData('yiiGridView');
            });
        },

        data: function () {
            var id = $(this).attr('id');
            return gridData[id];
        }
    };
})(window.jQuery);
<commit_msg>Correct MSIE8 reserved word error (#12722)<commit_after>/**
 * Yii GridView widget.
 *
 * This is the JavaScript widget used by the yii\grid\GridView widget.
 *
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
(function ($) {
    $.fn.yiiGridView = function (method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === 'object' || !method) {
            return methods.init.apply(this, arguments);
        } else {
            $.error('Method ' + method + ' does not exist on jQuery.yiiGridView');
            return false;
        }
    };

    var defaults = {
        filterUrl: undefined,
        filterSelector: undefined
    };

    var gridData = {};

    var gridEvents = {
        /**
         * beforeFilter event is triggered before filtering the grid.
         * The signature of the event handler should be:
         *     function (event)
         * where
         *  - event: an Event object.
         *
         * If the handler returns a boolean false, it will stop filter form submission after this event. As
         * a result, afterFilter event will not be triggered.
         */
        beforeFilter: 'beforeFilter',
        /**
         * afterFilter event is triggered after filtering the grid and filtered results are fetched.
         * The signature of the event handler should be:
         *     function (event)
         * where
         *  - event: an Event object.
         */
        afterFilter: 'afterFilter'
    };

    var methods = {
        init: function (options) {
            return this.each(function () {
                var $e = $(this);
                var settings = $.extend({}, defaults, options || {});
                var id = $e.attr('id');
                if (gridData[id] === undefined) {
                    gridData[id] = {};
                }

                gridData[id] = $.extend(gridData[id], {settings: settings});

                var enterPressed = false;
                $(document).off('change.yiiGridView keydown.yiiGridView', settings.filterSelector)
                    .on('change.yiiGridView keydown.yiiGridView', settings.filterSelector, function (event) {
                        if (event.type === 'keydown') {
                            if (event.keyCode !== 13) {
                                return; // only react to enter key
                            } else {
                                enterPressed = true;
                            }
                        } else {
                            // prevent processing for both keydown and change events
                            if (enterPressed) {
                                enterPressed = false;
                                return;
                            }
                        }

                        methods.applyFilter.apply($e);

                        return false;
                    });
            });
        },

        applyFilter: function () {
            var $grid = $(this), event;
            var settings = gridData[$grid.attr('id')].settings;
            var data = {};
            $.each($(settings.filterSelector).serializeArray(), function () {
                if (!(this.name in data)) {
                    data[this.name] = [];
                }
                data[this.name].push(this.value);
            });

            var namesInFilter = Object.keys(data);

            $.each(yii.getQueryParams(settings.filterUrl), function (name, value) {
                if (namesInFilter.indexOf(name) === -1 && namesInFilter.indexOf(name.replace(/\[\]$/, '')) === -1) {
                    if (!$.isArray(value)) {
                        value = [value];
                    }
                    if (!(name in data)) {
                        data[name] = value;
                    } else {
                        $.each(value, function (i, val) {
                            if ($.inArray(val, data[name])) {
                                data[name].push(val);
                            }
                        });
                    }
                }
            });

            var pos = settings.filterUrl.indexOf('?');
            var url = pos < 0 ? settings.filterUrl : settings.filterUrl.substring(0, pos);
            var hashPos = settings.filterUrl.indexOf('#');
            if (hashPos >= 0) {
                url += settings.filterUrl.substring(pos);
            }

            $grid.find('form.gridview-filter-form').remove();
            var $form = $('<form/>', {
                action: url,
                method: 'get',
                'class': 'gridview-filter-form',
                style: 'display:none',
                'data-pjax': ''
            }).appendTo($grid);
            $.each(data, function (name, values) {
                $.each(values, function (index, value) {
                    $form.append($('<input/>').attr({type: 'hidden', name: name, value: value}));
                });
            });

            event = $.Event(gridEvents.beforeFilter);
            $grid.trigger(event);
            if (event.result === false) {
                return;
            }

            $form.submit();

            $grid.trigger(gridEvents.afterFilter);
        },

        setSelectionColumn: function (options) {
            var $grid = $(this);
            var id = $(this).attr('id');
            if (gridData[id] === undefined) {
                gridData[id] = {};
            }
            gridData[id].selectionColumn = options.name;
            if (!options.multiple || !options.checkAll) {
                return;
            }
            var checkAll = "#" + id + " input[name='" + options.checkAll + "']";
            var inputs = options['class'] ? "input." + options['class'] : "input[name='" + options.name + "']";
            var inputsEnabled = "#" + id + " " + inputs + ":enabled";
            $(document).off('click.yiiGridView', checkAll).on('click.yiiGridView', checkAll, function () {
                $grid.find(inputs + ":enabled").prop('checked', this.checked);
            });
            $(document).off('click.yiiGridView', inputsEnabled).on('click.yiiGridView', inputsEnabled, function () {
                var all = $grid.find(inputs).length == $grid.find(inputs + ":checked").length;
                $grid.find("input[name='" + options.checkAll + "']").prop('checked', all);
            });
        },

        getSelectedRows: function () {
            var $grid = $(this);
            var data = gridData[$grid.attr('id')];
            var keys = [];
            if (data.selectionColumn) {
                $grid.find("input[name='" + data.selectionColumn + "']:checked").each(function () {
                    keys.push($(this).parent().closest('tr').data('key'));
                });
            }
            return keys;
        },

        destroy: function () {
            return this.each(function () {
                $(window).unbind('.yiiGridView');
                $(this).removeData('yiiGridView');
            });
        },

        data: function () {
            var id = $(this).attr('id');
            return gridData[id];
        }
    };
})(window.jQuery);
<|endoftext|>


<commit_before>var app = app || {};

app.UserEditView = Backbone.View.extend({
	template: _.template($('#user-edit-template').html()),
	tagName: 'div',
	className: 'user-edit',

	events: {
		'keyup .search': 'onSearch',
		'click #user-search-button': 'onUserSearchClick',
		'blur .search-container' : 'onUserSearchBlur'
	},

	initialize: function (options) {

	},

	select: function(e) {
		 Backbone.pubSub.trigger('user:select', this.model);
	},

	render: function () {
		this.$el.html(this.template(this.model.toJSON()));
		this.$users = this.$('#users');
		this.$user_search_container = this.$('.search-container');
		this.$user_search = this.$('.search');
		this.$user_attributes = this.$('.user-attr');
		this.$name = this.$('#name');
		this.$name_container = this.$('#name-container');

		if(this.model.get('name') == '') {
			this.$name.text('Select a name');
		}

		this.libraryViewUsers =  new app.LibraryUserView({
				el: this.$users[0],
				collection: app.UserCollection,
				itemView: app.UserView
			});

		this.libraryViewUsers.render();

		Backbone.pubSub.on('user:select', this.userSelect, this);

		return this;
	},

	onSearch: function(e){
		var val = $(e.currentTarget).val(),
			options,
			searchAllAttributes = false;

			//check for search operand character '~'
			if(val.indexOf('~') == 0){
				//set val to exclude '~'
				val = val.substring(1);
				searchAllAttributes = true;
			}

			options = (searchAllAttributes ? {val: val} : {key: 'name', val: val});

		Backbone.pubSub.trigger('library_users:search', options);
	},

	onUserSearchClick: function(e){
		e.stopPropagation();
		this.toggleUserDropdown();
	},

	onUserSearchBlur: function(e){
		//in the event that a user is selected (userSelect is pending call)
		//we delay the blur actions so that the events can be called
		(function(that){
			setTimeout(function(){
				that.toggleUserDropdown();
			},100);
		})(this);
	},

	userSelect: function(user){
		if(!user.hasOwnProperty('attributes')){
			return;
		}
		this.$user_attributes.each(function( i, el ){
			$(el).text(user.attributes[el.id]);
		});
		this.toggleUserDropdown();

		//fetch user permissions
		if(user.attributes.hasOwnProperty('username')){
			this.getUserPermissions(user.attributes.username);
		}
	},

	getUserPermissions: function(username){
		app.data.getPermissions(app.config.url, username, function(results){
			//format results
			results = app.utility.procesData(results);
			//publish results globally
			Backbone.pubSub.trigger('user:permissions-fetched', results);
		});
	},
	toggleUserDropdown: function(){
		if(this.$name_container.is(':visible')){
			this.$name_container.hide();
			this.$user_search_container.show();
			this.$users.show();
			this.$user_search.focus();
		} else {
			this.$name_container.show();
			this.$user_search_container.hide();
			this.$users.hide();
		}
	}
});
<commit_msg>...another function name typo :|<commit_after>var app = app || {};

app.UserEditView = Backbone.View.extend({
	template: _.template($('#user-edit-template').html()),
	tagName: 'div',
	className: 'user-edit',

	events: {
		'keyup .search': 'onSearch',
		'click #user-search-button': 'onUserSearchClick',
		'blur .search-container' : 'onUserSearchBlur'
	},

	initialize: function (options) {

	},

	select: function(e) {
		 Backbone.pubSub.trigger('user:select', this.model);
	},

	render: function () {
		this.$el.html(this.template(this.model.toJSON()));
		this.$users = this.$('#users');
		this.$user_search_container = this.$('.search-container');
		this.$user_search = this.$('.search');
		this.$user_attributes = this.$('.user-attr');
		this.$name = this.$('#name');
		this.$name_container = this.$('#name-container');

		if(this.model.get('name') == '') {
			this.$name.text('Select a name');
		}

		this.libraryViewUsers =  new app.LibraryUserView({
				el: this.$users[0],
				collection: app.UserCollection,
				itemView: app.UserView
			});

		this.libraryViewUsers.render();

		Backbone.pubSub.on('user:select', this.userSelect, this);

		return this;
	},

	onSearch: function(e){
		var val = $(e.currentTarget).val(),
			options,
			searchAllAttributes = false;

			//check for search operand character '~'
			if(val.indexOf('~') == 0){
				//set val to exclude '~'
				val = val.substring(1);
				searchAllAttributes = true;
			}

			options = (searchAllAttributes ? {val: val} : {key: 'name', val: val});

		Backbone.pubSub.trigger('library_users:search', options);
	},

	onUserSearchClick: function(e){
		e.stopPropagation();
		this.toggleUserDropdown();
	},

	onUserSearchBlur: function(e){
		//in the event that a user is selected (userSelect is pending call)
		//we delay the blur actions so that the events can be called
		(function(that){
			setTimeout(function(){
				that.toggleUserDropdown();
			},100);
		})(this);
	},

	userSelect: function(user){
		if(!user.hasOwnProperty('attributes')){
			return;
		}
		this.$user_attributes.each(function( i, el ){
			$(el).text(user.attributes[el.id]);
		});
		this.toggleUserDropdown();

		//fetch user permissions
		if(user.attributes.hasOwnProperty('username')){
			this.getUserPermissions(user.attributes.username);
		}
	},

	getUserPermissions: function(username){
		app.data.getPermissions(app.config.url, username, function(results){
			//format results
			results = app.utility.processData(results);
			//publish results globally
			Backbone.pubSub.trigger('user:permissions-fetched', results);
		});
	},
	toggleUserDropdown: function(){
		if(this.$name_container.is(':visible')){
			this.$name_container.hide();
			this.$user_search_container.show();
			this.$users.show();
			this.$user_search.focus();
		} else {
			this.$name_container.show();
			this.$user_search_container.hide();
			this.$users.hide();
		}
	}
});
<|endoftext|>


<commit_before>/* jshint maxdepth: 5 */

(function(W, U) {
	'use strict';

	W.fn.make('routes', {
		/**
		 * Get currently bound URI values or set with string or value object
		 *
		 * @param {(object|string)} [value]
		 * @param {string} [value.full]
		 * @param {string} [value.hash]
		 * @param {boolean} [value.history]
		 * @param {string} [value.path]
		 * @param {object} [value.query]
		 * @param {array} [value.segments]
		 * @param {string} [value.url]
		 * @returns {object} data
		 */
		uri: function(value) {
			if (value) {
				if (W.$isObject(value)) {
					return this.$set('uri', W.$extend(this.uri(), value));
				}

				var a = W._doc.createElement('a'),
					query = {};
				a.href = value;

				var search = a.search.slice(1);

				if (search) {
					var arr = decodeURIComponent(search).slice(1).split('&'),
						i = 0;

					for (; i < arr.length; i++) {
						var split = arr[i].split('=');
						query[split[0]] = split[1] || '';
					}
				}

				var path = a.pathname.replace(/^\/|\/$/g, '');

				return this.$set('uri', {
					full: '/' + path + a.search + a.hash,
					hash: a.hash.slice(1),
					history: false,
					path: '/' + path,
					query: query,
					segments: path.split('/'),
					url: a.href
				});
			}

			return this.$get('uri', function() {
				return W.routes.uri(W._win.location.href);
			}, true);
		},

		/**
		 * Get all segments or single segment at index integer
		 *
		 * @param {int} [index]
		 * @returns {(Array|string)} segments
		 */
		segments: function(index) {
			var segs = this.uri().segments;

			return index !== U ? (segs[index] || '') : segs;
		},

		/**
		 * Retrieve or add route endpoints to route storage
		 *
		 * @param {object} routes
		 * @param {bool} [init=false] - evaluate the map immediately
		 * @returns {object} routes
		 */
		map: function(routes, init) {
			var curr = this.$get('routes', {});

			if (routes) {
				this.$set('routes', W.$extend(curr, routes));

				if (init) {
					this.run({
						routes: routes
					});
				}
			}

			return curr;
		},

		/**
		 * Add conditional route handler
		 *
		 * @param {string} name
		 * @param {function} fn
		 */
		addFilter: function(name, fn) {
			this.$private.extend(name, fn);
		},

		/**
		 * Process stored routes
		 *
		 * @param {object} [conf]
		 */
		run: function(conf) {
			conf = conf || {};

			var routes = conf.routes || this.$get('routes');

			if (conf.path) {
				this.path(conf.path);
			}

			if (routes) {
				this.$private.process(routes, 0,
					this.$set(
						'segs',
						this.segments()
					).length
				);

				// Execute queued init functions on last iteration
				var any = this.$private.any;

				if (any.length) {
					for (var i = 0; i < any.length; i++) {
						var rule = any[i];

						W.$exec(rule[0], {
							args: rule[1]
						});
					}

					// Clear array for next iteration
					this.$private.any = [];
				}
			}
		}
	}, {
		/**
		 * Any route matching storage
		 */
		any: [],

		/**
		 * Add default filters
		 */
		filters: {
			any: function(seg, child) {
				if (W.$isObject(child)) {
					return true;
				} else {
					W.routes.$private.any.push([child, seg]);
				}
			},
			'any:fire': function(seg, child) {
				W.$exec(child, {
					args: [seg]
				});
			},
			root: function(seg, child, depth) {
				if (! seg) {
					W.$exec(child, {
						args: W.routes.segments(depth - 2)
					});
				}
			},
			num: function(seg) {
				return ! isNaN(seg) && seg.trim() !== '';
			}
		},

		/**
		 * Extend routing engine
		 *
		 * @param {(object|string)} a
		 * @param {function} b
		 */
		extend: function(a, b) {
			var obj = a;

			if (typeof a == 'string') {
				obj = [];
				obj[a] = b;
			}

			W.$extend(this.filters, obj);
		},

		/**
		 * Recursively process routes
		 *
		 * @private
		 * @param {string} route - route to evaluate
		 * @param {int} i - current index in iteration
		 * @param {int} total - total number of routes
		 */
		process: function(route, i, total) {
			var seg = this.$get('segs')[i],
				keys = Object.keys(route),
				x = 0;
			i++;

			// Match against patterns
			for (; x < keys.length; x++) {
				var key = keys[x],
					child = route[key],
					opts = key.split('||'),
					k = 0,
					filtered,
					match;

				for (; k < opts.length; k++) {
					var opt = opts[k];

					if (opt.slice(-5) == ':eval') {
						opt = opt.slice(0, -5);
						i--;
					}

					if (opt == seg) {
						match = true;
					} else if (opt[0] == '$') {
						opt = opt.slice(1);

						// If the second character is / then test regex
						if (opt[0] == '/') {
							var split = opt.split('/');

							if (new RegExp(split[1], split[2]).test(seg)) {
								match = true;
							}
						} else {
							var filter = this.filters[opt];

							if (filter) {
								match = filter(seg, child, i);

								if (match) {
									filtered = true;

									this.any.push([child, seg]);
								}
							} else if (seg && seg.trim() !== '') {
								match = true;
							}
						}
					}
				}

				// If matched process recursively or execute if complete
				if (match) {
					if (W.$isObject(child)) {
						this.process(child, i, total);
					} else if (! filtered && i === total) {
						W.$exec(child, {
							args: seg
						});
					}
				}
			}
		}
	});
})(Wee, undefined);<commit_msg>Update unavailable path method call to uri<commit_after>/* jshint maxdepth: 5 */

(function(W, U) {
	'use strict';

	W.fn.make('routes', {
		/**
		 * Get currently bound URI values or set with string or value object
		 *
		 * @param {(object|string)} [value]
		 * @param {string} [value.full]
		 * @param {string} [value.hash]
		 * @param {boolean} [value.history]
		 * @param {string} [value.path]
		 * @param {object} [value.query]
		 * @param {array} [value.segments]
		 * @param {string} [value.url]
		 * @returns {object} data
		 */
		uri: function(value) {
			if (value) {
				if (W.$isObject(value)) {
					return this.$set('uri', W.$extend(this.uri(), value));
				}

				var a = W._doc.createElement('a'),
					query = {};
				a.href = value;

				var search = a.search.slice(1);

				if (search) {
					var arr = decodeURIComponent(search).slice(1).split('&'),
						i = 0;

					for (; i < arr.length; i++) {
						var split = arr[i].split('=');
						query[split[0]] = split[1] || '';
					}
				}

				var path = a.pathname.replace(/^\/|\/$/g, '');

				return this.$set('uri', {
					full: '/' + path + a.search + a.hash,
					hash: a.hash.slice(1),
					history: false,
					path: '/' + path,
					query: query,
					segments: path.split('/'),
					url: a.href
				});
			}

			return this.$get('uri', function() {
				return W.routes.uri(W._win.location.href);
			}, true);
		},

		/**
		 * Get all segments or single segment at index integer
		 *
		 * @param {int} [index]
		 * @returns {(Array|string)} segments
		 */
		segments: function(index) {
			var segs = this.uri().segments;

			return index !== U ? (segs[index] || '') : segs;
		},

		/**
		 * Retrieve or add route endpoints to route storage
		 *
		 * @param {object} routes
		 * @param {bool} [init=false] - evaluate the map immediately
		 * @returns {object} routes
		 */
		map: function(routes, init) {
			var curr = this.$get('routes', {});

			if (routes) {
				this.$set('routes', W.$extend(curr, routes));

				if (init) {
					this.run({
						routes: routes
					});
				}
			}

			return curr;
		},

		/**
		 * Add conditional route handler
		 *
		 * @param {string} name
		 * @param {function} fn
		 */
		addFilter: function(name, fn) {
			this.$private.extend(name, fn);
		},

		/**
		 * Process stored routes
		 *
		 * @param {object} [conf]
		 */
		run: function(conf) {
			conf = conf || {};

			var routes = conf.routes || this.$get('routes');

			if (conf.path) {
				this.uri(conf.path);
			}

			if (routes) {
				this.$private.process(routes, 0,
					this.$set(
						'segs',
						this.segments()
					).length
				);

				// Execute queued init functions on last iteration
				var any = this.$private.any;

				if (any.length) {
					for (var i = 0; i < any.length; i++) {
						var rule = any[i];

						W.$exec(rule[0], {
							args: rule[1]
						});
					}

					// Clear array for next iteration
					this.$private.any = [];
				}
			}
		}
	}, {
		/**
		 * Any route matching storage
		 */
		any: [],

		/**
		 * Add default filters
		 */
		filters: {
			any: function(seg, child) {
				if (W.$isObject(child)) {
					return true;
				} else {
					W.routes.$private.any.push([child, seg]);
				}
			},
			'any:fire': function(seg, child) {
				W.$exec(child, {
					args: [seg]
				});
			},
			root: function(seg, child, depth) {
				if (! seg) {
					W.$exec(child, {
						args: W.routes.segments(depth - 2)
					});
				}
			},
			num: function(seg) {
				return ! isNaN(seg) && seg.trim() !== '';
			}
		},

		/**
		 * Extend routing engine
		 *
		 * @param {(object|string)} a
		 * @param {function} b
		 */
		extend: function(a, b) {
			var obj = a;

			if (typeof a == 'string') {
				obj = [];
				obj[a] = b;
			}

			W.$extend(this.filters, obj);
		},

		/**
		 * Recursively process routes
		 *
		 * @private
		 * @param {string} route - route to evaluate
		 * @param {int} i - current index in iteration
		 * @param {int} total - total number of routes
		 */
		process: function(route, i, total) {
			var seg = this.$get('segs')[i],
				keys = Object.keys(route),
				x = 0;
			i++;

			// Match against patterns
			for (; x < keys.length; x++) {
				var key = keys[x],
					child = route[key],
					opts = key.split('||'),
					k = 0,
					filtered,
					match;

				for (; k < opts.length; k++) {
					var opt = opts[k];

					if (opt.slice(-5) == ':eval') {
						opt = opt.slice(0, -5);
						i--;
					}

					if (opt == seg) {
						match = true;
					} else if (opt[0] == '$') {
						opt = opt.slice(1);

						// If the second character is / then test regex
						if (opt[0] == '/') {
							var split = opt.split('/');

							if (new RegExp(split[1], split[2]).test(seg)) {
								match = true;
							}
						} else {
							var filter = this.filters[opt];

							if (filter) {
								match = filter(seg, child, i);

								if (match) {
									filtered = true;

									this.any.push([child, seg]);
								}
							} else if (seg && seg.trim() !== '') {
								match = true;
							}
						}
					}
				}

				// If matched process recursively or execute if complete
				if (match) {
					if (W.$isObject(child)) {
						this.process(child, i, total);
					} else if (! filtered && i === total) {
						W.$exec(child, {
							args: seg
						});
					}
				}
			}
		}
	});
})(Wee, undefined);<|endoftext|>