<commit_before>/**************************************************************************************************
 *
 * Copyright (c) 2014 Digium, Inc.
 * All Rights Reserved. Licensed Software.
 *
 * @authors : Erin Spiceland <espiceland@digium.com>
 */

/**
 * Create a new WebRTC Client object.
 * @author Erin Spiceland <espiceland@digium.com>
 * @class brightstream.Client
 * @constructor
 * @augments brightstream.EventEmitter
 * @classdesc This is a top-level interface to the API. It handles authenticating the app to the
 * API server and receiving server-side app-specific information.
 * @param {object} clientSettings
 * @param {string} appId
 * @param {RTCConstraints} [constraints]
 * @param {RTCICEServers} [servers]
 * @returns {brightstream.Client}
 * @property {object} clientSettings Client settings.
 * @property {brightstream.SignalingChannel} signalingChannel A reference to the signaling channel.
 * @property {function} chatMessage Class to use for chat messages.
 * @property {function} signalingMessage Class to use for signaling.
 * @property {function} presenceMessage Class to use for presence messages.
 * @property {brightstream.User} user Logged-in user's User object.
 */
/*global brightstream: false */
brightstream.Client = function (params) {
    "use strict";
    params = params || {};
    var client = brightstream.makeUniqueID().toString();
    var that = brightstream.EventEmitter(params);
    brightstream.instances[client] = that;
    that.className = 'brightstream.Client';

    var host = window.location.hostname;
    var port = window.location.port;
    var connected = false;
    var app = {
        baseURL: params.baseURL,
        appId: params.appId
    };
    var signalingChannel = null;
    var turnRefresher = null;
    var groups = [];
    var endpoints = [];

    if (!app.appId) {
        throw new Error("appId is a required parameter to Client.");
    }
    delete params.appId;

    log.debug("Client ID is ", client);

    var callSettings = {
        constraints: params.constraints || {
            video : true,
            audio : true,
            optional: [],
            mandatory: {}
        },
        servers: params.servers || {
            iceServers: []
        }
    };

    signalingChannel = brightstream.SignalingChannel({'client': client});
    that.user = null;
    log.debug(signalingChannel);

    /**
     * Connect to the Digium infrastructure and authenticate using the appkey.  Store
     * a token to be used in API requests.
     * @memberof! brightstream.Client
     * @method brightstream.Client.connect
     * @param {string} authToken
     * @param {function} [onSuccess]
     * @param {function} [onError]
     * @param {function} [onGroupJoin]
     * @param {function} [onGroupLeave]
     * @param {function} [onMessage]
     * @param {function} [onConnect]
     * @param {function} [onDisconnect]
     * @param {function} [onReconnect]
     * @param {function} [onCall]
     */
    var connect = that.publicize('connect', function (params) {
        params = params || {};
        var deferred = brightstream.makeDeferred(params.onSuccess, params.onError);

        app.authToken = params.authToken;
        signalingChannel.open({
            appId: app.appId,
            token: app.authToken
        }).then(function () {
            return signalingChannel.authenticate({
                appId: app.appId
            });
        }, function (err) {
            deferred.reject("Couldn't connect to brightstream.");
            log.error(err.message);
        }).done(function (user) {
            connected = true;

            user.setOnline(); // Initiates presence.
            user.listen('call', params.onCall);
            user.listen('join', params.onGroupJoin);
            user.listen('leave', params.onGroupLeave);
            that.user = user;

            that.listen('message', params.onMessage);
            that.listen('connect', params.onConnect);
            that.listen('disconnect', params.onDisconnect);
            that.listen('reconnect', params.onReconnect);

            log.info('logged in as user ' + user.getName());
            log.debug(user);
            //updateTurnCredentials(); // TODO fix TURN credentials with Endpoints instead of Users.

            that.fire('connect', user);
            deferred.resolve(user);
        }, function (err) {
            deferred.reject("Couldn't create an endpoint.");
            log.error(err.message);
        });
        return deferred.promise;
    });

    /**
     * Disconnect from the Digium infrastructure. Invalidates the API token.
     * @memberof! brightstream.Client
     * @method brightstream.Client.disconnect
     */
    var disconnect = that.publicize('disconnect', function () {
        // TODO: also call this on socket disconnect
        var disconnectPromise = signalingChannel.close();
        disconnectPromise.then(function () {
            connected = false;
        });
        return disconnectPromise;
    });

    /**
     * Get the client ID
     * @memberof! brightstream.Client
     * @method brightstream.Client.getID
     * @return {string}
     */
    var getID = that.publicize('getID', function () {
        return client;
    });

    /**
     * Call an endpoint.
     * @memberof! brightstream.Client
     * @method brightstream.Client.call
     * @param {string} endpoint
     * @param {string} connection
     * @param {function} [onSuccess]
     * @param {function} [onError]
     * @return {brightstream.Call}
     */
    var call = that.publicize('call', function (params) {
        var endpoint = that.getEndpoint({id: params.id});

        if (!endpoint) {
            throw new Error("Can't find an endpoint with id", params.id);
        }

        return endpoint.call({
            constraints: params.constraints,
            servers: params.servers
        });
    });

    /**
     * Update TURN credentials and set a timeout to do it again in 20 hours.
     * @memberof! brightstream.Client
     * @method brightstream.Client.updateTurnCredentials
     */
    var updateTurnCredentials = that.publicize('updateTurnCredentials', function () {
        if (callSettings.disableTurn === true) {
            return;
        }

        clearInterval(turnRefresher);
        signalingChannel.getTurnCredentials().done(function successHandler(creds) {
            callSettings.servers.iceServers = creds;
        }, function errorHandler(error) {
            throw error;
        });
        turnRefresher = setInterval(updateTurnCredentials, 20 * (60 * 60 * 1000)); // 20 hours
    });

    /**
     * Determine whether the Client has authenticated with its appKey against Digium services
     * by checking the validity of the apiToken.
     * @memberof! brightstream.Client
     * @method brightstream.Client.isConnected
     * @returns {boolean}
     */
    var isConnected = that.publicize('isConnected', function () {
        return !!connected;
    });

     /**
     * Get an object containing the client settings.
     * @memberof! brightstream.Client
     * @method brightstream.Client.getClientSettings
     * @returns {object} An object containing the client settings.
     */
    var getClientSettings = that.publicize('getClientSettings', function () {
        return app;
    });

    /**
     * Get an object containing the default media constraints and other media settings.
     * @memberof! brightstream.Client
     * @method brightstream.Client.getCallSettings
     * @returns {object} An object containing the media settings which will be used in
     * brightstream calls.
     */
    var getCallSettings = that.publicize('getCallSettings', function () {
        return callSettings;
    });

    /**
     * Set the default media constraints and other media settings.
     * @memberof! brightstream.Client
     * @method brightstream.Client.setDefaultCallSettings
     * @param {object} [constraints]
     * @param {object} [servers]
     */
    var setDefaultCallSettings = that.publicize('setDefaultCallSettings', function (params) {
        params = params || {};
        if (params.constraints) {
            callSettings.constraints = params.constraints;
        }
        if (params.servers) {
            callSettings.servers = params.servers;
        }
    });

    /**
     * Get the SignalingChannel.
     * @memberof! brightstream.Client
     * @method brightstream.Client.getSignalingChannel
     * @returns {brightstream.SignalingChannel} The instance of the brightstream.SignalingChannel.
     */
    var getSignalingChannel = that.publicize('getSignalingChannel', function () {
        return signalingChannel;
    });

    /**
     * Get a Group
     * @memberof! brightstream.Client
     * @method brightstream.Client.join
     * @param {string} The name of the group.
     * @param {string} id
     * @param {function} [onSuccess]
     * @param {function} [onError]
     * @param {function} [onMessage]
     * @param {function} [onJoin]
     * @param {function} [onLeave]
     * @param {function} [onPresence]
     * @returns {brightstream.Group} The instance of the brightstream.Group which the user joined.
     */
    var join = that.publicize('join', function (params) {
        var deferred = brightstream.makeDeferred(params.onSuccess, params.onError);
        if (!params.id) {
            deferred.reject(new Error("Can't join a group with no group id."));
            return deferred.promise;
        }

        signalingChannel.joinGroup({
            id: params.id
        }).done(function () {
            var group = brightstream.Group({
                client: client,
                id: params.id,
                onMessage: params.onMessage,
                onJoin: params.onJoin,
                onLeave: params.onLeave,
                onPresence: params.onPresence
            });
            addGroup(group);
            that.user.fire('join', group);
            deferred.resolve(group);
        }, function (err) {
            deferred.reject(err);
        });
        return deferred.promise;
    });

    /**
     * Add a Group
     * @memberof! brightstream.Client
     * @method brightstream.Client.addGroup
     * @param {brightstream.Group}
     * @private
     */
    var addGroup = function (newGroup) {
        var group;
        if (!newGroup || newGroup.className !== 'brightstream.Group') {
            throw new Error("Can't add group to internal tracking without a group.");
        }
        groups.every(function (grp) {
            if (grp.id === newGroup.id) {
                group = grp;
                return false;
            }
            return true;
        });

        if (!group) {
            groups.push(newGroup);
        }
    };

    /**
     * Remove a Group
     * @memberof! brightstream.Client
     * @method brightstream.Client.removeGroup
     * @param {brightstream.Group}
     * @private
     */
    var removeGroup = function (newGroup) {
        var index;
        var endpoints;
        if (!newGroup || !(newGroup instanceof brightstream.Group)) {
            throw new Error("Can't remove group to internal tracking without a group.");
        }

        groups.every(function (grp, i) {
            if (grp.id === newGroup.id) {
                index = i;
                return false;
            }
            return true;
        });

        if (index > -1) {
            groups[index].getEndpoints().done(function (list) {
                endpoints = list;
                groups.splice(index, 1);
                endpoints.forEach(function (endpoint) {
                    checkEndpointForRemoval(endpoint);
                });
            });
        }
    };

    /**
     * Find a group by id and return it.
     * @memberof! brightstream.Client
     * @method brightstream.Client.getGroup
     * @param {string} id
     * @returns {brightstream.Group}
     */
    var getGroup = that.publicize('getGroup', function (params) {
        var group;
        if (!params || !params.id) {
            throw new Error("Can't get a group without group id.");
        }

        groups.every(function (grp) {
            if (grp.id === params.id) {
                group = grp;
                return false;
            }
            return true;
        });
        return group;
    });

    /**
     * Add an Endpoint
     * @memberof! brightstream.Client
     * @method brightstream.Client.addEndpoint
     * @param {brightstream.Contact}
     * @private
     */
    var addEndpoint = that.publicize('addEndpoint', function (newEndpoint) {
        var absent = false;
        if (!newEndpoint || newEndpoint.className !== 'brightstream.Contact') {
            throw new Error("Can't add endpoint to internal tracking. No endpoint given.");
        }
        absent = endpoints.every(function (ept) {
            if (ept.id === newEndpoint.id) {
                return false;
            }
            return true;
        });

        if (absent) {
            endpoints.push(newEndpoint);
        }
    });

    /**
     * Remove an Endpoint
     * @memberof! brightstream.Client
     * @method brightstream.Client.removeEndpoint
     * @param {brightstream.Contact}
     * @private
     */
    var checkEndpointForRemoval = that.publicize('checkEndpointForRemoval', function (theEndpoint) {
        var inAGroup;
        var index;
        if (!theEndpoint || theEndpoint.className !== 'brightstream.Contact') {
            throw new Error("Can't remove endpoint from internal tracking without group id.");
        }

        Q.all(groups.map(function (group) {
            return group.getEndpoints();
        })).done(function (groupEndpoints) {
            groupEndpoints.forEach(function (endpoints) {
                endpoints.forEach(function (endpoint) {
                    if (endpoint.id === theEndpoint.id) {
                        inAGroup = true;
                    }
                });
            });
            if (inAGroup) {
                endpoints.every(function (ept, i) {
                    if (ept.id === theEndpoint.id) {
                        index = i;
                        return false;
                    }
                    return true;
                });
                if (index > -1) {
                    endpoints.splice(index, 1);
                }
            }
        });
    });

    /**
     * Find an endpoint by id and return it.
     * @memberof! brightstream.Client
     * @method brightstream.Client.getEndpoint
     * @param {string} id
     * @returns {brightstream.Contact}
     */
    var getEndpoint = that.publicize('getEndpoint', function (params) {
        var endpoint;
        if (!params || !params.id) {
            throw new Error("Can't get an endpoint without group id.");
        }

        endpoints.every(function (ept) {
            if (ept.id === params.id) {
                endpoint = ept;
                return false;
            }
            return true;
        });

        if (!endpoint && params.createData) {
            endpoint = brightstream.Contact(params.createData);
            addEndpoint(endpoint);
        }

        return endpoint;
    });

    /**
     * Get the list of all endpoints we know about.
     * @memberof! brightstream.Client
     * @method brightstream.Client.getEndpoints
     * @returns {Array<brightstream.Contact>}
     */
    var getEndpoints = that.publicize('getEndpoints', function () {
        return endpoints;
    });

    return that;
}; // End brightstream.Client
<commit_msg>Pass all params to client.call.<commit_after>/**************************************************************************************************
 *
 * Copyright (c) 2014 Digium, Inc.
 * All Rights Reserved. Licensed Software.
 *
 * @authors : Erin Spiceland <espiceland@digium.com>
 */

