<commit_before>(function () { "use strict";

function parentPath(x) {
	var match = x.match(/(\/[\w_-]+)+\/[\w_-]+$/);
	return match ? match[1] : '/';
}

var _ = require('underscore');
var util = require('util');
var assert = require('assert');
var buscomponent = require('./buscomponent.js');

function AdminDB () {
}
util.inherits(AdminDB, buscomponent.BusComponent);

function _reqpriv_x (required, f) {
	var requiredPermission = required;
	return function(query, user, access, xdata, cb) {
		if (user === null || !access.has(requiredPermission))
			(cb ? cb : xdata)('permission-denied');
		else
			return _.bind(f, this)(query, user, access, xdata, cb);
	};
}

function _reqpriv (required, f) {
	return _reqpriv_x(required, function(query, user, access, xdata, cb) {
		return _.bind(f, this)(query, user, access, cb = xdata);
	});
}

AdminDB.prototype.listAllUsers = buscomponent.provideQUA('client-list-all-users', _reqpriv('userdb', function(query, user, access, cb) {
	this.query('SELECT birthday, deletiontime, street, zipcode, town, `desc`, users.name, giv_name, fam_name, users.id AS uid, tradecount, ' +
		'email, email_verif AS emailverif, wprovision, lprovision, freemoney, totalvalue, wprov_sum, lprov_sum, ticks, registertime, ' +
		'logins.logintime AS lastlogintime, schools.path AS schoolpath, schools.id AS schoolid, pending, jointime, ' +
		'(SELECT COUNT(*) FROM ecomments WHERE ecomments.commenter=users.id) AS commentcount, '+
		'(SELECT MAX(time) FROM ecomments WHERE ecomments.commenter=users.id) AS lastcommenttime FROM users ' +
		'LEFT JOIN schoolmembers AS sm ON sm.uid = users.id ' +
		'LEFT JOIN schools ON schools.id = sm.schoolid ' +
		'LEFT JOIN logins ON logins.id = (SELECT id FROM logins AS l WHERE l.uid = users.id ORDER BY logintime DESC LIMIT 1)',
		[], function(userlist) {
		cb('list-all-users-success', {results: userlist});
	});
}));

AdminDB.prototype.evalCode = buscomponent.provideQUA('client-eval-code', _reqpriv('*', function(query, user, access, cb) {
	if (!query.authorizationKey)
		cb('permission-denied');
	else
		cb('eval-code-success', {result: eval(query.code)});
}));

AdminDB.prototype.shutdown = buscomponent.provideQUA('client-shutdown', _reqpriv('server', function(query, user, access, cb) {
	this.emit('globalShutdown');
	this.emit('localShutdown');

	cb('shutdown-success');
}));

AdminDB.prototype.impersonateUser = buscomponent.provideQUA('client-impersonate-user', _reqpriv('server', function(query, user, access, cb) {
	this.query('SELECT COUNT(*) AS c FROM users WHERE id=?', [query.uid], function(r) {
		assert.equal(r.length, 1);
		if (r[0].c == 0)
			return cb('impersonate-user-notfound', null, 'repush');

		this.query('UPDATE sessions SET uid = ? WHERE id = ?', [query.uid, user.sid], function() {
			cb('impersonate-user-success', null, 'repush');
		});
	});
}));

AdminDB.prototype.deleteUser = buscomponent.provideQUA('client-delete-user', _reqpriv('userdb', function(query, user, access, cb) {
	if (user.id == query.uid)
		return cb('delete-user-self-notallowed');

	this.getConnection(function(conn) {
		conn.query('START TRANSACTION', [], function() {
		conn.query('DELETE FROM sessions WHERE uid = ?', [query.uid], function() {
		conn.query('DELETE FROM schoolmembers WHERE uid = ?', [query.uid], function() {
		conn.query('UPDATE stocks SET name = CONCAT("leader:deleted", ?) WHERE leader = ?', [query.uid, query.uid], function() {
		conn.query('UPDATE users SET name = CONCAT("user_deleted", ?), giv_name="__user_deleted__", email = CONCAT("deleted:", email), ' +
		'fam_name="", pwhash="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", birthday=NULL, realnamepublish=0, `desc`="", wprovision=0, lprovision=0, ' +
		'street="", zipcode="", town="", traditye=0, deletiontime = UNIX_TIMESTAMP() WHERE id = ?', [query.uid, query.uid], function() {
			conn.query('COMMIT', [], function() {
				conn.release();
				cb('delete-user-success');
			});
		});
		});
		});
		});
		});
	});
}));

AdminDB.prototype.changeUserEMail = buscomponent.provideQUA('client-change-user', _reqpriv('userdb', function(query, user, access, cb) {
	this.query('UPDATE users SET email = ?, email_verif = ? WHERE id = ?', [query.email, query.emailverif ? 1 : 0, query.uid], function() {
		cb('change-user-email-success');
	});
}));

AdminDB.prototype.changeCommentText = buscomponent.provideQUA('client-change-comment-text', _reqpriv('moderate', function(query, user, access, cb) {
	this.query('UPDATE ecomments SET comment = ?, trustedhtml = ? WHERE commentid = ?', [query.comment, access.has('server') && query.trustedhtml ? 1:0, query.commentid], function() {
		cb('change-comment-text-success');
	});
}));

AdminDB.prototype.notifyUnstickAll = buscomponent.provideQUA('client-notify-unstick-all', _reqpriv('moderate', function(query, user, access, cb) {
	this.query('UPDATE mod_notif SET sticky = 0', [], function() {
		cb('notify-unstick-all-success');
	});
}));

AdminDB.prototype.notifyAll = buscomponent.provideQUA('client-notify-all', _reqpriv('moderate', function(query, user, access, cb) {
	this.query('INSERT INTO mod_notif (content, sticky) VALUES (?, ?)', [query.content, query.sticky ? 1 : 0], function(res) {
		this.feed({'type': 'mod-notification', 'targetid': res.insertId, 'srcuser': user.id, 'everyone': true});
		cb('notify-all-success');
	});
}));

AdminDB.prototype.renameSchool = buscomponent.provideQUA('client-rename-school', _reqpriv('schooldb', function(query, user, access, cb) {
	this.query('SELECT path FROM schools WHERE id = ?', [query.schoolid], function(r) {
		if (r.length == 0 || (query.schoolpath && parentPath(r[0].path) != parentPath(query.schoolpath)))
			return cb('rename-school-notfound');

		this.query('UPDATE schools SET name = ? WHERE id = ?', [query.schoolname, query.schoolid], function() {
			if (query.schoolpath) {
				this.query('UPDATE schools SET path = REPLACE(path, ?, ?) WHERE path LIKE ? OR path = ?', [r[0].path, query.schoolpath, r[0].path + '/%', r[0].path], function() {
					cb('rename-school-success');
				});
			} else {
				cb('rename-school-success');
			}
		});
	});
}));

AdminDB.prototype.joinSchools = buscomponent.provideQUA('client-join-schools', _reqpriv('schooldb', function(query, user, access, cb) {
	this.query('SELECT path FROM schools WHERE id = ?', [query.masterschool], function(mr) {
	this.query('SELECT path FROM schools WHERE id = ?', [query.subschool], function(sr) {
		assert.ok(mr.length <= 1);
		assert.ok(sr.length <= 1);

		if (sr.length == 0 || ((mr.length == 0 || mr[0].path == sr[0].path) && query.masterschool != null))
			return cb('join-schools-notfound');
		if (mr.length > 0 && parentPath(mr[0].path) != parentPath(sr[0].path))
			return cb('join-schools-diff-parent');

		this.query('UPDATE schoolmembers SET schoolid = ? WHERE schoolid = ?', [query.masterschool, query.subschool], function() {
		this.query('DELETE FROM schooladmins WHERE schoolid = ?', [query.subschool], function() {
			this.query('DELETE FROM schools WHERE id = ?', [query.subschool], function() {
				cb('join-schools-success');
			});
		});
		});
	});
	});
}));

AdminDB.prototype.getUserLogins = buscomponent.provideQUA('client-get-user-logins', _reqpriv('userdb', function(query, user, access, cb) {
	this.query('SELECT * FROM logins WHERE uid = ?', [query.uid], function(res) {
		_.each(res, function(e) {
			e.headers = JSON.parse(e.headers);
		});

		cb('get-user-logins-success', {results: res});
	});
}));

AdminDB.prototype.getTicksStatistics = buscomponent.provideQUA('client-get-ticks-statistics', _reqpriv('userdb', function(query, user, access, cb) {
	var now = Math.floor(new Date().getTime() / 1000);
	var todayStart = now - now % 86400;
	var ndays = parseInt(query.ndays) || 365;
	var timespanStart = todayStart - ndays * 86400;
	var dt = 300;

	this.query('SELECT FLOOR(time/?)*? AS timeindex, SUM(ticks) AS ticksum, COUNT(ticks) AS tickcount ' +
		'FROM valuehistory ' +
		'GROUP BY timeindex',
		[dt, dt, dt, timespanStart, todayStart], function(res) {
		cb('get-ticks-statistics-success', {results: res});
	});
}));

exports.AdminDB = AdminDB;

})();
<commit_msg><commit_after>(function () { "use strict";

function parentPath(x) {
	var match = x.match(/(\/[\w_-]+)+\/[\w_-]+$/);
	return match ? match[1] : '/';
}

var _ = require('underscore');
var util = require('util');
var assert = require('assert');
var buscomponent = require('./buscomponent.js');

function AdminDB () {
}
util.inherits(AdminDB, buscomponent.BusComponent);

function _reqpriv_x (required, f) {
	var requiredPermission = required;
	return function(query, user, access, xdata, cb) {
		if (user === null || !access.has(requiredPermission))
			(cb ? cb : xdata)('permission-denied');
		else
			return _.bind(f, this)(query, user, access, xdata, cb);
	};
}

function _reqpriv (required, f) {
	return _reqpriv_x(required, function(query, user, access, xdata, cb) {
		return _.bind(f, this)(query, user, access, cb = xdata);
	});
}

AdminDB.prototype.listAllUsers = buscomponent.provideQUA('client-list-all-users', _reqpriv('userdb', function(query, user, access, cb) {
	this.query('SELECT birthday, deletiontime, street, zipcode, town, `desc`, users.name, giv_name, fam_name, users.id AS uid, tradecount, ' +
		'email, email_verif AS emailverif, wprovision, lprovision, freemoney, totalvalue, wprov_sum, lprov_sum, ticks, registertime, ' +
		'logins.logintime AS lastlogintime, schools.path AS schoolpath, schools.id AS schoolid, pending, jointime, ' +
		'(SELECT COUNT(*) FROM ecomments WHERE ecomments.commenter=users.id) AS commentcount, '+
		'(SELECT MAX(time) FROM ecomments WHERE ecomments.commenter=users.id) AS lastcommenttime FROM users ' +
		'LEFT JOIN schoolmembers AS sm ON sm.uid = users.id ' +
		'LEFT JOIN schools ON schools.id = sm.schoolid ' +
		'LEFT JOIN logins ON logins.id = (SELECT id FROM logins AS l WHERE l.uid = users.id ORDER BY logintime DESC LIMIT 1)',
		[], function(userlist) {
		cb('list-all-users-success', {results: userlist});
	});
}));

AdminDB.prototype.evalCode = buscomponent.provideQUA('client-eval-code', _reqpriv('*', function(query, user, access, cb) {
	if (!query.authorizationKey)
		cb('permission-denied');
	else
		cb('eval-code-success', {result: eval(query.code)});
}));

AdminDB.prototype.shutdown = buscomponent.provideQUA('client-shutdown', _reqpriv('server', function(query, user, access, cb) {
	this.emit('globalShutdown');
	this.emit('localShutdown');

	cb('shutdown-success');
}));

AdminDB.prototype.impersonateUser = buscomponent.provideQUA('client-impersonate-user', _reqpriv('server', function(query, user, access, cb) {
	this.query('SELECT COUNT(*) AS c FROM users WHERE id=?', [query.uid], function(r) {
		assert.equal(r.length, 1);
		if (r[0].c == 0)
			return cb('impersonate-user-notfound', null, 'repush');

		this.query('UPDATE sessions SET uid = ? WHERE id = ?', [query.uid, user.sid], function() {
			cb('impersonate-user-success', null, 'repush');
		});
	});
}));

AdminDB.prototype.deleteUser = buscomponent.provideQUA('client-delete-user', _reqpriv('userdb', function(query, user, access, cb) {
	if (user.id == query.uid)
		return cb('delete-user-self-notallowed');

	this.getConnection(function(conn) {
		conn.query('START TRANSACTION', [], function() {
		conn.query('DELETE FROM sessions WHERE uid = ?', [query.uid], function() {
		conn.query('DELETE FROM schoolmembers WHERE uid = ?', [query.uid], function() {
		conn.query('UPDATE stocks SET name = CONCAT("leader:deleted", ?) WHERE leader = ?', [query.uid, query.uid], function() {
		conn.query('UPDATE users SET name = CONCAT("user_deleted", ?), giv_name="__user_deleted__", email = CONCAT("deleted:", email), ' +
		'fam_name="", pwhash="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", birthday=NULL, realnamepublish=0, `desc`="", wprovision=0, lprovision=0, ' +
		'street="", zipcode="", town="", traditye=0, deletiontime = UNIX_TIMESTAMP() WHERE id = ?', [query.uid, query.uid], function() {
			conn.query('COMMIT', [], function() {
				conn.release();
				cb('delete-user-success');
			});
		});
		});
		});
		});
		});
	});
}));

AdminDB.prototype.changeUserEMail = buscomponent.provideQUA('client-change-user', _reqpriv('userdb', function(query, user, access, cb) {
	this.query('UPDATE users SET email = ?, email_verif = ? WHERE id = ?', [query.email, query.emailverif ? 1 : 0, query.uid], function() {
		cb('change-user-email-success');
	});
}));

AdminDB.prototype.changeCommentText = buscomponent.provideQUA('client-change-comment-text', _reqpriv('moderate', function(query, user, access, cb) {
	this.query('UPDATE ecomments SET comment = ?, trustedhtml = ? WHERE commentid = ?', [query.comment, access.has('server') && query.trustedhtml ? 1:0, query.commentid], function() {
		cb('change-comment-text-success');
	});
}));

AdminDB.prototype.notifyUnstickAll = buscomponent.provideQUA('client-notify-unstick-all', _reqpriv('moderate', function(query, user, access, cb) {
	this.query('UPDATE mod_notif SET sticky = 0', [], function() {
		cb('notify-unstick-all-success');
	});
}));

AdminDB.prototype.notifyAll = buscomponent.provideQUA('client-notify-all', _reqpriv('moderate', function(query, user, access, cb) {
	this.query('INSERT INTO mod_notif (content, sticky) VALUES (?, ?)', [query.content, query.sticky ? 1 : 0], function(res) {
		this.feed({'type': 'mod-notification', 'targetid': res.insertId, 'srcuser': user.id, 'everyone': true});
		cb('notify-all-success');
	});
}));

AdminDB.prototype.renameSchool = buscomponent.provideQUA('client-rename-school', _reqpriv('schooldb', function(query, user, access, cb) {
	this.query('SELECT path FROM schools WHERE id = ?', [query.schoolid], function(r) {
		if (r.length == 0)
			return cb('rename-school-notfound');

		this.query('UPDATE schools SET name = ? WHERE id = ?', [query.schoolname, query.schoolid], function() {
			if (query.schoolpath) {
				this.query('UPDATE schools SET path = REPLACE(path, ?, ?) WHERE path LIKE ? OR path = ?', [r[0].path, query.schoolpath, r[0].path + '/%', r[0].path], function() {
					cb('rename-school-success');
				});
			} else {
				cb('rename-school-success');
			}
		});
	});
}));

AdminDB.prototype.joinSchools = buscomponent.provideQUA('client-join-schools', _reqpriv('schooldb', function(query, user, access, cb) {
	this.query('SELECT path FROM schools WHERE id = ?', [query.masterschool], function(mr) {
	this.query('SELECT path FROM schools WHERE id = ?', [query.subschool], function(sr) {
		assert.ok(mr.length <= 1);
		assert.ok(sr.length <= 1);

		if (sr.length == 0 || ((mr.length == 0 || mr[0].path == sr[0].path) && query.masterschool != null))
			return cb('join-schools-notfound');
		if (mr.length > 0 && parentPath(mr[0].path) != parentPath(sr[0].path))
			return cb('join-schools-diff-parent');

		this.query('UPDATE schoolmembers SET schoolid = ? WHERE schoolid = ?', [query.masterschool, query.subschool], function() {
		this.query('DELETE FROM schooladmins WHERE schoolid = ?', [query.subschool], function() {
			this.query('DELETE FROM schools WHERE id = ?', [query.subschool], function() {
				cb('join-schools-success');
			});
		});
		});
	});
	});
}));

AdminDB.prototype.getUserLogins = buscomponent.provideQUA('client-get-user-logins', _reqpriv('userdb', function(query, user, access, cb) {
	this.query('SELECT * FROM logins WHERE uid = ?', [query.uid], function(res) {
		_.each(res, function(e) {
			e.headers = JSON.parse(e.headers);
		});

		cb('get-user-logins-success', {results: res});
	});
}));

AdminDB.prototype.getTicksStatistics = buscomponent.provideQUA('client-get-ticks-statistics', _reqpriv('userdb', function(query, user, access, cb) {
	var now = Math.floor(new Date().getTime() / 1000);
	var todayStart = now - now % 86400;
	var ndays = parseInt(query.ndays) || 365;
	var timespanStart = todayStart - ndays * 86400;
	var dt = 300;

	this.query('SELECT FLOOR(time/?)*? AS timeindex, SUM(ticks) AS ticksum, COUNT(ticks) AS tickcount ' +
		'FROM valuehistory ' +
		'GROUP BY timeindex',
		[dt, dt, dt, timespanStart, todayStart], function(res) {
		cb('get-ticks-statistics-success', {results: res});
	});
}));

exports.AdminDB = AdminDB;

})();
<|endoftext|>


