<commit_before>/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 PLAT;
if (/Android/.exec(navigator.userAgent)) {
    PLAT = 'android';
} else if (/(iPad)|(iPhone)|(iPod)/.exec(navigator.userAgent)) {
    PLAT = 'ios';
} else if (/(BB10)|(PlayBook)|(BlackBerry)/.exec(navigator.userAgent)) {
    PLAT = 'blackberry';
}

var scripts = document.getElementsByTagName('script');
var currentPath = scripts[scripts.length - 1].src;
var platformCordovaPath = currentPath.replace("cordova-incl.js", "cordova." + PLAT + ".js");
var normalCordovaPath = currentPath.replace("cordova-incl.js", "cordova.js");
var cordovaPath = normalCordovaPath;

if (PLAT) {
    // XHR to local file is an error on some platforms, windowsphone for one
    try {
        var xhr = new XMLHttpRequest();
        xhr.open("GET", platformCordovaPath, false);
        xhr.onreadystatechange = function() {

            if (this.readyState == this.DONE && this.responseText.length > 0) {
                if(parseInt(this.status) >= 400){
                    cordovaPath = normalCordovaPath;
                }else{
                    cordovaPath = platformCordovaPath;
                }
            }
        };
        xhr.send(null);
    }
    catch(e){
        cordovaPath = normalCordovaPath;
    } // access denied!
}

if (!window._doNotWriteCordovaScript) {
    document.write('<script type="text/javascript" charset="utf-8" src="' + cordovaPath + '"></script>');
}

function backHome() {
	if (window.device && device.platform && device.platform.toLowerCase() == 'android') {
            navigator.app.backHistory();
	}
	else {
	    window.history.go(-1);
	}
}
<commit_msg>1. User Agent detection now detects AmazonWebView. 2. Change to use amazon-fireos as the platform if user agent string contains 'cordova-amazon-fireos'<commit_after>/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 PLAT;
if (/cordova-amazon-fireos/.exec(navigator.userAgent)) {
    PLAT = 'amazon-fireos';
}else if (/Android/.exec(navigator.userAgent)) {
    PLAT = 'android';
} else if (/(iPad)|(iPhone)|(iPod)/.exec(navigator.userAgent)) {
    PLAT = 'ios';
} else if (/(BB10)|(PlayBook)|(BlackBerry)/.exec(navigator.userAgent)) {
    PLAT = 'blackberry';
}

var scripts = document.getElementsByTagName('script');
var currentPath = scripts[scripts.length - 1].src;
var platformCordovaPath = currentPath.replace("cordova-incl.js", "cordova." + PLAT + ".js");
var normalCordovaPath = currentPath.replace("cordova-incl.js", "cordova.js");
var cordovaPath = normalCordovaPath;

if (PLAT) {
    // XHR to local file is an error on some platforms, windowsphone for one
    try {
        var xhr = new XMLHttpRequest();
        xhr.open("GET", platformCordovaPath, false);
        xhr.onreadystatechange = function() {

            if (this.readyState == this.DONE && this.responseText.length > 0) {
                if(parseInt(this.status) >= 400){
                    cordovaPath = normalCordovaPath;
                }else{
                    cordovaPath = platformCordovaPath;
                }
            }
        };
        xhr.send(null);
    }
    catch(e){
        cordovaPath = normalCordovaPath;
    } // access denied!
}

if (!window._doNotWriteCordovaScript) {
    document.write('<script type="text/javascript" charset="utf-8" src="' + cordovaPath + '"></script>');
}

function backHome() {
	if (window.device && device.platform && (device.platform.toLowerCase() == 'android' || device.platform.toLowerCase() == 'amazon-fireos')) {
            navigator.app.backHistory();
	}
	else {
	    window.history.go(-1);
	}
}
<|endoftext|>


<commit_before>var Network = require('../../core/Network');
var fbp = require('../..');
var fs = require('fs');

describe('Network', function () {
  it('can load FBP components from this module\'s core via path', function() {
    var network = new Network();
    var process = network.defProc('./components/copier.js');

    expect(process.func).to.be.a('function');
  });

  it('can load FBP components from this module\'s core via package/component', function() {
    var network = new Network();
    var process = network.defProc('jsfbp/copier');

    expect(process.func).to.be.a('function');
  });

  it('can load FBP components directly from modules', function() {
    var network = new Network();
    var process = network.defProc('dummy-module');

    expect(process.func).to.be.an('object');
  });

  it('can load FBP components that are part of a larger package', function() {
    var network = new Network();
    var process = network.defProc('dummy-module/getP3');

    expect(process.func).to.be.an('function');
  });

  it('can be created from an FBP file', function(done) {
    fs.readFile(__dirname + '/network.fbp', function(err, graph) {
      if(err) {
        return done(err);
      }

      var network = Network.createFromGraph(graph.toString());

      var fiberRuntime = new fbp.FiberRuntime();
      network.run(fiberRuntime, {trace: false});

      var receiverProcess = network.getProcessByName("receiver");
      var result = receiverProcess.func.getResult();

      expect(result).to.deep.equal(['1,m1', '1,d11', '1,d12', '2,m2', '2,d21', '3,m3', '3,d31', '3,d32', '3,d33', '4,d41']);

      done();
    });
  });

  it('correctly identified empty IIPs', function() {
    expect(function() {Network.createFromGraph("'' -> IN RECVR(jsfbp/recvr)");}).not.to.throw(Error);
  });
});
<commit_msg>Update Network.js<commit_after>var Network = require('../../core/Network');
var fbp = require('../..');
var fs = require('fs');

describe('Network', function () {
  it('can load FBP components from this module\'s core via path', function() {
    var network = new Network();
    var process = network.defProc('./components/copier.js');

    expect(process.func).to.be.a('function');
  });

  it('can load FBP components from this module\'s core via package/component', function() {
    var network = new Network();
    var process = network.defProc('jsfbp/copier');

    expect(process.func).to.be.a('function');
  });

  it('can load FBP components directly from modules', function() {
    var network = new Network();
    var process = network.defProc('dummy-module');

    expect(process.func).to.be.an('object');
  });

  it('can load FBP components that are part of a larger package', function() {
    var network = new Network();
    var process = network.defProc('dummy-module/getP3');

    expect(process.func).to.be.an('function');
  });

  it('can be created from an FBP file', function(done) {
    fs.readFile(__dirname + '/network.fbp', function(err, graph) {
      if(err) {
        return done(err);
      }

      var network = Network.createFromGraph(graph.toString());

      var fiberRuntime = new fbp.FiberRuntime();
      network.run(fiberRuntime, {trace: false});

      var receiverProcess = network.getProcessByName("receiver");
      var result = receiverProcess.func.getResult();

      expect(result).to.deep.equal(['1,m1', '1,d11', '1,d12', '2,m2', '2,d21', '3,m3', '3,d31', '3,d32', '3,d33', '4,d41']);

      done();
    });
  });

  it('correctly identifies empty IIPs', function() {
    expect(function() {Network.createFromGraph("'' -> IN RECVR(jsfbp/recvr)");}).not.to.throw(Error);
  });
});
<|endoftext|>


<commit_before>// Filename: images/list.js
define([
  'jquery',
  'underscore',
  'backbone',
  'collections/assets',
  'views/images/show'
],
function($, _, Backbone, AssetCollection, ImageView) {

    var assetView = Backbone.View.extend({

        initialize: function() {
            var self = this;
            this.assets = new AssetCollection();

            this.assets.bind('reset', this.onReset, this);

            this.activeXhr = $.ajax({
                url: '/api/media',
                data: {},
                type: 'GET',
                error: function(jqXHR, textStatus, errorThrown) {
                    alert('WE FAILED!');
                },
                success: function(data, textStatus, jqXHR) {
                    self.assets.reset(data.images);
                },
                complete: function(jqHXR, textStatus) {
                     self.activeXhr = null;
                }
            });
        },

        onReset: function() {
            console.log(this.$el);
            var self = this;
            _.map(this.assets.models, function(model) {
                var el = new ImageView({model: model}).render().el;
                self.$el.append(el);
                // Make the Textarea prettier with jQueryUI
                this.$(el).draggable({
                    revert: "invalid", // when not dropped, the item will revert back to its initial position
                    containment: self.parent ? self.parent.el : "document", // stick to editor (el) if present
                    helper: "clone",
                    cursor: "move"
                });
            });
        }
    });

    return assetView;
});
<commit_msg>Added more models and views and made everything twice as confusing<commit_after>// Filename: images/list.js
define([
  'jquery',
  'underscore',
  'backbone',
  'collections/assets',
  'views/images/show'
],
function($, _, Backbone, AssetCollection, ImageView) {

    var assetView = Backbone.View.extend({

        initialize: function() {
            var self = this;
            this.assets = new AssetCollection();

            this.assets.bind('reset', this.onReset, this);
            this.assets.bind('change', this.render, this);

            this.assets.fetch({
                error: function(jqXHR, textStatus, errorThrown) {
                    alert('WE FAILED!');
                },
                success: function(data, textStatus, jqXHR) {
                    self.assets.reset(data.images);
                }
            });
        },

        addOne: function() {
            var view = new ImageView({model: model})
              , el = view.render().el;
            $(el).draggable({
                revert: "invalid", // when not dropped, the item will revert back to its initial position
                containment: this.parent ? this.parent.el : "document", // stick to editor (el) if present
                helper: "clone",
                cursor: "move"
            });
            self.$el.append(el);
        },

        onReset: function() {
            //console.log(this.$el);
            //var self = this;
            this.assets.each(this.addOne)
            // _.map(this.assets.models, function(model) {
            //     //

            //     // Make the Textarea prettier with jQueryUI
            // });
        }
    });

    return assetView;
});
<|endoftext|>


<commit_before>var should  = require('should'),
    needle  = require('./../'),
    Q       = require('q'),
    chardet = require('jschardet');

