<commit_before>/**
 * @file build test file
 * @author zhoumin
 */

const san = require('../../dist/san.ssr');
const fs = require('fs');
const path = require('path');

let htmlTpl = fs.readFileSync(path.resolve(__dirname, '..', 'index-ssr.html.tpl'), 'UTF-8');
let html = '';
let specTpls = '';

// generate html
function genContent({componentClass, componentSource, compontentData, specTpl, dirName, result}) {
    let renderer = san.compileToRenderer(componentClass);
    let id = dirName;

    // if no inject mark, add it
    if (!/\/\/\s*\[inject\]/.test(specTpl)) {
        specTpl = specTpl.replace(/function\s*\([a-z0-9_,$\s]*\)\s*\{/, function ($0) {
            return $0 + '\n// [inject] init';
        });
    }

    let injectHtml = result ? result : renderer(compontentData);

    html += `<div id="${id}">${injectHtml}</div>\n\n`;

    let preCode = `
        ${componentSource}
        var wrap = document.getElementById('${id}');
        var myComponent = new MyComponent({
            el: wrap.firstChild
        });
    `;
    specTpl = specTpl.replace(/\/\/\s*\[inject\]\s* init/, preCode);
    specTpls += specTpl;
};

function buildFile(filePath) {
    let files = fs.readdirSync(filePath);
    let componentClass;
    let componentSource;
    let specTpl;
    let compontentData;
    let dirName;
    let result;
    let sourceFile = '';

    if (!files.length) {
        return;
    }

    files.forEach(filename => {
        // absolute path
        let abFilePath = path.join(filePath, filename);
        let stats = fs.statSync(abFilePath);
        let isFile = stats.isFile();
        let isDir = stats.isDirectory();

        // if it's a file, init data
        if (isFile) {
            switch (filename) {
                case 'component.js':
                    componentClass = require(abFilePath);
                    componentSource = fs.readFileSync(path.resolve(abFilePath), 'UTF-8')
                        .split('\n')
                        .map(line => {
                            if (/(\.|\s)exports\s*=/.test(line)
                                || /san\s*=\s*require\(/.test(line)
                            ) {
                                return '';
                            }

                            return line;
                        })
                        .join('\n');
                    sourceFile = filename;
                    break;

                case 'spec.js':
                    specTpl = fs.readFileSync(path.resolve(abFilePath), 'UTF-8');
                    break;

                case 'data.js':
                    compontentData = require(abFilePath);
                    break;

                case 'result.html':
                    result = fs.readFileSync(path.resolve(abFilePath), 'UTF-8').replace('\n', '');
                    break;
            }

        }

        // iterate
        if (isDir) {
            console.log(`[Build SSR spec] ${filename}`);
            buildFile(abFilePath);
        }
    });

    let match = filePath.match(/[\/\\]([a-zA-Z0-9_,$\-]*)$/);
    // dirName is the identity of each component
    dirName = match[1];
    // generate html when it has source file
    if (sourceFile) {
        genContent({
            componentClass,
            componentSource,
            compontentData,
            specTpl,
            dirName,
            result
        });
    }
};

function writeIn({htmlTpl, html, specTpls}) {
    let karmaHtml = fs.readFileSync(path.resolve(__dirname, '..', 'karma-context.html.tpl'), 'UTF-8');
    fs.writeFileSync(
        path.resolve(__dirname, '..', 'karma-context.html'),
        karmaHtml.replace('##ssr-elements##', html),
        'UTF-8'
    );

    fs.writeFileSync(
        path.resolve(__dirname, '..', 'index-ssr.html'),
        htmlTpl.replace('##ssr-elements##', html),
        'UTF-8'
    );

    fs.writeFileSync(
        path.resolve(__dirname, 'ssr.spec.js'),
        specTpls,
        'UTF-8'
    );
};

console.log();
console.log('----- Build SSR Specs -----');

buildFile(path.resolve(__dirname, './'));
// write into file
writeIn({htmlTpl, html, specTpls});

console.log();
<commit_msg>no data output spec build<commit_after>/**
 * @file build test file
 * @author zhoumin
 */

const san = require('../../dist/san.ssr');
const fs = require('fs');
const path = require('path');

let htmlTpl = fs.readFileSync(path.resolve(__dirname, '..', 'index-ssr.html.tpl'), 'UTF-8');
let html = '';
let specTpls = '';

// generate html
function genContent({ componentClass, componentSource, compontentData, componentDataLiteral, specTpl, dirName, result}) {
    let renderer = san.compileToRenderer(componentClass);
    let id = dirName;
    let noDataOutput = /-ndo$/.test(dirName);

    // if no inject mark, add it
    if (!/\/\/\s*\[inject\]/.test(specTpl)) {
        specTpl = specTpl.replace(/function\s*\([a-z0-9_,$\s]*\)\s*\{/, function ($0) {
            return $0 + '\n// [inject] init';
        });
    }

    let injectHtml = result ? result : renderer(compontentData, noDataOutput);

    html += `<div id="${id}">${injectHtml}</div>\n\n`;

    let preCode = `
        ${componentSource}
        var wrap = document.getElementById('${id}');
        var myComponent = new MyComponent({
            el: wrap.firstChild
    `;

    if (noDataOutput) {
        preCode += ',data:' + componentDataLiteral
    }
    preCode += '        });'
    specTpl = specTpl.replace(/\/\/\s*\[inject\]\s* init/, preCode);
    specTpls += specTpl;
};

function buildFile(filePath) {
    let files = fs.readdirSync(filePath);
    let componentClass;
    let componentSource;
    let specTpl;
    let compontentData;
    let componentDataLiteral;
    let dirName;
    let result;
    let sourceFile = '';

    if (!files.length) {
        return;
    }

    files.forEach(filename => {
        // absolute path
        let abFilePath = path.join(filePath, filename);
        let stats = fs.statSync(abFilePath);
        let isFile = stats.isFile();
        let isDir = stats.isDirectory();

        // if it's a file, init data
        if (isFile) {
            switch (filename) {
                case 'component.js':
                    componentClass = require(abFilePath);
                    componentSource = fs.readFileSync(path.resolve(abFilePath), 'UTF-8')
                        .split('\n')
                        .map(line => {
                            if (/(\.|\s)exports\s*=/.test(line)
                                || /san\s*=\s*require\(/.test(line)
                            ) {
                                return '';
                            }

                            return line;
                        })
                        .join('\n');
                    sourceFile = filename;
                    break;

                case 'spec.js':
                    specTpl = fs.readFileSync(path.resolve(abFilePath), 'UTF-8');
                    break;

                case 'data.js':
                    compontentData = require(abFilePath);
                    componentDataLiteral = fs.readFileSync(abFilePath, 'UTF-8');
                    componentDataLiteral = componentDataLiteral
                        .slice(componentDataLiteral.indexOf('{'))
                        .replace(/;\s*$/, '');
                    break;

                case 'result.html':
                    result = fs.readFileSync(path.resolve(abFilePath), 'UTF-8').replace('\n', '');
                    break;
            }

        }

        // iterate
        if (isDir) {
            console.log(`[Build SSR spec] ${filename}`);
            buildFile(abFilePath);
        }
    });

    let match = filePath.match(/[\/\\]([a-zA-Z0-9_,$\-]*)$/);
    // dirName is the identity of each component
    dirName = match[1];
    // generate html when it has source file
    if (sourceFile) {
        genContent({
            componentClass,
            componentSource,
            compontentData,
            componentDataLiteral,
            specTpl,
            dirName,
            result
        });
    }
};

function writeIn({htmlTpl, html, specTpls}) {
    let karmaHtml = fs.readFileSync(path.resolve(__dirname, '..', 'karma-context.html.tpl'), 'UTF-8');
    fs.writeFileSync(
        path.resolve(__dirname, '..', 'karma-context.html'),
        karmaHtml.replace('##ssr-elements##', html),
        'UTF-8'
    );

    fs.writeFileSync(
        path.resolve(__dirname, '..', 'index-ssr.html'),
        htmlTpl.replace('##ssr-elements##', html),
        'UTF-8'
    );

    fs.writeFileSync(
        path.resolve(__dirname, 'ssr.spec.js'),
        specTpls,
        'UTF-8'
    );
};

console.log();
console.log('----- Build SSR Specs -----');

buildFile(path.resolve(__dirname, './'));
// write into file
writeIn({htmlTpl, html, specTpls});

console.log();
<|endoftext|>


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

var Stopwatch = require('../lib/Stopwatch');
var defaultPrecision = 15;
var assert = require('assert');
var should = require('should');

describe('stopwatch', function () {
    this.timeout(5000);

    describe('constructor', function () {
        it('w/no params', function () {
            var stopwatch = new Stopwatch();
            should.exist(stopwatch);
        });

        it('w/name as first param', function () {
            var stopwatch = new Stopwatch('metric-name');
            stopwatch.name().should.equal('metric-name');
        });

        it('w/autostart as first param', function () {
            var stopwatch = new Stopwatch(true);
            should.exist(stopwatch.name());
            stopwatch.name().should.not.equal(true);
        });

        it('w/both name and autostart', function () {
            var stopwatch = new Stopwatch('metric-name', true);
            stopwatch.name().should.equal('metric-name');
        });

        it('autocreated names are not constant', function () {
            var stopwatch1 = new Stopwatch(true);
            var stopwatch2 = new Stopwatch(true);
            stopwatch1.name().should.not.equal(stopwatch2.name());
        });
    });

    it('start and read (100ms)', function (done) {
        var testtime = 100;

        var stopwatch = new Stopwatch();
        stopwatch.start();
        setTimeout(function () {
            var delta = stopwatch.read();
            verifyDelta(testtime, delta, defaultPrecision);
            done();
        }, testtime);
    });

    it('start and read (10ms)', function (done) {
        var testtime = 10;

        var stopwatch = new Stopwatch();
        stopwatch.start();
        setTimeout(function () {
            var delta = stopwatch.read();
            verifyDelta(testtime, delta, defaultPrecision);
            done();
        }, testtime);
    });

    it('autostart set to true automatically starts stopwatch', function (done) {
        var testtime = 10;

        var stopwatch = new Stopwatch(true);
        setTimeout(function () {
            var delta = stopwatch.read();
            verifyDelta(testtime, delta, defaultPrecision);
            done();
        }, testtime);
    });

    it('autostart set to false does NOT automatically start stopwatch', function (done) {
        var testtime = 10;

        var stopwatch = new Stopwatch(false);
        setTimeout(function () {
            stopwatch.read().should.be.NaN();
            done();
        }, testtime);
    });

    it('with two stopwatches, do independent reads of each', function (done) {
        var stopwatch1 = new Stopwatch();
        var stopwatch2 = new Stopwatch();

        stopwatch1.start();

        //start first stopwatch, then do a read .3s later
        var testtimeA = 300;
        setTimeout(function () {
            var delta1 = stopwatch1.read();
            verifyDelta(testtimeA, delta1, defaultPrecision);
        }, testtimeA);

        //start second stopwatch .1s second after the first, then do a read .5s later
        var testtimeB = 500;
        setTimeout(function () {
            stopwatch2.start();
            setTimeout(function () {
                var delta2 = stopwatch2.read();
                verifyDelta(testtimeB, delta2, defaultPrecision);
                done();
            }, testtimeB);
        }, 100);
    });

    it('start, stop, and read should return the time at stop', function (done) {
        var testtime = 100;

        var stopwatch = new Stopwatch();
        stopwatch.start();
        setTimeout(function () {
            stopwatch.stop();

            setTimeout(function () {
                var delta = stopwatch.read();
                verifyDelta(testtime, delta, defaultPrecision);
                done();
            }, 500);
        }, testtime);
    });

    it('performing read without start() or stop() returns NaN', function (done) {
        var stopwatch = new Stopwatch();
        assert.ok(isNaN(stopwatch.read()));
        done();
    });

    it('performing read without start() returns NaN', function (done) {
        var stopwatch = new Stopwatch();
        stopwatch.stop();
        assert.ok(isNaN(stopwatch.read()));
        done();
    });

    it('executing stop twice should return time at second stop', function (done) {
        //start(), wait .1s, stop(), wait .2s, stop(), wait .5s, read(), ensure delta = .3s
        var stopwatch = new Stopwatch();
        stopwatch.start();
        setTimeout(function () {
            stopwatch.stop();

            setTimeout(function () {
                verifyDelta(100 + 200, stopwatch.stop(), defaultPrecision);

                setTimeout(function () {
                    var delta = stopwatch.read();
                    verifyDelta(100 + 200, delta, defaultPrecision);
                    done();
                }, 500);
            }, 200);
        }, 100);
    });

    it('ensure that stop() returns time', function (done) {
        var testtime = 100;
        var stopwatch = new Stopwatch();
        stopwatch.start();
        setTimeout(function () {
            var delta = stopwatch.stop();
            verifyDelta(testtime, delta, defaultPrecision);
            done();
        }, testtime);
    });

    describe('toString()', function () {
        it('idle', function () {
            var stopwatch = new Stopwatch('sw');
            //[sw => state:init; value:NaN]
            stopwatch.toString().should.containEql('state:init');
            stopwatch.toString().should.containEql('value:');
        });
        it('started', function () {
            var stopwatch = new Stopwatch('sw', true);
            //[sw => state:running; value:0.01]
            stopwatch.toString().should.containEql('state:running');
            stopwatch.toString().should.containEql('value:0');
        });
        it('stopped', function () {
            var stopwatch = new Stopwatch('sw', true);
            stopwatch.stop();
            //[sw => state:stopped; value:0.01]
            stopwatch.toString().should.containEql('state:stopped');
            stopwatch.toString().should.containEql('value:0');
        });
    });

    // https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/time/StopWatch.html
    describe('java stopwatch compliance', function () {
        it('time should equal read on a running stopwatch', function () {
            //TODO: list time as alias of read
            var stopwatch = new Stopwatch('sw');
            stopwatch.start();

            var readTime = stopwatch.read();
            var time = stopwatch.time();

            verifyDelta(readTime, time, 10);
        });
        it('time should equal read on a stopped stopwatch', function () {
            //TODO: list time as alias of read
            var stopwatch = new Stopwatch('sw');
            stopwatch.start();
            setTimeout(function () {
                stopwatch.read().should.be.equal(stopwatch.time());
            }, 10);

        });
        it.skip('reset', function () {
            // Resets the stopwatch. Stops it if need be.
            // This method clears the internal values to allow the object to be reused.
        });
        it.skip('split/unsplit/getSplitTime', function () {
            // Split the time.  This method sets the stop time of the watch to allow a time to be extracted. The start time is unaffected, enabling unsplit() to continue the timing from the original start point.
            // Remove a split.  This method clears the stop time. The start time is unaffected, enabling timing from the original start point to continue.
            // IllegalStateException - if the StopWatch is not running. (on split)
            // IllegalStateException - if the StopWatch has not yet been split. (on unsplit)
        });
        it.skip('suspend/resume', function () {
            // This method suspends the watch until it is resumed. The watch will not include time between the suspend and resume calls in the total time.
            // IllegalStateException - if the StopWatch is not currently running.
            // IllegalStateException - if the StopWatch has not been suspended.
        });
        it.skip('start while already running', function () {
            // IllegalStateException - if the StopWatch is already running.
        });
        it.skip('stop while not running', function () {
            // IllegalStateException - if the StopWatch is not running.
        });
    });
});

//TODO:
//replace with: statman.TestHelper.assertCloseEnough(testtime, delta, defaultPrecision);
function verifyDelta(expected, actual, acceptedVariance) {
    var lowerThreshold = expected - acceptedVariance;
    var upperThreshold = expected + acceptedVariance;
    var message = "Expected " + expected + " ± " + acceptedVariance + ", was " + actual + ".";
    assert.ok((actual >= lowerThreshold) && (actual <= upperThreshold), message);
}<commit_msg>add reset test<commit_after>/*jslint node: true */
"use strict";

var Stopwatch = require('../lib/Stopwatch');
var defaultPrecision = 15;
var assert = require('assert');
var should = require('should');

describe('stopwatch', function () {
    this.timeout(5000);

    describe('constructor', function () {
        it('w/no params', function () {
            var stopwatch = new Stopwatch();
            should.exist(stopwatch);
        });

        it('w/name as first param', function () {
            var stopwatch = new Stopwatch('metric-name');
            stopwatch.name().should.equal('metric-name');
        });

        it('w/autostart as first param', function () {
            var stopwatch = new Stopwatch(true);
            should.exist(stopwatch.name());
            stopwatch.name().should.not.equal(true);
        });

        it('w/both name and autostart', function () {
            var stopwatch = new Stopwatch('metric-name', true);
            stopwatch.name().should.equal('metric-name');
        });

        it('autocreated names are not constant', function () {
            var stopwatch1 = new Stopwatch(true);
            var stopwatch2 = new Stopwatch(true);
            stopwatch1.name().should.not.equal(stopwatch2.name());
        });
    });

    it('start and read (100ms)', function (done) {
        var testtime = 100;

        var stopwatch = new Stopwatch();
        stopwatch.start();
        setTimeout(function () {
            var delta = stopwatch.read();
            verifyDelta(testtime, delta, defaultPrecision);
            done();
        }, testtime);
    });

    it('start and read (10ms)', function (done) {
        var testtime = 10;

        var stopwatch = new Stopwatch();
        stopwatch.start();
        setTimeout(function () {
            var delta = stopwatch.read();
            verifyDelta(testtime, delta, defaultPrecision);
            done();
        }, testtime);
    });

    it('autostart set to true automatically starts stopwatch', function (done) {
        var testtime = 10;

        var stopwatch = new Stopwatch(true);
        setTimeout(function () {
            var delta = stopwatch.read();
            verifyDelta(testtime, delta, defaultPrecision);
            done();
        }, testtime);
    });

    it('autostart set to false does NOT automatically start stopwatch', function (done) {
        var testtime = 10;

        var stopwatch = new Stopwatch(false);
        setTimeout(function () {
            stopwatch.read().should.be.NaN();
            done();
        }, testtime);
    });

    it('with two stopwatches, do independent reads of each', function (done) {
        var stopwatch1 = new Stopwatch();
        var stopwatch2 = new Stopwatch();

        stopwatch1.start();

        //start first stopwatch, then do a read .3s later
        var testtimeA = 300;
        setTimeout(function () {
            var delta1 = stopwatch1.read();
            verifyDelta(testtimeA, delta1, defaultPrecision);
        }, testtimeA);

        //start second stopwatch .1s second after the first, then do a read .5s later
        var testtimeB = 500;
        setTimeout(function () {
            stopwatch2.start();
            setTimeout(function () {
                var delta2 = stopwatch2.read();
                verifyDelta(testtimeB, delta2, defaultPrecision);
                done();
            }, testtimeB);
        }, 100);
    });

    it('start, stop, and read should return the time at stop', function (done) {
        var testtime = 100;

        var stopwatch = new Stopwatch();
        stopwatch.start();
        setTimeout(function () {
            stopwatch.stop();

            setTimeout(function () {
                var delta = stopwatch.read();
                verifyDelta(testtime, delta, defaultPrecision);
                done();
            }, 500);
        }, testtime);
    });

    it('performing read without start() or stop() returns NaN', function (done) {
        var stopwatch = new Stopwatch();
        assert.ok(isNaN(stopwatch.read()));
        done();
    });

    it('performing read without start() returns NaN', function (done) {
        var stopwatch = new Stopwatch();
        stopwatch.stop();
        assert.ok(isNaN(stopwatch.read()));
        done();
    });

    it('executing stop twice should return time at second stop', function (done) {
        //start(), wait .1s, stop(), wait .2s, stop(), wait .5s, read(), ensure delta = .3s
        var stopwatch = new Stopwatch();
        stopwatch.start();
        setTimeout(function () {
            stopwatch.stop();

            setTimeout(function () {
                verifyDelta(100 + 200, stopwatch.stop(), defaultPrecision);

                setTimeout(function () {
                    var delta = stopwatch.read();
                    verifyDelta(100 + 200, delta, defaultPrecision);
                    done();
                }, 500);
            }, 200);
        }, 100);
    });

    it('ensure that stop() returns time', function (done) {
        var testtime = 100;
        var stopwatch = new Stopwatch();
        stopwatch.start();
        setTimeout(function () {
            var delta = stopwatch.stop();
            verifyDelta(testtime, delta, defaultPrecision);
            done();
        }, testtime);
    });

    describe('toString()', function () {
        it('idle', function () {
            var stopwatch = new Stopwatch('sw');
            //[sw => state:init; value:NaN]
            stopwatch.toString().should.containEql('state:init');
            stopwatch.toString().should.containEql('value:');
        });
        it('started', function () {
            var stopwatch = new Stopwatch('sw', true);
            //[sw => state:running; value:0.01]
            stopwatch.toString().should.containEql('state:running');
            stopwatch.toString().should.containEql('value:0');
        });
        it('stopped', function () {
            var stopwatch = new Stopwatch('sw', true);
            stopwatch.stop();
            //[sw => state:stopped; value:0.01]
            stopwatch.toString().should.containEql('state:stopped');
            stopwatch.toString().should.containEql('value:0');
        });
    });

    // https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/time/StopWatch.html
    describe('java stopwatch compliance', function () {
        it('time should equal read on a running stopwatch', function () {
            //TODO: list time as alias of read
            var stopwatch = new Stopwatch('sw');
            stopwatch.start();

            var readTime = stopwatch.read();
            var time = stopwatch.time();

            verifyDelta(readTime, time, 10);
        });
        it('time should equal read on a stopped stopwatch', function () {
            //TODO: list time as alias of read
            var stopwatch = new Stopwatch('sw');
            stopwatch.start();
            setTimeout(function () {
                stopwatch.read().should.be.equal(stopwatch.time());
            }, 10);

        });
        it('reseting a not-started stopwatch should have no effect', function () {
            var stopwatch = new Stopwatch('sw');
            stopwatch.reset();
            stopwatch.state().should.be.equal("init");
        });
        it.skip('split/unsplit/getSplitTime', function () {
            // Split the time.  This method sets the stop time of the watch to allow a time to be extracted. The start time is unaffected, enabling unsplit() to continue the timing from the original start point.
            // Remove a split.  This method clears the stop time. The start time is unaffected, enabling timing from the original start point to continue.
            // IllegalStateException - if the StopWatch is not running. (on split)
            // IllegalStateException - if the StopWatch has not yet been split. (on unsplit)
        });
        it.skip('suspend/resume', function () {
            // This method suspends the watch until it is resumed. The watch will not include time between the suspend and resume calls in the total time.
            // IllegalStateException - if the StopWatch is not currently running.
            // IllegalStateException - if the StopWatch has not been suspended.
        });
        it.skip('start while already running', function () {
            // IllegalStateException - if the StopWatch is already running.
        });
        it.skip('stop while not running', function () {
            // IllegalStateException - if the StopWatch is not running.
        });
    });
});

//TODO:
//replace with: statman.TestHelper.assertCloseEnough(testtime, delta, defaultPrecision);
function verifyDelta(expected, actual, acceptedVariance) {
    var lowerThreshold = expected - acceptedVariance;
    var upperThreshold = expected + acceptedVariance;
    var message = "Expected " + expected + " ± " + acceptedVariance + ", was " + actual + ".";
    assert.ok((actual >= lowerThreshold) && (actual <= upperThreshold), message);
}<|endoftext|>


<commit_before>/**
 * Created by Dana Zhang on 3/31/2014.
 */

'use strict';

define(['plugin/PluginConfig',
    'plugin/PluginBase',
    'plugin/PluginResult',
    'plugin/PetriNetExporter/PetriNetExporter/json2xml'], function (PluginConfig, PluginBase, PluginResult, json2xml) {

    // TODO: to modify the base dir path in config.json? to allow dependencies from other dirs

    var PetriNetExporterPlugin = function () {
        PluginBase.call(this);
    };

    PetriNetExporterPlugin.prototype = Object.create(PluginBase.prototype);
    PetriNetExporterPlugin.prototype.constructor = PetriNetExporterPlugin;

    PetriNetExporterPlugin.prototype.getName = function () {
        return 'PetriNetExporter';
    };

    PetriNetExporterPlugin.prototype.main = function (callback) {
        var self = this,
            core = self.core,
            selectedNode = self.activeNode;

        var pluginResult = new PluginResult();

        if (!selectedNode) {
            callback('selectedNode is not defined', pluginResult);
        }

        // TODO: this is not the right way to do it..., but a way at least
        this.objectToVisit = 0; // number of objects that have to be visited
        this.visitedObjects = 0; // number of already visited

        this.objectToVisit += 1; // we need to visit the selected node

        this.diagramPath = "";

        this.modelID = 0;

        this.diagrams = [];
        this.diagram = {};
        this.places = [];
        this.transitions = [];
        this.arcs = [];

        this.ID_LUT = {};

        // TODO: maybe there is an existing function that can access position data directly from a given pointer path?
        this.XPOS_LUT = {};
        this.YPOS_LUT = {};

        // only when node is diagram folder then traverse
        core.loadChildren(selectedNode, function(err, childNodes) {
            self.visitObject(err, childNodes, core, callback);
        });

    };

    PetriNetExporterPlugin.prototype.visitObject = function (err, childNodes, core, callback) {
        var self = this;

        this.objectToVisit += childNodes.length; // all child objects have to be visited

        var i;
        for (i = 0; i < childNodes.length; ++i) {

            var child = childNodes[i],
                metaType,
                parentPath = child.parent ? core.getPath(child.parent) : "",
                parentBaseClass = parentPath ? core.getBase(child.parent) : "",
                parentMetaType = parentBaseClass ? core.getAttribute(parentBaseClass, 'name') : "";

            // get its base META Type
            var baseClass = core.getBase(child);
            if (baseClass) {
                metaType = core.getAttribute(baseClass, 'name');
            }

            // if visiting a new diagram, reset global values
            if ((this.diagramPath && parentPath !== this.diagramPath) || (!this.diagramPath && parentMetaType === 'PetriNetDiagram')) {

                this.diagram = {"petrinet":
                {
                    "@Name": "untitled",
                    "page" :
                        {

                            "@id" : "page0",
                            "@name" : "page0"
                        }
                    }
                };

                this.diagram.petrinet.page["place"] = this.places;
                this.diagram.petrinet.page["transition"] = this.transitions;
                this.diagram.petrinet.page["arc"] = this.arcs;

                this.diagrams.push(this.diagram);

                this.places = [];
                this.transitions = [];
                this.arcs = [];
                this.diagram = {};
                this.modelID = 0;

                this.diagramPath = parentPath;
            }

            console.log(core.getAttribute(child, 'name'));
            console.log(core.getPath(child));
//            console.log(core.getAttribute(child.parent, 'name'));

            var name = core.getAttribute(child, 'name'),
                xPos = child.data.reg.position.x,
                yPos = child.data.reg.position.y;

            var visitType = metaType === 'Place' || metaType === 'Transition' || metaType === 'Place2Transition' || metaType === 'Transition2Place';

            if (visitType) {

                ++ this.modelID;
                // foreach eligible component, add its unique id and modelID to the LUT

                if (metaType === 'Place') {
                    // TODO: if key not exist already, add key; otherwise ignore
                    var gmeID = core.getPath(child);

                    if (!this.ID_LUT.hasOwnProperty(gmeID)) {

                        this.ID_LUT[gmeID] = this.modelID;
                        this.XPOS_LUT[gmeID] = xPos;
                        this.YPOS_LUT[gmeID] = yPos;
                        var capacity = core.getAttribute(child, 'Capacity'),
                            marking = core.getAttribute(child, 'InitialMarking');

                        // create a new json object for each place
                        var place = {
                            "@id": this.modelID,
                            "@name": name,
                            "@portdir": "None",
                            "@initialmarking": marking,
                            "@capacity": capacity,
                            "location": {
                                "@x": xPos,
                                "@y": yPos
                            },
                            "size": {
                                "@width": 50,
                                "@height": 30
                            }
                        };

                        this.places.push(place);
                    }

                    // Place component's attrs: id, name, portdir, initialmarking, capacity
                    //                   elements: location (attrs: x, y), size (attrs: width, height)

                } else if (metaType === 'Transition') {

                    // Transition component's attrs: id, name, portdir
                    //                        elements: location (attrs: x, y), size (attrs: width, height)

                    // TODO: if key not exist already, add key; otherwise ignore

                    var gmeID = core.getPath(child);

                    if (!this.ID_LUT.hasOwnProperty(gmeID)) {

                        this.ID_LUT[gmeID] = this.modelID;
                        this.XPOS_LUT[gmeID] = xPos;
                        this.YPOS_LUT[gmeID] = yPos;

                        var transition = {
                            "@id": this.modelID,
                            "@name": name,
                            "@portdir": "None",
                            "location": {
                                "@x": xPos,
                                "@y": yPos
                            },
                            "size": {
                                "@width": 50,
                                "@height": 20
                            }
                        };

                        this.transitions.push(transition);
                    }

                } else if (metaType === 'Place2Transition' || metaType === 'Transition2Place') {
                    // Arc component's attrs: id, source, target, delay, weight
                    //                 elements: points (element: point (attrs: x, y))

                    // getting source and destination paths of a connection object

                    var src = core.getPointerPath(child, "src"),
                        dst = core.getPointerPath(child, "dst"),
                        delay = core.getAttribute(child, 'Delay'),
                        weight = core.getAttribute(child, 'Weight');

                    // TODO: if src or dst hasn't existed, add them to dictionary here
                    // TODO: and also get src and dst positions from nodeobj somehow
                    // TODO: how to get attributes given a gmeid
                    // TODO: get a node from path (gmeid)

                    var srcMetaType,
                        dstMetaType,
                        capacity,
                        marking;
                    self.core.loadByPath(self.rootNode, src, function (err, nodeObj) {
                        if (!err) {
                            // nodeObj is available to use and it is loaded.
                                xPos = nodeObj.data.reg.position.x;
                                yPos = nodeObj.data.reg.position.y;
                                capacity = core.getAttribute(nodeObj, 'Capacity');
                                marking = core.getAttribute(nodeObj, 'InitialMarking');
                                srcMetaType = core.getAttribute(core.getBase(nodeObj), 'name');

                                console.log("type is " + srcMetaType);
                        }
                    });

                    if (!this.ID_LUT.hasOwnProperty(src)) {

                        this.ID_LUT[src] = this.modelID;
                        this.XPOS_LUT[src] = xPos;
                        this.YPOS_LUT[src] = yPos;

                        if (srcMetaType === 'Transition') {

                            var transition = {
                                "@id": this.modelID,
                                "@name": name,
                                "@portdir": "None",
                                "location": {
                                    "@x": xPos,
                                    "@y": yPos
                                },
                                "size": {
                                    "@width": 50,
                                    "@height": 20
                                }
                            };

                            this.transitions.push(transition);
                        } else {

                            var place = {
                                "@id": this.modelID,
                                "@name": name,
                                "@portdir": "None",
                                "@initialmarking": marking,
                                "@capacity": capacity,
                                "location": {
                                    "@x": xPos,
                                    "@y": yPos
                                },
                                "size": {
                                    "@width": 50,
                                    "@height": 30
                                }
                            };

                            this.places.push(place);
                        }
                        this.modelID++;
                    }

                    self.core.loadByPath(self.rootNode, dst, function (err, nodeObj) {
                        if (!err) {
                            // nodeObj is available to use and it is loaded.
                                xPos = nodeObj.data.reg.position.x;
                                yPos = nodeObj.data.reg.position.y;
                                dstMetaType = core.getAttribute(core.getBase(nodeObj), 'name');
                                console.log("type is " + dstMetaType);

                        }
                    });

                    if (!this.ID_LUT.hasOwnProperty(dst)) {

                        this.ID_LUT[dst] = this.modelID;
                        this.XPOS_LUT[dst] = xPos;
                        this.YPOS_LUT[dst] = yPos;

                        if (dstMetaType === 'Transition') {

                            var transition = {
                                "@id": this.modelID,
                                "@name": name,
                                "@portdir": "None",
                                "location": {
                                    "@x": xPos,
                                    "@y": yPos
                                },
                                "size": {
                                    "@width": 50,
                                    "@height": 20
                                }
                            };

                            this.transitions.push(transition);

                        } else if (dstMetaType === 'Place') {

                            var place = {
                                "@id": this.modelID,
                                "@name": name,
                                "@portdir": "None",
                                "@initialmarking": marking,
                                "@capacity": capacity,
                                "location": {
                                    "@x": xPos,
                                    "@y": yPos
                                },
                                "size": {
                                    "@width": 50,
                                    "@height": 30
                                }
                            };

                            this.places.push(place);
                        }
                        this.modelID++;
                    }

                    var arc = {
                        "@id": this.modelID,
                        "@source": this.ID_LUT[src],
                        "@target": this.ID_LUT[dst],
                        "@delay": delay,
                        "@weight": weight,
                        "points": {
                            "point": [

                                {
                                    "@x": this.XPOS_LUT[src],
                                    "@y": this.YPOS_LUT[src]
                                },
                                {
                                    "@x": this.XPOS_LUT[dst],
                                    "@y": this.YPOS_LUT[dst]
                                }
                            ]
                        }
                    };
                    this.arcs.push(arc);
                }
            }

            //    HEIGHT = isTypePlace ? 30 : 20; can we use META Aspect

            core.loadChildren(childNodes[i], function(err, childNodes) {
                self.visitObject(err, childNodes, core, callback);
            });
        }

        this.visitedObjects += 1; // another object was just visited

        if (this.objectToVisit === this.visitedObjects) {

                this.diagram = {"petrinet":
                {
                    "@Name": "untitled",
                    "page" :
                    {

                        "@id" : "page0",
                        "@name" : "page0"
                    }
                }
            };

            // TODO: need to fix this. Not a good way to do

//            for (var k = 0; k < this.arcs.length; ++k) {
//
//                if (!this.arcs[k]["@source"]) {
//
//
//                }
//            }

            this.diagram.petrinet.page["place"] = this.places;
            this.diagram.petrinet.page["transition"] = this.transitions;
            this.diagram.petrinet.page["arc"] = this.arcs;

            this.diagrams.push(this.diagram);

            var j2x = new json2xml;

            for (var j = 1; j < this.diagrams.length; ++j) {

                var output = j2x.convert(this.diagrams[j]);
                // this.fs.addFile("output" + j + ".json", output);
                this.fs.addFile("output" + j + ".xml", output);
            }

            this.fs.saveArtifact();

            // all objects have been visited
            var pluginResult = new PluginResult();
            pluginResult.success = true;
            if (callback) {
                callback(null, pluginResult);
            }
        }

//        else {
//            some objects still need to be visited
//            this.logger.info('Visiting progress: ' + this.visitedObjects + '/' + this.objectToVisit);
//        }
    };

    return PetriNetExporterPlugin;
});<commit_msg>#2 Cleaned up and restructured code<commit_after>/**
 * Created by Dana Zhang on 3/31/2014.
 */

'use strict';

define(['plugin/PluginConfig',
        'plugin/PluginBase',
        'plugin/PluginResult',
        'plugin/PetriNetExporter/PetriNetExporter/json2xml'], function (PluginConfig, PluginBase, PluginResult, json2xml) {

    // TODO: to modify the base dir path in config.json? to allow dependencies from other dirs

    var PetriNetExporterPlugin = function () {
        PluginBase.call(this);
    };

    PetriNetExporterPlugin.prototype = Object.create(PluginBase.prototype);
    PetriNetExporterPlugin.prototype.constructor = PetriNetExporterPlugin;

    PetriNetExporterPlugin.prototype.getName = function () {
        return 'PetriNetExporter';
    };

    PetriNetExporterPlugin.prototype.main = function (callback) {
        var self = this,
            core = self.core,
            selectedNode = self.activeNode;

        var pluginResult = new PluginResult();

        if (!selectedNode) {
            callback('selectedNode is not defined', pluginResult);
        }

        // TODO: this is not the right way to do it..., but a way at least
        this.objectToVisit = 0; // number of objects that have to be visited
        this.visitedObjects = 0; // number of already visited

        this.objectToVisit += 1; // we need to visit the selected node

        this.diagramPath = "";

        this.modelID = 0;

        this.diagrams = [];
        this.diagram = {};
        this.places = [];
        this.transitions = [];
        this.arcs = [];

        this.ID_LUT = {};

        // only when node is diagram folder then traverse
        core.loadChildren(selectedNode, function(err, childNodes) {
            self.visitObject(err, childNodes, core, callback);
        });

    };

    PetriNetExporterPlugin.prototype.visitObject = function (err, childNodes, core, callback) {
        var self = this;

        this.objectToVisit += childNodes.length; // all child objects have to be visited

        var i;
        for (i = 0; i < childNodes.length; ++i) {

            var child = childNodes[i];

            var parentPath = child.parent ? core.getPath(child.parent) : "",
                parentBaseClass = parentPath ? core.getBase(child.parent) : "",
                parentMetaType = parentBaseClass ? core.getAttribute(parentBaseClass, 'name') : "";

            // if visiting a new diagram, reset global values
            if ((this.diagramPath && parentPath !== this.diagramPath) || (!this.diagramPath && parentMetaType === 'PetriNetDiagram')) {

                this.diagram = {"petrinet":
                    {
                        "@Name": "untitled",
                        "page" :
                        {

                            "@id" : "page0",
                            "@name" : "page0"
                        }
                    }
                };

                this.diagram.petrinet.page["place"] = this.places;
                this.diagram.petrinet.page["transition"] = this.transitions;
                this.diagram.petrinet.page["arc"] = this.arcs;

                this.diagrams.push(this.diagram);

                // reset values
                this.ID_LUT = {};
                this.places = [];
                this.transitions = [];
                this.arcs = [];
                this.diagram = {};
                this.modelID = 0;

                this.diagramPath = parentPath;
            }

            var baseClass = core.getBase(child),
                metaType = baseClass ? core.getAttribute(baseClass, 'name') : "", // get child's base META Type
                visitType = metaType === 'Place' || metaType === 'Transition' || metaType === 'Place2Transition' || metaType === 'Transition2Place';

            if (visitType) {

                ++ this.modelID;

                if (metaType === 'Place' || metaType === 'Transition') {

                    // if key not exist already, add key; otherwise ignore
                    var gmeID = core.getPath(child);

                    if (!this.ID_LUT.hasOwnProperty(gmeID)) {

                        this.addComponent(child, metaType);
                    }

                } else if (metaType === 'Place2Transition' || metaType === 'Transition2Place') {

                    this.addConnection(child);
                }
            }

            core.loadChildren(childNodes[i], function(err, childNodes) {
                self.visitObject(err, childNodes, core, callback);
            });
        }

        this.visitedObjects += 1; // another object was just visited

        if (this.objectToVisit === this.visitedObjects) {

            this.diagram = {"petrinet":
            {
                "@Name": "untitled",
                "page" :
                {

                    "@id" : "page0",
                    "@name" : "page0"
                }
            }
            };

            // TODO: need to fix this. Not a good way to do

            this.diagram.petrinet.page["place"] = this.places;
            this.diagram.petrinet.page["transition"] = this.transitions;
            this.diagram.petrinet.page["arc"] = this.arcs;

            this.diagrams.push(this.diagram);

            var j2x = new json2xml;

            for (var j = 1; j < this.diagrams.length; ++j) {

                var output = j2x.convert(this.diagrams[j]);
                // this.fs.addFile("output" + j + ".json", output);
                this.fs.addFile("output" + j + ".xml", output);
            }

            this.fs.saveArtifact();

            // all objects have been visited
            var pluginResult = new PluginResult();
            pluginResult.success = true;
            if (callback) {
                callback(null, pluginResult);
            }
        }

    };

    PetriNetExporterPlugin.prototype.addComponent = function(nodeObj, metaType) {

        var core = this.core,
            gmeID = core.getPath(nodeObj),
            name = core.getAttribute(nodeObj, 'name'),
            xPos = nodeObj.data.reg.position.x,
            yPos = nodeObj.data.reg.position.y;

        this.ID_LUT[gmeID] = this.modelID;

        if (metaType === 'Place') {

            // Place component's attrs: id, name, portdir, initialmarking, capacity
            //                   elements: location (attrs: x, y), size (attrs: width, height)
            var capacity = core.getAttribute(nodeObj, 'Capacity'),
                marking = core.getAttribute(nodeObj, 'InitialMarking');

            var place = {
                "@id": this.modelID,
                "@name": name,
                "@portdir": "None",
                "@initialmarking": marking,
                "@capacity": capacity,
                "location": {
                    "@x": xPos,
                    "@y": yPos
                },
                "size": {
                    "@width": 50,
                    "@height": 30
                }
            };
            this.places.push(place);

        } else {

            // Transition component's attrs: id, name, portdir
            //                        elements: location (attrs: x, y), size (attrs: width, height)
            var transition = {
                "@id": this.modelID,
                "@name": name,
                "@portdir": "None",
                "location": {
                    "@x": xPos,
                    "@y": yPos
                },
                "size": {
                    "@width": 50,
                    "@height": 20
                }
            };

            this.transitions.push(transition);
        }
    };

    PetriNetExporterPlugin.prototype.addConnection = function(nodeObj) {

        var core = this.core,
            self = this,
            src = core.getPointerPath(nodeObj, "src"),
            dst = core.getPointerPath(nodeObj, "dst"),
            delay = core.getAttribute(nodeObj, 'Delay'),
            weight = core.getAttribute(nodeObj, 'Weight');

        var srcMetaType,
            dstMetaType,
            srcX,
            srcY,
            dstX,
            dstY;

        core.loadByPath(self.rootNode, src, function (err, nodeObj) {
            if (!err) {
                // nodeObj is available to use and it is loaded.
                if (!self.ID_LUT.hasOwnProperty(src)) {
                    srcMetaType = core.getAttribute(core.getBase(nodeObj), 'name');
                    self.addComponent(nodeObj, srcMetaType);

                    self.modelID++;
                }

                srcX = nodeObj.data.reg.position.x;
                srcY = nodeObj.data.reg.position.y;
            }
        });

        core.loadByPath(self.rootNode, dst, function (err, nodeObj) {
            if (!err) {
                // nodeObj is available to use and it is loaded.
                if (!self.ID_LUT.hasOwnProperty(dst)) {
                    srcMetaType = core.getAttribute(core.getBase(nodeObj), 'name');
                    self.addComponent(nodeObj, dstMetaType);
                    self.modelID++;
                }

                dstX = nodeObj.data.reg.position.x;
                dstY = nodeObj.data.reg.position.y;
            }
        });

        // Arc component's attrs: id, source, target, delay, weight
        //                 elements: points (element: point (attrs: x, y))

        var arc = {
            "@id": this.modelID,
            "@source": this.ID_LUT[src],
            "@target": this.ID_LUT[dst],
            "@delay": delay,
            "@weight": weight,
            "points": {
                "point": [
                    {
                        "@x": srcX,
                        "@y": srcY
                    },
                    {
                        "@x": dstX,
                        "@y": dstY
                    }
                ]
            }
        };
        this.arcs.push(arc);
    };

    return PetriNetExporterPlugin;
});<|endoftext|>


<commit_before>/*
 * Translated default messages for the jQuery validation plugin.
 * Locale: FA (Persian; فارسی)
 */
$.extend( $.validator.messages, {
	required: "تکمیل این فیلد اجباری است.",
	remote: "لطفا این فیلد را تصحیح کنید.",
	email: ".لطفا یک ایمیل صحیح وارد کنید",
	url: "لطفا آدرس صحیح وارد کنید.",
	date: "لطفا یک تاریخ صحیح وارد کنید",
	dateFA: "لطفا یک تاریخ صحیح وارد کنید",
	dateISO: "لطفا تاریخ صحیح وارد کنید (ISO).",
	number: "لطفا عدد صحیح وارد کنید.",
	digits: "لطفا تنها رقم وارد کنید",
	creditcard: "لطفا کریدیت کارت صحیح وارد کنید.",
	equalTo: "لطفا مقدار برابری وارد کنید",
	extension: "لطفا مقداری وارد کنید که ",
	maxlength: $.validator.format( "لطفا بیشتر از {0} حرف وارد نکنید." ),
	minlength: $.validator.format( "لطفا کمتر از {0} حرف وارد نکنید." ),
	rangelength: $.validator.format( "لطفا مقداری بین {0} تا {1} حرف وارد کنید." ),
	range: $.validator.format( "لطفا مقداری بین {0} تا {1} حرف وارد کنید." ),
	max: $.validator.format( "لطفا مقداری کمتر از {0} حرف وارد کنید." ),
	min: $.validator.format( "لطفا مقداری بیشتر از {0} حرف وارد کنید." ),
	minWords: $.validator.format( "لطفا حداقل {0} کلمه وارد کنید." ),
	maxWords: $.validator.format( "لطفا حداکثر {0} کلمه وارد کنید." )
} );
<commit_msg>Localisation: fixed Persian translation of min/max message.<commit_after>/*
 * Translated default messages for the jQuery validation plugin.
 * Locale: FA (Persian; فارسی)
 */
$.extend( $.validator.messages, {
	required: "تکمیل این فیلد اجباری است.",
	remote: "لطفا این فیلد را تصحیح کنید.",
	email: ".لطفا یک ایمیل صحیح وارد کنید",
	url: "لطفا آدرس صحیح وارد کنید.",
	date: "لطفا یک تاریخ صحیح وارد کنید",
	dateFA: "لطفا یک تاریخ صحیح وارد کنید",
	dateISO: "لطفا تاریخ صحیح وارد کنید (ISO).",
	number: "لطفا عدد صحیح وارد کنید.",
	digits: "لطفا تنها رقم وارد کنید",
	creditcard: "لطفا کریدیت کارت صحیح وارد کنید.",
	equalTo: "لطفا مقدار برابری وارد کنید",
	extension: "لطفا مقداری وارد کنید که ",
	maxlength: $.validator.format( "لطفا بیشتر از {0} حرف وارد نکنید." ),
	minlength: $.validator.format( "لطفا کمتر از {0} حرف وارد نکنید." ),
	rangelength: $.validator.format( "لطفا مقداری بین {0} تا {1} حرف وارد کنید." ),
	range: $.validator.format( "لطفا مقداری بین {0} تا {1} حرف وارد کنید." ),
	max: $.validator.format( "لطفا مقداری کمتر از {0} وارد کنید." ),
	min: $.validator.format( "لطفا مقداری بیشتر از {0} وارد کنید." ),
	minWords: $.validator.format( "لطفا حداقل {0} کلمه وارد کنید." ),
	maxWords: $.validator.format( "لطفا حداکثر {0} کلمه وارد کنید." )
} );
<|endoftext|>


<commit_before>(function() {

var kifu_move;

module('Kifu.Move', {
  setup: function() {
    kifu_move = Kifu.Move();
  }
});

test('initialization', 1, function() {
  same(kifu_move.moves(), [{type: 'init'}]);
});

test('addComment', 11, function() {
  var moves = Kifu.clone(kifu_move.moves());

  // comment1
  var move1 = {type: 'init', comment: "comment1\n"};
  ok(kifu_move.addComment('comment1'), 'comment1');
  same(kifu_move.get(0), move1, 'comment1 move1');

  // comment2
  move1['comment'] += "comment2\n";
  moves[0] = move1;
  ok(kifu_move.addComment('comment2'), 'comment2');
  same(kifu_move.get(0), move1, 'comment2 move1');

  // comment3
  kifu_move.addMove([2, 7], [2, 6], 'FU');
  var move2 = Kifu.clone(kifu_move.get(1));
  move2['comment'] = "comment3\n";
  ok(kifu_move.addComment('comment3'), 'comment3');
  same(kifu_move.get(0), move1, 'comment3 move1');
  same(kifu_move.get(1), move2, 'comment3 move2');

  // comment4
  move2['comment'] += "comment4\n";
  moves.push(move2);
  ok(kifu_move.addComment('comment4'), 'comment4');
  same(kifu_move.get(0), move1, 'comment4 move1');
  same(kifu_move.get(1), move2, 'comment4 move2');

  // check moves
  same(kifu_move.moves(), moves, 'moves');
});

test('addMove', 6, function() {
  var moves = Kifu.clone(kifu_move.moves());

  // +2726FU
  var move = {
    black: true,
    from:  {             x: 2, y: 7},
    to:    {piece: 'FU', x: 2, y: 6},
    type:  'move'};
  moves.push(move);
  kifu_move.addMove([2, 7], [2, 6], 'FU', {black: true});
  same(kifu_move.get(1), move, '+2726FU');

  // -2326FU
  var move = {
    black: false,
    from:  {             x: 2, y: 3},
    to:    {piece: 'FU', x: 2, y: 6},
    type:  'move'};
  moves.push(move);
  kifu_move.addMove([2, 3], [2, 6], 'FU', {black: false});
  same(kifu_move.get(2), move, '-2326FU');

  // 2800HI
  var move = {
    str:   '同　飛',
    from:  {             x: 2, y: 8},
    to:    {piece: 'HI', x: 2, y: 6},
    type:  'move'};
  moves.push(move);
  kifu_move.addMove([2, 8], [0, 0], 'HI', {str: '同　飛'});
  same(kifu_move.get(3), move, '2800HI');

  // 0025FU
  var move = {
    str:   '２五歩打',
    from:  {             x: 0, y: 0},
    to:    {piece: 'FU', x: 2, y: 5},
    type:  'move'};
  moves.push(move);
  kifu_move.addMove([0, 0], [2, 5], 'FU', {str: '２五歩打'});
  same(kifu_move.get(4), move, '0025FU');

  // 2600HI
  var move = {
    str:   '同　飛',
    from:  {             x: 2, y: 6},
    to:    {piece: 'HI', x: 2, y: 5},
    type:  'move'};
  moves.push({type: 'MATTA'});
  moves.push(move);
  kifu_move.addSpecial('MATTA');
  kifu_move.addMove([2, 6], [0, 0], 'HI', {str: '同　飛'});
  same(kifu_move.get(6), move, '2600HI');

  // check moves
  same(kifu_move.moves(), moves, 'moves');
});

test('addPeriod', 9, function() {
  var moves = Kifu.clone(kifu_move.moves());

  // 10sec
  var move = Kifu.clone(kifu_move.get(0));
  move['period'] = 10;
  ok(kifu_move.addPeriod(10), '10sec');
  same(kifu_move.get(0), move, '10sec move');

  // 20sec
  var move = Kifu.clone(kifu_move.get(0));
  move['period'] = 20;
  moves[0] = move;
  ok(kifu_move.addPeriod(20), '20sec');
  same(kifu_move.get(0), move, '20sec move');

  // 15sec
  kifu_move.addMove([2, 7], [2, 6], 'FU');
  var move = Kifu.clone(kifu_move.get(1));
  move['period'] = 15;
  ok(kifu_move.addPeriod(15), '15sec');
  same(kifu_move.get(1), move, '15sec move');

  // 30sec
  var move = Kifu.clone(kifu_move.get(1));
  move['period'] = 30;
  moves.push(move);
  ok(kifu_move.addPeriod(30), '30sec');
  same(kifu_move.get(1), move, '30sec move');

  // check moves
  same(kifu_move.moves(), moves, 'moves');
});

test('addSpecial', 4, function() {
  var moves = Kifu.clone(kifu_move.moves());

  // TORYO
  var move = {type: 'TORYO'};
  moves.push(move);
  kifu_move.addSpecial('TORYO');
  same(kifu_move.get(1), move, 'TORYO');

  // +ILLEGAL_ACTION
  var move = {black: true, type: 'ILLEGAL_ACTION'};
  moves.push(move);
  kifu_move.addSpecial('ILLEGAL_ACTION', {black: true});
  same(kifu_move.get(2), move, '+ILLEGAL_ACTION');

  // -ILLEGAL_ACTION
  var move = {black: false, type: 'ILLEGAL_ACTION'};
  moves.push(move);
  kifu_move.addSpecial('ILLEGAL_ACTION', {black: false});
  same(kifu_move.get(3), move, '-ILLEGAL_ACTION');

  // check moves
  same(kifu_move.moves(), moves, 'moves');
});

})();

/* vim: set expandtab tabstop=2 shiftwidth=2 softtabstop=2: */
<commit_msg>added tests for Kifu.Move().newMove()<commit_after>(function() {

var kifu_move;

module('Kifu.Move', {
  setup: function() {
    kifu_move = Kifu.Move();
  }
});

test('initialization', 1, function() {
  same(kifu_move.moves(), [{type: 'init'}]);
});

test('addComment', 11, function() {
  var moves = Kifu.clone(kifu_move.moves());

  // comment1
  var move1 = {type: 'init', comment: "comment1\n"};
  ok(kifu_move.addComment('comment1'), 'comment1');
  same(kifu_move.get(0), move1, 'comment1 move1');

  // comment2
  move1['comment'] += "comment2\n";
  moves[0] = move1;
  ok(kifu_move.addComment('comment2'), 'comment2');
  same(kifu_move.get(0), move1, 'comment2 move1');

  // comment3
  kifu_move.addMove([2, 7], [2, 6], 'FU');
  var move2 = Kifu.clone(kifu_move.get(1));
  move2['comment'] = "comment3\n";
  ok(kifu_move.addComment('comment3'), 'comment3');
  same(kifu_move.get(0), move1, 'comment3 move1');
  same(kifu_move.get(1), move2, 'comment3 move2');

  // comment4
  move2['comment'] += "comment4\n";
  moves.push(move2);
  ok(kifu_move.addComment('comment4'), 'comment4');
  same(kifu_move.get(0), move1, 'comment4 move1');
  same(kifu_move.get(1), move2, 'comment4 move2');

  // check moves
  same(kifu_move.moves(), moves, 'moves');
});

test('addMove', 6, function() {
  var moves = Kifu.clone(kifu_move.moves());

  // +2726FU
  var move = {
    black: true,
    from:  {             x: 2, y: 7},
    to:    {piece: 'FU', x: 2, y: 6},
    type:  'move'};
  moves.push(move);
  kifu_move.addMove([2, 7], [2, 6], 'FU', {black: true});
  same(kifu_move.get(1), move, '+2726FU');

  // -2326FU
  var move = {
    black: false,
    from:  {             x: 2, y: 3},
    to:    {piece: 'FU', x: 2, y: 6},
    type:  'move'};
  moves.push(move);
  kifu_move.addMove([2, 3], [2, 6], 'FU', {black: false});
  same(kifu_move.get(2), move, '-2326FU');

  // 2800HI
  var move = {
    str:   '同　飛',
    from:  {             x: 2, y: 8},
    to:    {piece: 'HI', x: 2, y: 6},
    type:  'move'};
  moves.push(move);
  kifu_move.addMove([2, 8], [0, 0], 'HI', {str: '同　飛'});
  same(kifu_move.get(3), move, '2800HI');

  // 0025FU
  var move = {
    str:   '２五歩打',
    from:  {             x: 0, y: 0},
    to:    {piece: 'FU', x: 2, y: 5},
    type:  'move'};
  moves.push(move);
  kifu_move.addMove([0, 0], [2, 5], 'FU', {str: '２五歩打'});
  same(kifu_move.get(4), move, '0025FU');

  // 2600HI
  var move = {
    str:   '同　飛',
    from:  {             x: 2, y: 6},
    to:    {piece: 'HI', x: 2, y: 5},
    type:  'move'};
  moves.push({type: 'MATTA'});
  moves.push(move);
  kifu_move.addSpecial('MATTA');
  kifu_move.addMove([2, 6], [0, 0], 'HI', {str: '同　飛'});
  same(kifu_move.get(6), move, '2600HI');

  // check moves
  same(kifu_move.moves(), moves, 'moves');
});

test('addPeriod', 9, function() {
  var moves = Kifu.clone(kifu_move.moves());

  // 10sec
  var move = Kifu.clone(kifu_move.get(0));
  move['period'] = 10;
  ok(kifu_move.addPeriod(10), '10sec');
  same(kifu_move.get(0), move, '10sec move');

  // 20sec
  var move = Kifu.clone(kifu_move.get(0));
  move['period'] = 20;
  moves[0] = move;
  ok(kifu_move.addPeriod(20), '20sec');
  same(kifu_move.get(0), move, '20sec move');

  // 15sec
  kifu_move.addMove([2, 7], [2, 6], 'FU');
  var move = Kifu.clone(kifu_move.get(1));
  move['period'] = 15;
  ok(kifu_move.addPeriod(15), '15sec');
  same(kifu_move.get(1), move, '15sec move');

  // 30sec
  var move = Kifu.clone(kifu_move.get(1));
  move['period'] = 30;
  moves.push(move);
  ok(kifu_move.addPeriod(30), '30sec');
  same(kifu_move.get(1), move, '30sec move');

  // check moves
  same(kifu_move.moves(), moves, 'moves');
});

test('addSpecial', 4, function() {
  var moves = Kifu.clone(kifu_move.moves());

  // TORYO
  var move = {type: 'TORYO'};
  moves.push(move);
  kifu_move.addSpecial('TORYO');
  same(kifu_move.get(1), move, 'TORYO');

  // +ILLEGAL_ACTION
  var move = {black: true, type: 'ILLEGAL_ACTION'};
  moves.push(move);
  kifu_move.addSpecial('ILLEGAL_ACTION', {black: true});
  same(kifu_move.get(2), move, '+ILLEGAL_ACTION');

  // -ILLEGAL_ACTION
  var move = {black: false, type: 'ILLEGAL_ACTION'};
  moves.push(move);
  kifu_move.addSpecial('ILLEGAL_ACTION', {black: false});
  same(kifu_move.get(3), move, '-ILLEGAL_ACTION');

  // check moves
  same(kifu_move.moves(), moves, 'moves');
});

test('newMove', 5, function() {
  var moves = Kifu.clone(kifu_move.moves());

  same(kifu_move.get(1), undefined, 'undefined first move');
  kifu_move.newMove();
  same(kifu_move.get(1), {}, 'defined first move');
  same(kifu_move.get(2), undefined, 'undefined second move');
  kifu_move.newMove();
  same(kifu_move.get(2), undefined, 'undefined second move');
  moves.push({});

  // check moves
  same(kifu_move.moves(), moves, 'moves');
});

})();

/* vim: set expandtab tabstop=2 shiftwidth=2 softtabstop=2: */
<|endoftext|>


<commit_before>/* global $, document, messages, event, textarea */
'use strict';

$(function(){

  /**
  * Markdown editor
  */
  $("#text-editor").markdown({
    autofocus:true,
    savable:false,
    iconlibrary:'fa',
    height:125
  });

  textarea.onkeydown = function(e) {
    e = e || event;
    if(e.keyCode === 13 && !document.getElementById('disable-enter-action').checked) {
      e.preventDefault();
      if(textarea.value.length > 1)
        messages.vm.send();
      else
        textarea.value = null;
    }
    return true;
  }

});
<commit_msg>fix(): correction l'event 'onkeydown' du textarea<commit_after>/* global $, document, messages, event, textarea */
'use strict';

$(function(){

  /**
  * Markdown editor
  */
  $("#text-editor").markdown({
    autofocus:true,
    savable:false,
    iconlibrary:'fa',
    height:125
  });

  textarea.onkeydown = function(e) {
    e = e || event;
    if(e.keyCode === 13 && !document.getElementById('disable-enter-action').checked) {
      e.preventDefault();
      if(textarea.value.length > 0)
        messages.vm.send();
      else
        textarea.value = null;
    }
    return true;
  }

});
<|endoftext|>


<commit_before>/**
 * Copyright 2017 The AMP HTML Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import {Services} from '../../../src/services';
import {StateProperty, getStoreService} from './amp-story-store-service';
import {getDataParamsFromAttributes} from '../../../src/dom';
import {getVariableService} from './variable-service';
import {map} from '../../../src/utils/object';
import {registerServiceBuilder} from '../../../src/service';
import {triggerAnalyticsEvent} from '../../../src/analytics';

/** @package @const {string} */
export const ANALYTICS_TAG_NAME = '__AMP_ANALYTICS_TAG_NAME__';

/** @enum {string} */
export const StoryAnalyticsEvent = {
  BOOKEND_CLICK: 'story-bookend-click',
  BOOKEND_ENTER: 'story-bookend-enter',
  BOOKEND_EXIT: 'story-bookend-exit',
  CLICK_THROUGH: 'story-click-through',
  FOCUS: 'story-focus',
  LAST_PAGE_VISIBLE: 'story-last-page-visible',
  OPEN: 'story-open',
  CLOSE: 'story-close',
  PAGE_ATTACHMENT_ENTER: 'story-page-attachment-enter',
  PAGE_ATTACHMENT_EXIT: 'story-page-attachment-exit',
  PAGE_VISIBLE: 'story-page-visible',
  REACTION: 'story-reaction',
  STORY_MUTED: 'story-audio-muted',
  STORY_UNMUTED: 'story-audio-unmuted',
};

/** @enum {string} */
export const AdvancementMode = {
  GO_TO_PAGE: 'goToPageAction',
  AUTO_ADVANCE_TIME: 'autoAdvanceTime',
  AUTO_ADVANCE_MEDIA: 'autoAdvanceMedia',
  MANUAL_ADVANCE: 'manualAdvance',
  ADVANCE_TO_ADS: 'manualAdvanceFromAd',
  VIEWER_SELECT_PAGE: 'viewerSelectPage',
};

/** @typedef {!Object<string, !PageEventCountDef>} */
let EventsPerPageDef;

/** @typedef {!Object<string, number>} */
let PageEventCountDef;

/**
 * Util function to retrieve the analytics service. Ensures we can retrieve the
 * service synchronously from the amp-story codebase without running into race
 * conditions.
 * @param {!Window} win
 * @param {!Element} el
 * @return {!StoryAnalyticsService}
 */
export const getAnalyticsService = (win, el) => {
  let service = Services.storyAnalyticsService(win);

  if (!service) {
    service = new StoryAnalyticsService(win, el);
    registerServiceBuilder(win, 'story-analytics', function () {
      return service;
    });
  }

  return service;
};

/**
 * Intermediate handler for amp-story specific analytics.
 */
export class StoryAnalyticsService {
  /**
   * @param {!Window} win
   * @param {!Element} element
   */
  constructor(win, element) {
    /** @protected @const {!Window} */
    this.win_ = win;

    /** @private @const {!Element} */
    this.element_ = element;

    /** @const @private {!./variable-service.AmpStoryVariableService} */
    this.variableService_ = getVariableService(win);

    /** @private {EventsPerPageDef} */
    this.pageEventsMap_ = map();

    /** @private @const {!./amp-story-store-service.AmpStoryStoreService} */
    this.storeService_ = getStoreService(win);

    this.initializeListeners_();
  }

  /** @private */
  initializeListeners_() {
    this.storeService_.subscribe(StateProperty.BOOKEND_STATE, (isActive) => {
      this.triggerEvent(
        isActive
          ? StoryAnalyticsEvent.BOOKEND_ENTER
          : StoryAnalyticsEvent.BOOKEND_EXIT
      );
    });

    this.storeService_.subscribe(
      StateProperty.CURRENT_PAGE_ID,
      (pageId) => {
        if (!pageId) {
          return;
        }

        this.triggerEvent(StoryAnalyticsEvent.PAGE_VISIBLE);

        const pageIds = this.storeService_.get(StateProperty.PAGE_IDS);
        const pageIndex = this.storeService_.get(
          StateProperty.CURRENT_PAGE_INDEX
        );
        if (pageIndex === pageIds.length - 1) {
          this.triggerEvent(StoryAnalyticsEvent.LAST_PAGE_VISIBLE);
        }
      },
      true /* callToInitialize */
    );
  }

  /**
   * @param {!StoryAnalyticsEvent} eventType
   * @param {Element=} element
   */
  triggerEvent(eventType, element = null) {
    this.incrementPageEventCount_(eventType);

    triggerAnalyticsEvent(
      this.element_,
      eventType,
      this.updateDetails(eventType, element)
    );
  }

  /**
   * Updates event details.
   * @param {!StoryAnalyticsEvent} eventType
   * @param {Element=} element
   * @visibleForTesting
   * @return {!JsonObject}}
   */
  updateDetails(eventType, element = null) {
    const details = {};
    const vars = this.variableService_.get();
    const pageId = vars['storyPageId'];

    if (this.pageEventsMap_[pageId][eventType] > 1) {
      details.repeated = true;
    }

    if (element) {
      details.tagName =
        element[ANALYTICS_TAG_NAME] || element.tagName.toLowerCase();
      Object.assign(
        vars,
        getDataParamsFromAttributes(
          element,
          /* computeParamNameFunc */ undefined,
          /^vars(.+)/
        )
      );
    }

    return /** @type {!JsonObject} */ ({eventDetails: details, ...vars});
  }

  /**
   * Keeps count of number of events emitted by page for an event type.
   * @param {!StoryAnalyticsEvent} eventType
   * @private
   */
  incrementPageEventCount_(eventType) {
    const vars = this.variableService_.get();
    const pageId = vars['storyPageId'];

    this.pageEventsMap_[pageId] = this.pageEventsMap_[pageId] || {};
    this.pageEventsMap_[pageId][eventType] =
      this.pageEventsMap_[pageId][eventType] || 0;
    this.pageEventsMap_[pageId][eventType]++;
  }
}
<commit_msg>Always prefix auto advance advancement modes with autoAdvance. (#28104)<commit_after>/**
 * Copyright 2017 The AMP HTML Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import {Services} from '../../../src/services';
import {StateProperty, getStoreService} from './amp-story-store-service';
import {getDataParamsFromAttributes} from '../../../src/dom';
import {getVariableService} from './variable-service';
import {map} from '../../../src/utils/object';
import {registerServiceBuilder} from '../../../src/service';
import {triggerAnalyticsEvent} from '../../../src/analytics';

/** @package @const {string} */
export const ANALYTICS_TAG_NAME = '__AMP_ANALYTICS_TAG_NAME__';

/** @enum {string} */
export const StoryAnalyticsEvent = {
  BOOKEND_CLICK: 'story-bookend-click',
  BOOKEND_ENTER: 'story-bookend-enter',
  BOOKEND_EXIT: 'story-bookend-exit',
  CLICK_THROUGH: 'story-click-through',
  FOCUS: 'story-focus',
  LAST_PAGE_VISIBLE: 'story-last-page-visible',
  OPEN: 'story-open',
  CLOSE: 'story-close',
  PAGE_ATTACHMENT_ENTER: 'story-page-attachment-enter',
  PAGE_ATTACHMENT_EXIT: 'story-page-attachment-exit',
  PAGE_VISIBLE: 'story-page-visible',
  REACTION: 'story-reaction',
  STORY_MUTED: 'story-audio-muted',
  STORY_UNMUTED: 'story-audio-unmuted',
};

/**
 * @enum {string}
 * Note: auto advance advancements should always be prefixed with "autoAdvance".
 */
export const AdvancementMode = {
  GO_TO_PAGE: 'goToPageAction',
  AUTO_ADVANCE_TIME: 'autoAdvanceTime',
  AUTO_ADVANCE_MEDIA: 'autoAdvanceMedia',
  MANUAL_ADVANCE: 'manualAdvance',
  ADVANCE_TO_ADS: 'manualAdvanceFromAd',
  VIEWER_SELECT_PAGE: 'viewerSelectPage',
};

/** @typedef {!Object<string, !PageEventCountDef>} */
let EventsPerPageDef;

/** @typedef {!Object<string, number>} */
let PageEventCountDef;

/**
 * Util function to retrieve the analytics service. Ensures we can retrieve the
 * service synchronously from the amp-story codebase without running into race
 * conditions.
 * @param {!Window} win
 * @param {!Element} el
 * @return {!StoryAnalyticsService}
 */
export const getAnalyticsService = (win, el) => {
  let service = Services.storyAnalyticsService(win);

  if (!service) {
    service = new StoryAnalyticsService(win, el);
    registerServiceBuilder(win, 'story-analytics', function () {
      return service;
    });
  }

  return service;
};

/**
 * Intermediate handler for amp-story specific analytics.
 */
export class StoryAnalyticsService {
  /**
   * @param {!Window} win
   * @param {!Element} element
   */
  constructor(win, element) {
    /** @protected @const {!Window} */
    this.win_ = win;

    /** @private @const {!Element} */
    this.element_ = element;

    /** @const @private {!./variable-service.AmpStoryVariableService} */
    this.variableService_ = getVariableService(win);

    /** @private {EventsPerPageDef} */
    this.pageEventsMap_ = map();

    /** @private @const {!./amp-story-store-service.AmpStoryStoreService} */
    this.storeService_ = getStoreService(win);

    this.initializeListeners_();
  }

  /** @private */
  initializeListeners_() {
    this.storeService_.subscribe(StateProperty.BOOKEND_STATE, (isActive) => {
      this.triggerEvent(
        isActive
          ? StoryAnalyticsEvent.BOOKEND_ENTER
          : StoryAnalyticsEvent.BOOKEND_EXIT
      );
    });

    this.storeService_.subscribe(
      StateProperty.CURRENT_PAGE_ID,
      (pageId) => {
        if (!pageId) {
          return;
        }

        this.triggerEvent(StoryAnalyticsEvent.PAGE_VISIBLE);

        const pageIds = this.storeService_.get(StateProperty.PAGE_IDS);
        const pageIndex = this.storeService_.get(
          StateProperty.CURRENT_PAGE_INDEX
        );
        if (pageIndex === pageIds.length - 1) {
          this.triggerEvent(StoryAnalyticsEvent.LAST_PAGE_VISIBLE);
        }
      },
      true /* callToInitialize */
    );
  }

  /**
   * @param {!StoryAnalyticsEvent} eventType
   * @param {Element=} element
   */
  triggerEvent(eventType, element = null) {
    this.incrementPageEventCount_(eventType);

    triggerAnalyticsEvent(
      this.element_,
      eventType,
      this.updateDetails(eventType, element)
    );
  }

  /**
   * Updates event details.
   * @param {!StoryAnalyticsEvent} eventType
   * @param {Element=} element
   * @visibleForTesting
   * @return {!JsonObject}}
   */
  updateDetails(eventType, element = null) {
    const details = {};
    const vars = this.variableService_.get();
    const pageId = vars['storyPageId'];

    if (this.pageEventsMap_[pageId][eventType] > 1) {
      details.repeated = true;
    }

    if (element) {
      details.tagName =
        element[ANALYTICS_TAG_NAME] || element.tagName.toLowerCase();
      Object.assign(
        vars,
        getDataParamsFromAttributes(
          element,
          /* computeParamNameFunc */ undefined,
          /^vars(.+)/
        )
      );
    }

    return /** @type {!JsonObject} */ ({eventDetails: details, ...vars});
  }

  /**
   * Keeps count of number of events emitted by page for an event type.
   * @param {!StoryAnalyticsEvent} eventType
   * @private
   */
  incrementPageEventCount_(eventType) {
    const vars = this.variableService_.get();
    const pageId = vars['storyPageId'];

    this.pageEventsMap_[pageId] = this.pageEventsMap_[pageId] || {};
    this.pageEventsMap_[pageId][eventType] =
      this.pageEventsMap_[pageId][eventType] || 0;
    this.pageEventsMap_[pageId][eventType]++;
  }
}
<|endoftext|>