<commit_before>var MaterialUI = {
    AutoComplete : {
        noFilter: {},
        defaultFilter: {},
        caseInsensitiveFilter: {},
        levenshteinDistanceFilter: {},
        fuzzyFilter: {}
    },
    FontIcon: {},
    Drawer: {},
    MenuItem: {},
    AppBar: {},
    IconButton: {},
    SvgIcon: {}
};

var MaterialUIStyles = {
    MuiThemeProvider : function() {},
    darkBaseTheme: function() {},
    lightBaseTheme: function() {},
    getMuiTheme : function() {},
    themeManager: {
        getMuiTheme: function() {},
        modifyRawThemeFontFamily: function() {},
        modifyRawThemePalette: function() {},
        modifyRawThemeSpacing: function() {}
    },
    transitions : {
        create : function() {},
        easeOut  : function() {}
    }
};

var MaterialUIUtils = {
    withWidth : {
        SMALL : {},
        MEDIUM : {},
        LARGE : {},
        "default" : function() {}
    },
    colorManipulator : {
        convertColorToString : function() {},
        convertHexToRGB : function() {},
        darken : function() {},
        decomposeColor : function() {},
        emphasize : function() {},
        fade : function() {},
        getContrastRatio : function() {},
        getLuminance : function() {},
        lighten : function() {}
    }
};<commit_msg>added material component to extern<commit_after>var MaterialUI = {
    ToolbarTitle: {},
    ToolbarSeparator: {},
    ToolbarGroup: {},
    Toolbar: {},
    Toggle: {},
    TimePicker: {},
    TextField: {},
    TableRowColumn: {},
    TableRow: {},
    TableHeaderColumn: {},
    TableHeader: {},
    TableFooter: {},
    TableBody: {},
    Table: {},
    Tab: {},
    Tabs: {},
    Snackbar: {},
    Stepper: {},
    StepLabel: {},
    StepContent: {},
    StepButton: {},
    Step: {},
    SvgIcon: {},
    Subheader: {},
    Slider: {},
    SelectField: {},
    RefreshIndicator: {},
    RaisedButton: {},
    RadioButtonGroup: {},
    RadioButton: {},
    Popover: {},
    Paper: {},
    MenuItem: {},
    Menu: {},
    ListItem: {},
    List: {},
    LinearProgress: {},
    IconMenu: {},
    IconButton: {},
    GridTile: {},
    GridList: {},
    FontIcon: {},
    FloatingActionButton: {},
    FlatButton: {},
    DropDownMenu: {},
    Drawer: {},
    Divider: {},
    Dialog: {},
    DatePicker: {},
    CircularProgress: {},
    Chip: {},
    Checkbox: {},
    CardText: {},
    CardTitle: {},
    CardMedia: {},
    CardHeader: {},
    CardActions: {},
    Card: {},
    BottomNavigationItem: {},
    BottomNavigation: {},
    Badge: {},
    Avatar: {},
    AutoComplete: {
        noFilter: {},
        defaultFilter: {},
        caseInsensitiveFilter: {},
        levenshteinDistanceFilter: {},
        fuzzyFilter: {}
    },
    AppBar: {}
};