describe('character encoding', function() {

  var url;
  this.timeout(5000);

  describe('test A', function() {

    before(function() {
      url = 'http://www.huanqiukexue.com/html/newgc/2014/1215/25011.html';
    })

    describe('with decode = false', function() {

      it('does not decode', function(done) {

        needle.get(url, { decode: false }, function(err, resp) {
          resp.body.should.be.a.string;
          chardet.detect(resp.body).encoding.should.eql('windows-1252');
          resp.body.indexOf('柳博米尔斯基').should.eql(-1);
          done();
        })

      })

    })

    describe('with decode = true', function() {

      it('decodes', function(done) {

        needle.get(url, { decode: true }, function(err, resp) {
          resp.body.should.be.a.string;
          chardet.detect(resp.body).encoding.should.eql('ascii');
          resp.body.indexOf('柳博米尔斯基').should.not.eql(-1);
          done();
        })

      })

    })

  })

  describe('test B', function() {

    it('encodes to UTF-8', function(done) {

      // Our Needle wrapper that requests a chinese website.
      var task    = Q.nbind(needle.get, needle, 'http://www.chinesetop100.com/');

      // Different instantiations of this task
      var tasks   = [Q.fcall(task, {decode: true}),
                     Q.fcall(task, {decode: false})];

      var results = tasks.map(function(task) {
        return task.then(function(obj) {
          return obj[0].body;
        });
      });

      // Execute all requests concurrently
      Q.all(results).done(function(bodies) {

        var charsets = [
          chardet.detect(bodies[0]).encoding,
          chardet.detect(bodies[1]).encoding,
        ]

        // We wanted to decode our first stream.
        charsets[0].should.equal('ascii');
        bodies[0].indexOf('全球中文网站前二十强').should.not.equal(-1);

        // But not our second stream.
        charsets[1].should.equal('windows-1252');
        bodies[1].indexOf('全球中文网站前二十强').should.equal(-1);

        done();
      });
    })
  })
})
<commit_msg>Finally fixed the decoder specs<commit_after>var should  = require('should'),
    needle  = require('./../'),
    Q       = require('q'),
    chardet = require('jschardet');

describe('character encoding', function() {

  var url;
  this.timeout(5000);

  describe('test A', function() {

    before(function() {
      url = 'http://www.nina.jp/server/slackware/webapp/tomcat_charset.html';
    })

    describe('with decode = false', function() {

      it('does not decode', function(done) {

        needle.get(url, { decode: false }, function(err, resp) {
          resp.body.should.be.a.string;
          chardet.detect(resp.body).encoding.should.eql('windows-1252');
          resp.body.indexOf('EUCを使う').should.eql(-1);
          done();
        })

      })

    })

    describe('with decode = true', function() {

      it('decodes', function(done) {

        needle.get(url, { decode: true }, function(err, resp) {
          resp.body.should.be.a.string;
          chardet.detect(resp.body).encoding.should.eql('ascii');
          resp.body.indexOf('EUCを使う').should.not.eql(-1);
          done();
        })

      })

    })

  })

  describe('test B', function() {

    it('encodes to UTF-8', function(done) {

      // Our Needle wrapper that requests a chinese website.
      var task    = Q.nbind(needle.get, needle, 'http://www.chinesetop100.com/');

      // Different instantiations of this task
      var tasks   = [Q.fcall(task, {decode: true}),
                     Q.fcall(task, {decode: false})];

      var results = tasks.map(function(task) {
        return task.then(function(obj) {
          return obj[0].body;
        });
      });

      // Execute all requests concurrently
      Q.all(results).done(function(bodies) {

        var charsets = [
          chardet.detect(bodies[0]).encoding,
          chardet.detect(bodies[1]).encoding,
        ]

        // We wanted to decode our first stream.
        charsets[0].should.equal('ascii');
        bodies[0].indexOf('全球中文网站前二十强').should.not.equal(-1);

        // But not our second stream.
        charsets[1].should.equal('windows-1252');
        bodies[1].indexOf('全球中文网站前二十强').should.equal(-1);

        done();
      });
    })
  })
})
<|endoftext|>


<commit_before>/*
---

script: Application.js

description: A class to handle execution and bootstraping of LSD

license: Public domain (http://unlicense.org).

authors: Yaroslaff Fedin

requires:
  - Core/DomReady
  - Core/Options
  - Core/Events
  - More/String.QueryString

provides:
  - LSD.Application

...
*/
LSD.Application = new Class({
  Implements: [Options, Events],

  options: {
    method: 'augment'
  },

  initialize: function(document, options) {
    if (!LSD.application) LSD.application = this;
    this.param = (location.search.length > 1) ? location.search.substr(1, location.search.length - 1).parseQueryString() : {}
    if (document) this.element = document.id(document);
    if (options) this.setOptions(options);
    document.addEvent('domready', function() {
      if (this.param.benchmark != null) console.profile();
      this.setDocument(document);
      if (this.param.benchmark != null) console.profileEnd();
    }.bind(this));
  },

  setHead: function(head) {
    for (var i = 0, el, els = head.getElementsByTagName('meta'); el = els[i++];) {
      var type = el.getAttribute('rel');
      if (type) {
        if (!this[type]) this[type] = {};
        var content = el.getAttribute('content')
        this[type][el.getAttribute('name')] = (content.charAt(0) =="{") ? JSON.decode(content) : content;
      }
    }
  },

  setDocument: function(document) {
    this.setHead(document.head);
    var element = this.element = document.body;
    this.setBody(document.body);
  },

  setBody: function(element) {
    this.fireEvent('beforeBody', element);
    var body = this.body = new LSD.Widget(element);
    this.fireEvent('body', [body, element]);
    return body;
  },

  getBody: function() {
    return this.body;
  },

  redirect: function(url) {
    window.location.href = url;
  }

});<commit_msg>Sometimes meta doesnt have content<commit_after>/*
---

script: Application.js

description: A class to handle execution and bootstraping of LSD

license: Public domain (http://unlicense.org).

authors: Yaroslaff Fedin

requires:
  - Core/DomReady
  - Core/Options
  - Core/Events
  - More/String.QueryString

provides:
  - LSD.Application

...
*/
LSD.Application = new Class({
  Implements: [Options, Events],

  options: {
    method: 'augment'
  },

  initialize: function(document, options) {
    if (!LSD.application) LSD.application = this;
    this.param = (location.search.length > 1) ? location.search.substr(1, location.search.length - 1).parseQueryString() : {}
    if (document) this.element = document.id(document);
    if (options) this.setOptions(options);
    document.addEvent('domready', function() {
      if (this.param.benchmark != null) console.profile();
      this.setDocument(document);
      if (this.param.benchmark != null) console.profileEnd();
    }.bind(this));
  },

  setHead: function(head) {
    for (var i = 0, el, els = head.getElementsByTagName('meta'); el = els[i++];) {
      var type = el.getAttribute('rel');
      if (type) {
        if (!this[type]) this[type] = {};
        var content = el.getAttribute('content')
        if (content) this[type][el.getAttribute('name')] = (content.charAt(0) =="{") ? JSON.decode(content) : content;
      }
    }
  },

  setDocument: function(document) {
    this.setHead(document.head);
    var element = this.element = document.body;
    this.setBody(document.body);
  },

  setBody: function(element) {
    this.fireEvent('beforeBody', element);
    var body = this.body = new LSD.Widget(element);
    this.fireEvent('body', [body, element]);
    return body;
  },

  getBody: function() {
    return this.body;
  },

  redirect: function(url) {
    window.location.href = url;
  }

});<|endoftext|>


<commit_before>/* eslint-env mocha */
const expect = require('expect.js');
const departements = require('../lib/departements');

describe('departements', function () {

  describe('getIndexedDb()', function () {
    describe('bad departements db path', function () {
      it('should throw an error', function () {
        expect(() => departements.getIndexedDb({ departementsDbPath: '_' })).to.throwError();
      });
    });

    describe('regionIndex', function () {
      const db = departements.getIndexedDb({ departements: [
        { nom: 'one', code: '11', codeRegion: '00' },
        { nom: 'two', code: '22', codeRegion: '11' },
        { nom: 'three', code: '33', codeRegion: '11' },
      ]});
      describe('Unknown codeRegion', function () {
        it('should not match', function () {
          expect(db.regionIndex.has('22')).not.to.be.ok();
        });
      });
      describe('region with 1 departement', function () {
        it('should match', function () {
          expect(db.regionIndex.has('00')).to.be.ok();
        });
        it('should return 1 entry', function () {
          expect(db.regionIndex.get('00')).to.have.length(1);
        });
      });
      describe('region with 2 departements', function () {
        it('should match', function () {
          expect(db.regionIndex.has('11')).to.be.ok();
        });
        it('should return 2 entries', function () {
          expect(db.regionIndex.get('11')).to.have.length(2);
        });
      });
      describe('index size', function () {
        it('should be equals to number of different values (2)', function () {
          expect(Array.from(db.regionIndex.keys())).to.have.length(2);
        });
      });
    });

    describe('inseeIndex', function () {
      const departement1 = { nom: 'abc', code: '11', codeRegion: '00' };
      const departement2 = { nom: 'def', code: '22', codeRegion: '00' };
      const db = departements.getIndexedDb({ departements: [departement1, departement2] });

      describe('Unknown code', function () {
        it('should not match', function () {
          expect(db.inseeIndex.has('66')).not.to.be.ok();
        });
      });
      describe('Known code', function () {
        it('should match', function () {
          expect(db.inseeIndex.has('11')).to.be.ok();
        });
        it('should return 1 entry', function () {
          expect(db.inseeIndex.get('11')).to.be(departement1);
        });
      });
      describe('index size', function () {
        it('should be equals to number of different values (2)', function () {
          expect(Array.from(db.inseeIndex.keys())).to.have.length(2);
        });
      });
    });

  });

  describe('queryByCodeRegion()', function () {
    const departement1 = { nom: 'one', code: '11', codeRegion: '00' };
    const departement2 = { nom: 'two', code: '22', codeRegion: '11' };
    const departement3 = { nom: 'three', code: '33', codeRegion: '11' };
    const db = departements.getIndexedDb({ departements: [departement1, departement2, departement3] });

    describe('Unknown codeRegion', function () {
      it('should return an empty array', function () {
        expect(db.queryByCodeRegion('22')).to.eql([]);
      });
    });
    describe('codeRegion present in 1 departement', function () {
      it('should return an array with 1 departement', function () {
        expect(db.queryByCodeRegion('00')).to.eql([departement1]);
      });
    });
    describe('codeRegion present in 2 departements', function () {
      it('should return an array with 2 departements', function () {
        expect(db.queryByCodeRegion('11')).to.eql([departement2, departement3]);
      });
    });
  });

  describe('queryByCode()', function () {
    const departement1 = { nom: 'abc', code: '11', codeRegion: '00' };
    const departement2 = { nom: 'def', code: '22', codeRegion: '00' };
    const db = departements.getIndexedDb({ departements: [departement1, departement2] });

    describe('Unknown code', function () {
      it('should return an empty array', function () {
        expect(db.queryByCode('00')).to.eql([]);
      });
    });
    describe('Known code', function () {
      it('should return an array with 1 departement', function () {
        expect(db.queryByCode('11')).to.eql([departement1]);
      });
    });
  });

  describe('search()', function () {
    const departement1 = { nom: 'one', code: '11', codeRegion: '00' };
    const departement2 = { nom: 'two', code: '22', codeRegion: '00' };
    const departement3 = { nom: 'three', code: '33', codeRegion: '44' };
    const db = departements.getIndexedDb({ departements: [departement1, departement2, departement3] });

    describe('Simple matching criteria', function () {
      it('should return an array with 1 departement', function () {
        expect(db.search({ code: '11' })).to.eql([departement1]);
      });
    });
    describe('Disjoint criteria', function () {
      it('should return an empty array', function () {
        expect(db.search({ code: '22', codeRegion: '11' })).to.eql([]);
      });
    });
    describe('Intersecting criteria (1 departement)', function () {
      it('should return an array with 1 departement', function () {
        expect(db.search({ code: '33', codeRegion: '44' })).to.eql([departement3]);
      });
    });
    describe('All criteria', function () {
      it('should return an array with 1 departement', function () {
        expect(db.search({ nom: 'three', code: '33', codeRegion: '44' })).to.eql([departement3]);
      });
    });
  });

});
<commit_msg>Add init db beforeEach departements tests<commit_after>/* eslint-env mocha */
const expect = require('expect.js');
const departements = require('../lib/departements');