/**
 * Create a new WebRTC Client object.
 * @author Erin Spiceland <espiceland@digium.com>
 * @class brightstream.Client
 * @constructor
 * @augments brightstream.EventEmitter
 * @classdesc This is a top-level interface to the API. It handles authenticating the app to the
 * API server and receiving server-side app-specific information.
 * @param {object} clientSettings
 * @param {string} appId
 * @param {RTCConstraints} [constraints]
 * @param {RTCICEServers} [servers]
 * @returns {brightstream.Client}
 * @property {object} clientSettings Client settings.
 * @property {brightstream.SignalingChannel} signalingChannel A reference to the signaling channel.
 * @property {function} chatMessage Class to use for chat messages.
 * @property {function} signalingMessage Class to use for signaling.
 * @property {function} presenceMessage Class to use for presence messages.
 * @property {brightstream.User} user Logged-in user's User object.
 */
/*global brightstream: false */
brightstream.Client = function (params) {
    "use strict";
    params = params || {};
    var client = brightstream.makeUniqueID().toString();
    var that = brightstream.EventEmitter(params);
    brightstream.instances[client] = that;
    that.className = 'brightstream.Client';

    var host = window.location.hostname;
    var port = window.location.port;
    var connected = false;
    var app = {
        baseURL: params.baseURL,
        appId: params.appId
    };
    var signalingChannel = null;
    var turnRefresher = null;
    var groups = [];
    var endpoints = [];

    if (!app.appId) {
        throw new Error("appId is a required parameter to Client.");
    }
    delete params.appId;

    log.debug("Client ID is ", client);

    var callSettings = {
        constraints: params.constraints || {
            video : true,
            audio : true,
            optional: [],
            mandatory: {}
        },
        servers: params.servers || {
            iceServers: []
        }
    };

    signalingChannel = brightstream.SignalingChannel({'client': client});
    that.user = null;
    log.debug(signalingChannel);

    /**
     * Connect to the Digium infrastructure and authenticate using the appkey.  Store
     * a token to be used in API requests.
     * @memberof! brightstream.Client
     * @method brightstream.Client.connect
     * @param {string} authToken
     * @param {function} [onSuccess]
     * @param {function} [onError]
     * @param {function} [onGroupJoin]
     * @param {function} [onGroupLeave]
     * @param {function} [onMessage]
     * @param {function} [onConnect]
     * @param {function} [onDisconnect]
     * @param {function} [onReconnect]
     * @param {function} [onCall]
     */
    var connect = that.publicize('connect', function (params) {
        params = params || {};
        var deferred = brightstream.makeDeferred(params.onSuccess, params.onError);

        app.authToken = params.authToken;
        signalingChannel.open({
            appId: app.appId,
            token: app.authToken
        }).then(function () {
            return signalingChannel.authenticate({
                appId: app.appId
            });
        }, function (err) {
            deferred.reject("Couldn't connect to brightstream.");
            log.error(err.message);
        }).done(function (user) {
            connected = true;

            user.setOnline(); // Initiates presence.
            user.listen('call', params.onCall);
            user.listen('join', params.onGroupJoin);
            user.listen('leave', params.onGroupLeave);
            that.user = user;

            that.listen('message', params.onMessage);
            that.listen('connect', params.onConnect);
            that.listen('disconnect', params.onDisconnect);
            that.listen('reconnect', params.onReconnect);

            log.info('logged in as user ' + user.getName());
            log.debug(user);
            //updateTurnCredentials(); // TODO fix TURN credentials with Endpoints instead of Users.

            that.fire('connect', user);
            deferred.resolve(user);
        }, function (err) {
            deferred.reject("Couldn't create an endpoint.");
            log.error(err.message);
        });
        return deferred.promise;
    });

    /**
     * Disconnect from the Digium infrastructure. Invalidates the API token.
     * @memberof! brightstream.Client
     * @method brightstream.Client.disconnect
     */
    var disconnect = that.publicize('disconnect', function () {
        // TODO: also call this on socket disconnect
        var disconnectPromise = signalingChannel.close();
        disconnectPromise.then(function () {
            connected = false;
        });
        return disconnectPromise;
    });

    /**
     * Get the client ID
     * @memberof! brightstream.Client
     * @method brightstream.Client.getID
     * @return {string}
     */
    var getID = that.publicize('getID', function () {
        return client;
    });

    /**
     * Call an endpoint.
     * @memberof! brightstream.Client
     * @method brightstream.Client.call
     * @param {string} endpoint
     * @param {string} connection
     * @param {function} [onSuccess]
     * @param {function} [onError]
     * @return {brightstream.Call}
     */
    var call = that.publicize('call', function (params) {
        var endpoint = that.getEndpoint({id: params.id});

        if (!endpoint) {
            throw new Error("Can't find an endpoint with id", params.id);
        }

        delete params.id;
        return endpoint.call(params);
    });

    /**
     * Update TURN credentials and set a timeout to do it again in 20 hours.
     * @memberof! brightstream.Client
     * @method brightstream.Client.updateTurnCredentials
     */
    var updateTurnCredentials = that.publicize('updateTurnCredentials', function () {
        if (callSettings.disableTurn === true) {
            return;
        }

        clearInterval(turnRefresher);
        signalingChannel.getTurnCredentials().done(function successHandler(creds) {
            callSettings.servers.iceServers = creds;
        }, function errorHandler(error) {
            throw error;
        });
        turnRefresher = setInterval(updateTurnCredentials, 20 * (60 * 60 * 1000)); // 20 hours
    });

    /**
     * Determine whether the Client has authenticated with its appKey against Digium services
     * by checking the validity of the apiToken.
     * @memberof! brightstream.Client
     * @method brightstream.Client.isConnected
     * @returns {boolean}
     */
    var isConnected = that.publicize('isConnected', function () {
        return !!connected;
    });

     /**
     * Get an object containing the client settings.
     * @memberof! brightstream.Client
     * @method brightstream.Client.getClientSettings
     * @returns {object} An object containing the client settings.
     */
    var getClientSettings = that.publicize('getClientSettings', function () {
        return app;
    });

    /**
     * Get an object containing the default media constraints and other media settings.
     * @memberof! brightstream.Client
     * @method brightstream.Client.getCallSettings
     * @returns {object} An object containing the media settings which will be used in
     * brightstream calls.
     */
    var getCallSettings = that.publicize('getCallSettings', function () {
        return callSettings;
    });

    /**
     * Set the default media constraints and other media settings.
     * @memberof! brightstream.Client
     * @method brightstream.Client.setDefaultCallSettings
     * @param {object} [constraints]
     * @param {object} [servers]
     */
    var setDefaultCallSettings = that.publicize('setDefaultCallSettings', function (params) {
        params = params || {};
        if (params.constraints) {
            callSettings.constraints = params.constraints;
        }
        if (params.servers) {
            callSettings.servers = params.servers;
        }
    });

    /**
     * Get the SignalingChannel.
     * @memberof! brightstream.Client
     * @method brightstream.Client.getSignalingChannel
     * @returns {brightstream.SignalingChannel} The instance of the brightstream.SignalingChannel.
     */
    var getSignalingChannel = that.publicize('getSignalingChannel', function () {
        return signalingChannel;
    });

    /**
     * Get a Group
     * @memberof! brightstream.Client
     * @method brightstream.Client.join
     * @param {string} The name of the group.
     * @param {string} id
     * @param {function} [onSuccess]
     * @param {function} [onError]
     * @param {function} [onMessage]
     * @param {function} [onJoin]
     * @param {function} [onLeave]
     * @param {function} [onPresence]
     * @returns {brightstream.Group} The instance of the brightstream.Group which the user joined.
     */
    var join = that.publicize('join', function (params) {
        var deferred = brightstream.makeDeferred(params.onSuccess, params.onError);
        if (!params.id) {
            deferred.reject(new Error("Can't join a group with no group id."));
            return deferred.promise;
        }

        signalingChannel.joinGroup({
            id: params.id
        }).done(function () {
            var group = brightstream.Group({
                client: client,
                id: params.id,
                onMessage: params.onMessage,
                onJoin: params.onJoin,
                onLeave: params.onLeave,
                onPresence: params.onPresence
            });
            addGroup(group);
            that.user.fire('join', group);
            deferred.resolve(group);
        }, function (err) {
            deferred.reject(err);
        });
        return deferred.promise;
    });

    /**
     * Add a Group
     * @memberof! brightstream.Client
     * @method brightstream.Client.addGroup
     * @param {brightstream.Group}
     * @private
     */
    var addGroup = function (newGroup) {
        var group;
        if (!newGroup || newGroup.className !== 'brightstream.Group') {
            throw new Error("Can't add group to internal tracking without a group.");
        }
        groups.every(function (grp) {
            if (grp.id === newGroup.id) {
                group = grp;
                return false;
            }
            return true;
        });

        if (!group) {
            groups.push(newGroup);
        }
    };

    /**
     * Remove a Group
     * @memberof! brightstream.Client
     * @method brightstream.Client.removeGroup
     * @param {brightstream.Group}
     * @private
     */
    var removeGroup = function (newGroup) {
        var index;
        var endpoints;
        if (!newGroup || !(newGroup instanceof brightstream.Group)) {
            throw new Error("Can't remove group to internal tracking without a group.");
        }

        groups.every(function (grp, i) {
            if (grp.id === newGroup.id) {
                index = i;
                return false;
            }
            return true;
        });

        if (index > -1) {
            groups[index].getEndpoints().done(function (list) {
                endpoints = list;
                groups.splice(index, 1);
                endpoints.forEach(function (endpoint) {
                    checkEndpointForRemoval(endpoint);
                });
            });
        }
    };

    /**
     * Find a group by id and return it.
     * @memberof! brightstream.Client
     * @method brightstream.Client.getGroup
     * @param {string} id
     * @returns {brightstream.Group}
     */
    var getGroup = that.publicize('getGroup', function (params) {
        var group;
        if (!params || !params.id) {
            throw new Error("Can't get a group without group id.");
        }

        groups.every(function (grp) {
            if (grp.id === params.id) {
                group = grp;
                return false;
            }
            return true;
        });
        return group;
    });

    /**
     * Add an Endpoint
     * @memberof! brightstream.Client
     * @method brightstream.Client.addEndpoint
     * @param {brightstream.Contact}
     * @private
     */
    var addEndpoint = that.publicize('addEndpoint', function (newEndpoint) {
        var absent = false;
        if (!newEndpoint || newEndpoint.className !== 'brightstream.Contact') {
            throw new Error("Can't add endpoint to internal tracking. No endpoint given.");
        }
        absent = endpoints.every(function (ept) {
            if (ept.id === newEndpoint.id) {
                return false;
            }
            return true;
        });

        if (absent) {
            endpoints.push(newEndpoint);
        }
    });

    /**
     * Remove an Endpoint
     * @memberof! brightstream.Client
     * @method brightstream.Client.removeEndpoint
     * @param {brightstream.Contact}
     * @private
     */
    var checkEndpointForRemoval = that.publicize('checkEndpointForRemoval', function (theEndpoint) {
        var inAGroup;
        var index;
        if (!theEndpoint || theEndpoint.className !== 'brightstream.Contact') {
            throw new Error("Can't remove endpoint from internal tracking without group id.");
        }

        Q.all(groups.map(function (group) {
            return group.getEndpoints();
        })).done(function (groupEndpoints) {
            groupEndpoints.forEach(function (endpoints) {
                endpoints.forEach(function (endpoint) {
                    if (endpoint.id === theEndpoint.id) {
                        inAGroup = true;
                    }
                });
            });
            if (inAGroup) {
                endpoints.every(function (ept, i) {
                    if (ept.id === theEndpoint.id) {
                        index = i;
                        return false;
                    }
                    return true;
                });
                if (index > -1) {
                    endpoints.splice(index, 1);
                }
            }
        });
    });

    /**
     * Find an endpoint by id and return it.
     * @memberof! brightstream.Client
     * @method brightstream.Client.getEndpoint
     * @param {string} id
     * @returns {brightstream.Contact}
     */
    var getEndpoint = that.publicize('getEndpoint', function (params) {
        var endpoint;
        if (!params || !params.id) {
            throw new Error("Can't get an endpoint without group id.");
        }

        endpoints.every(function (ept) {
            if (ept.id === params.id) {
                endpoint = ept;
                return false;
            }
            return true;
        });

        if (!endpoint && params.createData) {
            endpoint = brightstream.Contact(params.createData);
            addEndpoint(endpoint);
        }

        return endpoint;
    });

    /**
     * Get the list of all endpoints we know about.
     * @memberof! brightstream.Client
     * @method brightstream.Client.getEndpoints
     * @returns {Array<brightstream.Contact>}
     */
    var getEndpoints = that.publicize('getEndpoints', function () {
        return endpoints;
    });

    return that;
}; // End brightstream.Client
<|endoftext|>