var MaterialUIStyles = {
    MuiThemeProvider : function() {},
    darkBaseTheme: function() {},
    lightBaseTheme: function() {},
    getMuiTheme : function() {},
    themeManager: {
        getMuiTheme: function() {},
        modifyRawThemeFontFamily: function() {},
        modifyRawThemePalette: function() {},
        modifyRawThemeSpacing: function() {}
    },
    transitions : {
        create : function() {},
        easeOut  : function() {}
    }
};

var MaterialUIUtils = {
    withWidth : {
        SMALL : {},
        MEDIUM : {},
        LARGE : {},
        "default" : function() {}
    },
    colorManipulator : {
        convertColorToString : function() {},
        convertHexToRGB : function() {},
        darken : function() {},
        decomposeColor : function() {},
        emphasize : function() {},
        fade : function() {},
        getContrastRatio : function() {},
        getLuminance : function() {},
        lighten : function() {}
    }
};<|endoftext|>


<commit_before>(() => {

    const scinder = {}
    const getSegments = (context, audioBuffer, times, durations) => {

        // the returned array
        const segments = []

        times.forEach((time, i) => {
            if (time < 0 || time >= 1)
                throw new Error('segment start point must be a float in the range [0;1[')
            const cutPosition = Math.floor(audioBuffer.duration * time) * audioBuffer.sampleRate

            let frameCount = 0
            if (Array.isArray(durations) && durations.length >= i)
                frameCount = audioBuffer.sampleRate * durations[i]
            else if (Array.isArray(durations))
                throw new Error('the durations array must be have the same length as the time array, or either be an int value')
            else if (!Number.isNaN(durations))
                frameCount = audioBuffer.sampleRate * durations
            else
                throw new Error('the durations array must be have the same length as the time array, or either be an int value')

            // the duration cannot be greater than the length of the music
            if (cutPosition + frameCount > audioBuffer.length)
                frameCount = audioBuffer.length - cutPosition

            const segment = context.createBuffer(
                audioBuffer.numberOfChannels,
                frameCount,
                audioBuffer.sampleRate
            )
            for (let channel = 0; channel < audioBuffer.numberOfChannels; channel++) {

                const nowBuffering = segment.getChannelData(channel)
                const sourceBuffering = audioBuffer.getChannelData(channel)
                for (let i = 0; i < frameCount; i++)
                    nowBuffering[i] = sourceBuffering[cutPosition + i]
            }

            segments.push(segment)

        })

        return segments
    }
    scinder.getSegments = getSegments

    // create and return a new audiobuffer with smoothen beginning/end
    const smoothenSegment = (context, audioBuffer, smoothLength) => {
        if (smoothLength >= 0.5 || smoothLength <= 0)
            return

        const bytesNumber = Math.floor(audioBuffer.getChannelData(0).length * smoothLength)

        const segment = context.createBuffer(
            audioBuffer.numberOfChannels,
            audioBuffer.length,
            audioBuffer.sampleRate
        )
        for (let channel = 0; channel < audioBuffer.numberOfChannels; channel++) {

            const nowBuffering = segment.getChannelData(channel)
            const sourceBuffering = audioBuffer.getChannelData(channel)
            const length = audioBuffer.length

            for (let i = 0; i < length; i++) {

                // check if it's the first bytes
                if (i <= bytesNumber) {
                    nowBuffering[i] = sourceBuffering[i] * (i / bytesNumber)

                // check if it's the last bytes
                } else if (i >= length - bytesNumber) {
                    const baseIndex = i - (length - bytesNumber)
                    nowBuffering[/*s*/ + i] = sourceBuffering[i] * ((bytesNumber - baseIndex) / bytesNumber)

                // unchanged bytes
                } else {
                    nowBuffering[i] = sourceBuffering[i]
                }

            }
        }

        return segment
    }
    scinder.smoothenSegment = smoothenSegment

    const packAudioBuffers = (context, audioBuffers, silenceBetween = 0) => {
        const flooredSilenceBetween = Math.floor(silenceBetween)

        let totalLength = 0
        audioBuffers.forEach(b => totalLength += b.length)
        const numberOfChannels = audioBuffers[0].numberOfChannels

        const pack = context.createBuffer(
            numberOfChannels,
            totalLength + audioBuffers[0].sampleRate * (audioBuffers.length - 1) * flooredSilenceBetween, // 2s of silence between each cut
            audioBuffers[0].sampleRate
        )

        for (let channel = 0; channel < numberOfChannels; channel++) {
            const packChannel = pack.getChannelData(channel)
            let totalIndex = 0

            for (let buffer of audioBuffers) {
                const bufferChannel = buffer.getChannelData(channel)
                const length = bufferChannel.length

                for (let i = 0; i < length; i++)
                    packChannel[totalIndex++] = bufferChannel[i]

                // then X seconds of silence
                for (let s = 0; s < audioBuffers[0].sampleRate * flooredSilenceBetween; s++)
                    packChannel[totalIndex++] = 0
            }

        }

        return pack
    }
    scinder.packAudioBuffers = packAudioBuffers

    const getAudioBuffer = (file) => {
        context = new AudioContext()
        const reader = new FileReader()

        return new Promise((resolve, reject) => {

            reader.onload = function () {

                const arrayBuffer = this.result

                context.decodeAudioData(arrayBuffer)
                .then(audioBuffer => {
                    resolve({audioBuffer, context, reader})
                })
            }
            reader.readAsArrayBuffer(file)
        })
    }
    scinder.getAudioBuffer = getAudioBuffer

    const sliceAndPack = (file, times, durations) => {
        const context = new AudioContext()
        const reader = new FileReader()

        return getAudioBuffer(file)
        .then(({audioBuffer, context}) => {
            const segments = getSegments(context, audioBuffer, times, durations)
            const smoothenSegments = segments.map(s => smoothenSegment(context, s, 0.15))

            return{pack: packAudioBuffers(context, smoothenSegments, 2), context}
        }, e => console.error(e))
    }
    scinder.sliceAndPack = sliceAndPack

    // prepare and play a music from an audioBuffer
    const playAudioBuffer = (context, audioBuffer) => {
        if (!context) context = new AudioContext()

        const audioSource = context.createBufferSource()
        audioSource.connect(context.destination)
        audioSource.buffer = audioBuffer
        audioSource.loop = false
        audioSource.start(0)
    }
    scinder.playAudioBuffer = playAudioBuffer

    this.scinder = scinder
})()