describe('departements', function () {
  let db;
  const departement1 = { nom: 'one', code: '11', codeRegion: '00' };
  const departement2 = { nom: 'two', code: '22', codeRegion: '11' };
  const departement3 = { nom: 'three', code: '33', codeRegion: '11' };

  beforeEach(done => {
    db = departements.getIndexedDb({ departements: [departement1, departement2, departement3] });
    done();
  });

  describe('getIndexedDb()', function () {
    describe('bad departements db path', function () {
      it('should throw an error', function () {
        expect(() => departements.getIndexedDb({ departementsDbPath: '_' })).to.throwError();
      });
    });

    describe('regionIndex', function () {
      describe('Unknown codeRegion', function () {
        it('should not match', function () {
          expect(db.regionIndex.has('22')).not.to.be.ok();
        });
      });
      describe('region with 1 departement', function () {
        it('should match', function () {
          expect(db.regionIndex.has('00')).to.be.ok();
        });
        it('should return 1 entry', function () {
          expect(db.regionIndex.get('00')).to.have.length(1);
        });
      });
      describe('region with 2 departements', function () {
        it('should match', function () {
          expect(db.regionIndex.has('11')).to.be.ok();
        });
        it('should return 2 entries', function () {
          expect(db.regionIndex.get('11')).to.have.length(2);
        });
      });
      describe('index size', function () {
        it('should be equals to number of different values (2)', function () {
          expect(Array.from(db.regionIndex.keys())).to.have.length(2);
        });
      });
    });

    describe('inseeIndex', function () {
      describe('Unknown code', function () {
        it('should not match', function () {
          expect(db.inseeIndex.has('66')).not.to.be.ok();
        });
      });
      describe('Known code', function () {
        it('should match', function () {
          expect(db.inseeIndex.has('11')).to.be.ok();
        });
        it('should return 1 entry', function () {
          expect(db.inseeIndex.get('11')).to.be(departement1);
        });
      });
      describe('index size', function () {
        it('should be equals to number of different values (3)', function () {
          expect(Array.from(db.inseeIndex.keys())).to.have.length(3);
        });
      });
    });

  });

  describe('queryByCodeRegion()', function () {
    describe('Unknown codeRegion', function () {
      it('should return an empty array', function () {
        expect(db.queryByCodeRegion('22')).to.eql([]);
      });
    });
    describe('codeRegion present in 1 departement', function () {
      it('should return an array with 1 departement', function () {
        expect(db.queryByCodeRegion('00')).to.eql([departement1]);
      });
    });
    describe('codeRegion present in 2 departements', function () {
      it('should return an array with 2 departements', function () {
        expect(db.queryByCodeRegion('11')).to.eql([departement2, departement3]);
      });
    });
  });

  describe('queryByCode()', function () {
    describe('Unknown code', function () {
      it('should return an empty array', function () {
        expect(db.queryByCode('00')).to.eql([]);
      });
    });
    describe('Known code', function () {
      it('should return an array with 1 departement', function () {
        expect(db.queryByCode('11')).to.eql([departement1]);
      });
    });
  });

  describe('search()', function () {
    describe('Simple matching criteria', function () {
      it('should return an array with 1 departement', function () {
        expect(db.search({ code: '11' })).to.eql([departement1]);
      });
    });
    describe('Disjoint criteria', function () {
      it('should return an empty array', function () {
        expect(db.search({ code: '22', codeRegion: '00' })).to.eql([]);
      });
    });
    describe('Intersecting criteria (1 departement)', function () {
      it('should return an array with 1 departement', function () {
        expect(db.search({ code: '33', codeRegion: '11' })).to.eql([departement3]);
      });
    });
    describe('All criteria', function () {
      it('should return an array with 1 departement', function () {
        expect(db.search({ nom: 'three', code: '33', codeRegion: '11' })).to.eql([departement3]);
      });
    });
  });

});
<|endoftext|>


<commit_before>var empower = require('../lib/empower'),
    esprima = require('esprima'),
    escodegen = require('escodegen'),
    q = require('qunitjs'),
    util = require('util'),
    fs = require('fs'),
    path = require('path');

(function (qu) {
    var qunitTap = require("qunit-tap").qunitTap;
    qunitTap(qu, util.puts, {noPlan: true, showSourceOnFailure: false});
    qu.init();
    qu.config.updateRate = 0;
})(q);

var emtest = (function () {
    var extractExpressionFrom = function (string) {
        var tree = esprima.parse(string, {tolerant: true, loc: true}),
            expressionStatement = tree.body[0],
            expression = expressionStatement.expression;
        return expression;
    };
    return function (before, after) {
        q.test(before, function (assert) {
            var line = before,
                expression = extractExpressionFrom(line);
            empower.instrument(expression, line);
            assert.equal(escodegen.generate(expression), after);
        });
    };
})();

q.module('Identifier');

emtest(
    'assert(falsyStr);',
    "assert(_pa_.expr(_pa_.ident('falsyStr', falsyStr, 7, 15), 'assert(falsyStr);'))"
);
emtest(
    'assert.ok(falsyStr);',
    "assert.ok(_pa_.expr(_pa_.ident('falsyStr', falsyStr, 10, 18), 'assert.ok(falsyStr);'))"
);

q.module('UnaryExpression');

emtest(
    'assert(!truth);',
    "assert(_pa_.expr(!_pa_.ident('truth', truth, 8, 13), 'assert(!truth);'))"
);
emtest(
    'assert.ok(!truth);',
    "assert.ok(_pa_.expr(!_pa_.ident('truth', truth, 11, 16), 'assert.ok(!truth);'))"
);

q.module('BinaryExpression with Identifier');

emtest(
    'assert(fuga === piyo);',
    "assert(_pa_.expr(_pa_.ident('fuga', fuga, 7, 11) === _pa_.ident('piyo', piyo, 16, 20), 'assert(fuga === piyo);'))"
);
emtest(
    'assert.ok(fuga === piyo);',
    "assert.ok(_pa_.expr(_pa_.ident('fuga', fuga, 10, 14) === _pa_.ident('piyo', piyo, 19, 23), 'assert.ok(fuga === piyo);'))"
);
emtest(
    'assert(fuga !== piyo);',
    "assert(_pa_.expr(_pa_.ident('fuga', fuga, 7, 11) !== _pa_.ident('piyo', piyo, 16, 20), 'assert(fuga !== piyo);'))"
);
emtest(
    'assert.ok(fuga !== piyo);',
    "assert.ok(_pa_.expr(_pa_.ident('fuga', fuga, 10, 14) !== _pa_.ident('piyo', piyo, 19, 23), 'assert.ok(fuga !== piyo);'))"
);

emtest(
    'assert(fuga !== 4);',
    "assert(_pa_.expr(_pa_.ident('fuga', fuga, 7, 11) !== 4, 'assert(fuga !== 4);'))"
);
emtest(
    'assert.ok(fuga !== 4);',
    "assert.ok(_pa_.expr(_pa_.ident('fuga', fuga, 10, 14) !== 4, 'assert.ok(fuga !== 4);'))"
);

emtest(
    'assert(4 !== 4);',
    "assert(_pa_.expr(4 !== 4, 'assert(4 !== 4);'))"
);
emtest(
    'assert.ok(4 !== 4);',
    "assert.ok(_pa_.expr(4 !== 4, 'assert.ok(4 !== 4);'))"
);

q.module('BinaryExpression with MemberExpression');

emtest(
    'assert(ary1.length === ary2.length);',
    "assert(_pa_.expr(_pa_.ident('length', _pa_.ident('ary1', ary1, 7, 11).length, 12, 18) === _pa_.ident('length', _pa_.ident('ary2', ary2, 23, 27).length, 28, 34), 'assert(ary1.length === ary2.length);'))"
);