<commit_before>function imageConstructor(filePath,){

this.filePath = filePath;
this.voteNumber = Math.floor((Math.random() * 49 ) + 2);

}

treeDirectory = ["tree1", "tree2", "tree3"]
cityDirectory = ["city1", "city2", "city3"]

var tree1 = new imageConstructor(images/tree1.jpg)
var tree2 = new imageConstructor(images/tree2.jpg)
var tree3 = new imageConstructor(images/tree3.jpg)
var city1 = new imageConstructor(images/city1.jpg)
var city2 = new imageConstructor(images/city2.jpg)
var city3 = new imageConstructor(images/city3.jpg)

var imageTrees = [];
var imageCities = [];

var randomTree = function() {            //selects our tree image
Math.floor((Math.random() * treeDirectory.length)

}

function randomCity{             //selects our city image
Math.

}

function upLoadImages(left,right){                            //function will put images on page
var left = leftImageEl       //  accesing our dom elemnt by Id
var right= rightImageEl      //  accessing our dom elenment by id
leftImageEl = get random tree
rightImageEl = get random city
push left image on
push right image on

}

function MakeImage(filePath){
  used = false;
  this.filePath = filePath;
}

leftImageEl = document.getElementById("leftImage");
rightImageEl = document.getElementById("rightImage");
resetButtonEl = document.getElementById("resetButton");
voteButtonEl = document.getElementById("voteButton");

leftImageEl.addEventListener("click", selectImage);
rightImageEl.addEventListener("click", selectImage);
leftImageEl.addEventListener("mouseover", selectImage);
rightImageEl.addEventListener("mouseover", selectImage);

<commit_msg>re-organized code and added new methods in our functions<commit_after>

treeDirectory = ["tree1", "tree2", "tree3"]
cityDirectory = ["city1", "city2", "city3"]

var tree1 = new imageConstructor(images/tree1.jpg)
var tree2 = new imageConstructor(images/tree2.jpg)
var tree3 = new imageConstructor(images/tree3.jpg)
var city1 = new imageConstructor(images/city1.jpg)
var city2 = new imageConstructor(images/city2.jpg)
var city3 = new imageConstructor(images/city3.jpg)

function imageConstructor(filePath,){

this.filePath = filePath;
this.voteNumber = Math.floor((Math.random() * 49 ) + 2);     ///utility zone
}
                                                              //this is our utility area
emptyHat = [];

var imageTrees = [];
var imageCities = [];

var randomTree = function() {            //selects our tree image

return Math.floor(Math.random() * treeDirectory.length);
}

var randomCity = function(){             //selects our city image

return Math.floor(Math.random() * cityDirectory.length);

}

function upLoadImages(left,right){                            //function will put images on page
var left = leftImageEl       //  accesing our dom elemnt by Id
var right= rightImageEl      //  accessing our dom elenment by id
leftImageEl = get random tree
rightImageEl = get random city
push left image on
push right image on

}

leftImageEl = document.getElementById("leftImage");
rightImageEl = document.getElementById("rightImage");
resetButtonEl = document.getElementById("resetButton");
voteButtonEl = document.getElementById("voteButton");

leftImageEl.addEventListener("click", selectImage);
rightImageEl.addEventListener("click", selectImage);
leftImageEl.addEventListener("mouseover", selectImage);
rightImageEl.addEventListener("mouseover", selectImage);

<|endoftext|>


<commit_before>//socket io
const URL = 'http://localhost:6277'
const socket = io.connect(URL)
//user input all infomation
let inclipinfo = []
let intileinfo = []
//user input item
let incliptags
let intiletags = []
// svg con stack(not loaded)
let svg_con_stack_clip = {}
let svg_con_stack_tile = {}
//recieve tags stack
let stacktile = []
//clip form flag
let cflag = true

//send to get all tags
socket.emit('get_allcliptags')

//recieve all clip tags
socket.on('res_allcliptags', (rec) => {
  //set complete clip
  let cliptags = new Bloodhound({
    datumTokenizer: Bloodhound.tokenizers.obj.whitespace('clip'),
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    local: $.map(rec, (tag) => {
      return {
        clip: tag
      }
    })
  })
  //reflection of clip setting
  cliptags.initialize()
  //input auto complete clip
  $('.clip-tags-form').tagsinput({
    typeaheadjs: [{
      minLength: 1,
      highlight: true,
    },{
      minlength: 1,
      name: 'cliptags',
      displayKey: 'clip',
      valueKey: 'clip',
      source: cliptags.ttAdapter()
    }],
    freeInput: true
  })
})

//search button event
$('#search-button').click(() => {
  $('.clip-form').css('overflow-y', 'scroll')
  cflag = true
  $('.aleart-text').css('display', 'none')
  incliptags = $('.clip-tags-form').tagsinput('items')
  //select dropdown item to array
  for(i = 0; i < $('.dropdown-menu li').length; i++){
    if($('#'+i).prop('checked')){
      intiletags.push($('#'+i).val())
    }
  }
  if(incliptags.length == 0){
    $('.clip-form').css('overflow', 'hidden')
    incliptags = undefined
    stacktile = []
    $('.dropdown-menu').empty()
    $('.aleart-text').css('display', 'inline')
  }
  if(intiletags.length == 0){
    intiletags = undefined
  }else{
    cflag = false
  }
  inclipinfo.push({
    cliptags: incliptags,
    startdate: Date.parse($('.start').val()),
    enddate: Date.parse($('.end').val())
  })
  intileinfo.push({
    tiletags: intiletags,
    cliptags: incliptags,
    startdate: Date.parse($('.start').val()),
    enddate: Date.parse($('.end').val())
  })
  $('.clip-form').empty()
  $('.tile-form').empty()
  //send input data
  socket.emit('send_clipsearchdata', inclipinfo[0])
  if(intiletags !== undefined){
    socket.emit('send_tilesearchdata', intileinfo[0])
  }
  inclipinfo = []
  intileinfo = []
  intiletags = []
})

//tile tags dropdown
socket.on('res_alltiletags', (rec) => {
  if(rec.join(',') != stacktile.join(',')){
    $('.dropdown-menu').empty()
    for(i = 0; i < rec.length; i++){
      let $li = $('

')
      let $input = $('<input></input>', {
        id: i,
        type: "checkbox",
        value: rec[i]
      })
      let $label = $('', {
        for: i,
        text: rec[i]
      })
      $('.dropdown-menu').append($li.append($input))
      $('.dropdown-menu').append($li.append($label))
    }
  }
  stacktile = rec
})

//clip form
socket.on('res_clips', (rec) => {
  if(cflag){
    for(i = 0; i < rec.length; i++){
      let $div = $('

', {
        class: 'clip-field ' + i + ' clearfix'
      })
      $('.clip-form').append($div)
      for(j = 0; j < rec[i].tile.length; j++){
        switch(rec[i].tile[j].sty){
          case "txt":
            let $div = $('

', {
              class: 'col-sm-' + rec[i].tile[j].col + ' col-xs-' + rec[i].title[j].col + ' tile',
              text: rec[i].tile[j].con
            })
            $('.'+i).append($div)

            MathJax.Hub.Queue(["Typeset", MathJax.Hub, "clip-field"])
            break
          case "svg":
            let $span = $('', {
              class: 'col-sm-' + rec[i].tile[j].col + ' col-xs-' + rec[i].tile[j].col + ' iframe-wrap'
            })
            let $iframe = $('', {
              id: rec[i].tile[j]._id,
              src: URL + "/html/read_nu/",
              scrolling: "auto"
            })
            $('.'+i).append(
              $span.append($iframe)
            )

            // stack to var
            svg_con_stack_clip[rec[i].tile[j]._id] = rec[i].tile[j].con

            // onload
            // caution: can not use arrow func
            $iframe.on('load', function(){
              // write path
              $(this)[0].contentWindow.loadPath(svg_con_stack_clip[$(this).attr("id")])
              // delete from stack
              delete svg_con_stack_clip[$(this).attr("id")]
            })
            break
          default:
            console.error('sty error')
            break
        }
      }
    }
  }
})