(() => {

    const scinder = {}
    const getSegments = (context, audioBuffer, times, durations) => {

        // the returned array
        const segments = []

        times.forEach((time, i) => {
            if (time < 0 || time >= 1)
                throw new Error('segment start point must be a float in the range [0;1[')
            const cutPosition = Math.floor(audioBuffer.duration * time) * audioBuffer.sampleRate

            let frameCount = 0
            if (Array.isArray(durations) && durations.length >= i)
                frameCount = audioBuffer.sampleRate * durations[i]
            else if (Array.isArray(durations))
                throw new Error('the durations array must be have the same length as the time array, or either be an int value')
            else if (!Number.isNaN(durations))
                frameCount = audioBuffer.sampleRate * durations
            else
                throw new Error('the durations array must be have the same length as the time array, or either be an int value')

            // the duration cannot be greater than the length of the music
            if (cutPosition + frameCount > audioBuffer.length)
                frameCount = audioBuffer.length - cutPosition

            const segment = context.createBuffer(
                audioBuffer.numberOfChannels,
                frameCount,
                audioBuffer.sampleRate
            )
            for (let channel = 0; channel < audioBuffer.numberOfChannels; channel++) {

                const nowBuffering = segment.getChannelData(channel)
                const sourceBuffering = audioBuffer.getChannelData(channel)
                for (let i = 0; i < frameCount; i++)
                    nowBuffering[i] = sourceBuffering[cutPosition + i]
            }

            segments.push(segment)

        })

        return segments
    }
    scinder.getSegments = getSegments

    // create and return a new audiobuffer with smoothen beginning/end
    const smoothenSegment = (context, audioBuffer, smoothLength) => {
        if (smoothLength >= 0.5 || smoothLength <= 0)
            return

        const bytesNumber = Math.floor(audioBuffer.getChannelData(0).length * smoothLength)

        const segment = context.createBuffer(
            audioBuffer.numberOfChannels,
            audioBuffer.length,
            audioBuffer.sampleRate
        )
        for (let channel = 0; channel < audioBuffer.numberOfChannels; channel++) {

            const nowBuffering = segment.getChannelData(channel)
            const sourceBuffering = audioBuffer.getChannelData(channel)
            const length = audioBuffer.length

            for (let i = 0; i < length; i++) {

                // check if it's the first bytes
                if (i <= bytesNumber) {
                    nowBuffering[i] = sourceBuffering[i] * (i / bytesNumber)

                // check if it's the last bytes
                } else if (i >= length - bytesNumber) {
                    const baseIndex = i - (length - bytesNumber)
                    nowBuffering[/*s*/ + i] = sourceBuffering[i] * ((bytesNumber - baseIndex) / bytesNumber)

                // unchanged bytes
                } else {
                    nowBuffering[i] = sourceBuffering[i]
                }

            }
        }

        return segment
    }
    scinder.smoothenSegment = smoothenSegment

    const packAudioBuffers = (context, audioBuffers, silenceBetween = 0) => {
        flooredSilenceBetween = Math.floor(silenceBetween)

        let totalLength = 0
        audioBuffers.forEach(b => totalLength += b.length)
        const numberOfChannels = audioBuffers[0].numberOfChannels

        const pack = context.createBuffer(
            numberOfChannels,
            totalLength + audioBuffers[0].sampleRate * (audioBuffers.length - 1) * flooredSilenceBetween, // 2s of silence between each cut
            audioBuffers[0].sampleRate
        )

        for (let channel = 0; channel < numberOfChannels; channel++) {
            const packChannel = pack.getChannelData(channel)
            let totalIndex = 0

            for (let buffer of audioBuffers) {
                const bufferChannel = buffer.getChannelData(channel)
                const length = bufferChannel.length

                for (let i = 0; i < length; i++)
                    packChannel[totalIndex++] = bufferChannel[i]

                // then X seconds of silence
                for (let s = 0; s < audioBuffers[0].sampleRate * flooredSilenceBetween; s++)
                    packChannel[totalIndex++] = 0
            }

        }

        return pack
    }
    scinder.packAudioBuffers = packAudioBuffers

    const getAudioBuffer = (file) => {
        const context = new AudioContext()
        const reader = new FileReader()

        return new Promise((resolve, reject) => {

            reader.onload = function () {

                const arrayBuffer = this.result

                context.decodeAudioData(arrayBuffer)
                .then(audioBuffer => {
                    resolve({audioBuffer, context, reader})
                })
            }
            reader.readAsArrayBuffer(file)
        })
    }
    scinder.getAudioBuffer = getAudioBuffer

    const sliceAndPack = (file, times, durations) => {

        return getAudioBuffer(file)
        .then(({audioBuffer, context}) => {
            const segments = getSegments(context, audioBuffer, times, durations)
            const smoothenSegments = segments.map(s => smoothenSegment(context, s, 0.15))

            return{pack: packAudioBuffers(context, smoothenSegments, 2), context}
        }, e => console.error(e))

    }
    scinder.sliceAndPack = sliceAndPack

    // prepare and play a music from an audioBuffer
    const playAudioBuffer = (context, audioBuffer) => {
        if (!context) context = new AudioContext()

        const audioSource = context.createBufferSource()
        audioSource.connect(context.destination)
        audioSource.buffer = audioBuffer
        audioSource.loop = false
        audioSource.start(0)
    }
    scinder.playAudioBuffer = playAudioBuffer

    if (module && module.exports) {
        module.exports = scinder
    } else {
        this.scinder = scinder
    }
})()
<commit_msg>fixed mistake<commit_after>(() => {

    const scinder = {}
    const getSegments = (context, audioBuffer, times, durations) => {

        // the returned array
        const segments = []

        times.forEach((time, i) => {
            if (time < 0 || time >= 1)
                throw new Error('segment start point must be a float in the range [0;1[')
            const cutPosition = Math.floor(audioBuffer.duration * time) * audioBuffer.sampleRate

            let frameCount = 0
            if (Array.isArray(durations) && durations.length >= i)
                frameCount = audioBuffer.sampleRate * durations[i]
            else if (Array.isArray(durations))
                throw new Error('the durations array must be have the same length as the time array, or either be an int value')
            else if (!Number.isNaN(durations))
                frameCount = audioBuffer.sampleRate * durations
            else
                throw new Error('the durations array must be have the same length as the time array, or either be an int value')

            // the duration cannot be greater than the length of the music
            if (cutPosition + frameCount > audioBuffer.length)
                frameCount = audioBuffer.length - cutPosition

            const segment = context.createBuffer(
                audioBuffer.numberOfChannels,
                frameCount,
                audioBuffer.sampleRate
            )
            for (let channel = 0; channel < audioBuffer.numberOfChannels; channel++) {

                const nowBuffering = segment.getChannelData(channel)
                const sourceBuffering = audioBuffer.getChannelData(channel)
                for (let i = 0; i < frameCount; i++)
                    nowBuffering[i] = sourceBuffering[cutPosition + i]
            }

            segments.push(segment)

        })

        return segments
    }
    scinder.getSegments = getSegments

    // create and return a new audiobuffer with smoothen beginning/end
    const smoothenSegment = (context, audioBuffer, smoothLength) => {
        if (smoothLength >= 0.5 || smoothLength <= 0)
            return

        const bytesNumber = Math.floor(audioBuffer.getChannelData(0).length * smoothLength)

        const segment = context.createBuffer(
            audioBuffer.numberOfChannels,
            audioBuffer.length,
            audioBuffer.sampleRate
        )
        for (let channel = 0; channel < audioBuffer.numberOfChannels; channel++) {

            const nowBuffering = segment.getChannelData(channel)
            const sourceBuffering = audioBuffer.getChannelData(channel)
            const length = audioBuffer.length

            for (let i = 0; i < length; i++) {

                // check if it's the first bytes
                if (i <= bytesNumber) {
                    nowBuffering[i] = sourceBuffering[i] * (i / bytesNumber)

                // check if it's the last bytes
                } else if (i >= length - bytesNumber) {
                    const baseIndex = i - (length - bytesNumber)
                    nowBuffering[/*s*/ + i] = sourceBuffering[i] * ((bytesNumber - baseIndex) / bytesNumber)

                // unchanged bytes
                } else {
                    nowBuffering[i] = sourceBuffering[i]
                }

            }
        }

        return segment
    }
    scinder.smoothenSegment = smoothenSegment

    const packAudioBuffers = (context, audioBuffers, silenceBetween = 0) => {
        flooredSilenceBetween = Math.floor(silenceBetween)

        let totalLength = 0
        audioBuffers.forEach(b => totalLength += b.length)
        const numberOfChannels = audioBuffers[0].numberOfChannels

        const pack = context.createBuffer(
            numberOfChannels,
            totalLength + audioBuffers[0].sampleRate * (audioBuffers.length - 1) * flooredSilenceBetween, // 2s of silence between each cut
            audioBuffers[0].sampleRate
        )

        for (let channel = 0; channel < numberOfChannels; channel++) {
            const packChannel = pack.getChannelData(channel)
            let totalIndex = 0

            for (let buffer of audioBuffers) {
                const bufferChannel = buffer.getChannelData(channel)
                const length = bufferChannel.length

                for (let i = 0; i < length; i++)
                    packChannel[totalIndex++] = bufferChannel[i]

                // then X seconds of silence
                for (let s = 0; s < audioBuffers[0].sampleRate * flooredSilenceBetween; s++)
                    packChannel[totalIndex++] = 0
            }

        }

        return pack
    }
    scinder.packAudioBuffers = packAudioBuffers

    const getAudioBuffer = (file) => {
        const context = new AudioContext()
        const reader = new FileReader()

        return new Promise((resolve, reject) => {

            reader.onload = function () {

                const arrayBuffer = this.result

                context.decodeAudioData(arrayBuffer)
                .then(audioBuffer => {
                    resolve({audioBuffer, context, reader})
                })
            }
            reader.readAsArrayBuffer(file)
        })
    }
    scinder.getAudioBuffer = getAudioBuffer

    const sliceAndPack = (file, times, durations) => {

        return getAudioBuffer(file)
        .then(({audioBuffer, context}) => {
            const segments = getSegments(context, audioBuffer, times, durations)
            const smoothenSegments = segments.map(s => smoothenSegment(context, s, 0.15))

            return{pack: packAudioBuffers(context, smoothenSegments, 2), context}
        }, e => console.error(e))

    }
    scinder.sliceAndPack = sliceAndPack

    // prepare and play a music from an audioBuffer
    const playAudioBuffer = (context, audioBuffer) => {
        if (!context) context = new AudioContext()

        const audioSource = context.createBufferSource()
        audioSource.connect(context.destination)
        audioSource.buffer = audioBuffer
        audioSource.loop = false
        audioSource.start(0)
    }
    scinder.playAudioBuffer = playAudioBuffer

    if (module && module.exports) {
        module.exports = scinder
    } else {
        this.scinder = scinder
    }
})()
<|endoftext|>


<commit_before>'use strict';
//require('js-toolkit').Promise.ext;

// external deps
var ObjectId = require('mongodb').ObjectId;

// internal deps
require('mongodb-toolkit');
var BateeqModels = require('bateeq-models');
var map = BateeqModels.map;

var ExpeditionDoc = BateeqModels.inventory.ExpeditionDoc;
var TransferOutDoc = BateeqModels.inventory.TransferOutDoc;
var TransferOutItem = BateeqModels.inventory.TransferOutItem;
var SPK = BateeqModels.merchandiser.SPK;
var generateCode = require('../../utils/code-generator');