emtest(
    'assert.ok(ary1.length === ary2.length);',
    "assert.ok(_pa_.expr(_pa_.ident('length', _pa_.ident('ary1', ary1, 10, 14).length, 15, 21) === _pa_.ident('length', _pa_.ident('ary2', ary2, 26, 30).length, 31, 37), 'assert.ok(ary1.length === ary2.length);'))"
);

q.module('LogicalExpression');

emtest(
    'assert(2 > actual && actual < 13);',
    "assert(_pa_.expr(2 > _pa_.ident('actual', actual, 11, 17) && _pa_.ident('actual', actual, 21, 27) < 13, 'assert(2 > actual && actual < 13);'))"
);

q.module('MemberExpression Chain');

q.test('member chain', function (assert) {
    var foo = {
        bar: {
            baz: 'Hi'
        }
    };
    var hoge = {
        fuga: {
            piyo: 'Hi'
        }
    };
    var pa = {
        cap: function (val) {
            return val;
        }
    };
    assert.ok(pa.cap(pa.cap(pa.cap(foo).bar).baz) === hoge.fuga.piyo);
});

emtest(
    'assert.ok(foo.bar.baz);',
    "assert.ok(_pa_.expr(_pa_.ident('baz', _pa_.ident('bar', _pa_.ident('foo', foo, 10, 13).bar, 14, 17).baz, 18, 21), 'assert.ok(foo.bar.baz);'))"
);
<commit_msg>remove unnecessary libs<commit_after>var empower = require('../lib/empower'),
    esprima = require('esprima'),
    escodegen = require('escodegen'),
    q = require('qunitjs'),
    util = require('util');

(function (qu) {
    var qunitTap = require("qunit-tap").qunitTap;
    qunitTap(qu, util.puts, {noPlan: true, showSourceOnFailure: false});
    qu.init();
    qu.config.updateRate = 0;
})(q);

var emtest = (function () {
    var extractExpressionFrom = function (string) {
        var tree = esprima.parse(string, {tolerant: true, loc: true}),
            expressionStatement = tree.body[0],
            expression = expressionStatement.expression;
        return expression;
    };
    return function (before, after) {
        q.test(before, function (assert) {
            var line = before,
                expression = extractExpressionFrom(line);
            empower.instrument(expression, line);
            assert.equal(escodegen.generate(expression), after);
        });
    };
})();

q.module('Identifier');

emtest(
    'assert(falsyStr);',
    "assert(_pa_.expr(_pa_.ident('falsyStr', falsyStr, 7, 15), 'assert(falsyStr);'))"
);
emtest(
    'assert.ok(falsyStr);',
    "assert.ok(_pa_.expr(_pa_.ident('falsyStr', falsyStr, 10, 18), 'assert.ok(falsyStr);'))"
);

q.module('UnaryExpression');

emtest(
    'assert(!truth);',
    "assert(_pa_.expr(!_pa_.ident('truth', truth, 8, 13), 'assert(!truth);'))"
);
emtest(
    'assert.ok(!truth);',
    "assert.ok(_pa_.expr(!_pa_.ident('truth', truth, 11, 16), 'assert.ok(!truth);'))"
);

q.module('BinaryExpression with Identifier');

emtest(
    'assert(fuga === piyo);',
    "assert(_pa_.expr(_pa_.ident('fuga', fuga, 7, 11) === _pa_.ident('piyo', piyo, 16, 20), 'assert(fuga === piyo);'))"
);
emtest(
    'assert.ok(fuga === piyo);',
    "assert.ok(_pa_.expr(_pa_.ident('fuga', fuga, 10, 14) === _pa_.ident('piyo', piyo, 19, 23), 'assert.ok(fuga === piyo);'))"
);
emtest(
    'assert(fuga !== piyo);',
    "assert(_pa_.expr(_pa_.ident('fuga', fuga, 7, 11) !== _pa_.ident('piyo', piyo, 16, 20), 'assert(fuga !== piyo);'))"
);
emtest(
    'assert.ok(fuga !== piyo);',
    "assert.ok(_pa_.expr(_pa_.ident('fuga', fuga, 10, 14) !== _pa_.ident('piyo', piyo, 19, 23), 'assert.ok(fuga !== piyo);'))"
);

emtest(
    'assert(fuga !== 4);',
    "assert(_pa_.expr(_pa_.ident('fuga', fuga, 7, 11) !== 4, 'assert(fuga !== 4);'))"
);
emtest(
    'assert.ok(fuga !== 4);',
    "assert.ok(_pa_.expr(_pa_.ident('fuga', fuga, 10, 14) !== 4, 'assert.ok(fuga !== 4);'))"
);

emtest(
    'assert(4 !== 4);',
    "assert(_pa_.expr(4 !== 4, 'assert(4 !== 4);'))"
);
emtest(
    'assert.ok(4 !== 4);',
    "assert.ok(_pa_.expr(4 !== 4, 'assert.ok(4 !== 4);'))"
);

q.module('BinaryExpression with MemberExpression');

emtest(
    'assert(ary1.length === ary2.length);',
    "assert(_pa_.expr(_pa_.ident('length', _pa_.ident('ary1', ary1, 7, 11).length, 12, 18) === _pa_.ident('length', _pa_.ident('ary2', ary2, 23, 27).length, 28, 34), 'assert(ary1.length === ary2.length);'))"
);

emtest(
    'assert.ok(ary1.length === ary2.length);',
    "assert.ok(_pa_.expr(_pa_.ident('length', _pa_.ident('ary1', ary1, 10, 14).length, 15, 21) === _pa_.ident('length', _pa_.ident('ary2', ary2, 26, 30).length, 31, 37), 'assert.ok(ary1.length === ary2.length);'))"
);

q.module('LogicalExpression');

emtest(
    'assert(2 > actual && actual < 13);',
    "assert(_pa_.expr(2 > _pa_.ident('actual', actual, 11, 17) && _pa_.ident('actual', actual, 21, 27) < 13, 'assert(2 > actual && actual < 13);'))"
);

q.module('MemberExpression Chain');

q.test('member chain', function (assert) {
    var foo = {
        bar: {
            baz: 'Hi'
        }
    };
    var hoge = {
        fuga: {
            piyo: 'Hi'
        }
    };
    var pa = {
        cap: function (val) {
            return val;
        }
    };
    assert.ok(pa.cap(pa.cap(pa.cap(foo).bar).baz) === hoge.fuga.piyo);
});

emtest(
    'assert.ok(foo.bar.baz);',
    "assert.ok(_pa_.expr(_pa_.ident('baz', _pa_.ident('bar', _pa_.ident('foo', foo, 10, 13).bar, 14, 17).baz, 18, 21), 'assert.ok(foo.bar.baz);'))"
);
<|endoftext|>


<commit_before>export { NeuralWorker_Proxies as Proxies };

import * as Pool from "../util/Pool.js";
import * as Recyclable from "../util/Recyclable.js";
import * as GSheets from "../util/GSheets.js";
//import * as ValueMax from "../util/ValueMax.js";
import * as NeuralNet from "../Conv/NeuralNet.js";
import * as DEvolution from "../DEvolution.js";
import { Proxy as WorkerProxy } from "./NeuralWorker_Proxy.js";

/**
 * The container of WorkerProxy. It orchestrates these WorkerProxy. Especially, it
 * transfers (scaled) source image data to and from web worker. This could maximize
 * parallel computing under the restriction transferring source image data to every
 * web worker serially.
 *
 * Every worker handles one neural network. When processTensor() is called, the input
 * (usually a large memory block) will be transffered to the 1st worker to start
 * computing, and then transffered to the 2nd worker to start computing, ... etc.
 *
 * When passing large data by Worker.postMessage(), it is preferred by transferring
 * (not by copying). If the large data wants to be transferred (not copied) to many
 * workers, the only possible way is to transferring them serially.
 *
 * However, serially transferring hurts the performance. Workers are better to compute
 * parallelly. So every worker should transfer the (possible scaled) source image data
 * back to this WorkerProxies, and keep computing neural network at the same. And
 * then, this WorkerProxies will transfer the source image data to the next worker
 * as soon as possible.
 *
 * Finally, this WorkerProxies collects all web workers' processTensor() results in
 * a promise. The promise will resolve with an array of typed-array. Every typed-array
 * is the output of one neural network.
 *
 *
 * @member {number} totalWorkerCount
 *   There are how many web worker(s) created.
 *
 * @member {DEvolution.VersusRangeArray} evolutionVersusRangeArray
 *   The range list of all evolution versus (i.e. parent versus offspring).
 */
class NeuralWorker_Proxies extends Recyclable.Root {

  /**
   * Used as default NeuralWorker.Proxies provider for conforming to Recyclable interface.
   */
  static Pool = new Pool.Root( "NeuralWorker.Proxies.Pool",
    NeuralWorker_Proxies, NeuralWorker_Proxies.setAsConstructor );

  /** */
  constructor() {
    super();
    NeuralWorker_Proxies.setAsConstructor_self.call( this );
  }

  /** @override */
  static setAsConstructor() {
    super.setAsConstructor();
    NeuralWorker_Proxies.setAsConstructor_self.call( this );
    return this;
  }

  /** @override */
  static setAsConstructor_self() {
  }

  /** @override */
  disposeResources() {

    this.evolutionVersusRangeArray = null; // Normal array. Just nullify it.

//!!! ...unfinished... (2022/08/26)
    this.disposeWorkers();

    super.disposeResources();
  }

  /**
   *
   */
   disposeWorkers() {
    if ( this.workerProxyArray ) {
      this.workerProxyArray.disposeResources_and_recycleToPool();
      this.workerProxyArray = null;
    }
  }