//tile form
socket.on('res_tiles', (rec) => {
  let $div = $('

', {
    class: 'clip-field clearfix with_tile'
  })
  $('.clip-form').append($div)
  for(i = 0; i < rec.length; i++){
    switch(rec[i].sty){
      case "txt":
        let $div = $('

', {
          class: 'col-sm-' + rec[i].col + ' col-xs-'+ rec[i].col +' tile',
          text: rec[i].con
        })
        $('.with_tile').append($div)

        MathJax.Hub.Queue(["Typeset", MathJax.Hub, "clip-field"])
        break
      case "svg":
        let $span = $('', {
          class: 'col-sm-' + rec[i].col + ' col-xs-'+ rec[i].col + ' iframe-wrap'
        })
        let $iframe = $('', {
          id: rec[i]._id,
          src: URL + "/html/read_nu/",
          scrolling: "auto"
        })
        $('.with_tile').append(
          $span.append($iframe)
        )

        // stack to var
        svg_con_stack_tile[rec[i]._id] = rec[i].con

        // onload
        // caution: can not use arrow func
        $iframe.on('load', function(){
          // write path
          $(this)[0].contentWindow.loadPath(svg_con_stack_tile[$(this).attr("id")])
          // delete from stack
          delete svg_con_stack_tile[$(this).attr("id")]
        })
        break
      default:
        console.error('sty error')
        break
    }
  }
})

<commit_msg>fix bug<commit_after>//socket io
const URL = 'http://localhost:6277'
const socket = io.connect(URL)
//user input all infomation
let inclipinfo = []
let intileinfo = []
//user input item
let incliptags
let intiletags = []
// svg con stack(not loaded)
let svg_con_stack_clip = {}
let svg_con_stack_tile = {}
//recieve tags stack
let stacktile = []
//clip form flag
let cflag = true

//send to get all tags
socket.emit('get_allcliptags')

//recieve all clip tags
socket.on('res_allcliptags', (rec) => {
  //set complete clip
  let cliptags = new Bloodhound({
    datumTokenizer: Bloodhound.tokenizers.obj.whitespace('clip'),
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    local: $.map(rec, (tag) => {
      return {
        clip: tag
      }
    })
  })
  //reflection of clip setting
  cliptags.initialize()
  //input auto complete clip
  $('.clip-tags-form').tagsinput({
    typeaheadjs: [{
      minLength: 1,
      highlight: true,
    },{
      minlength: 1,
      name: 'cliptags',
      displayKey: 'clip',
      valueKey: 'clip',
      source: cliptags.ttAdapter()
    }],
    freeInput: true
  })
})

//search button event
$('#search-button').click(() => {
  $('.clip-form').css('overflow-y', 'scroll')
  cflag = true
  $('.aleart-text').css('display', 'none')
  incliptags = $('.clip-tags-form').tagsinput('items')
  //select dropdown item to array
  for(i = 0; i < $('.dropdown-menu li').length; i++){
    if($('#'+i).prop('checked')){
      intiletags.push($('#'+i).val())
    }
  }
  if(incliptags.length == 0){
    $('.clip-form').css('overflow', 'hidden')
    incliptags = undefined
    stacktile = []
    $('.dropdown-menu').empty()
    $('.aleart-text').css('display', 'inline')
  }
  if(intiletags.length == 0){
    intiletags = undefined
  }else{
    cflag = false
  }
  inclipinfo.push({
    cliptags: incliptags,
    startdate: Date.parse($('.start').val()),
    enddate: Date.parse($('.end').val())
  })
  intileinfo.push({
    tiletags: intiletags,
    cliptags: incliptags,
    startdate: Date.parse($('.start').val()),
    enddate: Date.parse($('.end').val())
  })
  $('.clip-form').empty()
  $('.tile-form').empty()
  //send input data
  socket.emit('send_clipsearchdata', inclipinfo[0])
  if(intiletags !== undefined){
    socket.emit('send_tilesearchdata', intileinfo[0])
  }
  inclipinfo = []
  intileinfo = []
  intiletags = []
})

//tile tags dropdown
socket.on('res_alltiletags', (rec) => {
  if(rec.join(',') != stacktile.join(',')){
    $('.dropdown-menu').empty()
    for(i = 0; i < rec.length; i++){
      let $li = $('

')
      let $input = $('<input></input>', {
        id: i,
        type: "checkbox",
        value: rec[i]
      })
      let $label = $('', {
        for: i,
        text: rec[i]
      })
      $('.dropdown-menu').append($li.append($input))
      $('.dropdown-menu').append($li.append($label))
    }
  }
  stacktile = rec
})

//clip form
socket.on('res_clips', (rec) => {
  if(cflag){
    for(i = 0; i < rec.length; i++){
      let $div = $('

', {
        class: 'clip-field ' + i + ' clearfix'
      })
      $('.clip-form').append($div)
      for(j = 0; j < rec[i].tile.length; j++){
        switch(rec[i].tile[j].sty){
          case "txt":
            let $div = $('

', {
              class: 'col-sm-' + rec[i].tile[j].col + ' col-xs-' + rec[i].tile[j].col + ' tile',
              text: rec[i].tile[j].con
            })
            $('.'+i).append($div)

            MathJax.Hub.Queue(["Typeset", MathJax.Hub, "clip-field"])
            break
          case "svg":
            let $span = $('', {
              class: 'col-sm-' + rec[i].tile[j].col + ' col-xs-' + rec[i].tile[j].col + ' iframe-wrap'
            })
            let $iframe = $('', {
              id: rec[i].tile[j]._id,
              src: URL + "/html/read_nu/",
              scrolling: "auto"
            })
            $('.'+i).append(
              $span.append($iframe)
            )

            // stack to var
            svg_con_stack_clip[rec[i].tile[j]._id] = rec[i].tile[j].con

            // onload
            // caution: can not use arrow func
            $iframe.on('load', function(){
              // write path
              $(this)[0].contentWindow.loadPath(svg_con_stack_clip[$(this).attr("id")])
              // delete from stack
              delete svg_con_stack_clip[$(this).attr("id")]
            })
            break
          default:
            console.error('sty error')
            break
        }
      }
    }
  }
})

//tile form
socket.on('res_tiles', (rec) => {
  let $div = $('

', {
    class: 'clip-field clearfix with_tile'
  })
  $('.clip-form').append($div)
  for(i = 0; i < rec.length; i++){
    switch(rec[i].sty){
      case "txt":
        let $div = $('

', {
          class: 'col-sm-' + rec[i].col + ' col-xs-'+ rec[i].col +' tile',
          text: rec[i].con
        })
        $('.with_tile').append($div)

        MathJax.Hub.Queue(["Typeset", MathJax.Hub, "clip-field"])
        break
      case "svg":
        let $span = $('', {
          class: 'col-sm-' + rec[i].col + ' col-xs-'+ rec[i].col + ' iframe-wrap'
        })
        let $iframe = $('', {
          id: rec[i]._id,
          src: URL + "/html/read_nu/",
          scrolling: "auto"
        })
        $('.with_tile').append(
          $span.append($iframe)
        )

        // stack to var
        svg_con_stack_tile[rec[i]._id] = rec[i].con

        // onload
        // caution: can not use arrow func
        $iframe.on('load', function(){
          // write path
          $(this)[0].contentWindow.loadPath(svg_con_stack_tile[$(this).attr("id")])
          // delete from stack
          delete svg_con_stack_tile[$(this).attr("id")]
        })
        break
      default:
        console.error('sty error')
        break
    }
  }
})

<|endoftext|>


<commit_before>var say = require('../../utils/say');
var global = require('../../global');