const moduleId = "EFR-KB/EXP";
module.exports = class PusatBarangBaruKirimBarangJadiAksesorisManager {
    constructor(db, user) {
        this.db = db;
        this.user = user;
        this.expeditionDocCollection = this.db.use(map.inventory.ExpeditionDoc);

        var StorageManager = require('../master/storage-manager');
        this.storageManager = new StorageManager(db, user);

        var TransferOutDocManager = require('./transfer-out-doc-manager');
        this.transferOutDocManager = new TransferOutDocManager(db, user);

        var SpkManager = require('../merchandiser/efr-pk-manager');
        this.spkManager = new SpkManager(db, user);

        var ModuleManager = require('../master/module-manager');
        this.moduleManager = new ModuleManager(db, user);
    }

    read(paging) {
        var _paging = Object.assign({
            page: 1,
            size: 20,
            order: '_id',
            asc: true
        }, paging);

        return new Promise((resolve, reject) => {
            var regexModuleId = new RegExp(moduleId, "i");
            var filter = {
                _deleted: false,
                _createdBy : this.user.username,
                'code': {
                    '$regex': regexModuleId
                }
            };
            var query = _paging.keyword ? {
                '$and': [filter]
            } : filter;

            if (_paging.keyword) {
                var regex = new RegExp(_paging.keyword, "i");
                var filterCode = {
                    'code': {
                        '$regex': regex
                    }
                };
                var $or = {
                    '$or': [filterCode]
                };

                query['$and'].push($or);
            }

            this.expeditionDocCollection
                .where(query)
                .page(_paging.page, _paging.size)
                .orderBy(_paging.order, _paging.asc)
                .execute()
                .then(expeditionDocs => {
                    resolve(expeditionDocs);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    getSingleById(id) {
        return new Promise((resolve, reject) => {
            var query = {
                _id: new ObjectId(id),
                _deleted: false
            };
            this.getSingleByQuery(query)
                .then(expeditionDoc => {
                    resolve(expeditionDoc);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    getSingleByIdOrDefault(id) {
        return new Promise((resolve, reject) => {
            var query = {
                _id: new ObjectId(id),
                _deleted: false
            };
            this.getSingleByQueryOrDefault(query)
                .then(expeditionDoc => {
                    resolve(expeditionDoc);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    getSingleByQuery(query) {
        return new Promise((resolve, reject) => {
            this.expeditionDocCollection
                .single(query)
                .then(expeditionDoc => {
                    resolve(expeditionDoc);
                })
                .catch(e => {
                    reject(e);
                });
        })
    }

    getSingleByQueryOrDefault(query) {
        return new Promise((resolve, reject) => {
            this.expeditionDocCollection
                .singleOrDefault(query)
                .then(expeditionDoc => {
                    resolve(expeditionDoc);
                })
                .catch(e => {
                    reject(e);
                });
        })
    }

    getBySpk(code) {
        var query = { "spkDocuments.code": code };
        return new Promise((resolve, reject) => {
            this.expeditionDocCollection
                .where(query)
                .execute()
                .then(expeditionDocs => {
                    resolve(expeditionDocs);
                })
                .catch(e => {
                    reject(e);
                });
        })
    }

    create(expeditionDoc) {
        return new Promise((resolve, reject) => {
            //Validate Input Model
            this._validate(expeditionDoc)
                .then(validatedExpeditionDoc => {
                    var getTransferOuts = [];
                    //Create Promise to Create Transfer Out
                    for (var spkDocument of validatedExpeditionDoc.spkDocuments) {
                        //getTransferOuts.push(this.transferOutDocManager.create(validTransferOutDoc));
                        var f = (spkDoc, outManager) => {
                            return () => {
                                var code = generateCode(moduleId);
                                var validTransferOutDoc = {};
                                validTransferOutDoc.code = code;
                                validTransferOutDoc.reference = spkDoc.packingList;
                                validTransferOutDoc.sourceId = spkDoc.sourceId;
                                validTransferOutDoc.destinationId = spkDoc.destinationId;
                                validTransferOutDoc.items = [];
                                for (var item of spkDoc.items) {
                                    var newitem = {};
                                    newitem.itemId = item.itemId;
                                    newitem.quantity = item.quantity;
                                    validTransferOutDoc.items.push(newitem);
                                }
                                return outManager.create(validTransferOutDoc)
                            }
                        };
                        getTransferOuts.push(f(spkDocument, this.transferOutDocManager));
                    }
                    //Create Transfer Out
                    //Promise.all(getTransferOuts)
                    require('js-toolkit').Promise.ext;
                    Promise.chain(getTransferOuts)
                        .then(results => {
                            getTransferOuts = [];
                            //Create Promise Get Transfer Out using ID
                            for (var transferOutResultId of results) {
                                getTransferOuts.push(this.transferOutDocManager.getSingleByIdOrDefault(transferOutResultId));
                            }
                            //Get Transfer Out
                            Promise.all(getTransferOuts)
                                .then(transferOutResults => {
                                    //Create Expedition Model
                                    var validExpeditionDoc = {};
                                    validExpeditionDoc.code = generateCode(moduleId);
                                    validExpeditionDoc.expedition = validatedExpeditionDoc.expedition;
                                    validExpeditionDoc.weight = validatedExpeditionDoc.weight;
                                    validExpeditionDoc.transferOutDocuments = [];
                                    validExpeditionDoc.spkDocuments = validatedExpeditionDoc.spkDocuments
                                    for (var transferOut of transferOutResults) {
                                        validExpeditionDoc.transferOutDocuments.push(transferOut);
                                    }
                                    validExpeditionDoc = new ExpeditionDoc(validExpeditionDoc);
                                    validExpeditionDoc._createdDate = new Date();
                                    validExpeditionDoc.stamp(this.user.username, 'manager');
                                    //Create Promise Expedition
                                    this.expeditionDocCollection.insert(validExpeditionDoc)
                                        .then(resultExpeditionId => {
                                            //Get Expedition Data
                                            this.getSingleByIdOrDefault(resultExpeditionId)
                                                .then(resultExpedition => {
                                                    var getSPKData = [];
                                                    //Create Promise get SPK Data for update
                                                    for (var spkDocument of validExpeditionDoc.spkDocuments) {
                                                        getSPKData.push(this.spkManager.getSingleByIdOrDefault(spkDocument._id));
                                                    }
                                                    //Get SPK Data
                                                    Promise.all(getSPKData)
                                                        .then(resultSPKs => {
                                                            //Create Promise Update SPK Data
                                                            var getUpdateSPKData = [];
                                                            for (var resultSPK of resultSPKs) {
                                                                resultSPK.expeditionDocumentId = resultExpeditionId;
                                                                resultSPK.expeditionDocument = resultExpedition;
                                                                resultSPK = new SPK(resultSPK);
                                                                getUpdateSPKData.push(this.spkManager.update(resultSPK));
                                                            }
                                                            //Update SPK Data
                                                            Promise.all(getUpdateSPKData)
                                                                .then(resultUpdateSPKs => {
                                                                    resolve(resultExpeditionId);
                                                                })
                                                                .catch(e => {
                                                                    reject(e);
                                                                });
                                                        })
                                                        .catch(e => {
                                                            reject(e);
                                                        });
                                                })
                                                .catch(e => {
                                                    reject(e);
                                                });
                                        })
                                        .catch(e => {
                                            reject(e);
                                        });
                                })
                                .catch(e => {
                                    reject(e);
                                });
                        })
                        .catch(e => {
                            reject(e);
                        });
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    update(expeditionDoc) {
        return new Promise((resolve, reject) => {
            resolve(null);
        });
    }

    delete(expeditionDoc) {
        return new Promise((resolve, reject) => {
            resolve(null);
        });
    }

    _validate(expeditionDoc) {
        var errors = {};
        return new Promise((resolve, reject) => {
            var valid = expeditionDoc;
            this.moduleManager.getByCode(moduleId)
                .then(module => {
                    var config = module.config;
                    var getPromise = [];
                    var validateSPKisExist = [];

                    if (!valid.expedition || valid.expedition == '')
                        errors["expedition"] = "expedition is required";

                    if (!valid.spkDocuments || valid.spkDocuments.length == 0) {
                        errors["spkDocuments"] = "spkDocuments is required";
                    }
                    else {
                        var spkDocumentErrors = [];
                        var spkDocumentDestinationId = "";
                        expeditionDoc.weight = 0;
                        for (var spkDocument of valid.spkDocuments) {
                            expeditionDoc.weight += parseInt(spkDocument.weight || 0);
                            var spkDocumentError = {};
                            if (!spkDocument._id || spkDocument._id == "") {
                                spkDocumentError["code"] = "packing list harus diisi";
                                getPromise.push(Promise.resolve(null));
                            }
                            else {
                                for (var i = valid.spkDocuments.indexOf(spkDocument) + 1; i < valid.spkDocuments.length; i++) {
                                    var otherItem = valid.spkDocuments[i];
                                    if (spkDocument._id == otherItem._id) {
                                        spkDocumentError["code"] = "duplikat packing list";
                                    }
                                }

                                getPromise.push(this.spkManager.getSingleByIdOrDefault(spkDocument._id));
                            }

                            validateSPKisExist.push(this.getBySpk(spkDocument.code));

                            if (spkDocumentDestinationId == "")
                                spkDocumentDestinationId = spkDocument.destinationId;
                            else if (spkDocument.destinationId != spkDocumentDestinationId)
                                spkDocumentError["code"] = "packing list harus memiliki tujuan yang sama";

                            spkDocumentErrors.push(spkDocumentError);
                        }
                        for (var spkDocumentError of spkDocumentErrors) {
                            for (var prop in spkDocumentError) {
                                errors.spkDocuments = spkDocumentErrors;
                                break;
                            }
                            if (errors.spkDocuments)
                                break;
                        }
                    }

                    Promise.all(validateSPKisExist).then(
                        validateSPKisExistResult => {
                            Promise.all(getPromise)
                                .then(spkDocuments => {
                                    var index = 0;
                                    for (var spkDocument of valid.spkDocuments) {
                                        var spkDocumentError = spkDocumentErrors[index];

                                        if (spkDocuments[index]) {
                                            var spkspkDocumentError = spkDocumentError;
                                            if (spkDocument) {
                                                if (!spkDocument.items || spkDocument.items.length == 0) {
                                                    spkspkDocumentError["items"] = "items is required";
                                                }
                                                else {
                                                    var itemErrors = [];
                                                    for (var item of spkDocument.items) {
                                                        var itemError = {};
                                                        if (item.quantity == undefined || (item.quantity && item.quantity == '')) {
                                                            itemError["quantity"] = "kuantitas harus diisi";
                                                        }
                                                        else if (parseInt(item.quantity) <= 0) {
                                                            itemError["quantity"] = "kuantitas harus lebih besar dari 0";
                                                        }
                                                        if (item.quantitySend == undefined || (item.quantitySend && item.quantitySend == '')) {
                                                            itemError["quantitySend"] = "kuantitas pengiriman harus diisi";
                                                        }
                                                        else if (parseInt(item.quantitySend) <= 0) {
                                                            itemError["quantitySend"] = "kuantitas pengiriman harus lebih besar dari 0";
                                                        }

                                                        if (item.quantitySend > item.quantity) {
                                                            itemError["quantitySend"] = "kuantitas pengiriman tidak boleh lebih besar dari kuantitas packing list";
                                                        }
                                                        if (item.quantitySend != item.quantity && (!item.remark || item.remark == '')) {
                                                            itemError["remark"] = "catatan harus diisi";
                                                        }
                                                        item.quantity = item.quantitySend;

                                                        itemErrors.push(itemError);
                                                    }
                                                    for (var itemError of itemErrors) {
                                                        for (var prop in itemError) {
                                                            spkspkDocumentError.items = itemErrors;
                                                            break;
                                                        }
                                                        if (spkspkDocumentError.items)
                                                            break;
                                                    }
                                                }

                                                if ((spkDocument.weight || 0) == 0)
                                                    spkspkDocumentError["weight"] = "berat harus diisi";
                                            }

                                            for (var prop in spkspkDocumentError) {
                                                spkDocumentError = spkspkDocumentError;
                                                break;
                                            }

                                            if (validateSPKisExistResult[index].count > 0)
                                                spkDocumentError.code = "packing list sudah memiliki ekspedisi";

                                            spkDocument = spkDocuments[index];
                                        }
                                        // else {
                                        //     spkDocumentError["spkDocument"] = "SPK Document not found";
                                        // }
                                        index++;
                                    }
                                    for (var spkDocumentError of spkDocumentErrors) {
                                        for (var prop in spkDocumentError) {
                                            errors.spkDocuments = spkDocumentErrors;
                                            break;
                                        }
                                    }

                                    for (var prop in errors) {
                                        var ValidationError = require('module-toolkit').ValidationError;
                                        reject(new ValidationError('data does not pass validation', errors));
                                    }

                                    resolve(valid)
                                })
                                .catch(e => {
                                    reject(e);
                                });
                        }
                    )
                })
                .catch(e => {
                    reject(new Error(`Unable to load module:${moduleId}`));
                });
        });
    }

    pdf(id) {
        return new Promise((resolve, reject) => {

            this.getSingleById(id)
                .then(docs => {
                    var getDefinition = require('../../pdf/definitions/efr-kb-exp');
                    var definition = getDefinition(docs);

                    var generatePdf = require('../../pdf/pdf-generator');
                    generatePdf(definition)
                        .then(binary => {
                            resolve(binary);
                        })
                        .catch(e => {
                            reject(e);
                        });
                })
                .catch(e => {
                    reject(e);
                });

        });
    }
};<commit_msg>update sorting expedition<commit_after>'use strict';
//require('js-toolkit').Promise.ext;

// external deps
var ObjectId = require('mongodb').ObjectId;

// internal deps
require('mongodb-toolkit');
var BateeqModels = require('bateeq-models');
var map = BateeqModels.map;

var ExpeditionDoc = BateeqModels.inventory.ExpeditionDoc;
var TransferOutDoc = BateeqModels.inventory.TransferOutDoc;
var TransferOutItem = BateeqModels.inventory.TransferOutItem;
var SPK = BateeqModels.merchandiser.SPK;
var generateCode = require('../../utils/code-generator');

const moduleId = "EFR-KB/EXP";
module.exports = class PusatBarangBaruKirimBarangJadiAksesorisManager {
    constructor(db, user) {
        this.db = db;
        this.user = user;
        this.expeditionDocCollection = this.db.use(map.inventory.ExpeditionDoc);

        var StorageManager = require('../master/storage-manager');
        this.storageManager = new StorageManager(db, user);

        var TransferOutDocManager = require('./transfer-out-doc-manager');
        this.transferOutDocManager = new TransferOutDocManager(db, user);

        var InventoryManager = require('./inventory-manager');
        this.inventoryManager = new InventoryManager(db, user);

        var SpkManager = require('../merchandiser/efr-pk-manager');
        this.spkManager = new SpkManager(db, user);

        var ModuleManager = require('../master/module-manager');
        this.moduleManager = new ModuleManager(db, user);
    }

    read(paging) {
        var _paging = Object.assign({}, paging);

        return new Promise((resolve, reject) => {
            var regexModuleId = new RegExp(moduleId, "i");
            var filter = {
                _deleted: false,
                _createdBy: this.user.username,
                'code': {
                    '$regex': regexModuleId
                }
            };
            var query = _paging.keyword ? {
                '$and': [filter]
            } : filter;

            if (_paging.keyword) {
                var regex = new RegExp(_paging.keyword, "i");
                var filterCode = {
                    'code': {
                        '$regex': regex
                    }
                };
                var $or = {
                    '$or': [filterCode]
                };

                query['$and'].push($or);
            }

            this.expeditionDocCollection
                .where(query)
                .page(_paging.page, _paging.size)
                .order(_paging.order)
                .execute()
                .then(expeditionDocs => {
                    resolve(expeditionDocs);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    getSingleById(id) {
        return new Promise((resolve, reject) => {
            var query = {
                _id: new ObjectId(id),
                _deleted: false
            };
            this.getSingleByQuery(query)
                .then(expeditionDoc => {
                    resolve(expeditionDoc);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    getSingleByIdOrDefault(id) {
        return new Promise((resolve, reject) => {
            var query = {
                _id: new ObjectId(id),
                _deleted: false
            };
            this.getSingleByQueryOrDefault(query)
                .then(expeditionDoc => {
                    resolve(expeditionDoc);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    getSingleByQuery(query) {
        return new Promise((resolve, reject) => {
            this.expeditionDocCollection
                .single(query)
                .then(expeditionDoc => {
                    resolve(expeditionDoc);
                })
                .catch(e => {
                    reject(e);
                });
        })
    }

    getSingleByQueryOrDefault(query) {
        return new Promise((resolve, reject) => {
            this.expeditionDocCollection
                .singleOrDefault(query)
                .then(expeditionDoc => {
                    resolve(expeditionDoc);
                })
                .catch(e => {
                    reject(e);
                });
        })
    }

    getBySpk(code) {
        var query = { "spkDocuments.code": code };
        return new Promise((resolve, reject) => {
            this.expeditionDocCollection
                .where(query)
                .execute()
                .then(expeditionDocs => {
                    resolve(expeditionDocs);
                })
                .catch(e => {
                    reject(e);
                });
        })
    }

    create(expeditionDoc) {
        return new Promise((resolve, reject) => {
            //Validate Input Model
            this._validate(expeditionDoc)
                .then(validatedExpeditionDoc => {
                    var code = generateCode(moduleId);
                    var getTransferOuts = [];
                    //Create Promise to Create Transfer Out
                    for (var spkDocument of validatedExpeditionDoc.spkDocuments) {
                        //getTransferOuts.push(this.transferOutDocManager.create(validTransferOutDoc));
                        var f = (spkDoc, outManager) => {
                            return () => {
                                var validTransferOutDoc = {};
                                validTransferOutDoc.code = code;
                                validTransferOutDoc.reference = spkDoc.packingList;
                                validTransferOutDoc.sourceId = spkDoc.sourceId;
                                validTransferOutDoc.destinationId = spkDoc.destinationId;
                                validTransferOutDoc.items = [];
                                for (var item of spkDoc.items) {
                                    var newitem = {};
                                    newitem.itemId = item.itemId;
                                    newitem.quantity = item.quantity;
                                    validTransferOutDoc.items.push(newitem);
                                }
                                return outManager.create(validTransferOutDoc)
                            }
                        };
                        getTransferOuts.push(f(spkDocument, this.transferOutDocManager));
                    }
                    //Create Transfer Out
                    //Promise.all(getTransferOuts)
                    require('js-toolkit').Promise.ext;
                    Promise.chain(getTransferOuts)
                        .then(results => {
                            getTransferOuts = [];
                            //Create Promise Get Transfer Out using ID
                            for (var transferOutResultId of results) {
                                getTransferOuts.push(this.transferOutDocManager.getSingleByIdOrDefault(transferOutResultId));
                            }
                            //Get Transfer Out
                            Promise.all(getTransferOuts)
                                .then(transferOutResults => {
                                    //Create Expedition Model
                                    var validExpeditionDoc = {};
                                    validExpeditionDoc.code = code;
                                    validExpeditionDoc.expedition = validatedExpeditionDoc.expedition;
                                    validExpeditionDoc.weight = validatedExpeditionDoc.weight;
                                    validExpeditionDoc.transferOutDocuments = [];
                                    validExpeditionDoc.spkDocuments = validatedExpeditionDoc.spkDocuments
                                    for (var transferOut of transferOutResults) {
                                        validExpeditionDoc.transferOutDocuments.push(transferOut);
                                    }
                                    validExpeditionDoc = new ExpeditionDoc(validExpeditionDoc);
                                    validExpeditionDoc._createdDate = new Date();
                                    validExpeditionDoc.stamp(this.user.username, 'manager');
                                    //Create Promise Expedition
                                    this.expeditionDocCollection.insert(validExpeditionDoc)
                                        .then(resultExpeditionId => {
                                            //Get Expedition Data
                                            this.getSingleByIdOrDefault(resultExpeditionId)
                                                .then(resultExpedition => {
                                                    var getSPKData = [];
                                                    //Create Promise get SPK Data for update
                                                    for (var spkDocument of validExpeditionDoc.spkDocuments) {
                                                        getSPKData.push(this.spkManager.getSingleByIdOrDefault(spkDocument._id));
                                                    }
                                                    //Get SPK Data
                                                    Promise.all(getSPKData)
                                                        .then(resultSPKs => {
                                                            //Create Promise Update SPK Data
                                                            var getUpdateSPKData = [];
                                                            for (var resultSPK of resultSPKs) {
                                                                resultSPK.expeditionDocumentId = resultExpeditionId;
                                                                resultSPK.expeditionDocument = resultExpedition;
                                                                resultSPK = new SPK(resultSPK);
                                                                getUpdateSPKData.push(this.spkManager.update(resultSPK));
                                                            }
                                                            //Update SPK Data
                                                            Promise.all(getUpdateSPKData)
                                                                .then(resultUpdateSPKs => {
                                                                    resolve(resultExpeditionId);
                                                                })
                                                                .catch(e => {
                                                                    reject(e);
                                                                });
                                                        })
                                                        .catch(e => {
                                                            reject(e);
                                                        });
                                                })
                                                .catch(e => {
                                                    reject(e);
                                                });
                                        })
                                        .catch(e => {
                                            reject(e);
                                        });
                                })
                                .catch(e => {
                                    reject(e);
                                });
                        })
                        .catch(e => {
                            reject(e);
                        });
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    update(expeditionDoc) {
        return new Promise((resolve, reject) => {
            resolve(null);
        });
    }

    delete(expeditionDoc) {
        return new Promise((resolve, reject) => {
            resolve(null);
        });
    }

    _validate(expeditionDoc) {
        var errors = {};
        return new Promise((resolve, reject) => {
            var valid = expeditionDoc;
            this.moduleManager.getByCode(moduleId)
                .then(module => {
                    var config = module.config;
                    var getPromise = [];
                    var validateSPKisExist = [];

                    var getStock = [];

                    if (!valid.expedition || valid.expedition == '')
                        errors["expedition"] = "expedition is required";

                    if (!valid.spkDocuments || valid.spkDocuments.length == 0) {
                        errors["spkDocuments"] = "spkDocuments is required";
                    }
                    else {
                        var spkDocumentErrors = [];
                        var spkDocumentDestinationId = "";
                        expeditionDoc.weight = 0;
                        for (var spkDocument of valid.spkDocuments) {
                            expeditionDoc.weight += parseInt(spkDocument.weight || 0);
                            var spkDocumentError = {};
                            if (!spkDocument._id || spkDocument._id == "") {
                                spkDocumentError["code"] = "packing list harus diisi";
                                getPromise.push(Promise.resolve(null));
                            }
                            else {
                                for (var i = valid.spkDocuments.indexOf(spkDocument) + 1; i < valid.spkDocuments.length; i++) {
                                    var otherItem = valid.spkDocuments[i];
                                    if (spkDocument._id == otherItem._id) {
                                        spkDocumentError["code"] = "duplikat packing list";
                                    }
                                }

                                getPromise.push(this.spkManager.getSingleByIdOrDefault(spkDocument._id));
                            }

                            validateSPKisExist.push(this.getBySpk(spkDocument.code));

                            if (spkDocumentDestinationId == "")
                                spkDocumentDestinationId = spkDocument.destinationId;
                            else if (spkDocument.destinationId != spkDocumentDestinationId)
                                spkDocumentError["code"] = "packing list harus memiliki tujuan yang sama";

                            spkDocumentErrors.push(spkDocumentError);

                            for (var item of spkDocument.items) {
                                getStock.push(this.inventoryManager.getByStorageIdAndItemIdOrDefault(spkDocument.sourceId, item.itemId));
                            }
                        }
                        for (var spkDocumentError of spkDocumentErrors) {
                            for (var prop in spkDocumentError) {
                                errors.spkDocuments = spkDocumentErrors;
                                break;
                            }
                            if (errors.spkDocuments)
                                break;
                        }
                    }

                    Promise.all(validateSPKisExist).then(
                        validateSPKisExistResult => {
                            Promise.all([].concat(getPromise, getStock))
                                .then(spkDocuments => {
                                    var index = 0;
                                    var inventory = spkDocuments.filter(x => x._type === 'inventory')
                                    for (var spkDocument of valid.spkDocuments) {
                                        var spkDocumentError = spkDocumentErrors[index];

                                        if (spkDocuments[index]) {
                                            var spkspkDocumentError = spkDocumentError;
                                            if (spkDocument) {
                                                if (!spkDocument.items || spkDocument.items.length == 0) {
                                                    spkspkDocumentError["items"] = "items is required";
                                                }
                                                else {
                                                    var itemErrors = [];
                                                    for (var item of spkDocument.items) {
                                                        var itemError = {};
                                                        var quantityStock = inventory.find(x => x.itemId == item.itemId && x.storageId == spkDocument.sourceId);
                                                        if (item.quantitySend > quantityStock.quantity) {
                                                            itemError["quantitySend"] = "stok tidak tersedia";
                                                        }
                                                        if (item.quantity == undefined || (item.quantity && item.quantity == '')) {
                                                            itemError["quantity"] = "kuantitas harus diisi";
                                                        }
                                                        else if (parseInt(item.quantity) <= 0) {
                                                            itemError["quantity"] = "kuantitas harus lebih besar dari 0";
                                                        }
                                                        if (item.quantitySend == undefined || (item.quantitySend && item.quantitySend == '')) {
                                                            itemError["quantitySend"] = "kuantitas pengiriman harus diisi";
                                                        }
                                                        else if (parseInt(item.quantitySend) <= 0) {
                                                            itemError["quantitySend"] = "kuantitas pengiriman harus lebih besar dari 0";
                                                        }

                                                        if (item.quantitySend > item.quantity) {
                                                            itemError["quantitySend"] = "kuantitas pengiriman tidak boleh lebih besar dari kuantitas packing list";
                                                        }
                                                        if (item.quantitySend != item.quantity && (!item.remark || item.remark == '')) {
                                                            itemError["remark"] = "catatan harus diisi";
                                                        }
                                                        item.quantity = item.quantitySend;

                                                        itemErrors.push(itemError);
                                                    }
                                                    for (var itemError of itemErrors) {
                                                        for (var prop in itemError) {
                                                            spkspkDocumentError.items = itemErrors;
                                                            break;
                                                        }
                                                        if (spkspkDocumentError.items)
                                                            break;
                                                    }
                                                }

                                                if ((spkDocument.weight || 0) == 0)
                                                    spkspkDocumentError["weight"] = "berat harus diisi";
                                            }

                                            for (var prop in spkspkDocumentError) {
                                                spkDocumentError = spkspkDocumentError;
                                                break;
                                            }

                                            if (validateSPKisExistResult[index].count > 0)
                                                spkDocumentError.code = "packing list sudah memiliki ekspedisi";

                                            spkDocument = spkDocuments[index];
                                        }
                                        else {
                                            spkDocumentError.code = "packing list tidak ditemukan";
                                        }
                                        index++;
                                    }
                                    for (var spkDocumentError of spkDocumentErrors) {
                                        for (var prop in spkDocumentError) {
                                            errors.spkDocuments = spkDocumentErrors;
                                            break;
                                        }
                                    }

                                    for (var prop in errors) {
                                        var ValidationError = require('module-toolkit').ValidationError;
                                        reject(new ValidationError('data does not pass validation', errors));
                                    }

                                    resolve(valid)
                                })
                                .catch(e => {
                                    reject(e);
                                });
                        }
                    )
                })
                .catch(e => {
                    reject(new Error(`Unable to load module:${moduleId}`));
                });
        });
    }

    pdf(id) {
        return new Promise((resolve, reject) => {

            this.getSingleById(id)
                .then(docs => {
                    var getDefinition = require('../../pdf/definitions/efr-kb-exp');
                    var definition = getDefinition(docs);

                    var generatePdf = require('../../pdf/pdf-generator');
                    generatePdf(definition)
                        .then(binary => {
                            resolve(binary);
                        })
                        .catch(e => {
                            reject(e);
                        });
                })
                .catch(e => {
                    reject(e);
                });

        });
    }
};<|endoftext|>


<commit_before>/**
 * @license
 * Visual Blocks Editor
 *
 * Copyright 2019 Google Inc.
 * https://developers.google.com/blockly/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Methods for graphically rendering a block as SVG.
 * @author fenichel@google.com (Rachel Fenichel)
 */

'use strict';
goog.provide('Blockly.blockRendering.Debug');
goog.require('Blockly.blockRendering.RenderInfo');
goog.require('Blockly.blockRendering.Highlighter');
goog.require('Blockly.blockRendering.constants');
goog.require('Blockly.blockRendering.Measurable');

/**
 * An object that renders rectangles and dots for debugging rendering code.
 * @package
 */
Blockly.blockRendering.Debug = function() {
  /**
   * An array of SVG elements that have been created by this object.
   * @type {Array.<!SVGElement>}
   */
  this.debugElements_ = [];

  /**
   * The SVG root of the block that is being rendered.  Debug elements will
   * be attached to this root.
   * @type {!SVGElement}
   */
  this.svgRoot_ = null;
};

/**
 * Remove all elements the this object created on the last pass.
 * @package
 */
Blockly.blockRendering.Debug.prototype.clearElems = function() {
  for (var i = 0, elem; elem = this.debugElements_[i]; i++) {
    Blockly.utils.dom.removeNode(elem);
  }

  this.debugElements_ = [];
};

/**
 * Draw a debug rectangle for a spacer (empty) row.
 * @param {!Blockly.blockRendering.Row} row The row to render
 * @param {number} cursorY The y position of the top of the row.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawSpacerRow = function(row, cursorY) {
  this.debugElements_.push(Blockly.utils.dom.createSvgElement('rect',
      {
        'class': 'rowSpacerRect blockRenderDebug',
        'x': 0,
        'y': cursorY,
        'width': row.width,
        'height': row.height,
      },
      this.svgRoot_));
};

/**
 * Draw a debug rectangle for a horizontal spacer.
 * @param {!Blockly.BlockSvg.InRowSpacer} elem The spacer to render
 * @param {number} cursorX The x position of the left of the row.
 * @param {number} centerY The y position of the center of the row, vertically.
 * @param {number} rowHeight The height of the container row.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawSpacerElem =
    function(elem, cursorX, centerY, rowHeight) {
  var debugRenderedHeight = Math.min(15, rowHeight);
  var yPos = centerY - debugRenderedHeight / 2;
  this.debugElements_.push(Blockly.utils.dom.createSvgElement('rect',
      {
        'class': 'elemSpacerRect blockRenderDebug',
        'x': cursorX,
        'y': yPos,
        'width': elem.width,
        'height': debugRenderedHeight,
      },
      this.svgRoot_));
};

/**
 * Draw a debug rectangle for an in-row element.
 * @param {!Blockly.BlockSvg.Measurable} elem The element to render
 * @param {number} cursorX The x position of the left of the row.
 * @param {number} centerY The y position of the center of the row, vertically.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawRenderedElem = function(elem, cursorX, centerY) {
  var yPos = centerY - elem.height / 2;
  this.debugElements_.push(Blockly.utils.dom.createSvgElement('rect',
      {
        'class': 'rowRenderingRect blockRenderDebug',
        'x': cursorX,
        'y': yPos,
        'width': elem.width,
        'height': elem.height ,
      },
      this.svgRoot_));

  if (elem.isInput) {
    this.drawConnection(elem.connection);
  }
};

/**
 * Draw a circle at the location of the given connection.  Inputs and outputs
 * share the same colors, as do previous and next.  When positioned correctly
 * a connected pair will look like a bullseye.
 * @param {Blockly.RenderedConnection} conn The connection to circle.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawConnection = function(conn) {
  var colour;
  var size;
  var fill;
  if (conn.type == Blockly.INPUT_VALUE) {
    size = 4;
    colour = 'magenta';
    fill = 'none';
  } else if (conn.type == Blockly.OUTPUT_VALUE) {
    size = 2;
    colour = 'magenta';
    fill = colour;
  } else if (conn.type == Blockly.NEXT_STATEMENT) {
    size = 4;
    colour = 'goldenrod';
    fill = 'none';
  } else if (conn.type == Blockly.PREVIOUS_STATEMENT) {
    size = 2;
    colour = 'goldenrod';
    fill = colour;
  }
  this.debugElements_.push(Blockly.utils.dom.createSvgElement('circle',
      {
        'class': 'blockRenderDebug',
        'cx': conn.offsetInBlock_.x,
        'cy': conn.offsetInBlock_.y,
        'r': size,
        'fill': fill,
        'stroke': colour,
      },
      this.svgRoot_));
};

/**
 * Draw a debug rectangle for a non-empty row.
 * @param {!Blockly.BlockSvg.Row} row The non-empty row to render.
 * @param {number} cursorY The y position of the top of the row.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawRenderedRow = function(row, cursorY) {
  this.debugElements_.push(Blockly.utils.dom.createSvgElement('rect',
      {
        'class': 'elemRenderingRect blockRenderDebug',
        'x': 0,
        'y': cursorY ,
        'width': row.width,
        'height': row.height,
      },
      this.svgRoot_));
};

/**
 * Draw debug rectangles for a non-empty row and all of its subcomponents.
 * @param {!Blockly.BlockSvg.Row} row The non-empty row to render.
 * @param {number} cursorY The y position of the top of the row.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawRowWithElements = function(row, cursorY) {
  var centerY = cursorY + row.height / 2;
  var cursorX = 0;
  for (var e = 0; e < row.elements.length; e++) {
    var elem = row.elements[e];
    if (elem.isSpacer()) {
      this.drawSpacerElem(elem, cursorX, centerY, row.height);
    } else {
      this.drawRenderedElem(elem, cursorX, centerY);
    }
    cursorX += elem.width;
  }
  this.drawRenderedRow(row, cursorY);
};

/**
 * Do all of the work to draw debug information for the whole block.
 * @param {!Blockly.BlockSvg} block The block to draw debug information for.
 * @param {!Blockly.blockRendering.RenderInfo} info Rendering information about
 *     the block to debug.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawDebug = function(block, info) {
  this.clearElems();
  this.svgRoot_ = block.getSvgRoot();
  var cursorY = 0;
  for (var r = 0; r < info.rows.length; r++) {
    var row = info.rows[r];
    if (row.isSpacer()) {
      this.drawSpacerRow(row, cursorY);
    } else {
      this.drawRowWithElements(row, cursorY);
    }
    cursorY += row.height;
  }

  if (block.previousConnection) {
    this.drawConnection(block.previousConnection);
  }
  if (block.nextConnection) {
    this.drawConnection(block.nextConnection);
  }
  if (block.outputConnection) {
    this.drawConnection(block.outputConnection);
  }
};
<commit_msg>Updating indentation.<commit_after>/**
 * @license
 * Visual Blocks Editor
 *
 * Copyright 2019 Google Inc.
 * https://developers.google.com/blockly/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Methods for graphically rendering a block as SVG.
 * @author fenichel@google.com (Rachel Fenichel)
 */

'use strict';
goog.provide('Blockly.blockRendering.Debug');
goog.require('Blockly.blockRendering.RenderInfo');
goog.require('Blockly.blockRendering.Highlighter');
goog.require('Blockly.blockRendering.constants');
goog.require('Blockly.blockRendering.Measurable');

/**
 * An object that renders rectangles and dots for debugging rendering code.
 * @package
 */
Blockly.blockRendering.Debug = function() {
  /**
   * An array of SVG elements that have been created by this object.
   * @type {Array.<!SVGElement>}
   */
  this.debugElements_ = [];

  /**
   * The SVG root of the block that is being rendered.  Debug elements will
   * be attached to this root.
   * @type {!SVGElement}
   */
  this.svgRoot_ = null;
};

/**
 * Remove all elements the this object created on the last pass.
 * @package
 */
Blockly.blockRendering.Debug.prototype.clearElems = function() {
  for (var i = 0, elem; elem = this.debugElements_[i]; i++) {
    Blockly.utils.dom.removeNode(elem);
  }

  this.debugElements_ = [];
};

/**
 * Draw a debug rectangle for a spacer (empty) row.
 * @param {!Blockly.blockRendering.Row} row The row to render
 * @param {number} cursorY The y position of the top of the row.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawSpacerRow = function(row, cursorY) {
  this.debugElements_.push(Blockly.utils.dom.createSvgElement('rect',
      {
        'class': 'rowSpacerRect blockRenderDebug',
        'x': 0,
        'y': cursorY,
        'width': row.width,
        'height': row.height,
      },
      this.svgRoot_));
};

/**
 * Draw a debug rectangle for a horizontal spacer.
 * @param {!Blockly.BlockSvg.InRowSpacer} elem The spacer to render
 * @param {number} cursorX The x position of the left of the row.
 * @param {number} centerY The y position of the center of the row, vertically.
 * @param {number} rowHeight The height of the container row.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawSpacerElem =
    function(elem, cursorX,  centerY, rowHeight) {
      var debugRenderedHeight = Math.min(15, rowHeight);
      var yPos = centerY - debugRenderedHeight / 2;
      this.debugElements_.push(Blockly.utils.dom.createSvgElement('rect',
          {
            'class': 'elemSpacerRect blockRenderDebug',
            'x': cursorX,
            'y': yPos,
            'width': elem.width,
            'height': debugRenderedHeight,
          },
          this.svgRoot_));
    };

/**
 * Draw a debug rectangle for an in-row element.
 * @param {!Blockly.BlockSvg.Measurable} elem The element to render
 * @param {number} cursorX The x position of the left of the row.
 * @param {number} centerY The y position of the center of the row, vertically.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawRenderedElem = function(elem, cursorX, centerY) {
  var yPos = centerY - elem.height / 2;
  this.debugElements_.push(Blockly.utils.dom.createSvgElement('rect',
      {
        'class': 'rowRenderingRect blockRenderDebug',
        'x': cursorX,
        'y': yPos,
        'width': elem.width,
        'height': elem.height ,
      },
      this.svgRoot_));

  if (elem.isInput) {
    this.drawConnection(elem.connection);
  }
};

/**
 * Draw a circle at the location of the given connection.  Inputs and outputs
 * share the same colors, as do previous and next.  When positioned correctly
 * a connected pair will look like a bullseye.
 * @param {Blockly.RenderedConnection} conn The connection to circle.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawConnection = function(conn) {
  var colour;
  var size;
  var fill;
  if (conn.type == Blockly.INPUT_VALUE) {
    size = 4;
    colour = 'magenta';
    fill = 'none';
  } else if (conn.type == Blockly.OUTPUT_VALUE) {
    size = 2;
    colour = 'magenta';
    fill = colour;
  } else if (conn.type == Blockly.NEXT_STATEMENT) {
    size = 4;
    colour = 'goldenrod';
    fill = 'none';
  } else if (conn.type == Blockly.PREVIOUS_STATEMENT) {
    size = 2;
    colour = 'goldenrod';
    fill = colour;
  }
  this.debugElements_.push(Blockly.utils.dom.createSvgElement('circle',
      {
        'class': 'blockRenderDebug',
        'cx': conn.offsetInBlock_.x,
        'cy': conn.offsetInBlock_.y,
        'r': size,
        'fill': fill,
        'stroke': colour,
      },
      this.svgRoot_));
};

/**
 * Draw a debug rectangle for a non-empty row.
 * @param {!Blockly.BlockSvg.Row} row The non-empty row to render.
 * @param {number} cursorY The y position of the top of the row.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawRenderedRow = function(row, cursorY) {
  this.debugElements_.push(Blockly.utils.dom.createSvgElement('rect',
      {
        'class': 'elemRenderingRect blockRenderDebug',
        'x': 0,
        'y': cursorY ,
        'width': row.width,
        'height': row.height,
      },
      this.svgRoot_));
};

/**
 * Draw debug rectangles for a non-empty row and all of its subcomponents.
 * @param {!Blockly.BlockSvg.Row} row The non-empty row to render.
 * @param {number} cursorY The y position of the top of the row.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawRowWithElements = function(row, cursorY) {
  var centerY = cursorY + row.height / 2;
  var cursorX = 0;
  for (var e = 0; e < row.elements.length; e++) {
    var elem = row.elements[e];
    if (elem.isSpacer()) {
      this.drawSpacerElem(elem, cursorX, centerY, row.height);
    } else {
      this.drawRenderedElem(elem, cursorX, centerY);
    }
    cursorX += elem.width;
  }
  this.drawRenderedRow(row, cursorY);
};

/**
 * Do all of the work to draw debug information for the whole block.
 * @param {!Blockly.BlockSvg} block The block to draw debug information for.
 * @param {!Blockly.blockRendering.RenderInfo} info Rendering information about
 *     the block to debug.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawDebug = function(block, info) {
  this.clearElems();
  this.svgRoot_ = block.getSvgRoot();
  var cursorY = 0;
  for (var r = 0; r < info.rows.length; r++) {
    var row = info.rows[r];
    if (row.isSpacer()) {
      this.drawSpacerRow(row, cursorY);
    } else {
      this.drawRowWithElements(row, cursorY);
    }
    cursorY += row.height;
  }

  if (block.previousConnection) {
    this.drawConnection(block.previousConnection);
  }
  if (block.nextConnection) {
    this.drawConnection(block.nextConnection);
  }
  if (block.outputConnection) {
    this.drawConnection(block.outputConnection);
  }
};
<|endoftext|>