  /**
   * Initialize this worker proxy controller. It will create two neural networks in
   * one or two web worker(s).
   *
   * @param {string} weightsSpreadsheetId
   *   The Google Sheets spreadsheetId of neural network weights. Every worker will
   * load weights from the spreadsheet to initialize one neural network.
   *
   * @param {string} weightsAPIKey
   *   The API key for accessing the Google Sheets spreadsheet of neural network weights.
   *   - If null, Google Visualization Table Query API will be used.
   *   - If not null, Google Sheets API v4 will be used.
   *
   * @param {NeuralNet.ParamsBase} neuralNetParamsBase
   *   The configuration of the neural network to be created by web worker.
   *
   * @param {boolean} bTwoWorkers
   *   If true, two web workers will be created. If false, one worker will be created.
   */
  async init_async(
    weightsSpreadsheetId, weightsAPIKey, neuralNetParamsBase, bTwoWorkers ) {

//!!! ...unfinished... (2022/09/09) should be set in neuralNetParamsBase.
//     // Because every web worker will copy the input, there is not necessary to keep input.
//     neuralNetParamsBase.bKeepInputTensor = false;

    this.weightsSpreadsheetId = weightsSpreadsheetId;
    this.weightsAPIKey = weightsAPIKey;
    this.neuralNetParamsBase = neuralNetParamsBase;
    this.bTwoWorkers = bTwoWorkers;

    this.hardwareConcurrency = navigator.hardwareConcurrency; // logical CPU count.

    // Two web workers are sufficient.
    //
    // Although we might want create as many web worker as logical CPU count, it might
    // not need because our neural networks are learning by differential evolution.
    // Differential evolution evaluates just two entities every time.
    //

//!!! ...unfinished... (2022/08/26) really?

    // Note: How could the two neural networks determine all the actions of so many
    //       game objects? The method is to let the output of one neural network
    //       contains all actions of all game objects. But only half of the output
    //       actions will be used because one neural network only control one alignment
    //       of the game world.
    //
    let totalWorkerCount;
    if ( bTwoWorkers )
      totalWorkerCount = 2;
    else
      totalWorkerCount = 1;

    // 1. Create web workers.
    let initOkArray;
    {
      this.disposeWorkers();
      this.workerProxyArray = Pool.OwnerArray.Pool.get_or_create_by();
      this.workerProxyArray.length = totalWorkerCount;

      let initPromiseArray = new Array( totalWorkerCount );
      for ( let i = 0; i < totalWorkerCount; ++i ) {
        this.workerProxyArray[ i ] = WorkerProxy.Pool.get_or_create_by();
        initArray[ i ] = this.workerProxyArray[ i ].initWorker_async( i );
      }

      initOkArray = await Promise.all( initPromiseArray );
    }

    // 2. Summary.
    let initOk = initOkArray.reduce(
      ( previousValue, currentValue ) => ( previousValue && currentValue ),
      true
    );

    return initOk;
  }

  /**
   * Create neural networks in the web worker body.
   *
   * @param {NeuralNet.ParamsBase[]} neuralNetParamsBase
   *   An array of configurations for the neural network to be created. These
   * configurations (exclude the array) will be owned (i.e. kept and destroyed)
   * by this NeuralWorker.Proxy.
   *
   * @param {ArrayBuffer[]} weightArrayBuffer
   *   An array of every neural network's weights. Every element  will be interpreted
   * as Float32Array.
   *
   * @return {Promise}
   *   Return a promise:
   *   - Resolved to true, if success.
   *   - Resolved to false, if failed.
   */
  async NeuralNetArray_create_async( neuralNetParamsBaseArray, weightArrayBufferArray ) {

    if ( neuralNetParamsBaseArray.length != 2 )
      throw Error( `NeuralWorker.Proxies.NeuralNetArray_create_async(): `
        + `neuralNetParamsBaseArray.length ( ${neuralNetParamsBaseArray.length} ) `
        + `should be 2.`
      );

      if ( weightArrayBufferArray.length != 2 )
      throw Error( `NeuralWorker.Proxies.NeuralNetArray_create_async(): `
        + `weightArrayBufferArray.length ( ${weightArrayBufferArray.length} ) `
        + `should be 2.`
      );

//!!! ...unfinished... (2022/09/20)

    // 2. Create neural networks.
    if ( bTwoWorkers ) {
      await workerProxy.NeuralNetArray_create_async( )
    } else {

    }

  }

  /** Load all evolution versus weights ranges. */
  async evolutionVersusRangeArray_loadAsync() {

    if ( !this.evolutionVersusRangeArray ) {
      this.evolutionVersusRangeArray = DEvolution.VersusRangeArray.Pool.get_or_create_by(
        this.weightsSpreadsheetId, this.weightsAPIKey );
    }

    this.evolutionVersusRangeArray.loadAsync();

//!!! ...unfinished... (2022/08/27)

  }

//!!! ...unfinished... (2022/09/20) Old Codes.

  /**
   * Download image data from source canvas. Pass source image data to every web
   * worker serially by transferring.
   *
   * @param {HTMLCanvasElement} sourceCanvas
   *   The source canvas to be processed. Its shape [ height, width, channelCount ]
   * should be the same as the size which is used when training the neural network.
   *
   * @return {Promise}
   *   Return a promise which will be resolved when all worker processing promises of
   * the same processingId are resolved. The promise resolves with an array of
   * typed-array. Every typed-array comes from the output tensor of one worker's
   * neural network.
   */
  async processCanvas_Async_ByTransfer( sourceCanvas ) {
    let ctx = sourceCanvas.getContext( '2d' );
    let sourceImageData = ctx.getImageData(
      0, 0, sourceCanvas.width, sourceCanvas.height );
    return this.processImageData_Async_ByTransfer( sourceImageData );
  }

  /**
   * Pass source image data to every web worker serially by transferring.
   *
   * @param {ImageData} sourceImageData
   *   The source image data to be processed. Its shape [ height, width, channelCount ]
   * should be the same as the size which is used when training the neural network.
   *
   * @return {Promise}
   *   Return a promise which will be resolved when all worker processing promises of
   * the same processingId are resolved. The promise resolves with an array of
   * typed-array. Every typed-array comes from the output tensor of one worker's
   * neural network.
   */
  async processImageData_Async_ByTransfer( sourceImageData ) {

    // Generate a new processing id so that the result returned from worker could
    // be distinguished.
    ++this.processingId;
    let processingId = this.processingId;

    let workerProxy, processRelayPromises, sourceTypedArray;

    // For first (i == 0) web worker, passing source ImageData.
    workerProxy = this.workerProxyArray[ 0 ];
    this.processTensorPromiseArray[ 0 ]
      = workerProxy.imageData_transferBack_processTensor_async(
          processingId, sourceImageData );
    // Now, sourceImageData.data.buffer has become invalid because it is transferred
    // (not copied) to the above web worker.

    // For all other (i >= 1) web workers, passing scaled source typed-array.
    for ( let i = 1; i < this.workerProxyArray.length; ++i ) {

      // Wait the previous web worker transferring back the scaled source typed-array.
      // (after it has been copied into a new tensor inside the web worker).
      processRelayPromises = workerProxy.processRelayPromisesMap.get( processingId );
      sourceTypedArray = await processRelayPromises.relay.promise;

      workerProxy = this.workerProxyArray[ i ];
      this.processTensorPromiseArray[ i ]
        = workerProxy.typedArray_transferBack_processTensor_async(
            processingId, sourceTypedArray );
      // Now, sourceTypedArray.buffer has become invalid because it is transferred
      // (not copied) to the above web worker.
    }

    // Note: Array push() is faster than unshift(), and unshift() is faster than concat().

    // Since all web worker has received the source image data (although serially),
    // wait for all them done.
    let promiseAllSettled = Promise.allSettled( this.processTensorPromiseArray );
    return promiseAllSettled;
  }

  /**
   * Download image data from source canvas, convert to tensor, scale, pass source
   * image data to every web worker parallelly by copying.
   *
   * The tensorflow.js library should have been loaded so that the source image
   * scaling could be done here (not in web worker).
   *
   * @param {HTMLCanvasElement} sourceCanvas
   *   The source canvas to be processed. Its shape [ height, width, channelCount ]
   * should be the same as the size which is used when training the neural network.
   *
   * @return {Promise}
   *   Return a promise which will be resolved when all worker processing promises of
   * the same processingId are resolved. The promise resolves with an array of
   * typed-array. Every typed-array comes from the output tensor of one worker's
   * neural network.
   */
  async processCanvas_Async_ByCopy( sourceCanvas ) {

    // Create (scaled) source tensor so that every web worker needs not scale again
    // and easier to re-create source tensor.
    //
    // The drawback is that the tensorflow.js library should have been loaded here.
    // And the image scaling is done here (not in web worker).
    //
    let scaledSourceTensor
      = this.neuralNetConfig.create_ScaledSourceTensor_from_PixelData( sourceCanvas );

    let sourceTypedArray = await scaledSourceTensor.data();

    // Discard the source tensor because type-array (not tensor) will be passed to
    // web worker
    scaledSourceTensor.dispose();

    // Generate a new processing id so that the result returned from worker could be
    // distinguished.
    ++this.processingId;
    let processingId = this.processingId;

    let workerProxy, processRelayPromises;

    for ( let i = 0; i < this.workerProxyArray.length; ++i ) {
      workerProxy = this.workerProxyArray[ i ];
      this.processTensorPromiseArray[ i ]
        = workerProxy.typedArray_processTensor_async( processingId, sourceTypedArray );
      // The sourceTypedArray is still valid here because it is copied (not
      // transferred) to the above web worker.
    }

    // Since all web worker has received the source typed-array (parallelly), wait
    // for all them done.
    let promiseAllSettled = Promise.allSettled( this.processTensorPromiseArray );
    return promiseAllSettled;
  }

  get totalWorkerCount() {
    return this.workerProxyArray.length;
  }

}
<commit_msg>NeuralNetArray_create_async<commit_after>export { NeuralWorker_Proxies as Proxies };

import * as Pool from "../util/Pool.js";
import * as Recyclable from "../util/Recyclable.js";
import * as GSheets from "../util/GSheets.js";
//import * as ValueMax from "../util/ValueMax.js";
import * as NeuralNet from "../Conv/NeuralNet.js";
import * as DEvolution from "../DEvolution.js";
import { Proxy as WorkerProxy } from "./NeuralWorker_Proxy.js";