module.exports = function (unitPaymentCorrection, offset) {

    var items = unitPaymentCorrection.items.map((item) => {
        return {
            quantity: item.quantity,
            uom: item.uom,
            product: item.product,
            pricePerUnit: item.pricePerUnit,
            priceTotal: item.priceTotal,
            prNo: item.purchaseOrder.purchaseRequest.no
        };
    });

    items = [].concat.apply([], items);
    var iso = "FM-PB-00-06-015/R1";
    var currency = unitPaymentCorrection.items.find(r => true).currency.code;
    var urDates = unitPaymentCorrection.unitPaymentOrder.items.map(unitPaymentOrderItem => {
        return new Date(unitPaymentOrderItem.unitReceiptNote.date)
    })
    var sjDate = Math.max.apply(null, urDates);

    var locale = global.config.locale;

    var moment = require('moment');
    moment.locale(locale.name);

    var numberLocaleOptions = {
        style: 'decimal',
        maximumFractionDigits: 4

    };
    var header = [
        {
            columns: [
                {
                    width: '40%',
                    text: 'PT DAN LIRIS',
                    style: ['size15', 'bold', 'left']
                }, {
                    width: '60%',
                    text: 'NOTA KOREKSI',
                    style: ['size15', 'bold', 'left']

                }]
        }, {
            columns: [
                {
                    width: '70%',
                    text: 'BANARAN, GROGOL, SUKOHARJO',
                    style: ['size08']
                }, {
                    width: '30%',
                    stack: [
                        {
                            text: iso,
                            style: ['size09', 'bold']
                        },
                        `SUKOHARJO, ${moment(unitPaymentCorrection.date).format(locale.date.format)}`,
                        `(${unitPaymentCorrection.unitPaymentOrder.supplier.code}) ${unitPaymentCorrection.unitPaymentOrder.supplier.name}`,
                        `${unitPaymentCorrection.unitPaymentOrder.supplier.address}`],
                    alignment: 'left',
                    style: ['size08']

                }]
        }, '\n', {
            columns: [
                {
                    stack: [{
                        columns: [{
                            width: '35%',
                            text: "Retur/Potongan"
                        }, {
                                width: '5%',
                                text: ":"
                            }, {
                                width: '*',
                                text: unitPaymentCorrection.unitPaymentOrder.category.name
                            }],
                        style: ['size08']
                    }, {
                            columns: [{
                                width: '35%',
                                text: "Untuk"
                            }, {
                                    width: '5%',
                                    text: ":"
                                }, {
                                    width: '*',
                                    text: unitPaymentCorrection.unitPaymentOrder.division.name
                                }],
                            style: ['size08']
                        }
                    ]
                }, {
                    width: '20%',
                    text: ''
                }, {
                    width: '30%',
                    text: `Nomor : ${unitPaymentCorrection.no}`,
                    style: ['size13', 'left', 'bold']
                }]
        }, '\n'
    ];

    var thead = [
        {
            text: 'No.',
            style: 'tableHeader'
        }, {
            text: 'Nama Barang',
            style: 'tableHeader'
        }, {
            text: 'Jumlah',
            style: 'tableHeader'
        }, {
            text: 'Harga Satuan',
            style: 'tableHeader'
        }, {
            text: 'Harga Total',
            style: 'tableHeader'
        }, {
            text: 'Nomor Order',
            style: 'tableHeader'
        }
    ];

    var tbody = items.map(function (item, index) {
        return [{
            text: (index + 1).toString() || '',
            style: ['size08', 'center']
        }, {
                text: item.product.name,
                style: ['size08', 'left']
            }, {
                text: `${item.quantity} ${item.uom.unit}`,
                style: ['size08', 'right']
            }, {
                columns: [{
                    width: '20%',
                    text: currency,
                    style: ['size08']
                }, {
                        width: '*',
                        text: parseFloat(item.pricePerUnit).toLocaleString(locale, locale.currency),
                        style: ['size08', 'right']
                    }]
            }, {
                columns: [{
                    width: '20%',
                    text: currency,
                    style: ['size08']
                }, {
                        width: '*',
                        text: parseFloat(item.priceTotal).toLocaleString(locale, locale.currency),
                        style: ['size08', 'right']
                    }]
            }, {
                text: item.prNo,
                style: ['size08', 'left']
            }];
    });

    tbody = tbody.length > 0 ? tbody : [
        [{
            text: "tidak ada barang",
            style: ['size08', 'center'],
            colSpan: 6
        }, "", "", "", "", ""]
    ];

    var table = [{
        table: {
            widths: ['5%', '35%', '15%', '15%', '15%', '15%'],
            headerRows: 1,
            body: [].concat([thead], tbody)
        }
    }];

    var initialValue = {
        priceTotal: 0
    };

    var _jumlah = (items.length > 0 ? items : [initialValue])
        .map(item => item.priceTotal)
        .reduce(function (prev, curr, index, arr) {
            return prev + curr;
        }, 0);

    var useIncomeTax = unitPaymentCorrection.useIncomeTax ? _jumlah * 0.1 : 0;
    var useVAT = unitPaymentCorrection.useVat ? _jumlah * (unitPaymentCorrection.unitPaymentOrder.vatRate / 100) : 0;
    var _subTotal = _jumlah;
    var summary = _jumlah;

    if (unitPaymentCorrection.correctionType === "Jumlah") {
        if (unitPaymentCorrection.useIncomeTax) {
            _subTotal = _subTotal + useIncomeTax;
            summary = _subTotal;
        }
        if (unitPaymentCorrection.useVat) {
            summary = summary - useVAT;
        }
    } else {
        if (unitPaymentCorrection.useIncomeTax) {
            _subTotal = _subTotal + useIncomeTax;
            summary = _subTotal;
        }
        if (unitPaymentCorrection.useVat) {
            summary = summary - useVAT;
        }
    }

    var jumlah = {
        columns: [{
            width: '20%',
            text: 'Jumlah',
            style: ['size08']
        }, {
                width: '20%',
                text: currency,
                style: ['size08']
            }, {
                width: '60%',
                text: parseFloat(_jumlah).toLocaleString(locale, locale.currency),
                style: ['size08', 'right']
            }]
    };

    var incometaxTotal = {
        columns: [{
            width: '20%',
            text: 'PPn 10%',
            style: ['size08']
        }, {
                width: '20%',
                text: unitPaymentCorrection.useIncomeTax ? currency : " ",
                style: ['size08']
            }, {
                width: '60%',
                text: unitPaymentCorrection.useIncomeTax ? parseFloat(useIncomeTax).toLocaleString(locale, locale.currency) : "-",
                style: ['size08', 'right']
            }]
    };

    var vatTotal = {
        columns: [{
            width: '50%',
            text: `PPh ${unitPaymentCorrection.unitPaymentOrder.vat.name} ${unitPaymentCorrection.unitPaymentOrder.vatRate} %`,
            style: ['size08']
        }, {
                width: '20%',
                text: currency,
                style: ['size08']
            }, {
                width: '*',
                text: parseFloat(useVAT).toLocaleString(locale, locale.currency),
                style: ['size08', 'right']
            }]
    };

    var vatBayar = {
        columns: [{
            width: '50%',
            text: `Jumlah dibayar Ke Supplier`,
            style: ['size08']
        }, {
                width: '20%',
                text: currency,
                style: ['size08']
            }, {
                width: '*',
                text: parseFloat(summary).toLocaleString(locale, locale.currency),
                style: ['size08', 'right']
            }]
    };

    var subTotal = {
        columns: [{
                width: '20%',
                text: 'Total',
                style: ['size08']
            }, {
                width: '20%',
                text: currency,
                style: ['size08']
            }, {
                width: '60%',
                text: parseFloat(_subTotal).toLocaleString(locale, locale.currency),
                style: ['size08', 'right', 'bold']
            }]
    };

    var total = [];

    if (unitPaymentCorrection.correctionType === "Jumlah") {
        total = ['\n',{
            columns: [
                {
                    width: '40%',
                    stack: ['\n', unitPaymentCorrection.useVat ? vatTotal : '', unitPaymentCorrection.useVat ? vatBayar : '\n']
                },
                {
                    width: '20%',
                    text: ''
                },
                {
                    width: '40%',
                    stack: [jumlah, incometaxTotal, subTotal]
                }
            ],
            style: ['size08']
        },'\n'];

    } else {
        total = ["\n",{
            columns: [
                {
                    width: '40%',
                    stack: ['\n', unitPaymentCorrection.useVat ? vatTotal : '', unitPaymentCorrection.useVat ? vatBayar : '']
                },
                {
                    width: '20%',
                    text: ''
                },
                {
                    width: '40%',
                    stack: [jumlah, incometaxTotal, subTotal]
                }
            ],
            style: ['size08']
        },"\n"];
    }

    var terbilang = {
        text: `Terbilang : ${say(summary, unitPaymentCorrection.items.find(r => true).currency.description)}`,
        style: ['size09', 'bold']
    };

    var footer = ['\n',
        {
            columns: [
                {
                    width: '50%',
                    columns: [{
                        width: '35%',
                        text: 'Perjanjian Pembayaran',
                        style: ['size08']
                    }, {
                            width: '3%',
                            text: ':',
                            style: ['size08']
                        }, {
                            width: '*',
                            text: moment(unitPaymentCorrection.unitPaymentOrder.dueDate).add(offset,'h').format(locale.date.format),
                            style: ['size08']
                        }]
                }, {
                    width: '50%',
                    columns: [{
                        width: '35%',
                        text: '',
                        style: ['size08']
                    }, {
                            width: '3%',
                            text: '',
                            style: ['size08']
                        }, {
                            width: '*',
                            text: "",
                            style: ['size08']
                        }]
                }]
        }, {
            columns: [
                {
                    width: '50%',
                    columns: [{
                        width: '35%',
                        text: 'Nota',
                        style: ['size08']
                    }, {
                            width: '3%',
                            text: ':',
                            style: ['size08']
                        }, {
                            width: '*',
                            text: `${unitPaymentCorrection.unitPaymentOrder.no}`,
                            style: ['size08']
                        }]
                }, {
                    width: '50%',
                    columns: [{
                        width: '35%',
                        text: 'Barang Datang',
                        style: ['size08']
                    }, {
                            width: '3%',
                            text: ':',
                            style: ['size08']
                        }, {
                            width: '*',
                            text: `${moment(sjDate).add(offset,'h').format(locale.date.format)} `,
                            style: ['size08']
                        }]
                }]
        }, {
            columns: [{
                width: '50%',
                columns: [{
                    width: '35%',
                    text: 'Keterangan',
                    style: ['size08']
                }, {
                        width: '3%',
                        text: ':',
                        style: ['size08']
                    }, {
                        width: '*',
                        text: unitPaymentCorrection.remark,
                        style: ['size08']
                    }]
            }, {
                    width: '50%',
                    columns: [{
                        width: '35%',
                        text: 'Nomor Nota Retur',
                        style: ['size08']
                    }, {
                            width: '3%',
                            text: ':',
                            style: ['size08']
                        }, {
                            width: '*',
                            text: unitPaymentCorrection.returNoteNo,
                            style: ['size08']
                        }]
                }]
        }, '\n'];

    var signature = [{
        columns: [{
            width: '25%',
            stack: ['Diperiksa,', 'Verifikasi', '\n\n\n\n', '(                               )'],
            style: ['center']
        }, {
                width: '25%',
                stack: ['Mengetahui,', 'Pimpinan Bagian', '\n\n\n\n', '(                               )'],
                style: ['center']
            }, {
                width: '25%',
                stack: ['Tanda Terima,', 'Bagian Pembelian', '\n\n\n\n', '(                               )'],
                style: ['center']
            }, {
                width: '25%',
                stack: ['Dibuat Oleh,', ' ', '\n\n\n\n', `(  ${unitPaymentCorrection._createdBy}  )`],
                style: ['center']
            }],
        style: ['size08']
    }, '\n', {
            text: `Dicetak Oleh ${unitPaymentCorrection._createdBy}`,
            style: ['size08']
        }];

    var dd = {
        pageSize: 'A5',
        pageOrientation: 'landscape',
        pageMargins: 20,
        content: [].concat(header, table, total, terbilang, footer, signature),
        styles: {
            size06: {
                fontSize: 6
            },
            size07: {
                fontSize: 7
            },
            size08: {
                fontSize: 8
            },
            size09: {
                fontSize: 9
            },
            size10: {
                fontSize: 10
            },
            size15: {
                fontSize: 15
            },
            bold: {
                bold: true
            },
            center: {
                alignment: 'center'
            },
            left: {
                alignment: 'left'
            },
            right: {
                alignment: 'right'
            },
            justify: {
                alignment: 'justify'
            },
            tableHeader: {
                bold: true,
                fontSize: 8,
                color: 'black',
                alignment: 'center'
            }
        }
    }

    return dd;
}<commit_msg>Update Module PDF<commit_after>var say = require('../../utils/say');
var global = require('../../global');