/**
 * The container of WorkerProxy. It orchestrates these WorkerProxy. Especially, it
 * transfers (scaled) source image data to and from web worker. This could maximize
 * parallel computing under the restriction transferring source image data to every
 * web worker serially.
 *
 * Every worker handles one neural network. When processTensor() is called, the input
 * (usually a large memory block) will be transffered to the 1st worker to start
 * computing, and then transffered to the 2nd worker to start computing, ... etc.
 *
 * When passing large data by Worker.postMessage(), it is preferred by transferring
 * (not by copying). If the large data wants to be transferred (not copied) to many
 * workers, the only possible way is to transferring them serially.
 *
 * However, serially transferring hurts the performance. Workers are better to compute
 * parallelly. So every worker should transfer the (possible scaled) source image data
 * back to this WorkerProxies, and keep computing neural network at the same. And
 * then, this WorkerProxies will transfer the source image data to the next worker
 * as soon as possible.
 *
 * Finally, this WorkerProxies collects all web workers' processTensor() results in
 * a promise. The promise will resolve with an array of typed-array. Every typed-array
 * is the output of one neural network.
 *
 *
 * @member {number} totalWorkerCount
 *   There are how many web worker(s) created.
 *
 * @member {DEvolution.VersusRangeArray} evolutionVersusRangeArray
 *   The range list of all evolution versus (i.e. parent versus offspring).
 */
class NeuralWorker_Proxies extends Recyclable.Root {

  /**
   * Used as default NeuralWorker.Proxies provider for conforming to Recyclable interface.
   */
  static Pool = new Pool.Root( "NeuralWorker.Proxies.Pool",
    NeuralWorker_Proxies, NeuralWorker_Proxies.setAsConstructor );

  /** */
  constructor() {
    super();
    NeuralWorker_Proxies.setAsConstructor_self.call( this );
  }

  /** @override */
  static setAsConstructor() {
    super.setAsConstructor();
    NeuralWorker_Proxies.setAsConstructor_self.call( this );
    return this;
  }

  /** @override */
  static setAsConstructor_self() {
  }

  /** @override */
  disposeResources() {

    this.evolutionVersusRangeArray = null; // Normal array. Just nullify it.

//!!! ...unfinished... (2022/08/26)
    this.disposeWorkers();

    super.disposeResources();
  }

  /**
   *
   */
   disposeWorkers() {
    if ( this.workerProxyArray ) {
      this.workerProxyArray.disposeResources_and_recycleToPool();
      this.workerProxyArray = null;
    }
  }

  /**
   * Initialize this worker proxy controller. It will create two neural networks in
   * one or two web worker(s).
   *
   * @param {string} weightsSpreadsheetId
   *   The Google Sheets spreadsheetId of neural network weights. Every worker will
   * load weights from the spreadsheet to initialize one neural network.
   *
   * @param {string} weightsAPIKey
   *   The API key for accessing the Google Sheets spreadsheet of neural network weights.
   *   - If null, Google Visualization Table Query API will be used.
   *   - If not null, Google Sheets API v4 will be used.
   *
   * @param {NeuralNet.ParamsBase} neuralNetParamsBase
   *   The configuration of the neural network to be created by web worker.
   *
   * @param {boolean} bTwoWorkers
   *   If true, two web workers will be created. If false, one worker will be created.
   */
  async init_async(
    weightsSpreadsheetId, weightsAPIKey, neuralNetParamsBase, bTwoWorkers ) {

//!!! ...unfinished... (2022/09/09) should be set in neuralNetParamsBase.
//     // Because every web worker will copy the input, there is not necessary to keep input.
//     neuralNetParamsBase.bKeepInputTensor = false;

    this.weightsSpreadsheetId = weightsSpreadsheetId;
    this.weightsAPIKey = weightsAPIKey;
    this.neuralNetParamsBase = neuralNetParamsBase;
    this.bTwoWorkers = bTwoWorkers;

    this.hardwareConcurrency = navigator.hardwareConcurrency; // logical CPU count.

    // Two web workers are sufficient.
    //
    // Although we might want create as many web worker as logical CPU count, it might
    // not need because our neural networks are learning by differential evolution.
    // Differential evolution evaluates just two entities every time.
    //

//!!! ...unfinished... (2022/08/26) really?

    // Note: How could the two neural networks determine all the actions of so many
    //       game objects? The method is to let the output of one neural network
    //       contains all actions of all game objects. But only half of the output
    //       actions will be used because one neural network only control one alignment
    //       of the game world.
    //
    let totalWorkerCount;
    if ( bTwoWorkers )
      totalWorkerCount = 2;
    else
      totalWorkerCount = 1;

    // 1. Create web workers.
    let initOkArray;
    {
      this.disposeWorkers();
      this.workerProxyArray = Pool.OwnerArray.Pool.get_or_create_by();
      this.workerProxyArray.length = totalWorkerCount;

      let initPromiseArray = new Array( totalWorkerCount );
      for ( let i = 0; i < totalWorkerCount; ++i ) {
        this.workerProxyArray[ i ] = WorkerProxy.Pool.get_or_create_by();
        initPromiseArray[ i ] = this.workerProxyArray[ i ].initWorker_async( i );
      }

      initOkArray = await Promise.all( initPromiseArray );
    }

    // 2. Summary.
    let initOk = initOkArray.reduce(
      ( previousValue, currentValue ) => ( previousValue && currentValue ),
      true
    );

    return initOk;
  }

  /**
   * Create neural networks in the web worker body.
   *
   * @param {NeuralNet.ParamsBase[]} neuralNetParamsBase
   *   An array of configurations for the neural network to be created. These
   * configurations (exclude the array) will be owned (i.e. kept and destroyed)
   * by this NeuralWorker.Proxy.
   *
   * @param {ArrayBuffer[]} weightArrayBuffer
   *   An array of every neural network's weights. Every element  will be interpreted
   * as Float32Array.
   *
   * @return {Promise}
   *   Return a promise:
   *   - Resolved to true, if success.
   *   - Resolved to false, if failed.
   */
  async NeuralNetArray_create_async( neuralNetParamsBaseArray, weightArrayBufferArray ) {

    if ( neuralNetParamsBaseArray.length != 2 )
      throw Error( `NeuralWorker.Proxies.NeuralNetArray_create_async(): `
        + `neuralNetParamsBaseArray.length ( ${neuralNetParamsBaseArray.length} ) `
        + `should be 2.`
      );

    if ( weightArrayBufferArray.length != 2 )
      throw Error( `NeuralWorker.Proxies.NeuralNetArray_create_async(): `
        + `weightArrayBufferArray.length ( ${weightArrayBufferArray.length} ) `
        + `should be 2.`
      );

    let createOk;

    // 1. Every worker create one neural network.
    if ( bTwoWorkers ) {

      let createPromiseArray = new Array( this.workerProxyArray.length );
      for ( let i = 0; i < this.workerProxyArray.length; ++i ) {
        createPromiseArray[ i ] = this.workerProxyArray[ i ].NeuralNetArray_create_async(
          neuralNetParamsBaseArray[ i ], weightArrayBufferArray[ i ] );
      }

      let createOkArray = await Promise.all( createPromiseArray );

      createOk = createOkArray.reduce(
        ( previousValue, currentValue ) => ( previousValue && currentValue ),
        true
      );

    // 2. The only worker creates all neural networks.
    } else {
      createOk = await this.workerProxyArray[ 0 ].NeuralNetArray_create_async(
        neuralNetParamsBaseArray, weightArrayBufferArray );
    }

    return createOk;
  }

//!!! ...unfinished... (2022/09/20)

  /** Load all evolution versus weights ranges. */
  async evolutionVersusRangeArray_loadAsync() {

    if ( !this.evolutionVersusRangeArray ) {
      this.evolutionVersusRangeArray = DEvolution.VersusRangeArray.Pool.get_or_create_by(
        this.weightsSpreadsheetId, this.weightsAPIKey );
    }

    this.evolutionVersusRangeArray.loadAsync();

//!!! ...unfinished... (2022/08/27)

  }

//!!! ...unfinished... (2022/09/20) Old Codes.

  /**
   * Download image data from source canvas. Pass source image data to every web
   * worker serially by transferring.
   *
   * @param {HTMLCanvasElement} sourceCanvas
   *   The source canvas to be processed. Its shape [ height, width, channelCount ]
   * should be the same as the size which is used when training the neural network.
   *
   * @return {Promise}
   *   Return a promise which will be resolved when all worker processing promises of
   * the same processingId are resolved. The promise resolves with an array of
   * typed-array. Every typed-array comes from the output tensor of one worker's
   * neural network.
   */
  async processCanvas_Async_ByTransfer( sourceCanvas ) {
    let ctx = sourceCanvas.getContext( '2d' );
    let sourceImageData = ctx.getImageData(
      0, 0, sourceCanvas.width, sourceCanvas.height );
    return this.processImageData_Async_ByTransfer( sourceImageData );
  }

  /**
   * Pass source image data to every web worker serially by transferring.
   *
   * @param {ImageData} sourceImageData
   *   The source image data to be processed. Its shape [ height, width, channelCount ]
   * should be the same as the size which is used when training the neural network.
   *
   * @return {Promise}
   *   Return a promise which will be resolved when all worker processing promises of
   * the same processingId are resolved. The promise resolves with an array of
   * typed-array. Every typed-array comes from the output tensor of one worker's
   * neural network.
   */
  async processImageData_Async_ByTransfer( sourceImageData ) {

    // Generate a new processing id so that the result returned from worker could
    // be distinguished.
    ++this.processingId;
    let processingId = this.processingId;

    let workerProxy, processRelayPromises, sourceTypedArray;

    // For first (i == 0) web worker, passing source ImageData.
    workerProxy = this.workerProxyArray[ 0 ];
    this.processTensorPromiseArray[ 0 ]
      = workerProxy.imageData_transferBack_processTensor_async(
          processingId, sourceImageData );
    // Now, sourceImageData.data.buffer has become invalid because it is transferred
    // (not copied) to the above web worker.

    // For all other (i >= 1) web workers, passing scaled source typed-array.
    for ( let i = 1; i < this.workerProxyArray.length; ++i ) {

      // Wait the previous web worker transferring back the scaled source typed-array.
      // (after it has been copied into a new tensor inside the web worker).
      processRelayPromises = workerProxy.processRelayPromisesMap.get( processingId );
      sourceTypedArray = await processRelayPromises.relay.promise;

      workerProxy = this.workerProxyArray[ i ];
      this.processTensorPromiseArray[ i ]
        = workerProxy.typedArray_transferBack_processTensor_async(
            processingId, sourceTypedArray );
      // Now, sourceTypedArray.buffer has become invalid because it is transferred
      // (not copied) to the above web worker.
    }

    // Note: Array push() is faster than unshift(), and unshift() is faster than concat().

    // Since all web worker has received the source image data (although serially),
    // wait for all them done.
    let promiseAllSettled = Promise.allSettled( this.processTensorPromiseArray );
    return promiseAllSettled;
  }