module.exports = function (unitPaymentCorrection, offset) {

    var items = unitPaymentCorrection.items.map((item) => {
        return {
            quantity: item.quantity,
            uom: item.uom,
            product: item.product,
            pricePerUnit: item.pricePerUnit,
            priceTotal: item.priceTotal,
            prNo: item.purchaseOrder.purchaseRequest.no
        };
    });

    items = [].concat.apply([], items);
    var iso = "FM-PB-00-06-015/R1";
    var currency = unitPaymentCorrection.items.find(r => true).currency.code;
    var urDates = unitPaymentCorrection.unitPaymentOrder.items.map(unitPaymentOrderItem => {
        return new Date(unitPaymentOrderItem.unitReceiptNote.date)
    })
    var sjDate = Math.max.apply(null, urDates);

    var locale = global.config.locale;

    var moment = require('moment');
    moment.locale(locale.name);

    var numberLocaleOptions = {
        style: 'decimal',
        maximumFractionDigits: 4

    };
    var header = [
        {
            columns: [
                {
                    width: '40%',
                    text: 'PT DAN LIRIS',
                    style: ['size15', 'bold', 'left']
                }, {
                    width: '60%',
                    text: 'NOTA KOREKSI',
                    style: ['size15', 'bold', 'left']

                }]
        }, {
            columns: [
                {
                    width: '70%',
                    text: 'BANARAN, GROGOL, SUKOHARJO',
                    style: ['size08']
                }, {
                    width: '30%',
                    stack: [
                        {
                            text: iso,
                            style: ['size09', 'bold']
                        },
                        `SUKOHARJO, ${moment(unitPaymentCorrection.date).format(locale.date.format)}`,
                        `(${unitPaymentCorrection.unitPaymentOrder.supplier.code}) ${unitPaymentCorrection.unitPaymentOrder.supplier.name}`,
                        `${unitPaymentCorrection.unitPaymentOrder.supplier.address}`],
                    alignment: 'left',
                    style: ['size08']

                }]
        }, '\n', {
            columns: [
                {
                    stack: [{
                        columns: [{
                            width: '35%',
                            text: "Retur/Potongan"
                        }, {
                                width: '5%',
                                text: ":"
                            }, {
                                width: '*',
                                text: unitPaymentCorrection.unitPaymentOrder.category.name
                            }],
                        style: ['size08']
                    }, {
                            columns: [{
                                width: '35%',
                                text: "Untuk"
                            }, {
                                    width: '5%',
                                    text: ":"
                                }, {
                                    width: '*',
                                    text: unitPaymentCorrection.unitPaymentOrder.division.name
                                }],
                            style: ['size08']
                        }
                    ]
                }, {
                    width: '20%',
                    text: ''
                }, {
                    width: '30%',
                    text: `Nomor : ${unitPaymentCorrection.no}`,
                    style: ['size13', 'left', 'bold']
                }]
        }, '\n'
    ];

    var thead = [
        {
            text: 'No.',
            style: 'tableHeader'
        }, {
            text: 'Nama Barang',
            style: 'tableHeader'
        }, {
            text: 'Jumlah',
            style: 'tableHeader'
        }, {
            text: 'Harga Satuan',
            style: 'tableHeader'
        }, {
            text: 'Harga Total',
            style: 'tableHeader'
        }, {
            text: 'Nomor Order',
            style: 'tableHeader'
        }
    ];

if (unitPaymentCorrection.correctionType === "Jumlah") {
   var tbody = items.map(function (item, index) {
        return [{
            text: (index + 1).toString() || '',
            style: ['size08', 'center']
        }, {
                text: item.product.name,
                style: ['size08', 'left']
            }, {
                text: `${item.quantity * -1}   ${item.uom.unit}`,
                style: ['size08', 'right']
            }, {
                columns: [{
                    width: '20%',
                    text: currency,
                    style: ['size08']
                }, {
                        width: '*',
                        text: parseFloat(item.pricePerUnit).toLocaleString(locale, locale.currency),
                        style: ['size08', 'right']
                    }]
            }, {
                columns: [{
                    width: '20%',
                    text: currency,
                    style: ['size08']
                }, {
                        width: '*',
                        text: (parseFloat(item.priceTotal * -1).toLocaleString(locale, locale.currency)),
                        style: ['size08', 'right']
                    }]
            }, {
                text: item.prNo,
                style: ['size08', 'left']
            }];
    });
    } else {
     var tbody = items.map(function (item, index) {
        return [{
            text: (index + 1).toString() || '',
            style: ['size08', 'center']
        }, {
                text: item.product.name,
                style: ['size08', 'left']
            }, {
                text: `${item.quantity} ${item.uom.unit}`,
                style: ['size08', 'right']
            }, {
                columns: [{
                    width: '20%',
                    text: currency,
                    style: ['size08']
                }, {
                        width: '*',
                        text: parseFloat(item.pricePerUnit).toLocaleString(locale, locale.currency),
                        style: ['size08', 'right']
                    }]
            }, {
                columns: [{
                    width: '20%',
                    text: currency,
                    style: ['size08']
                }, {
                        width: '*',
                        text: (parseFloat(item.priceTotal).toLocaleString(locale, locale.currency)),
                        style: ['size08', 'right']
                    }]
            }, {
                text: item.prNo,
                style: ['size08', 'left']
            }];
       });
    }

    tbody = tbody.length > 0 ? tbody : [
        [{
            text: "tidak ada barang",
            style: ['size08', 'center'],
            colSpan: 6
        }, "", "", "", "", ""]
    ];

    var table = [{
        table: {
            widths: ['5%', '35%', '15%', '15%', '15%', '15%'],
            headerRows: 1,
            body: [].concat([thead], tbody)
        }
    }];

    var initialValue = {
        priceTotal: 0
    };

if (unitPaymentCorrection.correctionType === "Jumlah") {
       var _jumlah = (items.length > 0 ? items : [initialValue])
          .map(item => item.priceTotal)
           .reduce(function (prev, curr, index, arr) {
               return (prev + curr) * -1;
           }, 0);
    } else {
       var _jumlah = (items.length > 0 ? items : [initialValue])
          .map(item => item.priceTotal)
           .reduce(function (prev, curr, index, arr) {
               return prev + curr;
           }, 0);
    }

    var useIncomeTax = unitPaymentCorrection.useIncomeTax ? _jumlah * 0.1 : 0;
    var useVAT = unitPaymentCorrection.useVat ? _jumlah * (unitPaymentCorrection.unitPaymentOrder.vatRate / 100) : 0;
    var _subTotal = _jumlah;
    var summary = _jumlah;

    if (unitPaymentCorrection.correctionType === "Jumlah") {
        if (unitPaymentCorrection.useIncomeTax) {
            _subTotal = _subTotal + useIncomeTax;
            summary = _subTotal;
        }
        if (unitPaymentCorrection.useVat) {
            summary = summary - useVAT;
        }
    } else {
        if (unitPaymentCorrection.useIncomeTax) {
            _subTotal = _subTotal + useIncomeTax;
            summary = _subTotal;
        }
        if (unitPaymentCorrection.useVat) {
            summary = summary - useVAT;
        }
    }

    var jumlah = {
        columns: [{
            width: '20%',
            text: 'Jumlah',
            style: ['size08']
        }, {
                width: '20%',
                text: currency,
                style: ['size08']
            }, {
                width: '60%',
                text: parseFloat(_jumlah).toLocaleString(locale, locale.currency),
                style: ['size08', 'right']
            }]
    };

    var incometaxTotal = {
        columns: [{
            width: '20%',
            text: 'PPn 10%',
            style: ['size08']
        }, {
                width: '20%',
                text: unitPaymentCorrection.useIncomeTax ? currency : " ",
                style: ['size08']
            }, {
                width: '60%',
                text: unitPaymentCorrection.useIncomeTax ? parseFloat(useIncomeTax).toLocaleString(locale, locale.currency) : "-",
                style: ['size08', 'right']
            }]
    };

    var vatTotal = {
        columns: [{
            width: '50%',
            text: `PPh ${unitPaymentCorrection.unitPaymentOrder.vat.name} ${unitPaymentCorrection.unitPaymentOrder.vatRate} %`,
            style: ['size08']
        }, {
                width: '20%',
                text: currency,
                style: ['size08']
            }, {
                width: '*',
                text: parseFloat(useVAT).toLocaleString(locale, locale.currency),
                style: ['size08', 'right']
            }]
    };

    var vatBayar = {
        columns: [{
            width: '50%',
            text: `Jumlah dibayar Ke Supplier`,
            style: ['size08']
        }, {
                width: '20%',
                text: currency,
                style: ['size08']
            }, {
                width: '*',
                text: parseFloat(summary).toLocaleString(locale, locale.currency),
                style: ['size08', 'right']
            }]
    };

    var subTotal = {
        columns: [{
                width: '20%',
                text: 'Total',
                style: ['size08']
            }, {
                width: '20%',
                text: currency,
                style: ['size08']
            }, {
                width: '60%',
                text: parseFloat(_subTotal).toLocaleString(locale, locale.currency),
                style: ['size08', 'right', 'bold']
            }]
    };

    var total = [];

    if (unitPaymentCorrection.correctionType === "Jumlah") {
        total = ['\n',{
            columns: [
                {
                    width: '40%',
                    stack: ['\n', unitPaymentCorrection.useVat ? vatTotal : '', unitPaymentCorrection.useVat ? vatBayar : '\n']
                },
                {
                    width: '20%',
                    text: ''
                },
                {
                    width: '40%',
                    stack: [jumlah, incometaxTotal, subTotal]
                }
            ],
            style: ['size08']
        },'\n'];

    } else {
        total = ["\n",{
            columns: [
                {
                    width: '40%',
                    stack: ['\n', unitPaymentCorrection.useVat ? vatTotal : '', unitPaymentCorrection.useVat ? vatBayar : '']
                },
                {
                    width: '20%',
                    text: ''
                },
                {
                    width: '40%',
                    stack: [jumlah, incometaxTotal, subTotal]
                }
            ],
            style: ['size08']
        },"\n"];
    }

    var terbilang = {
        text: `Terbilang : ${say(summary, unitPaymentCorrection.items.find(r => true).currency.description)}`,
        style: ['size09', 'bold']
    };

    var footer = ['\n',
        {
            columns: [
                {
                    width: '50%',
                    columns: [{
                        width: '35%',
                        text: 'Perjanjian Pembayaran',
                        style: ['size08']
                    }, {
                            width: '3%',
                            text: ':',
                            style: ['size08']
                        }, {
                            width: '*',
                            text: moment(unitPaymentCorrection.unitPaymentOrder.dueDate).add(offset,'h').format(locale.date.format),
                            style: ['size08']
                        }]
                }, {
                    width: '50%',
                    columns: [{
                        width: '35%',
                        text: '',
                        style: ['size08']
                    }, {
                            width: '3%',
                            text: '',
                            style: ['size08']
                        }, {
                            width: '*',
                            text: "",
                            style: ['size08']
                        }]
                }]
        }, {
            columns: [
                {
                    width: '50%',
                    columns: [{
                        width: '35%',
                        text: 'Nota',
                        style: ['size08']
                    }, {
                            width: '3%',
                            text: ':',
                            style: ['size08']
                        }, {
                            width: '*',
                            text: `${unitPaymentCorrection.unitPaymentOrder.no}`,
                            style: ['size08']
                        }]
                }, {
                    width: '50%',
                    columns: [{
                        width: '35%',
                        text: 'Barang Datang',
                        style: ['size08']
                    }, {
                            width: '3%',
                            text: ':',
                            style: ['size08']
                        }, {
                            width: '*',
                            text: `${moment(sjDate).add(offset,'h').format(locale.date.format)} `,
                            style: ['size08']
                        }]
                }]
        }, {
            columns: [{
                width: '50%',
                columns: [{
                    width: '35%',
                    text: 'Keterangan',
                    style: ['size08']
                }, {
                        width: '3%',
                        text: ':',
                        style: ['size08']
                    }, {
                        width: '*',
                        text: unitPaymentCorrection.remark,
                        style: ['size08']
                    }]
            }, {
                    width: '50%',
                    columns: [{
                        width: '35%',
                        text: 'Nomor Nota Retur',
                        style: ['size08']
                    }, {
                            width: '3%',
                            text: ':',
                            style: ['size08']
                        }, {
                            width: '*',
                            text: unitPaymentCorrection.returNoteNo,
                            style: ['size08']
                        }]
                }]
        }, '\n'];

    var signature = [{
        columns: [{
            width: '25%',
            stack: ['Diperiksa,', 'Verifikasi', '\n\n\n\n', '(                               )'],
            style: ['center']
        }, {
                width: '25%',
                stack: ['Mengetahui,', 'Pimpinan Bagian', '\n\n\n\n', '(                               )'],
                style: ['center']
            }, {
                width: '25%',
                stack: ['Tanda Terima,', 'Bagian Pembelian', '\n\n\n\n', '(                               )'],
                style: ['center']
            }, {
                width: '25%',
                stack: ['Dibuat Oleh,', ' ', '\n\n\n\n', `(  ${unitPaymentCorrection._createdBy}  )`],
                style: ['center']
            }],
        style: ['size08']
    }, '\n', {
            text: `Dicetak Oleh ${unitPaymentCorrection._createdBy}`,
            style: ['size08']
        }];

    var dd = {
        pageSize: 'A5',
        pageOrientation: 'landscape',
        pageMargins: 20,
        content: [].concat(header, table, total, terbilang, footer, signature),
        styles: {
            size06: {
                fontSize: 6
            },
            size07: {
                fontSize: 7
            },
            size08: {
                fontSize: 8
            },
            size09: {
                fontSize: 9
            },
            size10: {
                fontSize: 10
            },
            size15: {
                fontSize: 15
            },
            bold: {
                bold: true
            },
            center: {
                alignment: 'center'
            },
            left: {
                alignment: 'left'
            },
            right: {
                alignment: 'right'
            },
            justify: {
                alignment: 'justify'
            },
            tableHeader: {
                bold: true,
                fontSize: 8,
                color: 'black',
                alignment: 'center'
            }
        }
    }

    return dd;
}<|endoftext|>


<commit_before>var schedule = require('node-schedule'),
    ScheduleWorker = require('./worker'),
    request = require('request'),
    registry = require('./registry');

var host = process.env.NODE_ENV === 'development'? 'http://localhost:9000/':'http://your_app_name.herokuapp.com/';

function pingPongHerokuHandler(){
    request(host, function(err, res, body){ });
}

exports.init = function(){
    var firstHerokuWorker = new ScheduleWorker({minute: 15}, pingPongHerokuHandler),
        secondHerokuWorker = new ScheduleWorker({minute: 45}, pingPongHerokuHandler);

    var registryWorker = new ScheduleWorker({hour: 1}, registry.handler, true);
}
<commit_msg>run registry worker every hour, #10<commit_after>var schedule = require('node-schedule'),
    ScheduleWorker = require('./worker'),
    request = require('request'),
    registry = require('./registry');

var host = process.env.NODE_ENV === 'development'? 'http://localhost:9000/':'http://your_app_name.herokuapp.com/';

function pingPongHerokuHandler(){
    request(host, function(err, res, body){ });
}

exports.init = function(){
    var firstHerokuWorker = new ScheduleWorker({minute: 15}, pingPongHerokuHandler),
        secondHerokuWorker = new ScheduleWorker({minute: 45}, pingPongHerokuHandler);

    var registryWorker = new ScheduleWorker({minute: 1}, registry.handler, true);
}
<|endoftext|>


<commit_before>var Wave = {};
Wave.Game = function(game) {};

Wave.Game.prototype = {
  init: function(){
    this.count = 0;
    this.waveTotalLength = 1600;
    this.numWaves = 10;
    this.waves = null;
    this.boat = null;
    this.lastWaveX = 0;
    this.WAVE_LENGTH = 160;
  },

  preload: function(){
    this.game.load.spritesheet('wave', 'wave.png', this.WAVE_LENGTH, this.WAVE_LENGTH);
    this.game.load.image('boat', 'boat.png');
  },

  create: function(){
    var x, y, wave;
    this.game.world.setBounds(0, 0, 3200, 600);
    this.game.physics.startSystem(Phaser.Physics.ARCADE);

    this.waves = this.game.add.group();
    this.waves.x = -this.WAVE_LENGTH*2;
    this.waves.y = this.game.world.height - 50;
    this.waves.enableBody = true;
    this.waves.physicsBodyType = Phaser.Physics.ARCADE;

    for (var i = 0; i < this.numWaves; i++)
    {
      x = i*waveLength;
      y = 0;
      wave = this.game.add.sprite(x, y, 'wave', this.game.rnd.between(0,1));
      wave.anchor.set(0.5,0.5);
      this.waves.add(wave);
      wave.body.setCircle(this.game.rnd.between(80,140));
      wave.body.offset.set(0, 50);
      wave.body.immovable = true;
      this.lastWaveX = wave.x;
    }

    this.boat = this.game.add.sprite(0, 0, 'boat');
    this.game.physics.arcade.enable(this.boat);
    this.boat.body.gravity.y = 250;
    this.boat.body.setCircle(32);
    this.game.camera.follow(this.boat);
  },

  update: function(){
    this.game.physics.arcade.collide(this.boat, this.waves);
    this.count += 0.1;
    this.boat.body.velocity.x = 90; // Constantly move boat to the right
    this.game.debug.text("Camera "+this.game.camera.x, 0, 10);

    this.waves.forEach(function(currentWave){
      var i = this.waves.getChildIndex(currentWave);
      var amp = 5;
      var x = i * 0.9 + this.count;
      var y = Math.sin(x) * amp;
      var newX;
      currentWave.y = y;

      this.game.debug.text("Wave["+i+"]: (" + currentWave.x + ","+ currentWave.y+")", 10, 11*i+20)

      // check if the current wave's right edge (in world coords) is less than the camera's left edge
      if((currentWave.world.x + currentWave.offsetX) < this.game.camera.x) {
        newX = this.lastWaveX+this.WAVE_LENGTH;
        currentWave.x = this.lastWaveX = newX;
      }
    }, this);
  },

  render: function(){
    // this.game.debug.body(this.boat);
    // for(var i = 0; i < this.numWaves; i++) {
    //   this.game.debug.body(this.waves.children[i]);
    // }
  }
};<commit_msg>Use WAVE_LENGTH in loop<commit_after>var Wave = {};
Wave.Game = function(game) {};

Wave.Game.prototype = {
  init: function(){
    this.count = 0;
    this.waveTotalLength = 1600;
    this.numWaves = 10;
    this.waves = null;
    this.boat = null;
    this.lastWaveX = 0;
    this.WAVE_LENGTH = 160;
  },

  preload: function(){
    this.game.load.spritesheet('wave', 'wave.png', this.WAVE_LENGTH, this.WAVE_LENGTH);
    this.game.load.image('boat', 'boat.png');
  },

  create: function(){
    var x, y, wave;
    this.game.world.setBounds(0, 0, 3200, 600);
    this.game.physics.startSystem(Phaser.Physics.ARCADE);

    this.waves = this.game.add.group();
    this.waves.x = -this.WAVE_LENGTH*2;
    this.waves.y = this.game.world.height - 50;
    this.waves.enableBody = true;
    this.waves.physicsBodyType = Phaser.Physics.ARCADE;

    for (var i = 0; i < this.numWaves; i++)
    {
      x = i*this.WAVE_LENGTH;
      y = 0;
      wave = this.game.add.sprite(x, y, 'wave', this.game.rnd.between(0,1));
      wave.anchor.set(0.5,0.5);
      this.waves.add(wave);
      wave.body.setCircle(this.game.rnd.between(80,140));
      wave.body.offset.set(0, 50);
      wave.body.immovable = true;
      this.lastWaveX = wave.x;
    }

    this.boat = this.game.add.sprite(0, 0, 'boat');
    this.game.physics.arcade.enable(this.boat);
    this.boat.body.gravity.y = 250;
    this.boat.body.setCircle(32);
    this.game.camera.follow(this.boat);
  },

  update: function(){
    this.game.physics.arcade.collide(this.boat, this.waves);
    this.count += 0.1;
    this.boat.body.velocity.x = 90; // Constantly move boat to the right
    this.game.debug.text("Camera "+this.game.camera.x, 0, 10);

    this.waves.forEach(function(currentWave){
      var i = this.waves.getChildIndex(currentWave);
      var amp = 5;
      var x = i * 0.9 + this.count;
      var y = Math.sin(x) * amp;
      var newX;
      currentWave.y = y;

      this.game.debug.text("Wave["+i+"]: (" + currentWave.x + ","+ currentWave.y+")", 10, 11*i+20)

      // check if the current wave's right edge (in world coords) is less than the camera's left edge
      if((currentWave.world.x + currentWave.offsetX) < this.game.camera.x) {
        newX = this.lastWaveX+this.WAVE_LENGTH;
        currentWave.x = this.lastWaveX = newX;
      }
    }, this);
  },

  render: function(){
    // this.game.debug.body(this.boat);
    // for(var i = 0; i < this.numWaves; i++) {
    //   this.game.debug.body(this.waves.children[i]);
    // }
  }
};<|endoftext|>