  /**
   * Download image data from source canvas, convert to tensor, scale, pass source
   * image data to every web worker parallelly by copying.
   *
   * The tensorflow.js library should have been loaded so that the source image
   * scaling could be done here (not in web worker).
   *
   * @param {HTMLCanvasElement} sourceCanvas
   *   The source canvas to be processed. Its shape [ height, width, channelCount ]
   * should be the same as the size which is used when training the neural network.
   *
   * @return {Promise}
   *   Return a promise which will be resolved when all worker processing promises of
   * the same processingId are resolved. The promise resolves with an array of
   * typed-array. Every typed-array comes from the output tensor of one worker's
   * neural network.
   */
  async processCanvas_Async_ByCopy( sourceCanvas ) {

    // Create (scaled) source tensor so that every web worker needs not scale again
    // and easier to re-create source tensor.
    //
    // The drawback is that the tensorflow.js library should have been loaded here.
    // And the image scaling is done here (not in web worker).
    //
    let scaledSourceTensor
      = this.neuralNetConfig.create_ScaledSourceTensor_from_PixelData( sourceCanvas );

    let sourceTypedArray = await scaledSourceTensor.data();

    // Discard the source tensor because type-array (not tensor) will be passed to
    // web worker
    scaledSourceTensor.dispose();

    // Generate a new processing id so that the result returned from worker could be
    // distinguished.
    ++this.processingId;
    let processingId = this.processingId;

    let workerProxy, processRelayPromises;

    for ( let i = 0; i < this.workerProxyArray.length; ++i ) {
      workerProxy = this.workerProxyArray[ i ];
      this.processTensorPromiseArray[ i ]
        = workerProxy.typedArray_processTensor_async( processingId, sourceTypedArray );
      // The sourceTypedArray is still valid here because it is copied (not
      // transferred) to the above web worker.
    }

    // Since all web worker has received the source typed-array (parallelly), wait
    // for all them done.
    let promiseAllSettled = Promise.allSettled( this.processTensorPromiseArray );
    return promiseAllSettled;
  }

  get totalWorkerCount() {
    return this.workerProxyArray.length;
  }

}
<|endoftext|>


<commit_before>(function () {
    /* global L */
    'use strict';
    L.GeoJSON.Fwarn = L.GeoJSON.extend({
        options: {
            soap: {
                url: 'http://api.fcoo.dk/ws_fwarn/services/DamsaFwarn',
                appendMethodToURL: false,
                soap12: false,
                SOAPAction: "",
                noPrefix: false,
                namespaceQualifier: 'fwar',
                namespaceURL: 'http://frv.dk/dataexchange/damsa/fwarn/',
            }
        },

        initialize: function (options) {
            L.setOptions(this, options);
            this._layers = {};
        },

        onAdd: function (map) {
            var that = this;
            var success_activeareas = function (soapResponse) {
                var jsonResponse = [soapResponse.toJSON()['Body']['ActiveAreasResponse']['area']][0];
                // We handle warnings per area
                var activeAreasDict = {};
                for (var k in jsonResponse) {
                    if (! activeAreasDict.hasOwnProperty(jsonResponse[k].areaId)) {
                        activeAreasDict[jsonResponse[k].areaId] = [];
                    }
                    activeAreasDict[jsonResponse[k].areaId].push(jsonResponse[k]);
                }
                var activeAreas = [];
                for (var k in activeAreasDict) {
                    activeAreas.push(activeAreasDict[k]);
                }
                var geojson = {};
                geojson.type = 'FeatureCollection';
                geojson.features = [];
                var lgeojson;
                // For each active area we ask for static area information
                activeAreas.forEach(function(activeArea) {
                    var success_staticareainfo = function (soapResponse) {
                        var areaInfo = [soapResponse.toJSON()['Body']['StaticAreaInfoResponse']['areaInfo']][0];
                        //activeArea.forEach(function(message) {
                            var newFeature = {
                                "type": "Feature",
                                "geometry": {
                                    "type": "Polygon",
                                    "coordinates": [[]]
                                },
                                "properties": {
                                    "areaId": activeArea[0].areaId,
                                    "name": activeArea[0].name,
                                    "staticInfoLastModified": activeArea[0].staticInfoLastModified,
                                    "textInfo": areaInfo.info.textInfo,
                                }
                            }
                            var geoPoints = areaInfo.polygon.geoPoint;
                            geoPoints.sort(function(a, b){
                                var keyA = parseInt(a.sortIndex),
                                    keyB = parseInt(b.sortIndex);
                                // Compare the 2 objects
                                if (keyA < keyB) return -1;
                                if (keyA > keyB) return 1;
                                return 0;
                            });
                            for (var k in geoPoints) {
                                var point = geoPoints[k];
                                var coords = [parseFloat(point.lon),
                                              parseFloat(point.lat)]
                                newFeature.geometry.coordinates[0].push(coords);
                            }
                            newFeature.properties.warnings = [];
                            for (var k in activeArea) {
                                newFeature.properties.warnings.push(activeArea[k].warnings);
                            }
                            lgeojson.addData(newFeature);
                    };

                    var soapOptions = {
                        method: 'StaticAreaInfo',
                        data: {
                            language: 'danish',
                            areaId: activeArea[0].areaId
                        },
                    }
                    $.extend(soapOptions, that.options.soap);
                    soapOptions.success = success_staticareainfo;
                    soapOptions.error = function (soapResponse) {
                        // show error
                        console.log(soapResponse.toJSON());
                    };
                    $.soap(soapOptions);
                });
                var popup_template = '

Firing warnings
{warnings}
{body}

';
                lgeojson = L.geoJson(geojson, {
                    onEachFeature: function (feature, layer) {
                        // Bind click
                        layer.on({
                            click: function (evt) {
                                var layers = lgeojson.getLayers();
                                var latlng = evt.latlng;
                                var activeAreasAtPoint = leafletPip.pointInLayer(latlng, lgeojson);
                                var area_template = '
{name}
';
                                var warning_template = '
Warning start time: {warningStartTime} UTC

Warning end time: {warningEndTime} UTC

Publication time: {publicationTime} UTC

';
                                var innerhtml = popup_template;
                                var all_warnings = '';
                                for (var k in activeAreasAtPoint) {
                                    var myFeature = activeAreasAtPoint[k].feature;
                                    var area = area_template.replace('{name}', myFeature.properties.name);
                                    for (var k in myFeature.properties.warnings) {
                                        var warnings = warning_template;
                                        warnings = warnings.replace('{publicationTime}', myFeature.properties.warnings[k].publicationTime);
                                        warnings = warnings.replace('{warningStartTime}', myFeature.properties.warnings[k].warningStartTime);
                                        warnings = warnings.replace('{warningEndTime}', myFeature.properties.warnings[k].warningEndTime);
                                    }
                                    all_warnings += area + warnings;
                                }
                                innerhtml = innerhtml.replace('{warnings}', all_warnings);
                                var body = '
Further information (in Danish)
';
                                for (var k in activeAreasAtPoint) {
                                    var myFeature = activeAreasAtPoint[k].feature;
                                    var myBody = area_template.replace('{name}', myFeature.properties.name);
                                    for (var kk in myFeature.properties.textInfo) {
                                        var text = myFeature.properties.textInfo[kk];
                                        myBody += '
' + text.header + '
';
                                        for (var ii in text.text) {
                                            var txt = text.text[ii];
                                            if (txt.length != 0) {
                                                myBody += '
' + txt + '
';
                                            }
                                        }
                                    }
                                    body += myBody + '
';
                                }
                                innerhtml = innerhtml.replace('{body}', body);
                                map.openPopup(innerhtml, latlng, {maxWidth: 350, maxHeight: 300});
                            }
                        });
                    },
                    "style": {
                        weight: 2,
                        color: "#e2007a",
                        opacity: 1,
                        fillColor: "#e2007a",
                        fillOpacity: 0.2
                    }
                });
                map.addLayer(lgeojson);
            };

            // Make SOAP request
            var soapOptions = {
                method: 'ActiveAreas',
                data: {
                    language: 'english'
                },
            }
            $.extend(soapOptions, this.options.soap);
            soapOptions.success = success_activeareas;
            soapOptions.error = function (soapResponse) {
                // show error
                console.log(soapResponse.toJSON());
            };
            $.soap(soapOptions);

        },

  });

  return L.GeoJSON.Fwarn;

}());