<commit_before>var wfjs = (function () {
var wfjs1 = {};

var SVGNS = "http://www.w3.org/2000/svg";

var TEXT_DEFAULT_OPTIONS = {
	fill : "black",
	"font-size" : "1em",
};

var draggingTarget = null;

var _onMouseDown = function(e){
	var target = e.target;
	draggingTarget = e.target;
};

wfjs1.Canvas = (function () {
    function Canvas(containerId) {

		var _this = this;
		var _onMouseUp = function(e){
			if(draggingTarget != null){
//				draggingTarget.setAttribute("cx", e.pageX);
//				draggingTarget.setAttribute("cy", e.pageY);
				var targetId = draggingTarget.getAttribute("id");
// TODO				var children = _this.children.getById(targetId).move();
				var node = _this.nodes.getById(targetId);
				node.move(e.offsetX, e.offsetY);
//				for(var i = 0; i < children.length; i++){
//					var text  = children[i];
//					var rect = text.getBBox();
//					text.setAttribute("x", e.pageX - (rect.width/2));
//					text.setAttribute("y", e.pageY);
//				}
				draggingTarget = null;
			}
		};

        this.containerId = containerId;
		this.container = document.getElementById(containerId);

		var svgElement = document.createElementNS(SVGNS, "svg");
		svgElement.setAttribute("id", "wfjs_svg");
		svgElement.setAttribute("version", "1.1");
		svgElement.addEventListener("mouseup", _onMouseUp, false);
		this.container.appendChild(svgElement);
		this.svgElement = svgElement;

		this.nodes = [];
		this.nodes.getById = function(id){
			for(var i = 0; i < this.length; i++){
				if(this[i].id == id){
					return this[i];
				}
			}
		}
    }

    return Canvas;
})();

wfjs1.Node = (function () {
    function Node(canvas, x, y, label, circle_options, text_options) {
		this.id = "wfjs_node_" + canvas.nodes.length;
        this.canvas = canvas;
        this.x = x;
        this.y = y;
        this.label = label;
        this.circle_options = circle_options;
        this.text_options = text_options;
		this.children = [];
    };

    Node.prototype.show = function () {
		//var circleId = "wfjs_circle_";
//		var textId = "wfjs_circle_" + this.circles.length + "_text";
		var textId = "wfjs_circle__text";

		this.circle = document.createElementNS(SVGNS, "circle");
		this.circle.setAttribute("id", this.id);

		for(var attr in this.circle_options){
			this.circle.setAttribute(attr, this.circle_options[attr]);
		}
		this.circle.setAttribute("cx", this.x);
		this.circle.setAttribute("cy", this.y);
		this.circle.addEventListener("mousedown", _onMouseDown, false);
		this.canvas.svgElement.appendChild(this.circle);

		var text = document.createElementNS(SVGNS, "text");

		text.setAttribute("id", textId);
		text.textContent = this.label;

		for(var attr in TEXT_DEFAULT_OPTIONS){
			text.setAttribute(attr, TEXT_DEFAULT_OPTIONS[attr]);
		}

		if(this.text_options !=null && this.text_options !== undefined){
			for(var attr in this.text_options){
				text.setAttribute(attr, this.text_options[attr]);
			}
		}

		this.canvas.svgElement.appendChild(text);
		var rect = text.getBBox();
		text.setAttribute("x", this.x - (rect.width/2));
		text.setAttribute("y", this.y);

		this.children.push(text);

		this.canvas.nodes.push(this);
//		this.canvas.nodes.push({
//			id : this.id,
//			obj : this,
//		});
    }; // End of show()

    Node.prototype.move = function(x, y) {
		this.circle.setAttribute("cx", x);
		this.circle.setAttribute("cy", y);
//		var children = this.children.getById(targetId).move();
		for(var i = 0; i < this.children.length; i++){
			var text  = this.children[i];
			var rect = text.getBBox();
			text.setAttribute("x", x - (rect.width/2));
			text.setAttribute("y", y);
		}

    }; // End of move()

    return Node;
})();

return wfjs1;
})();

var wfjs10 = {
	_wfjs : null,
	SVGNS : "http://www.w3.org/2000/svg",
	target: null,
	svg: null,

	text_default_options : {
		fill : "black",
		"font-size" : "1em",
	},

	circles : [],

	init : function(targetId){
		_wfjs = this;
		this.target = document.getElementById(targetId);
		var svg = document.createElementNS(this.SVGNS, "svg");
		svg.setAttribute("id", "wfjs_svg");
		svg.setAttribute("xmlns", this.SVGNS);
		svg.setAttribute("version", "1.1");
		this.target.appendChild(svg);
		this.svg = svg;
		svg.addEventListener("mouseup", this._onMouseUp, false);

		this.circles.getById = function(id){
			for(var i = 0; i < this.length; i++){
				if(this[i].id == id){
					return this[i];
				}
			}
		}

	},

	circle : function(x, y, label, circle_options, text_options){
		var circleId = "wfjs_circle_" + this.circles.length;
		var textId = "wfjs_circle_" + this.circles.length + "_text";

		var circle = document.createElementNS(this.SVGNS, "circle");
		circle.setAttribute("id", circleId);

		for(var attr in circle_options){
			circle.setAttribute(attr, circle_options[attr]);
		}
		circle.setAttribute("cx", x);
		circle.setAttribute("cy", y);
		circle.addEventListener("mousedown", this._onMouseDown, false);
		this.svg.appendChild(circle);

		var text = document.createElementNS(this.SVGNS, "text");

		text.setAttribute("id", textId);
		text.textContent = label;

		for(var attr in this.text_default_options){
			text.setAttribute(attr, this.text_default_options[attr]);
		}

		if(text_options !=null && text_options !== undefined){
			for(var attr in text_options){
				text.setAttribute(attr, text_options[attr]);
			}
		}

		this.svg.appendChild(text);
		var rect = text.getBBox();
		text.setAttribute("x", x - (rect.width/2));
		text.setAttribute("y", y);

		this.circles.push({
			id : circleId,
			children : [text]
		});
	},

	draggingTarget : null,

	_onMouseDown : function(e){
		var target = e.target;
		draggingTarget = e.target;
	},

	_onMouseUp : function(e){
		if(draggingTarget != null){
			draggingTarget.setAttribute("cx", e.pageX);
			draggingTarget.setAttribute("cy", e.pageY);
			var targetId = draggingTarget.getAttribute("id");
			var children = _wfjs.circles.getById(targetId).children;
			for(var i = 0; i < children.length; i++){
				var text  = children[i];
				var rect = text.getBBox();
				text.setAttribute("x", e.pageX - (rect.width/2));
				text.setAttribute("y", e.pageY);
			}
			draggingTarget = null;
		}
	},

}
<commit_msg>renamed a variable and removed comments<commit_after>var wfjs = (function () {
var wfjs1 = {};

var SVGNS = "http://www.w3.org/2000/svg";

var TEXT_DEFAULT_OPTIONS = {
	fill : "black",
	"font-size" : "1em",
};

var draggingTarget = null;

var _onMouseDown = function(e){
	var target = e.target;
	draggingTarget = e.target;
};

wfjs1.Canvas = (function () {
    function Canvas(containerId) {

		var _this = this;
		var _onMouseUp = function(e){
			if(draggingTarget != null){
//				draggingTarget.setAttribute("cx", e.pageX);
//				draggingTarget.setAttribute("cy", e.pageY);
				var targetId = draggingTarget.getAttribute("id");
				var node = _this.nodes.getById(targetId);
				node.move(e.offsetX, e.offsetY);
				draggingTarget = null;
			}
		};

        this.containerId = containerId;
		this.container = document.getElementById(containerId);

		var svgElement = document.createElementNS(SVGNS, "svg");
		svgElement.setAttribute("id", "wfjs_svg");
		svgElement.setAttribute("version", "1.1");
		svgElement.addEventListener("mouseup", _onMouseUp, false);
		this.container.appendChild(svgElement);
		this.svgElement = svgElement;

		this.nodes = [];
		this.nodes.getById = function(id){
			for(var i = 0; i < this.length; i++){
				if(this[i].id == id){
					return this[i];
				}
			}
			return null;
		}
    }

    return Canvas;
})();

wfjs1.Node = (function () {
    function Node(canvas, x, y, label, circle_options, text_options) {
		this.id = "wfjs_node_" + canvas.nodes.length;
        this.canvas = canvas;
        this.x = x;
        this.y = y;
        this.label = label;
        this.circle_options = circle_options;
        this.text_options = text_options;
		this.children = [];
    };

    Node.prototype.show = function () {
//		var textId = "wfjs_circle_" + this.circles.length + "_text";
		var textId = "wfjs_circle__text";

		this.circleElement = document.createElementNS(SVGNS, "circle");
		this.circleElement.setAttribute("id", this.id);

		for(var attr in this.circle_options){
			this.circleElement.setAttribute(attr, this.circle_options[attr]);
		}
		this.circleElement.setAttribute("cx", this.x);
		this.circleElement.setAttribute("cy", this.y);
		this.circleElement.addEventListener("mousedown", _onMouseDown, false);
		this.canvas.svgElement.appendChild(this.circleElement);

		var text = document.createElementNS(SVGNS, "text");

		text.setAttribute("id", textId);
		text.textContent = this.label;

		for(var attr in TEXT_DEFAULT_OPTIONS){
			text.setAttribute(attr, TEXT_DEFAULT_OPTIONS[attr]);
		}

		if(this.text_options !=null && this.text_options !== undefined){
			for(var attr in this.text_options){
				text.setAttribute(attr, this.text_options[attr]);
			}
		}

		this.canvas.svgElement.appendChild(text);
		var rect = text.getBBox();
		text.setAttribute("x", this.x - (rect.width/2));
		text.setAttribute("y", this.y);

		this.children.push(text);

		this.canvas.nodes.push(this);

    }; // End of show()

    Node.prototype.move = function(x, y) {
		this.circleElement.setAttribute("cx", x);
		this.circleElement.setAttribute("cy", y);
//		var children = this.children.getById(targetId).move();
		for(var i = 0; i < this.children.length; i++){
			var text  = this.children[i];
			var rect = text.getBBox();
			text.setAttribute("x", x - (rect.width/2));
			text.setAttribute("y", y);
		}

    }; // End of move()

    return Node;
})();

return wfjs1;
})();

var wfjs10 = {
	_wfjs : null,
	SVGNS : "http://www.w3.org/2000/svg",
	target: null,
	svg: null,

	text_default_options : {
		fill : "black",
		"font-size" : "1em",
	},

	circles : [],

	init : function(targetId){
		_wfjs = this;
		this.target = document.getElementById(targetId);
		var svg = document.createElementNS(this.SVGNS, "svg");
		svg.setAttribute("id", "wfjs_svg");
		svg.setAttribute("xmlns", this.SVGNS);
		svg.setAttribute("version", "1.1");
		this.target.appendChild(svg);
		this.svg = svg;
		svg.addEventListener("mouseup", this._onMouseUp, false);

		this.circles.getById = function(id){
			for(var i = 0; i < this.length; i++){
				if(this[i].id == id){
					return this[i];
				}
			}
		}

	},

	circle : function(x, y, label, circle_options, text_options){
		var circleId = "wfjs_circle_" + this.circles.length;
		var textId = "wfjs_circle_" + this.circles.length + "_text";

		var circle = document.createElementNS(this.SVGNS, "circle");
		circle.setAttribute("id", circleId);

		for(var attr in circle_options){
			circle.setAttribute(attr, circle_options[attr]);
		}
		circle.setAttribute("cx", x);
		circle.setAttribute("cy", y);
		circle.addEventListener("mousedown", this._onMouseDown, false);
		this.svg.appendChild(circle);

		var text = document.createElementNS(this.SVGNS, "text");

		text.setAttribute("id", textId);
		text.textContent = label;

		for(var attr in this.text_default_options){
			text.setAttribute(attr, this.text_default_options[attr]);
		}

		if(text_options !=null && text_options !== undefined){
			for(var attr in text_options){
				text.setAttribute(attr, text_options[attr]);
			}
		}

		this.svg.appendChild(text);
		var rect = text.getBBox();
		text.setAttribute("x", x - (rect.width/2));
		text.setAttribute("y", y);

		this.circles.push({
			id : circleId,
			children : [text]
		});
	},

	draggingTarget : null,

	_onMouseDown : function(e){
		var target = e.target;
		draggingTarget = e.target;
	},

	_onMouseUp : function(e){
		if(draggingTarget != null){
			draggingTarget.setAttribute("cx", e.pageX);
			draggingTarget.setAttribute("cy", e.pageY);
			var targetId = draggingTarget.getAttribute("id");
			var children = _wfjs.circles.getById(targetId).children;
			for(var i = 0; i < children.length; i++){
				var text  = children[i];
				var rect = text.getBBox();
				text.setAttribute("x", e.pageX - (rect.width/2));
				text.setAttribute("y", e.pageY);
			}
			draggingTarget = null;
		}
	},

}
<|endoftext|>