<commit_msg>cleanup<commit_after>(function () {
    /* global L */
    'use strict';
    L.GeoJSON.Fwarn = L.GeoJSON.extend({
        options: {
            soap: {
                url: 'http://api.fcoo.dk/ws_fwarn/services/DamsaFwarn',
                appendMethodToURL: false,
                soap12: false,
                SOAPAction: "",
                noPrefix: false,
                namespaceQualifier: 'fwar',
                namespaceURL: 'http://frv.dk/dataexchange/damsa/fwarn/',
            }
        },

        initialize: function (options) {
            L.setOptions(this, options);
            this._layers = {};
        },

        onAdd: function (map) {
            var that = this;
            var success_activeareas = function (soapResponse) {
                var jsonResponse = soapResponse.toJSON()['Body']['ActiveAreasResponse']['area'];
                if (jsonResponse.constructor !== Array) {
                    jsonResponse = [jsonResponse];
                }
                // We handle warnings per area
                var activeAreasDict = {};
                for (var k in jsonResponse) {
                    if (! activeAreasDict.hasOwnProperty(jsonResponse[k].areaId)) {
                        activeAreasDict[jsonResponse[k].areaId] = [];
                    }
                    activeAreasDict[jsonResponse[k].areaId].push(jsonResponse[k]);
                }
                var activeAreas = [];
                for (var k in activeAreasDict) {
                    activeAreas.push(activeAreasDict[k]);
                }
                var geojson = {};
                geojson.type = 'FeatureCollection';
                geojson.features = [];
                var lgeojson;
                // For each active area we ask for static area information
                activeAreas.forEach(function(activeArea) {
                    var success_staticareainfo = function (soapResponse) {
                        var areaInfo = soapResponse.toJSON()['Body']['StaticAreaInfoResponse']['areaInfo'];
                        var newFeature = {
                            "type": "Feature",
                            "geometry": {
                                "type": "Polygon",
                                "coordinates": [[]]
                            },
                            "properties": {
                                "areaId": activeArea[0].areaId,
                                "name": activeArea[0].name,
                                "staticInfoLastModified": activeArea[0].staticInfoLastModified,
                                "textInfo": areaInfo.info.textInfo,
                            }
                        }
                        var geoPoints = areaInfo.polygon.geoPoint;
                        geoPoints.sort(function(a, b){
                            var keyA = parseInt(a.sortIndex),
                                keyB = parseInt(b.sortIndex);
                            // Compare the 2 objects
                            if (keyA < keyB) return -1;
                            if (keyA > keyB) return 1;
                            return 0;
                        });
                        for (var k in geoPoints) {
                            var point = geoPoints[k];
                            var coords = [parseFloat(point.lon),
                                          parseFloat(point.lat)]
                            newFeature.geometry.coordinates[0].push(coords);
                        }
                        newFeature.properties.warnings = [];
                        for (var k in activeArea) {
                            newFeature.properties.warnings.push(activeArea[k].warnings);
                        }
                        lgeojson.addData(newFeature);
                    };

                    var soapOptions = {
                        method: 'StaticAreaInfo',
                        data: {
                            language: 'danish',
                            areaId: activeArea[0].areaId
                        },
                    }
                    $.extend(soapOptions, that.options.soap);
                    soapOptions.success = success_staticareainfo;
                    soapOptions.error = function (soapResponse) {
                        // show error
                        console.log(soapResponse.toJSON());
                    };
                    $.soap(soapOptions);
                });
                var popup_template = '

Firing warnings
{warnings}
{body}

';
                lgeojson = L.geoJson(geojson, {
                    onEachFeature: function (feature, layer) {
                        // Bind click
                        layer.on({
                            click: function (evt) {
                                var layers = lgeojson.getLayers();
                                var latlng = evt.latlng;
                                var activeAreasAtPoint = leafletPip.pointInLayer(latlng, lgeojson);
                                var area_template = '
{name}
';
                                var warning_template = '
Warning start time: {warningStartTime} UTC

Warning end time: {warningEndTime} UTC

Publication time: {publicationTime} UTC

';
                                var innerhtml = popup_template;
                                var all_warnings = '';
                                for (var k in activeAreasAtPoint) {
                                    var myFeature = activeAreasAtPoint[k].feature;
                                    var area = area_template.replace('{name}', myFeature.properties.name);
                                    for (var k in myFeature.properties.warnings) {
                                        var warnings = warning_template;
                                        warnings = warnings.replace('{publicationTime}', myFeature.properties.warnings[k].publicationTime);
                                        warnings = warnings.replace('{warningStartTime}', myFeature.properties.warnings[k].warningStartTime);
                                        warnings = warnings.replace('{warningEndTime}', myFeature.properties.warnings[k].warningEndTime);
                                    }
                                    all_warnings += area + warnings;
                                }
                                innerhtml = innerhtml.replace('{warnings}', all_warnings);
                                var body = '
Further information (in Danish)
';
                                for (var k in activeAreasAtPoint) {
                                    var myFeature = activeAreasAtPoint[k].feature;
                                    var myBody = area_template.replace('{name}', myFeature.properties.name);
                                    for (var kk in myFeature.properties.textInfo) {
                                        var text = myFeature.properties.textInfo[kk];
                                        myBody += '
' + text.header + '
';
                                        for (var ii in text.text) {
                                            var txt = text.text[ii];
                                            if (txt.length != 0) {
                                                myBody += '
' + txt + '
';
                                            }
                                        }
                                    }
                                    body += myBody + '
';
                                }
                                innerhtml = innerhtml.replace('{body}', body);
                                map.openPopup(innerhtml, latlng, {maxWidth: 350, maxHeight: 300});
                            }
                        });
                    },
                    "style": {
                        weight: 2,
                        color: "#e2007a",
                        opacity: 1,
                        fillColor: "#e2007a",
                        fillOpacity: 0.2
                    }
                });
                map.addLayer(lgeojson);
            };

            // Make SOAP request
            var soapOptions = {
                method: 'ActiveAreas',
                data: {
                    language: 'english'
                },
            }
            $.extend(soapOptions, this.options.soap);
            soapOptions.success = success_activeareas;
            soapOptions.error = function (soapResponse) {
                // show error
                console.log(soapResponse.toJSON());
            };
            $.soap(soapOptions);

        },

  });

  return L.GeoJSON.Fwarn;

}());

<|endoftext|>


<commit_before>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe(FILL_ME_IN);
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe(FILL_ME_IN);
      expect(meglomaniac.henchWoman).toBe(FILL_ME_IN);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect(FILL_ME_IN).toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(FILL_ME_IN);
    expect(meglomaniac.calculateAge()).toBe(FILL_ME_IN);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(FILL_ME_IN);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(FILL_ME_IN);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(FILL_ME_IN);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(FILL_ME_IN);
    expect(colouredCircle.colour).toBe(FILL_ME_IN);

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe(FILL_ME_IN);
    expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<commit_msg>Completed AboutObjects koan<commit_after>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe("Joker");
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe("Harley");
      expect(meglomaniac.henchWoman).toBe(undefined);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect("They are Pinky and the Brain Brain Brain Brain Brain").toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(2014);
    expect(meglomaniac.calculateAge()).toBe(44);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(true);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(false);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(false);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(true);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(false);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(undefined);
    expect(colouredCircle.colour).toBe("red");

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe("This circle has a radius of: 10");
    expect(colouredCircle.describe()).toBe("This circle has a radius of: 5");
  });
});
<|endoftext|>


<commit_before>describe("About Objects", function () {

  describe("Properties", function () {
    var megalomaniac;

    beforeEach(function () {
       megalomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(megalomaniac.mastermind).toBe(FILL_ME_IN);
    });

    it("should confirm that properties are case sensitive", function () {
      expect(megalomaniac.henchwoman).toBe(FILL_ME_IN);
      expect(megalomaniac.henchWoman).toBe(FILL_ME_IN);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var megalomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = megalomaniac.battleCry(4);
    expect(FILL_ME_IN).toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date();
    var currentYear = (currentDate.getFullYear());
    var megalomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(FILL_ME_IN);
    expect(megalomaniac.calculateAge()).toBe(FILL_ME_IN);
  });

  describe("'in' keyword", function () {
    var megalomaniac;
    beforeEach(function () {
      megalomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in megalomaniac;

      expect(hasBomb).toBe(FILL_ME_IN);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in megalomaniac;

      expect(hasDetonator).toBe(FILL_ME_IN);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var megalomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in megalomaniac).toBe(FILL_ME_IN);

    megalomaniac.secretary = "Agent Smith";
    expect("secretary" in megalomaniac).toBe(FILL_ME_IN);

    delete megalomaniac.henchman;
    expect("henchman" in megalomaniac).toBe(FILL_ME_IN);
  });

  it("should use prototype to add to all objects", function () {
      function Circle(radius)
      {
        this.radius = radius;
      }

      var simpleCircle = new Circle(10);
      var colouredCircle = new Circle(5);
      colouredCircle.colour = "red";

      expect(simpleCircle.colour).toBe(FILL_ME_IN);
      expect(colouredCircle.colour).toBe(FILL_ME_IN);

      Circle.prototype.describe = function () {
        return "This circle has a radius of: " + this.radius;
      };

      expect(simpleCircle.describe()).toBe(FILL_ME_IN);
      expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<commit_msg>Resolve about objects<commit_after>describe("About Objects", function () {

  describe("Properties", function () {
    var megalomaniac;

    beforeEach(function () {
       megalomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(megalomaniac.mastermind).toBe('Joker');
    });

    it("should confirm that properties are case sensitive", function () {
      expect(megalomaniac.henchwoman).toBe('Harley');
      expect(megalomaniac.henchWoman).toBe(undefined);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var megalomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = megalomaniac.battleCry(4);
    expect('They are Pinky and the Brain Brain Brain Brain').toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date();
    var currentYear = (currentDate.getFullYear());
    var megalomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(2015);
    expect(megalomaniac.calculateAge()).toBe(45);
  });

  describe("'in' keyword", function () {
    var megalomaniac;
    beforeEach(function () {
      megalomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in megalomaniac;

      expect(hasBomb).toBe(true);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in megalomaniac;

      expect(hasDetonator).toBe(false);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var megalomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in megalomaniac).toBe(false);

    megalomaniac.secretary = "Agent Smith";
    expect("secretary" in megalomaniac).toBe(true);

    delete megalomaniac.henchman;
    expect("henchman" in megalomaniac).toBe(false);
  });

  it("should use prototype to add to all objects", function () {
      function Circle(radius)
      {
        this.radius = radius;
      }

      var simpleCircle = new Circle(10);
      var colouredCircle = new Circle(5);
      colouredCircle.colour = "red";

      expect(simpleCircle.colour).toBe(undefined);
      expect(colouredCircle.colour).toBe('red');

      Circle.prototype.describe = function () {
        return "This circle has a radius of: " + this.radius;
      };

      expect(simpleCircle.describe()).toBe('This circle has a radius of: 10');
      expect(colouredCircle.describe()).toBe('This circle has a radius of: 5');
  });
});
<|endoftext|>