<commit_before>(function () {

"use strict";

angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])

.factory('MotionContentProvider', [
    'gettextCatalog',
    'PDFLayout',
    'Category',
    'Config',
    'Motion',
    function(gettextCatalog, PDFLayout, Category, Config, Motion) {
    /**
     * Provides the content as JS objects for Motions in pdfMake context
     * @constructor
     */

    var createInstance = function(converter, motion, $scope) {

        // title
        var identifier = motion.identifier ? ' ' + motion.identifier : '';
        var title = PDFLayout.createTitle(
                gettextCatalog.getString('Motion') + identifier + ': ' +
                motion.getTitle($scope.version)
        );

        // subtitle
        var subtitleLines = [];
        if (motion.parent_id) {
            var parentMotion = Motion.get(motion.parent_id);
            subtitleLines.push(
                gettextCatalog.getString('Amendment of motion') + ': ' +
                (parentMotion.identifier ? parentMotion.identifier : parentMotion.getTitle())
            );
        }
        subtitleLines.push(gettextCatalog.getString('Sequential number') + ': ' +  motion.id);
        var subtitle = PDFLayout.createSubtitle(subtitleLines);

        // meta data table
        var metaTable = function() {
            var metaTableBody = [];

            // submitters
            var submitters = _.map(motion.submitters, function (submitter) {
                return submitter.get_full_name();
            }).join(', ');
            metaTableBody.push([
                {
                    text: gettextCatalog.getString('Submitters') + ':',
                    style: ['bold', 'grey'],
                },
                {
                    text: submitters,
                    style: 'grey'
                }
            ]);

            // state
            metaTableBody.push([
                {
                    text: gettextCatalog.getString('State') + ':',
                    style: ['bold', 'grey']
                },
                {
                    text: motion.getStateName(),
                    style: 'grey'
                }
            ]);

            // recommendation
            if (motion.getRecommendationName()) {
                metaTableBody.push([
                    {
                        text: Config.get('motions_recommendations_by').value + ':',
                        style: ['bold', 'grey']
                    },
                    {
                        text: motion.getRecommendationName(),
                        style: 'grey'
                    }
                ]);
            }

            // category
            if (motion.category) {
                metaTableBody.push([
                    {
                        text: gettextCatalog.getString('Category') + ':',
                        style: ['bold', 'grey'] },
                    {
                        text: motion.category.name,
                        style: 'grey'
                    }
                ]);
            }

            // voting result
            if (motion.polls.length > 0 && motion.polls[0].has_votes) {
                var column1 = [];
                var column2 = [];
                var column3 = [];
                motion.polls.map(function(poll, index) {
                    if (poll.has_votes) {
                        // votenumber
                        if (motion.polls.length > 1) {
                            column1.push(index + 1 + '. ' + gettextCatalog.getString('Vote'));
                            column2.push('');
                            column3.push('');
                        }
                        // yes
                        var yes = poll.getVote(poll.yes, 'yes');
                        column1.push(gettextCatalog.getString('Yes') + ':');
                        column2.push(yes.value);
                        column3.push(yes.percentStr);
                        // no
                        var no = poll.getVote(poll.no, 'no');
                        column1.push(gettextCatalog.getString('No') + ':');
                        column2.push(no.value);
                        column3.push(no.percentStr);
                        // abstain
                        var abstain = poll.getVote(poll.abstain, 'abstain');
                        column1.push(gettextCatalog.getString('Abstain') + ':');
                        column2.push(abstain.value);
                        column3.push(abstain.percentStr);
                        // votes valid
                        if (poll.votesvalid) {
                            var valid = poll.getVote(poll.votesvalid, 'votesvalid');
                            column1.push(gettextCatalog.getString('Valid votes') + ':');
                            column2.push(valid.value);
                            column3.push(valid.percentStr);
                        }
                        // votes invalid
                        if (poll.votesvalid) {
                            var invalid = poll.getVote(poll.votesinvalid, 'votesinvalid');
                            column1.push(gettextCatalog.getString('Invalid votes') + ':');
                            column2.push(invalid.value);
                            column3.push(invalid.percentStr);
                        }
                        // votes cast
                        if (poll.votescast) {
                            var cast = poll.getVote(poll.votescast, 'votescast');
                            column1.push(gettextCatalog.getString('Votes cast') + ':');
                            column2.push(cast.value);
                            column3.push(cast.percentStr);
                        }
                    }
                });
                metaTableBody.push([
                    {
                        text: gettextCatalog.getString('Voting result') + ':',
                        style: ['bold', 'grey']
                    },
                    {
                        columns: [
                            {
                                text: column1.join('\n'),
                                width: 'auto'
                            },
                            {
                                text: column2.join('\n'),
                                width: 'auto',
                                alignment: 'right'
                            },
                            {
                                text: column3.join('\n'),
                                width: 'auto',
                                alignment: 'right'
                            },
                        ],
                        columnGap: 7,
                        style: 'grey'
                    }
                ]);
            }

            // summary of change recommendations (for motion diff version only)
            if ($scope.viewChangeRecommendations) {
                if ($scope.viewChangeRecommendations.mode == "diff") {
                    var columnLineNumbers = [];
                    var columnChangeType = [];
                    angular.forEach($scope.change_recommendations, function(change) {
                        // line numbers column
                        var line;
                        if (change.line_from >= change.line_to - 1) {
                            line = change.line_from;
                        } else {
                            line = change.line_from + ' - ' + (change.line_to - 1);
                        }
                        columnLineNumbers.push(
                            gettextCatalog.getString('Line') + ' ' + line + ': '
                        );
                        // change type column
                        if (change.getType(motion.getVersion($scope.version).text) === 0) {
                            columnChangeType.push(gettextCatalog.getString("Replacement"));
                        } else if (change.getType(motion.getVersion($scope.version).text) === 1) {
                            columnChangeType.push(gettextCatalog.getString("Insertion"));
                        } else if (change.getType(motion.getVersion($scope.version).text) === 2) {
                            columnChangeType.push(gettextCatalog.getString("Deletion"));
                        }
                    });
                    metaTableBody.push([
                        {
                            text: gettextCatalog.getString('Summary of change recommendations'),
                            style: ['bold', 'grey']
                        },
                        {
                            columns: [
                                {
                                    text: columnLineNumbers.join('\n'),
                                    width: 'auto'
                                },
                                {
                                    text: columnChangeType.join('\n'),
                                    width: 'auto'
                                }
                            ],
                            columnGap: 7,
                            style: 'grey'
                        }
                    ]);
                }
            }

            // build table
            // Used placeholder for 'layout' functions whiche are
            // replaced by lineWitdh/lineColor function in pfd-worker.js.
            // TODO: Remove placeholder and us static values for LineWidth and LineColor
            // if pdfmake has fixed this.
            var metaTableJsonString = {
                table: {
                    widths: ['30%','70%'],
                    body: metaTableBody,
                },
                margin: [0, 0, 0, 20],
                layout: '{{motion-placeholder-to-insert-functions-here}}'
            };
            return metaTableJsonString;
        };

        // motion title
        var motionTitle = function() {
            return [{
                text: motion.getTitle($scope.version),
                style: 'heading3'
            }];
        };

        // motion preamble
        var motionPreamble = function () {
            return {
                text: Config.translate(Config.get('motions_preamble').value),
                margin: [0, 10, 0, 0]
            };
        };

        // motion text (with line-numbers)
        var motionText = function() {
            var motionTextContent = motion.getTextByMode($scope.viewChangeRecommendations.mode, $scope.version);
            return converter.convertHTML(motionTextContent, $scope.lineNumberMode);
        };

        // motion reason heading
        var motionReason = function() {
            var reason = [];
            if (motion.getReason($scope.version)) {
                reason.push({
                    text:  gettextCatalog.getString('Reason'),
                    style: 'heading3',
                    marginTop: 25,
                });
                reason.push(converter.convertHTML(motion.getReason($scope.version), $scope.lineNumberMode));
            }
            return reason;
        };

        // getters
        var getTitle = function() {
            return motion.getTitle($scope.version);
        };

        var getIdentifier = function() {
            return motion.identifier ? motion.identifier : '';
        };

        var getCategory = function() {
            return motion.category;
        };

        // Generates content as a pdfmake consumable
        var getContent = function() {
            var content = [
                title,
                subtitle,
                metaTable(),
                motionTitle(),
                motionPreamble(),
                motionText(),
            ];
            if (motionReason()) {
                content.push(motionReason());
            }
            return content;
        };
        return {
            getContent: getContent,
            getTitle: getTitle,
            getIdentifier: getIdentifier,
            getCategory: getCategory
        };
    };

    return {
        createInstance: createInstance
    };
}])

.factory('PollContentProvider', [
    'PDFLayout',
    'Config',
    'User',
    function(PDFLayout, Config, User) {
    /**
    * Generates a content provider for polls
    * @constructor
    * @param {string} title - title of poll
    * @param {string} id - if of poll
    * @param {object} gettextCatalog - for translation
    */
    var createInstance = function(title, id, gettextCatalog) {

        /**
        * Returns a single section on the ballot paper
        * @function
        */
        var createSection = function() {
            var sheetend = 75;
            return {
                stack: [{
                    text: gettextCatalog.getString("Motion") + " " + id,
                    style: 'title',
                }, {
                    text: title,
                    style: 'description'
                },
                PDFLayout.createBallotEntry(gettextCatalog.getString("Yes")),
                PDFLayout.createBallotEntry(gettextCatalog.getString("No")),
                PDFLayout.createBallotEntry(gettextCatalog.getString("Abstain")),
                ],
                margin: [0, 0, 0, sheetend]
            };
        };

        /**
        * Returns Content for single motion
        * @function
        * @param {string} id - if of poll
        */
        var getContent = function() {
            var content = [];
            var amount;
            var amount_method = Config.get('motions_pdf_ballot_papers_selection').value;
            switch (amount_method) {
                    case 'NUMBER_OF_ALL_PARTICIPANTS':
                        amount = User.getAll().length;
                        break;
                    case 'NUMBER_OF_DELEGATES':
                        //TODO: assumption that DELEGATES is always group id 2. This may not be true
                        var group_id = 2;
                        amount = User.filter({where: {'groups_id': {contains:group_id} }}).length;
                        break;
                    case 'CUSTOM_NUMBER':
                        amount = Config.get('motions_pdf_ballot_papers_number').value;
                        break;
                    default:
                        // should not happen.
                        amount = 0;
            }
            var fullpages = Math.floor(amount / 8);

            for (var i=0; i < fullpages; i++) {
                content.push({
                    table: {
                        headerRows: 1,
                        widths: ['*', '*'],
                        body: [
                            [createSection(), createSection()],
                            [createSection(), createSection()],
                            [createSection(), createSection()],
                            [createSection(), createSection()]
                        ],
                        pageBreak: 'after'
                    },
                    layout: PDFLayout.getBallotLayoutLines(),
                    rowsperpage: 4
                });
            }
            amount = amount  - (fullpages * 8);
            if (amount > 0) {
                var partialpagebody = [];
                while (amount > 1) {
                    partialpagebody.push([createSection(), createSection()]);
                    amount -=2;
                }
                if (amount == 1) {
                    partialpagebody.push([createSection(), '']);
                }
                content.push({
                    table: {
                        headerRows: 1,
                        widths: ['50%', '50%'],
                        body: partialpagebody
                    },
                    layout: PDFLayout.getBallotLayoutLines(),
                    rowsperpage: 4
                });
            }
            return content;
        };

        return {
            getContent: getContent,
        };
    };
    return {
        createInstance: createInstance
    };
}])

.factory('MotionCatalogContentProvider', [
    'gettextCatalog',
    'PDFLayout',
    'Category',
    'Config',
    function(gettextCatalog, PDFLayout, Category, Config) {

    /**
    * Constructor
    * @function
    * @param {object} allMotions - A sorted array of all motions to parse
    * @param {object} $scope - Current $scope
    */
    var createInstance = function(allMotions, $scope) {

        var title = PDFLayout.createTitle(
                Config.translate(Config.get('motions_export_title').value)
        );

        var createPreamble = function() {
            var preambleText = Config.get('motions_export_preamble').value;
            if (preambleText) {
                return {
                    text: preambleText,
                    style: "preamble"
                };
            } else {
                return "";
            }
        };

        var createTOContent = function() {
            var heading = {
                text: gettextCatalog.getString("Table of contents"),
                style: "heading2"
            };

            var toc = [];
            angular.forEach(allMotions, function(motion) {
                var identifier = motion.getIdentifier() ? motion.getIdentifier() : '';
                toc.push(
                    {
                        columns: [
                            {
                                text: identifier,
                                style: 'tableofcontent',
                                width: 70
                            },
                            {
                                text: motion.getTitle(),
                                style: 'tableofcontent'
                            }
                        ]
                    }
                );
            });

            return [
                heading,
                toc,
                PDFLayout.addPageBreak()
            ];
        };

        // function to create the table of catergories (if any)
        var createTOCategories = function() {
            var categories = [];
            _.forEach(allMotions, function(motion) {
                var category = motion.getCategory();
                if (category) {
                    categories.push(category);
                }
            });
            categories = _.uniqBy(categories, 'id');
            if (categories.length > 1) {
                var heading = {
                    text: gettextCatalog.getString("Categories"),
                    style: "heading2"
                };

                var toc = [];
                angular.forEach(_.orderBy(categories, ['prefix']), function(cat) {
                    toc.push(
                        {
                            columns: [
                                {
                                    text: cat.prefix,
                                    style: 'tableofcontent',
                                    width: 50
                                },
                                {
                                    text: cat.name,
                                    style: 'tableofcontent'
                                }
                            ]
                        }
                    );
                });

                return [
                    heading,
                    toc,
                    PDFLayout.addPageBreak()
                ];
            } else {
                // if there are no categories, return "empty string"
                // pdfmake takes "null" literally and throws an error
                return "";
            }
        };

        // returns the pure content of the motion, parseable by pdfmake
        var getContent = function() {
            var motionContent = [];
            angular.forEach(allMotions, function(motion, key) {
                motionContent.push(motion.getContent());
                if (key < allMotions.length - 1) {
                    motionContent.push(PDFLayout.addPageBreak());
                }
            });

            return [
                title,
                createPreamble(),
                createTOCategories(),
                createTOContent(),
                motionContent
            ];
        };
        return {
            getContent: getContent
        };
    };

    return {
        createInstance: createInstance
    };
}]);

}());
<commit_msg>Fixed wrong order of change recommendations in summary box in PDF.<commit_after>(function () {

"use strict";

angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])

.factory('MotionContentProvider', [
    'gettextCatalog',
    'PDFLayout',
    'Category',
    'Config',
    'Motion',
    function(gettextCatalog, PDFLayout, Category, Config, Motion) {
    /**
     * Provides the content as JS objects for Motions in pdfMake context
     * @constructor
     */

    var createInstance = function(converter, motion, $scope) {

        // title
        var identifier = motion.identifier ? ' ' + motion.identifier : '';
        var title = PDFLayout.createTitle(
                gettextCatalog.getString('Motion') + identifier + ': ' +
                motion.getTitle($scope.version)
        );

        // subtitle
        var subtitleLines = [];
        if (motion.parent_id) {
            var parentMotion = Motion.get(motion.parent_id);
            subtitleLines.push(
                gettextCatalog.getString('Amendment of motion') + ': ' +
                (parentMotion.identifier ? parentMotion.identifier : parentMotion.getTitle())
            );
        }
        subtitleLines.push(gettextCatalog.getString('Sequential number') + ': ' +  motion.id);
        var subtitle = PDFLayout.createSubtitle(subtitleLines);

        // meta data table
        var metaTable = function() {
            var metaTableBody = [];

            // submitters
            var submitters = _.map(motion.submitters, function (submitter) {
                return submitter.get_full_name();
            }).join(', ');
            metaTableBody.push([
                {
                    text: gettextCatalog.getString('Submitters') + ':',
                    style: ['bold', 'grey'],
                },
                {
                    text: submitters,
                    style: 'grey'
                }
            ]);

            // state
            metaTableBody.push([
                {
                    text: gettextCatalog.getString('State') + ':',
                    style: ['bold', 'grey']
                },
                {
                    text: motion.getStateName(),
                    style: 'grey'
                }
            ]);

            // recommendation
            if (motion.getRecommendationName()) {
                metaTableBody.push([
                    {
                        text: Config.get('motions_recommendations_by').value + ':',
                        style: ['bold', 'grey']
                    },
                    {
                        text: motion.getRecommendationName(),
                        style: 'grey'
                    }
                ]);
            }

            // category
            if (motion.category) {
                metaTableBody.push([
                    {
                        text: gettextCatalog.getString('Category') + ':',
                        style: ['bold', 'grey'] },
                    {
                        text: motion.category.name,
                        style: 'grey'
                    }
                ]);
            }

            // voting result
            if (motion.polls.length > 0 && motion.polls[0].has_votes) {
                var column1 = [];
                var column2 = [];
                var column3 = [];
                motion.polls.map(function(poll, index) {
                    if (poll.has_votes) {
                        // votenumber
                        if (motion.polls.length > 1) {
                            column1.push(index + 1 + '. ' + gettextCatalog.getString('Vote'));
                            column2.push('');
                            column3.push('');
                        }
                        // yes
                        var yes = poll.getVote(poll.yes, 'yes');
                        column1.push(gettextCatalog.getString('Yes') + ':');
                        column2.push(yes.value);
                        column3.push(yes.percentStr);
                        // no
                        var no = poll.getVote(poll.no, 'no');
                        column1.push(gettextCatalog.getString('No') + ':');
                        column2.push(no.value);
                        column3.push(no.percentStr);
                        // abstain
                        var abstain = poll.getVote(poll.abstain, 'abstain');
                        column1.push(gettextCatalog.getString('Abstain') + ':');
                        column2.push(abstain.value);
                        column3.push(abstain.percentStr);
                        // votes valid
                        if (poll.votesvalid) {
                            var valid = poll.getVote(poll.votesvalid, 'votesvalid');
                            column1.push(gettextCatalog.getString('Valid votes') + ':');
                            column2.push(valid.value);
                            column3.push(valid.percentStr);
                        }
                        // votes invalid
                        if (poll.votesvalid) {
                            var invalid = poll.getVote(poll.votesinvalid, 'votesinvalid');
                            column1.push(gettextCatalog.getString('Invalid votes') + ':');
                            column2.push(invalid.value);
                            column3.push(invalid.percentStr);
                        }
                        // votes cast
                        if (poll.votescast) {
                            var cast = poll.getVote(poll.votescast, 'votescast');
                            column1.push(gettextCatalog.getString('Votes cast') + ':');
                            column2.push(cast.value);
                            column3.push(cast.percentStr);
                        }
                    }
                });
                metaTableBody.push([
                    {
                        text: gettextCatalog.getString('Voting result') + ':',
                        style: ['bold', 'grey']
                    },
                    {
                        columns: [
                            {
                                text: column1.join('\n'),
                                width: 'auto'
                            },
                            {
                                text: column2.join('\n'),
                                width: 'auto',
                                alignment: 'right'
                            },
                            {
                                text: column3.join('\n'),
                                width: 'auto',
                                alignment: 'right'
                            },
                        ],
                        columnGap: 7,
                        style: 'grey'
                    }
                ]);
            }

            // summary of change recommendations (for motion diff version only)
            if ($scope.viewChangeRecommendations) {
                if ($scope.viewChangeRecommendations.mode == "diff") {
                    var columnLineNumbers = [];
                    var columnChangeType = [];
                    angular.forEach(_.orderBy($scope.change_recommendations, ['line_from']), function(change) {
                        // line numbers column
                        var line;
                        if (change.line_from >= change.line_to - 1) {
                            line = change.line_from;
                        } else {
                            line = change.line_from + ' - ' + (change.line_to - 1);
                        }
                        columnLineNumbers.push(
                            gettextCatalog.getString('Line') + ' ' + line + ': '
                        );
                        // change type column
                        if (change.getType(motion.getVersion($scope.version).text) === 0) {
                            columnChangeType.push(gettextCatalog.getString("Replacement"));
                        } else if (change.getType(motion.getVersion($scope.version).text) === 1) {
                            columnChangeType.push(gettextCatalog.getString("Insertion"));
                        } else if (change.getType(motion.getVersion($scope.version).text) === 2) {
                            columnChangeType.push(gettextCatalog.getString("Deletion"));
                        }
                    });
                    metaTableBody.push([
                        {
                            text: gettextCatalog.getString('Summary of change recommendations'),
                            style: ['bold', 'grey']
                        },
                        {
                            columns: [
                                {
                                    text: columnLineNumbers.join('\n'),
                                    width: 'auto'
                                },
                                {
                                    text: columnChangeType.join('\n'),
                                    width: 'auto'
                                }
                            ],
                            columnGap: 7,
                            style: 'grey'
                        }
                    ]);
                }
            }

            // build table
            // Used placeholder for 'layout' functions whiche are
            // replaced by lineWitdh/lineColor function in pfd-worker.js.
            // TODO: Remove placeholder and us static values for LineWidth and LineColor
            // if pdfmake has fixed this.
            var metaTableJsonString = {
                table: {
                    widths: ['30%','70%'],
                    body: metaTableBody,
                },
                margin: [0, 0, 0, 20],
                layout: '{{motion-placeholder-to-insert-functions-here}}'
            };
            return metaTableJsonString;
        };

        // motion title
        var motionTitle = function() {
            return [{
                text: motion.getTitle($scope.version),
                style: 'heading3'
            }];
        };

        // motion preamble
        var motionPreamble = function () {
            return {
                text: Config.translate(Config.get('motions_preamble').value),
                margin: [0, 10, 0, 0]
            };
        };

        // motion text (with line-numbers)
        var motionText = function() {
            var motionTextContent = motion.getTextByMode($scope.viewChangeRecommendations.mode, $scope.version);
            return converter.convertHTML(motionTextContent, $scope.lineNumberMode);
        };

        // motion reason heading
        var motionReason = function() {
            var reason = [];
            if (motion.getReason($scope.version)) {
                reason.push({
                    text:  gettextCatalog.getString('Reason'),
                    style: 'heading3',
                    marginTop: 25,
                });
                reason.push(converter.convertHTML(motion.getReason($scope.version), $scope.lineNumberMode));
            }
            return reason;
        };

        // getters
        var getTitle = function() {
            return motion.getTitle($scope.version);
        };

        var getIdentifier = function() {
            return motion.identifier ? motion.identifier : '';
        };

        var getCategory = function() {
            return motion.category;
        };

        // Generates content as a pdfmake consumable
        var getContent = function() {
            var content = [
                title,
                subtitle,
                metaTable(),
                motionTitle(),
                motionPreamble(),
                motionText(),
            ];
            if (motionReason()) {
                content.push(motionReason());
            }
            return content;
        };
        return {
            getContent: getContent,
            getTitle: getTitle,
            getIdentifier: getIdentifier,
            getCategory: getCategory
        };
    };

    return {
        createInstance: createInstance
    };
}])

.factory('PollContentProvider', [
    'PDFLayout',
    'Config',
    'User',
    function(PDFLayout, Config, User) {
    /**
    * Generates a content provider for polls
    * @constructor
    * @param {string} title - title of poll
    * @param {string} id - if of poll
    * @param {object} gettextCatalog - for translation
    */
    var createInstance = function(title, id, gettextCatalog) {

        /**
        * Returns a single section on the ballot paper
        * @function
        */
        var createSection = function() {
            var sheetend = 75;
            return {
                stack: [{
                    text: gettextCatalog.getString("Motion") + " " + id,
                    style: 'title',
                }, {
                    text: title,
                    style: 'description'
                },
                PDFLayout.createBallotEntry(gettextCatalog.getString("Yes")),
                PDFLayout.createBallotEntry(gettextCatalog.getString("No")),
                PDFLayout.createBallotEntry(gettextCatalog.getString("Abstain")),
                ],
                margin: [0, 0, 0, sheetend]
            };
        };

        /**
        * Returns Content for single motion
        * @function
        * @param {string} id - if of poll
        */
        var getContent = function() {
            var content = [];
            var amount;
            var amount_method = Config.get('motions_pdf_ballot_papers_selection').value;
            switch (amount_method) {
                    case 'NUMBER_OF_ALL_PARTICIPANTS':
                        amount = User.getAll().length;
                        break;
                    case 'NUMBER_OF_DELEGATES':
                        //TODO: assumption that DELEGATES is always group id 2. This may not be true
                        var group_id = 2;
                        amount = User.filter({where: {'groups_id': {contains:group_id} }}).length;
                        break;
                    case 'CUSTOM_NUMBER':
                        amount = Config.get('motions_pdf_ballot_papers_number').value;
                        break;
                    default:
                        // should not happen.
                        amount = 0;
            }
            var fullpages = Math.floor(amount / 8);

            for (var i=0; i < fullpages; i++) {
                content.push({
                    table: {
                        headerRows: 1,
                        widths: ['*', '*'],
                        body: [
                            [createSection(), createSection()],
                            [createSection(), createSection()],
                            [createSection(), createSection()],
                            [createSection(), createSection()]
                        ],
                        pageBreak: 'after'
                    },
                    layout: PDFLayout.getBallotLayoutLines(),
                    rowsperpage: 4
                });
            }
            amount = amount  - (fullpages * 8);
            if (amount > 0) {
                var partialpagebody = [];
                while (amount > 1) {
                    partialpagebody.push([createSection(), createSection()]);
                    amount -=2;
                }
                if (amount == 1) {
                    partialpagebody.push([createSection(), '']);
                }
                content.push({
                    table: {
                        headerRows: 1,
                        widths: ['50%', '50%'],
                        body: partialpagebody
                    },
                    layout: PDFLayout.getBallotLayoutLines(),
                    rowsperpage: 4
                });
            }
            return content;
        };

        return {
            getContent: getContent,
        };
    };
    return {
        createInstance: createInstance
    };
}])

.factory('MotionCatalogContentProvider', [
    'gettextCatalog',
    'PDFLayout',
    'Category',
    'Config',
    function(gettextCatalog, PDFLayout, Category, Config) {

    /**
    * Constructor
    * @function
    * @param {object} allMotions - A sorted array of all motions to parse
    * @param {object} $scope - Current $scope
    */
    var createInstance = function(allMotions, $scope) {

        var title = PDFLayout.createTitle(
                Config.translate(Config.get('motions_export_title').value)
        );

        var createPreamble = function() {
            var preambleText = Config.get('motions_export_preamble').value;
            if (preambleText) {
                return {
                    text: preambleText,
                    style: "preamble"
                };
            } else {
                return "";
            }
        };

        var createTOContent = function() {
            var heading = {
                text: gettextCatalog.getString("Table of contents"),
                style: "heading2"
            };

            var toc = [];
            angular.forEach(allMotions, function(motion) {
                var identifier = motion.getIdentifier() ? motion.getIdentifier() : '';
                toc.push(
                    {
                        columns: [
                            {
                                text: identifier,
                                style: 'tableofcontent',
                                width: 70
                            },
                            {
                                text: motion.getTitle(),
                                style: 'tableofcontent'
                            }
                        ]
                    }
                );
            });

            return [
                heading,
                toc,
                PDFLayout.addPageBreak()
            ];
        };

        // function to create the table of catergories (if any)
        var createTOCategories = function() {
            var categories = [];
            _.forEach(allMotions, function(motion) {
                var category = motion.getCategory();
                if (category) {
                    categories.push(category);
                }
            });
            categories = _.uniqBy(categories, 'id');
            if (categories.length > 1) {
                var heading = {
                    text: gettextCatalog.getString("Categories"),
                    style: "heading2"
                };

                var toc = [];
                angular.forEach(_.orderBy(categories, ['prefix']), function(cat) {
                    toc.push(
                        {
                            columns: [
                                {
                                    text: cat.prefix,
                                    style: 'tableofcontent',
                                    width: 50
                                },
                                {
                                    text: cat.name,
                                    style: 'tableofcontent'
                                }
                            ]
                        }
                    );
                });

                return [
                    heading,
                    toc,
                    PDFLayout.addPageBreak()
                ];
            } else {
                // if there are no categories, return "empty string"
                // pdfmake takes "null" literally and throws an error
                return "";
            }
        };

        // returns the pure content of the motion, parseable by pdfmake
        var getContent = function() {
            var motionContent = [];
            angular.forEach(allMotions, function(motion, key) {
                motionContent.push(motion.getContent());
                if (key < allMotions.length - 1) {
                    motionContent.push(PDFLayout.addPageBreak());
                }
            });

            return [
                title,
                createPreamble(),
                createTOCategories(),
                createTOContent(),
                motionContent
            ];
        };
        return {
            getContent: getContent
        };
    };

    return {
        createInstance: createInstance
    };
}]);

}());
<|endoftext|>


<commit_before>Iron = {};
Iron.utils = {};

/**
 * Assert that the given condition is truthy and throw an error if not.
 */

Iron.utils.assert = function (condition, msg) {
  if (!condition)
    throw new Error(msg);
};

/**
 * Print a warning message to the console if the console is defined.
 */
Iron.utils.warn = function (condition, msg) {
  if (!condition)
    console && console.warn && console.warn(msg);
};

/**
 * Given a target object and a property name, if the value of that property is
 * undefined, set a default value and return it. If the value is already
 * defined, return the existing value.
 */
Iron.utils.defaultValue = function (target, prop, value) {
  if (typeof target[prop] === 'undefined') {
    target[prop] = value;
    return value;
  } else {
    return target[prop]
  }
};

/**
 * Make one constructor function inherit from another. Optionally provide
 * prototype properties for the child.
 *
 * @param {Function} Child The child constructor function.
 * @param {Function} Parent The parent constructor function.
 * @param {Object} [props] Prototype properties to add to the child
 */
Iron.utils.inherits = function (Child, Parent, props) {
  Iron.utils.assert(typeof Child !== "undefined", "Child is undefined in inherits function");
  Iron.utils.assert(typeof Parent !== "undefined", "Parent is undefined in inherits function");

  // copy static fields
  for (var key in Parent) {
    if (_.has(Parent, key))
      Child[key] = EJSON.clone(Parent[key]);
  }

  var Middle = function () {
    this.constructor = Child;
  };

  // hook up the proto chain
  Middle.prototype = Parent.prototype;
  Child.prototype = new Middle;
  Child.__super__ = Parent.prototype;

  // copy over the prototype props
  if (_.isObject(props))
    _.extend(Child.prototype, props);

  return Child;
};

/**
 * Create a new constructor function that inherits from Parent and copy in the
 * provided prototype properties.
 *
 * @param {Function} Parent The parent constructor function.
 * @param {Object} [props] Prototype properties to add to the child
 */
Iron.utils.extend = function (Parent, props) {
  props = props || {};

  var ctor = function () {
    // automatically call the parent constructor if a new one
    // isn't provided.
    var constructor;
    if (_.has(props, 'constructor'))
      constructor = props.constructor
    else
      constructor = ctor.__super__.constructor;

    constructor.apply(this, arguments);
  };

  return Iron.utils.inherits(ctor, Parent, props);
};

/**
 * Either window in the browser or global in NodeJS.
 */
Iron.utils.global = (function () {
  return Meteor.isClient ? window : global;
})();

/**
 * Ensure a given namespace exists and assign it to the given value or
 * return the existing value.
 */
Iron.utils.namespace = function (namespace, value) {
  var global = Iron.utils.global;
  var parts;
  var part;
  var name;
  var ptr;

  Iron.utils.assert(typeof namespace === 'string', "namespace must be a string");

  parts = namespace.split('.');
  name = parts.pop();
  ptr = global;

  for (var i = 0; i < parts.length; i++) {
    part = parts[i];
    ptr = ptr[part] = ptr[part] || {};
  }

  if (arguments.length === 2) {
    ptr[name] = value;
    return value;
  } else {
    return ptr[name];
  }
};

/**
 * Returns the resolved value at the given namespace or the value itself if it's
 * not a string.
 *
 * Example:
 *
 * var Iron = {};
 * Iron.foo = {};
 *
 * var baz = Iron.foo.baz = {};
 * Iron.utils.resolve("Iron.foo.baz") === baz
 */
Iron.utils.resolve = function (nameOrValue) {
  var global = Iron.utils.global;
  var parts;
  var ptr;

  if (typeof nameOrValue === 'string') {
    parts = nameOrValue.split('.');
    ptr = global;
    for (var i = 0; i < parts.length; i++) {
      ptr = ptr[parts[i]];
      if (!ptr)
        return undefined;
    }
  } else {
    ptr = nameOrValue;
  }

  // final position of ptr should be the resolved value
  return ptr;
};

/**
 * Capitalize a string.
 */
Iron.utils.capitalize = function (str) {
  return str.charAt(0).toUpperCase() + str.slice(1, str.length);
};

/**
 * Convert a string to class case.
 */
Iron.utils.classCase = function (str) {
  var re = /_|-|\.|\//;

  if (!str)
    return '';

  return _.map(str.split(re), function (word) {
    return Iron.utils.capitalize(word);
  }).join('');
};

/**
 * Convert a string to camel case.
 */
Iron.utils.camelCase = function (str) {
  var output = Iron.utils.classCase(str);
  output = output.charAt(0).toLowerCase() + output.slice(1, output.length);
  return output;
};

/**
 * deprecatation notice to the user which can be a string or object
 * of the form:
 *
 * {
 *  name: 'somePropertyOrMethod',
 *  where: 'RouteController',
 *  instead: 'someOtherPropertyOrMethod',
 *  message: ':name is deprecated. Please use :instead instead'
 * }
 */
Iron.utils.notifyDeprecated = function (info) {
  var name;
  var instead;
  var message;
  var where;
  var defaultMessage = "[:where] ':name' is deprecated. Please use ':instead' instead.";

  if (_.isObject(info)) {
    name = info.name;
    instead = info.instead;
    message = info.message || defaultMessage;
    where = info.where || 'IronRouter';
  } else {
    message = info;
    name = '';
    instead = '';
    where = '';
  }

  if (typeof console !== 'undefined' && console.warn) {
    console.warn(
      '<deprecated> ' +
      message
      .replace(':name', name)
      .replace(':instead', instead)
      .replace(':where', where) +
      ' ' +
      (new Error).stack
    );
  }
};

Iron.utils.withDeprecatedNotice = function (info, fn, thisArg) {
  return function () {
    Utils.notifyDeprecated(info);
    return fn && fn.apply(thisArg || this, arguments);
  };
};

// so we can do this:
//   getController: function () {
//    ...
//   }.deprecate({...})
Function.prototype.deprecate = function (info) {
  var fn = this;
  return Iron.utils.withDeprecatedNotice(info, fn);
};

/**
 * Returns a function that can be used to log debug messages for a given
 * package.
 */
Iron.utils.debug = function (package) {
  Iron.utils.assert(typeof package === 'string', "debug requires a package name");

  return function debug (/* args */) {
    if (console && console.log && Iron.debug === true) {
      var msg = _.toArray(arguments).join(' ');
      console.log("%c<" + package + "> %c" + msg, "color: #999;", "color: #000;");
    }
  };
};

// make sure Iron ends up in the global namespace
Iron.utils.global.Iron = Iron;
<commit_msg>add get method to Iron.utils<commit_after>Iron = {};
Iron.utils = {};

/**
 * Assert that the given condition is truthy and throw an error if not.
 */

Iron.utils.assert = function (condition, msg) {
  if (!condition)
    throw new Error(msg);
};

/**
 * Print a warning message to the console if the console is defined.
 */
Iron.utils.warn = function (condition, msg) {
  if (!condition)
    console && console.warn && console.warn(msg);
};

/**
 * Given a target object and a property name, if the value of that property is
 * undefined, set a default value and return it. If the value is already
 * defined, return the existing value.
 */
Iron.utils.defaultValue = function (target, prop, value) {
  if (typeof target[prop] === 'undefined') {
    target[prop] = value;
    return value;
  } else {
    return target[prop]
  }
};

/**
 * Make one constructor function inherit from another. Optionally provide
 * prototype properties for the child.
 *
 * @param {Function} Child The child constructor function.
 * @param {Function} Parent The parent constructor function.
 * @param {Object} [props] Prototype properties to add to the child
 */
Iron.utils.inherits = function (Child, Parent, props) {
  Iron.utils.assert(typeof Child !== "undefined", "Child is undefined in inherits function");
  Iron.utils.assert(typeof Parent !== "undefined", "Parent is undefined in inherits function");

  // copy static fields
  for (var key in Parent) {
    if (_.has(Parent, key))
      Child[key] = EJSON.clone(Parent[key]);
  }

  var Middle = function () {
    this.constructor = Child;
  };

  // hook up the proto chain
  Middle.prototype = Parent.prototype;
  Child.prototype = new Middle;
  Child.__super__ = Parent.prototype;

  // copy over the prototype props
  if (_.isObject(props))
    _.extend(Child.prototype, props);

  return Child;
};

/**
 * Create a new constructor function that inherits from Parent and copy in the
 * provided prototype properties.
 *
 * @param {Function} Parent The parent constructor function.
 * @param {Object} [props] Prototype properties to add to the child
 */
Iron.utils.extend = function (Parent, props) {
  props = props || {};

  var ctor = function () {
    // automatically call the parent constructor if a new one
    // isn't provided.
    var constructor;
    if (_.has(props, 'constructor'))
      constructor = props.constructor
    else
      constructor = ctor.__super__.constructor;

    constructor.apply(this, arguments);
  };

  return Iron.utils.inherits(ctor, Parent, props);
};

/**
 * Either window in the browser or global in NodeJS.
 */
Iron.utils.global = (function () {
  return Meteor.isClient ? window : global;
})();

/**
 * Ensure a given namespace exists and assign it to the given value or
 * return the existing value.
 */
Iron.utils.namespace = function (namespace, value) {
  var global = Iron.utils.global;
  var parts;
  var part;
  var name;
  var ptr;

  Iron.utils.assert(typeof namespace === 'string', "namespace must be a string");

  parts = namespace.split('.');
  name = parts.pop();
  ptr = global;

  for (var i = 0; i < parts.length; i++) {
    part = parts[i];
    ptr = ptr[part] = ptr[part] || {};
  }

  if (arguments.length === 2) {
    ptr[name] = value;
    return value;
  } else {
    return ptr[name];
  }
};

/**
 * Returns the resolved value at the given namespace or the value itself if it's
 * not a string.
 *
 * Example:
 *
 * var Iron = {};
 * Iron.foo = {};
 *
 * var baz = Iron.foo.baz = {};
 * Iron.utils.resolve("Iron.foo.baz") === baz
 */
Iron.utils.resolve = function (nameOrValue) {
  var global = Iron.utils.global;
  var parts;
  var ptr;

  if (typeof nameOrValue === 'string') {
    parts = nameOrValue.split('.');
    ptr = global;
    for (var i = 0; i < parts.length; i++) {
      ptr = ptr[parts[i]];
      if (!ptr)
        return undefined;
    }
  } else {
    ptr = nameOrValue;
  }

  // final position of ptr should be the resolved value
  return ptr;
};

/**
 * Capitalize a string.
 */
Iron.utils.capitalize = function (str) {
  return str.charAt(0).toUpperCase() + str.slice(1, str.length);
};

/**
 * Convert a string to class case.
 */
Iron.utils.classCase = function (str) {
  var re = /_|-|\.|\//;

  if (!str)
    return '';

  return _.map(str.split(re), function (word) {
    return Iron.utils.capitalize(word);
  }).join('');
};

/**
 * Convert a string to camel case.
 */
Iron.utils.camelCase = function (str) {
  var output = Iron.utils.classCase(str);
  output = output.charAt(0).toLowerCase() + output.slice(1, output.length);
  return output;
};

/**
 * deprecatation notice to the user which can be a string or object
 * of the form:
 *
 * {
 *  name: 'somePropertyOrMethod',
 *  where: 'RouteController',
 *  instead: 'someOtherPropertyOrMethod',
 *  message: ':name is deprecated. Please use :instead instead'
 * }
 */
Iron.utils.notifyDeprecated = function (info) {
  var name;
  var instead;
  var message;
  var where;
  var defaultMessage = "[:where] ':name' is deprecated. Please use ':instead' instead.";

  if (_.isObject(info)) {
    name = info.name;
    instead = info.instead;
    message = info.message || defaultMessage;
    where = info.where || 'IronRouter';
  } else {
    message = info;
    name = '';
    instead = '';
    where = '';
  }

  if (typeof console !== 'undefined' && console.warn) {
    console.warn(
      '<deprecated> ' +
      message
      .replace(':name', name)
      .replace(':instead', instead)
      .replace(':where', where) +
      ' ' +
      (new Error).stack
    );
  }
};

Iron.utils.withDeprecatedNotice = function (info, fn, thisArg) {
  return function () {
    Utils.notifyDeprecated(info);
    return fn && fn.apply(thisArg || this, arguments);
  };
};

// so we can do this:
//   getController: function () {
//    ...
//   }.deprecate({...})
Function.prototype.deprecate = function (info) {
  var fn = this;
  return Iron.utils.withDeprecatedNotice(info, fn);
};

/**
 * Returns a function that can be used to log debug messages for a given
 * package.
 */
Iron.utils.debug = function (package) {
  Iron.utils.assert(typeof package === 'string', "debug requires a package name");

  return function debug (/* args */) {
    if (console && console.log && Iron.debug === true) {
      var msg = _.toArray(arguments).join(' ');
      console.log("%c<" + package + "> %c" + msg, "color: #999;", "color: #000;");
    }
  };
};

/*
 * Meteor's version of this function is broke.
 */
Iron.utils.get = function (obj /*, arguments */) {
  for (var i = 1; i < arguments.length; i++) {
    if (!obj || !(arguments[i] in obj))
      return undefined;
    obj = obj[arguments[i]];
  }
  return obj;
};

// make sure Iron ends up in the global namespace
Iron.utils.global.Iron = Iron;
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */

'use strict';

var dimensions = document.querySelector('#dimensions');
var video = document.querySelector('video');
var stream;

var vgaButton = document.querySelector('#vga');
var qvgaButton = document.querySelector('#qvga');
var hdButton = document.querySelector('#hd');
var fullHdButton = document.querySelector('#full-hd');

vgaButton.onclick = function() {
  getMedia(vgaConstraints);
};

qvgaButton.onclick = function() {
  getMedia(qvgaConstraints);
};

hdButton.onclick = function() {
  getMedia(hdConstraints);
};

fullHdButton.onclick = function() {
  getMedia(fullHdConstraints);
};

var qvgaConstraints = {
  video: {width: {exact: 320}, height: {exact: 240}}
};

var vgaConstraints = {
  video: {width: {exact: 640}, height: {exact: 480}}
};

var hdConstraints = {
  video: {width: 1280, height: 720}
};

var fullHdConstraints = {
  video: {width: {exact: 1920}, height: {exact: 1080}}
};

function successCallback(stream) {
  window.stream = stream; // stream available to console
  video.src = window.URL.createObjectURL(stream);
}

function errorCallback(error) {
  console.log('navigator.getUserMedia error: ', error);
}

function displayVideoDimensions() {
  if (!video.videoWidth) {
    setTimeout(displayVideoDimensions, 500);
  }
  dimensions.innerHTML = 'Actual video dimensions: ' + video.videoWidth +
    'x' + video.videoHeight + 'px.';
}

video.onloadedmetadata = displayVideoDimensions;

function getMedia(constraints) {
  if (stream) {
    video.src = null;
    stream.stop();
  }
  setTimeout(function() {
    navigator.getUserMedia(constraints, successCallback, errorCallback);
  }, (stream ? 200 : 0));
}
<commit_msg>Use attachMediaStream() from adapter.js<commit_after>/*
 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */

'use strict';

var dimensions = document.querySelector('#dimensions');
var video = document.querySelector('video');
var stream;

var vgaButton = document.querySelector('#vga');
var qvgaButton = document.querySelector('#qvga');
var hdButton = document.querySelector('#hd');
var fullHdButton = document.querySelector('#full-hd');

vgaButton.onclick = function() {
  getMedia(vgaConstraints);
};

qvgaButton.onclick = function() {
  getMedia(qvgaConstraints);
};

hdButton.onclick = function() {
  getMedia(hdConstraints);
};

fullHdButton.onclick = function() {
  getMedia(fullHdConstraints);
};

var qvgaConstraints = {
  video: {width: {exact: 320}, height: {exact: 240}}
};

var vgaConstraints = {
  video: {width: {exact: 640}, height: {exact: 480}}
};

var hdConstraints = {
  video: {width: 1280, height: 720}
};

var fullHdConstraints = {
  video: {width: {exact: 1920}, height: {exact: 1080}}
};

function successCallback(stream) {
  window.stream = stream; // stream available to console
  attachMediaStream(video, stream);
}

function errorCallback(error) {
  console.log('navigator.getUserMedia error: ', error);
}

function displayVideoDimensions() {
  if (!video.videoWidth) {
    setTimeout(displayVideoDimensions, 500);
  }
  dimensions.innerHTML = 'Actual video dimensions: ' + video.videoWidth +
    'x' + video.videoHeight + 'px.';
}

video.onloadedmetadata = displayVideoDimensions;

function getMedia(constraints) {
  if (stream) {
    video.src = null;
    stream.stop();
  }
  setTimeout(function() {
    navigator.getUserMedia(constraints, successCallback, errorCallback);
  }, (stream ? 200 : 0));
}
<|endoftext|>


<commit_before>const JSONParser = require('stream-json/Parser')
const deepmerge = require('deepmerge')
const SwaggerParser = require('swagger-parser')

const { findMatchingUrls, fillUrlFromPartial } = require('./openapi/url.js')

const OPENAPI_SPEC_PATHS = ['openapi.json', 'openapi/v1', 'openapi/v2']
const MAXIMUM_SCHEMA_DEPTH = 1000

const postfixWith = postfix => str => str + postfix
const prefixWith = prefix => str => prefix + str

const arrayStartsWith = (a, b) => {
  return b.every((v, idx) => v === a[idx])
}

class OpenAPIPlugin {
  constructor ({ specEndpoints }) {
    this.spec = undefined
    this.specEndpoints = specEndpoints ? [specEndpoints].flat() : OPENAPI_SPEC_PATHS
    this.paths = []
    this.methods = []
    this.pathsByMethod = {}
    this.paths = []
    this.schemaByPathMethod = {}
    this.schemaPropertiesByPathMethod = {}
    this.methods = []
  }

  async onstart (httpConsole) {
    let spec
    const swaggerParser = new SwaggerParser()

    this.httpConsole = httpConsole
    // Perform OpenAPI autodiscovery.
    for (const path of this.specEndpoints) {
      try {
        const res = await this.httpConsole.got(path, { responseType: 'json' })
        if (res.statusCode === 200)
          spec = res.body
      }
      catch (e) {
        httpConsole.output.write(`Warning: error fetching OpenAPI spec: ${e.message}\n`)
      }
    }

    if (spec) {
      this.spec = await swaggerParser.dereference(spec)

      this.paths = Object.keys(this.spec.paths)

      // We're iterating into
      //
      // paths:
      //   /url: <- path
      //     get: ...
      //     post: ...
      //     ^ methods
      for (const [path, methods] of Object.entries(this.spec.paths)) {
        for (const method of Object.keys(methods)) {

          if (method === 'parameters') continue

          const addSchema = (schema) => {
            // This is an absolutely disgusting hack (but it works). Some APIs
            // will have cycles in them. For the time being, I can't be arsed
            // to develop any smart cycle detection here.
            let depth = 0

            const objectifyProperties = (schema) => {
              if (schema.type === 'object') {
                let ret = {}
                Object.entries(schema.properties || {}).forEach(([prop, propSchema]) => {

                  ++depth
                  if (depth >= MAXIMUM_SCHEMA_DEPTH) return { type: propSchema.type }

                  ret[prop] = objectifyProperties(propSchema)
                })
                return ret
              }
              else return { type: schema.type }
            }

            if (!this.schemaByPathMethod[path]) this.schemaByPathMethod[path] = {}
            this.schemaByPathMethod[path][method] = schema

            if (!this.schemaPropertiesByPathMethod[path])
              this.schemaPropertiesByPathMethod[path] = {}

            this.schemaPropertiesByPathMethod[path][method] = deepmerge(
              this.schemaPropertiesByPathMethod[path][method],
              objectifyProperties(schema)
            )
          }

          if (!this.pathsByMethod[method]) this.pathsByMethod[method] = []
          this.pathsByMethod[method].push(path)

          const operation = methods[method]
          const content = operation.requestBody && operation.requestBody.content
          const schema = content && content['application/json'] && content['application/json'].schema

          if (schema) addSchema(schema)

          const params = [
            ...(methods.parameters || []),
            ...(operation.parameters || [])
          ]

          const paramsByType = params.reduce((acc, param) => {
            if (!acc[param.in]) acc[param.in] = []
            acc[param.in].push(param)
            return acc
          }, {})

          if (paramsByType.body)
            paramsByType.body.forEach(body => addSchema(body.schema))
        }
      }
    }
  }

  completeMethod (partial, callback) {
    const hits = this.methods.filter(method => method.startsWith(partial.toLowerCase()))
    callback(null, (hits.length ? hits : this.methods).map(postfixWith(' ')))
  }

  completeUrl (method, partial, callback) {
    const paths = this.pathsByMethod[method] || this.paths

    const hits = findMatchingUrls(paths, partial, true)
    callback(null, hits.map(hit => fillUrlFromPartial(hit, partial)))
  }

  completeCommand (partial, callback) {
    const [method, url] = partial.split(' ').map(s => s.trim())
    if (typeof url !== 'string') this.completeMethod(partial, callback)
    else {
      this.completeUrl(method, url, (err, urlCompletions) => {
        if (err) return callback(err)
        callback(null, urlCompletions.map(prefixWith(method + ' ')))
      })
    }
  }

  completeBody (cmd, partial, callback) {
    const { method, url } = cmd
    const parser = new JSONParser()

    const urlMatches = findMatchingUrls(Object.keys(this.schemaPropertiesByPathMethod), url)
    if (urlMatches.length !== 1) return callback(null, [])

    const properties = this.schemaPropertiesByPathMethod[urlMatches[0]] &&
      this.schemaPropertiesByPathMethod[urlMatches[0]][method]

    if (!properties) return callback(null, [])

    const onparsed = () => {
      if (readingKey) {
        let prop = properties

        for (const key of currentStack.flat().filter(Boolean)) {
          prop = prop[key]
        }

        if (!prop) return callback(null, [])

        const partialKey = readingKey.join('')
        const proposals = Object.keys(prop)
          // The `typeof prop[key] !== 'string'` eliminates the final `{ "type": "string" }`
          // from showing up.
          .filter(key => key.startsWith(partialKey) && typeof prop[key] !== 'string')

        return callback(null,
          proposals
            .map(prefixWith(partial.slice(0, -partialKey.length)))
            .map(postfixWith('": '))
            .map((proposal, idx) => {
              const descriptor = prop[proposals[idx]]
              if (descriptor.type === 'string') return proposal + '"'
              if (typeof descriptor === 'object') return proposal + '{'
              return proposal
            })
        )
      }
    }

    let currentStack = []
    let readingKey = false

    parser.on('data', (data) => {
      if (readingKey) {
        if (data.name === 'stringChunk') readingKey.push(data.value)
        else if (data.name === 'endKey') {
          currentStack.push(readingKey.join(''))
          readingKey = false
        }
      }

      if (data.name === 'startKey') {
        readingKey = []
        currentStack.pop()
      }
      else if (data.name === 'startObject') currentStack.push([])
      else if (data.name === 'endObject') currentStack.pop()
    })

    parser.on('error', onparsed)
    parser.on('end', onparsed)

    parser.end(partial)
    // We can't `end` here, because we're dealing with partial JSON and the parser
    // will throw an error. It seems cleaner to use the

    callback(null, [])
  }
}

module.exports = OpenAPIPlugin
<commit_msg>Re-add method completion<commit_after>const JSONParser = require('stream-json/Parser')
const deepmerge = require('deepmerge')
const SwaggerParser = require('swagger-parser')

const { findMatchingUrls, fillUrlFromPartial } = require('./openapi/url.js')

const OPENAPI_SPEC_PATHS = ['openapi.json', 'openapi/v1', 'openapi/v2']
const MAXIMUM_SCHEMA_DEPTH = 1000

const postfixWith = postfix => str => str + postfix
const prefixWith = prefix => str => prefix + str

const arrayStartsWith = (a, b) => {
  return b.every((v, idx) => v === a[idx])
}

class OpenAPIPlugin {
  constructor ({ specEndpoints }) {
    this.spec = undefined
    this.specEndpoints = specEndpoints ? [specEndpoints].flat() : OPENAPI_SPEC_PATHS
    this.paths = []
    this.methods = new Set()
    this.pathsByMethod = {}
    this.paths = []
    this.schemaByPathMethod = {}
    this.schemaPropertiesByPathMethod = {}
  }

  async onstart (httpConsole) {
    let spec
    const swaggerParser = new SwaggerParser()

    this.httpConsole = httpConsole
    // Perform OpenAPI autodiscovery.
    for (const path of this.specEndpoints) {
      try {
        const res = await this.httpConsole.got(path, { responseType: 'json' })
        if (res.statusCode === 200)
          spec = res.body
      }
      catch (e) {
        httpConsole.output.write(`Warning: error fetching OpenAPI spec: ${e.message}\n`)
      }
    }

    if (spec) {
      this.spec = await swaggerParser.dereference(spec)

      this.paths = Object.keys(this.spec.paths)

      // We're iterating into
      //
      // paths:
      //   /url: <- path
      //     get: ...
      //     post: ...
      //     ^ methods
      for (const [path, methods] of Object.entries(this.spec.paths)) {
        for (const method of Object.keys(methods)) {

          if (method === 'parameters') continue

          this.methods.add(method)

          const addSchema = (schema) => {
            // This is an absolutely disgusting hack (but it works). Some APIs
            // will have cycles in them. For the time being, I can't be arsed
            // to develop any smart cycle detection here.
            let depth = 0

            const objectifyProperties = (schema) => {
              if (schema.type === 'object') {
                let ret = {}
                Object.entries(schema.properties || {}).forEach(([prop, propSchema]) => {

                  ++depth
                  if (depth >= MAXIMUM_SCHEMA_DEPTH) return { type: propSchema.type }

                  ret[prop] = objectifyProperties(propSchema)
                })
                return ret
              }
              else return { type: schema.type }
            }

            if (!this.schemaByPathMethod[path]) this.schemaByPathMethod[path] = {}
            this.schemaByPathMethod[path][method] = schema

            if (!this.schemaPropertiesByPathMethod[path])
              this.schemaPropertiesByPathMethod[path] = {}

            this.schemaPropertiesByPathMethod[path][method] = deepmerge(
              this.schemaPropertiesByPathMethod[path][method],
              objectifyProperties(schema)
            )
          }

          if (!this.pathsByMethod[method]) this.pathsByMethod[method] = []
          this.pathsByMethod[method].push(path)

          const operation = methods[method]
          const content = operation.requestBody && operation.requestBody.content
          const schema = content && content['application/json'] && content['application/json'].schema

          if (schema) addSchema(schema)

          const params = [
            ...(methods.parameters || []),
            ...(operation.parameters || [])
          ]

          const paramsByType = params.reduce((acc, param) => {
            if (!acc[param.in]) acc[param.in] = []
            acc[param.in].push(param)
            return acc
          }, {})

          if (paramsByType.body)
            paramsByType.body.forEach(body => addSchema(body.schema))
        }
      }
    }
  }

  completeMethod (partial, callback) {
    const methods = [...this.methods]
    const hits = methods.filter(method => method.startsWith(partial.toLowerCase()))
    callback(null, (hits.length ? hits : methods).map(postfixWith(' ')))
  }

  completeUrl (method, partial, callback) {
    const paths = this.pathsByMethod[method] || this.paths

    const hits = findMatchingUrls(paths, partial, true)
    callback(null, hits.map(hit => fillUrlFromPartial(hit, partial)))
  }

  completeCommand (partial, callback) {
    const [method, url] = partial.split(' ').map(s => s.trim())
    if (typeof url !== 'string') this.completeMethod(partial, callback)
    else {
      this.completeUrl(method, url, (err, urlCompletions) => {
        if (err) return callback(err)
        callback(null, urlCompletions.map(prefixWith(method + ' ')))
      })
    }
  }

  completeBody (cmd, partial, callback) {
    const { method, url } = cmd
    const parser = new JSONParser()

    const urlMatches = findMatchingUrls(Object.keys(this.schemaPropertiesByPathMethod), url)
    if (urlMatches.length !== 1) return callback(null, [])

    const properties = this.schemaPropertiesByPathMethod[urlMatches[0]] &&
      this.schemaPropertiesByPathMethod[urlMatches[0]][method]

    if (!properties) return callback(null, [])

    const onparsed = () => {
      if (readingKey) {
        let prop = properties

        for (const key of currentStack.flat().filter(Boolean)) {
          prop = prop[key]
        }

        if (!prop) return callback(null, [])

        const partialKey = readingKey.join('')
        const proposals = Object.keys(prop)
          // The `typeof prop[key] !== 'string'` eliminates the final `{ "type": "string" }`
          // from showing up.
          .filter(key => key.startsWith(partialKey) && typeof prop[key] !== 'string')

        return callback(null,
          proposals
            .map(prefixWith(partial.slice(0, -partialKey.length)))
            .map(postfixWith('": '))
            .map((proposal, idx) => {
              const descriptor = prop[proposals[idx]]
              if (descriptor.type === 'string') return proposal + '"'
              if (typeof descriptor === 'object') return proposal + '{'
              return proposal
            })
        )
      }
    }

    let currentStack = []
    let readingKey = false

    parser.on('data', (data) => {
      if (readingKey) {
        if (data.name === 'stringChunk') readingKey.push(data.value)
        else if (data.name === 'endKey') {
          currentStack.push(readingKey.join(''))
          readingKey = false
        }
      }

      if (data.name === 'startKey') {
        readingKey = []
        currentStack.pop()
      }
      else if (data.name === 'startObject') currentStack.push([])
      else if (data.name === 'endObject') currentStack.pop()
    })

    parser.on('error', onparsed)
    parser.on('end', onparsed)

    parser.end(partial)
    // We can't `end` here, because we're dealing with partial JSON and the parser
    // will throw an error. It seems cleaner to use the

    callback(null, [])
  }
}

module.exports = OpenAPIPlugin
<|endoftext|>


<commit_before>
var homeController = require("./home/controller");
var assignmentController = require("./assignments/controller");
var assignmentDetailsController = require("./assignment/controller");
var assignmentGroupController = require("./assignment_create_group/controller");
var assignmentLoginController = require("./assignment_group_login/controller");
var courseController = require("./course/controller");
var gradesController = require("./grades/controller");

module.exports = angular.module('app.views.student', [
    homeController.name,
    assignmentController.name,
    courseController.name,
    gradesController.name,
    assignmentDetailsController.name,
    assignmentGroupController.name,
    assignmentLoginController.name
]);
<commit_msg>ADD: assignment questions import<commit_after>
var homeController = require("./home/controller");
var assignmentController = require("./assignments/controller");
var assignmentDetailsController = require("./assignment/controller");
var assignmentGroupController = require("./assignment_create_group/controller");
var assignmentLoginController = require("./assignment_group_login/controller");
var assignmentQuestionsController = require('./assignment_questions/controller');
var courseController = require("./course/controller");
var gradesController = require("./grades/controller");

module.exports = angular.module('app.views.student', [
    homeController.name,
    assignmentController.name,
    courseController.name,
    gradesController.name,
    assignmentDetailsController.name,
    assignmentGroupController.name,
    assignmentLoginController.name,
    assignmentQuestionsController.name
]);
<|endoftext|>


<commit_before>/*#ifndef(UMD)*/
"use strict";
/*exported _GPF_HOST_BROWSER*/ // gpf.HOST_BROWSER
/*exported _GPF_HOST_NODEJS*/ // gpf.HOST_NODEJS
/*exported _GPF_HOST_PHANTOMJS*/ // gpf.HOST_PHANTOMJS
/*exported _GPF_HOST_RHINO*/ // gpf.HOST_RHINO
/*exported _GPF_HOST_UNKNOWN*/ // gpf.HOST_UNKNOWN
/*exported _GPF_HOST_WSCRIPT*/ // gpf.HOST_WSCRIPT
/*exported _gpfDosPath*/ // DOS-like path
/*exported _gpfEmptyFunc*/ // An empty function
/*exported _gpfExit*/ // Exit function
/*exported _gpfHost*/ // Host type
/*exported _gpfIgnore*/ // Helper to remove unused parameter warning
/*exported _gpfInBrowser*/ // The current host is a browser like
/*exported _gpfInNode*/ // The current host is a nodeJS like
/*exported _gpfMainContext*/ // Main context object
/*exported _gpfMsFSO*/ // Scripting.FileSystemObject activeX
/*exported _gpfNodeFs*/ // Node require("fs")
/*exported _gpfNodePath*/ // Node require("path")
/*exported _gpfVersion*/ // GPF version
/*exported _gpfWebDocument*/ // Browser document object
/*exported _gpfWebHead*/ // Browser head tag
/*exported _gpfWebWindow*/ // Browser window object
/*eslint-disable no-unused-vars*/
/*#endif*/

 /*eslint-disable no-invalid-this, no-useless-call*/ // this is used to grab the global context

// An empty function
function _gpfEmptyFunc () {}

var
    // GPF version
    _gpfVersion = "0.1.5-alpha",

    // Host type constants
    _GPF_HOST_BROWSER               = "browser",
    /*jshint browser: true*/
    /*eslint-env browser*/

    _GPF_HOST_NODEJS                = "nodejs",
    /*jshint node: true*/
    /*eslint-env node*/

    _GPF_HOST_PHANTOMJS             = "phantomjs",
    /*jshint phantom: true*/
    /*eslint-env phantomjs*/

    _GPF_HOST_RHINO                 = "rhino",
    /*jshint rhino: true*/
    /*eslint-env rhino*/

    _GPF_HOST_UNKNOWN               = "unknown",

    _GPF_HOST_WSCRIPT               = "wscript",
    /*jshint wsh: true*/
    /*eslint-env wsh*/

    // Host type, see _GPF_HOST_xxx
    _gpfHost = _GPF_HOST_UNKNOWN,

    // Indicates that paths are DOS-like (i.e. case insensitive with /)
    _gpfDosPath = false,

    /*jshint -W040*/ // This is the common way to get the global context
    // Main context object
    _gpfMainContext = this, //eslint-disable-line consistent-this
    /*jshint +W040*/

    /**
     * Helper to ignore unused parameter
     *
     * @param {*} param
     */
    /*gpf:nop*/ _gpfIgnore = _gpfEmptyFunc,

    /**
     * Exit function
     *
     * @param {Number} code
     */
    _gpfExit = _gpfEmptyFunc,

    // The current host is a nodeJS like
    _gpfInNode = false,

    // The current host is a browser like
    _gpfInBrowser = false,

    /**
     * Browser window object
     *
     * @type {Object}
     */
    _gpfWebWindow,

    /**
     * Browser document object
     *
     * @type {Object}
     */
    _gpfWebDocument,

    /**
     * Browser head tag
     *
     * @type {Object}
     */
    _gpfWebHead,

    /**
     * Scripting.FileSystemObject activeX
     *
     * @type {Object}
     */
    _gpfMsFSO,

    /**
     * Node require("fs")
     *
     * @type {Object}
     */
    _gpfNodeFs,

    /**
     * Node require("path")
     *
     * @type {Object}
     */
    _gpfNodePath;

/*#ifdef(DEBUG)*/

_gpfVersion += "-debug";

/*#endif*/

/*#ifndef(UMD)*/

/**
 * Synchronous read function
 *
 * @param {String} srcFileName
 * @return {String} content of the srcFileName
 */
var _gpfSyncReadForBoot;

/*#endif*/

/* Host detection */
/* istanbul ignore next */

// Microsoft cscript / wscript
if ("undefined" !== typeof WScript) {
    /*eslint-disable new-cap*/

    _gpfHost = _GPF_HOST_WSCRIPT;
    _gpfDosPath = true;
    _gpfMainContext = function () {
        return this;
    }.call(null);
    _gpfExit = function (code) {
        WScript.Quit(code);
    };

    // Define console APIs
    _gpfMainContext.console = {
        log: function (t) {
            WScript.Echo("    " + t);
        },
        info: function (t) {
            WScript.Echo("[?] " + t);
        },
        warn: function (t) {
            WScript.Echo("/!\\ " + t);
        },
        error: function (t) {
            WScript.Echo("(X) " + t);
        }
    };

/*#ifndef(UMD)*/

    _gpfMsFSO = new ActiveXObject("Scripting.FileSystemObject");

    _gpfSyncReadForBoot = function (srcFileName) {
        var srcFile = _gpfMsFSO.OpenTextFile(srcFileName),
            srcContent = srcFile.ReadAll();
        srcFile.Close();
        return srcContent;
    };

/*#endif*/

    /*eslint-enable new-cap*/
} else if ("undefined" !== typeof print && "undefined" !== typeof java) {
    _gpfHost = _GPF_HOST_RHINO;
    _gpfDosPath = false;
    _gpfMainContext = function () {
        return this;
    }.call(null);
    _gpfExit = function (code) {
        java.lang.System.exit(code);
    };

    // Define console APIs
    _gpfMainContext.console = {
        log: function (t) {
            print("    " + t);
        },
        info: function (t) {
            print("[?] " + t);
        },
        warn: function (t) {
            print("/!\\ " + t);
        },
        error: function (t) {
            print("(X) " + t);
        }
    };

/*#ifndef(UMD)*/

    _gpfSyncReadForBoot = readFile;

/*#endif*/

// PhantomJS
} else if ("undefined" !== typeof phantom && phantom.version) {
    _gpfHost = _GPF_HOST_PHANTOMJS;
    _gpfDosPath = require("fs").separator === "\\";
    _gpfMainContext = window;
    _gpfInNode = true;
    _gpfInBrowser = true;
    _gpfExit = phantom.exit;

/*#ifndef(UMD)*/

    _gpfNodeFs =  require("fs");

    _gpfSyncReadForBoot = function (srcFileName) {
        return _gpfNodeFs.read(srcFileName);
    };

/*#endif*/

// Nodejs
} else if ("undefined" !== typeof module && module.exports) {
    _gpfHost = _GPF_HOST_NODEJS;
    _gpfNodePath = require("path");
    _gpfDosPath = _gpfNodePath.sep === "\\";
    _gpfMainContext = global;
    _gpfInNode = true;
    _gpfExit = process.exit;

/*#ifndef(UMD)*/

    /*eslint-disable no-sync*/ // Simpler this way

    _gpfNodeFs =  require("fs");

    _gpfSyncReadForBoot = function (srcFileName) {
        return _gpfNodeFs.readFileSync(srcFileName).toString();
    };

/*#endif*/

// Browser
} else if ("undefined" !== typeof window) {
    _gpfHost = _GPF_HOST_BROWSER;
    _gpfMainContext = window;
    _gpfInBrowser = true;
    _gpfExit = _gpfEmptyFunc;
    _gpfWebWindow = window;
    _gpfWebDocument = document;
    _gpfWebHead = _gpfWebDocument.getElementsByTagName("head")[0] || _gpfWebDocument.documentElement;

/*#ifndef(UMD)*/

    _gpfSyncReadForBoot = function (srcFileName) {
        var xhr = new XMLHttpRequest();
        xhr.open("GET", srcFileName, false);
        xhr.send();
        return xhr.responseText;
    };

/*#endif*/

}

/*#ifndef(UMD)*/

_gpfMainContext.gpf = {
    internals: {} // To support testable internals
};

/*#endif*/

// Install host specifics (if any)
/* istanbul ignore else */ // Because tested with NodeJS
if (_gpfInNode) {
    gpf.node = {};
}
// Some web-related tools will be configured even if not in a browser, declare the namespace now
gpf.web = {};

// Returns the current version
gpf.version = function () {
    return _gpfVersion;
};

/**
 * Returns a string identifying the detected host
 *
 * @return {String}
 * - gpf.HOST_WSCRIPT for cscript and wscript
 * - gpf.HOST_NODEJS for nodejs
 * - gpf.HOST_PHANTOMJS for phantomjs
 * - gpf.HOST_BROWSER for any browser
 * - gpf.HOST_UNKNOWN if not detected
 */
gpf.host = function () {
    return _gpfHost;
};

/*#ifndef(UMD)*/

/**
 * Loading sources occurs here for the non UMD version.
 * UMD versions (debug / release) will have everything concatenated.
 */

/* istanbul ignore next */ // Handled the right way with NodeJS
// gpfSourcesPath - if defined - gives the relative path to sources
if ("undefined" === typeof gpfSourcesPath) {
    _gpfMainContext.gpfSourcesPath = "";
} else {
    var pathSep;
    if (_gpfDosPath) {
        pathSep = "\\";
    } else {
        pathSep = "/";
    }
    if (gpfSourcesPath.charAt(gpfSourcesPath.length - 1) !== pathSep) {
        gpfSourcesPath += pathSep;
    }
}

var _gpfSourcesContent = _gpfSyncReadForBoot(gpfSourcesPath + "sources.js");
/*jslint evil: true*/
eval(_gpfSourcesContent); //eslint-disable-line no-eval
/*jslint evil: false*/
var _gpfSources = gpf.sources(),
    _gpfAllContent = [],
    _gpfSourceIdx = 0,
    _gpfSourceModule;
for (_gpfSourceIdx = 0; _gpfSourceIdx < _gpfSources.length; ++_gpfSourceIdx) {
    _gpfSourceModule = _gpfSources[_gpfSourceIdx];
    if (!_gpfSourceModule) {
        break;
    }
    _gpfAllContent.push(_gpfSyncReadForBoot(gpfSourcesPath + _gpfSourceModule + ".js"));
}
/*jslint evil: true*/
eval(_gpfAllContent.join("\r\n")); //eslint-disable-line no-eval
/*jslint evil: false*/

/*#endif*/
<commit_msg>Boot from sources.json<commit_after>/*#ifndef(UMD)*/
"use strict";
/*exported _GPF_HOST_BROWSER*/ // gpf.HOST_BROWSER
/*exported _GPF_HOST_NODEJS*/ // gpf.HOST_NODEJS
/*exported _GPF_HOST_PHANTOMJS*/ // gpf.HOST_PHANTOMJS
/*exported _GPF_HOST_RHINO*/ // gpf.HOST_RHINO
/*exported _GPF_HOST_UNKNOWN*/ // gpf.HOST_UNKNOWN
/*exported _GPF_HOST_WSCRIPT*/ // gpf.HOST_WSCRIPT
/*exported _gpfDosPath*/ // DOS-like path
/*exported _gpfEmptyFunc*/ // An empty function
/*exported _gpfExit*/ // Exit function
/*exported _gpfHost*/ // Host type
/*exported _gpfIgnore*/ // Helper to remove unused parameter warning
/*exported _gpfInBrowser*/ // The current host is a browser like
/*exported _gpfInNode*/ // The current host is a nodeJS like
/*exported _gpfMainContext*/ // Main context object
/*exported _gpfMsFSO*/ // Scripting.FileSystemObject activeX
/*exported _gpfNodeFs*/ // Node require("fs")
/*exported _gpfNodePath*/ // Node require("path")
/*exported _gpfVersion*/ // GPF version
/*exported _gpfWebDocument*/ // Browser document object
/*exported _gpfWebHead*/ // Browser head tag
/*exported _gpfWebWindow*/ // Browser window object
/*eslint-disable no-unused-vars*/
/*#endif*/

// An empty function
function _gpfEmptyFunc () {}

var
    // GPF version
    _gpfVersion = "0.1.5-alpha",

    // Host type constants
    _GPF_HOST_BROWSER               = "browser",
    /*jshint browser: true*/
    /*eslint-env browser*/

    _GPF_HOST_NODEJS                = "nodejs",
    /*jshint node: true*/
    /*eslint-env node*/

    _GPF_HOST_PHANTOMJS             = "phantomjs",
    /*jshint phantom: true*/
    /*eslint-env phantomjs*/

    _GPF_HOST_RHINO                 = "rhino",
    /*jshint rhino: true*/
    /*eslint-env rhino*/

    _GPF_HOST_UNKNOWN               = "unknown",

    _GPF_HOST_WSCRIPT               = "wscript",
    /*jshint wsh: true*/
    /*eslint-env wsh*/

    // Host type, see _GPF_HOST_xxx
    _gpfHost = _GPF_HOST_UNKNOWN,

    // Indicates that paths are DOS-like (i.e. case insensitive with /)
    _gpfDosPath = false,

    /*jshint -W040*/ // This is the common way to get the global context
    // Main context object
    _gpfMainContext = this, //eslint-disable-line no-invalid-this, consistent-this
    /*jshint +W040*/

    /**
     * Helper to ignore unused parameter
     *
     * @param {*} param
     */
    /*gpf:nop*/ _gpfIgnore = _gpfEmptyFunc,

    /**
     * Exit function
     *
     * @param {Number} code
     */
    _gpfExit = _gpfEmptyFunc,

    // The current host is a nodeJS like
    _gpfInNode = false,

    // The current host is a browser like
    _gpfInBrowser = false,

    /**
     * Browser window object
     *
     * @type {Object}
     */
    _gpfWebWindow,

    /**
     * Browser document object
     *
     * @type {Object}
     */
    _gpfWebDocument,

    /**
     * Browser head tag
     *
     * @type {Object}
     */
    _gpfWebHead,

    /**
     * Scripting.FileSystemObject activeX
     *
     * @type {Object}
     */
    _gpfMsFSO,

    /**
     * Node require("fs")
     *
     * @type {Object}
     */
    _gpfNodeFs,

    /**
     * Node require("path")
     *
     * @type {Object}
     */
    _gpfNodePath;

/*#ifdef(DEBUG)*/

_gpfVersion += "-debug";

/*#endif*/

/*#ifndef(UMD)*/

_gpfVersion += "-source";

/**
 * Synchronous read function
 *
 * @param {String} srcFileName
 * @return {String} content of the srcFileName
 */
var _gpfSyncReadForBoot;

/*#endif*/

/* Host detection */
/* istanbul ignore next */

// Microsoft cscript / wscript
if ("undefined" !== typeof WScript) {
    _gpfHost = _GPF_HOST_WSCRIPT;
    _gpfDosPath = true;

/*#ifndef(UMD)*/
    /*eslint-disable new-cap*/

    _gpfMsFSO = new ActiveXObject("Scripting.FileSystemObject");

    _gpfSyncReadForBoot = function (srcFileName) {
        var srcFile = _gpfMsFSO.OpenTextFile(srcFileName),
            srcContent = srcFile.ReadAll();
        srcFile.Close();
        return srcContent;
    };

    /*eslint-enable new-cap*/
/*#endif*/

} else if ("undefined" !== typeof print && "undefined" !== typeof java) {
    _gpfHost = _GPF_HOST_RHINO;
    _gpfDosPath = false;

/*#ifndef(UMD)*/

    _gpfSyncReadForBoot = readFile;

/*#endif*/

// PhantomJS
} else if ("undefined" !== typeof phantom && phantom.version) {
    _gpfHost = _GPF_HOST_PHANTOMJS;
    _gpfDosPath = require("fs").separator === "\\";

/*#ifndef(UMD)*/

    _gpfNodeFs =  require("fs");

    _gpfSyncReadForBoot = function (srcFileName) {
        return _gpfNodeFs.read(srcFileName);
    };

/*#endif*/

// Nodejs
} else if ("undefined" !== typeof module && module.exports) {
    _gpfHost = _GPF_HOST_NODEJS;
    _gpfNodePath = require("path");
    _gpfDosPath = _gpfNodePath.sep === "\\";
    _gpfMainContext = global;

/*#ifndef(UMD)*/
    /*eslint-disable no-sync*/ // Simpler this way

    _gpfNodeFs =  require("fs");

    _gpfSyncReadForBoot = function (srcFileName) {
        return _gpfNodeFs.readFileSync(srcFileName).toString();
    };

/*#endif*/

// Browser
} else if ("undefined" !== typeof window) {
    _gpfHost = _GPF_HOST_BROWSER;
    _gpfMainContext = window;

/*#ifndef(UMD)*/

    _gpfSyncReadForBoot = function (srcFileName) {
        var xhr = new XMLHttpRequest();
        xhr.open("GET", srcFileName, false);
        xhr.send();
        return xhr.responseText;
    };

/*#endif*/

}

/*#ifndef(UMD)*/

/**
 * Loading sources occurs here for the non UMD version.
 * UMD versions (debug / release) will have everything concatenated.
 */

// Need to create the gpf name 'manually'
_gpfMainContext.gpf = {
    internals: {} // To support testable internals
};

// gpfSourcesPath - if defined - gives the relative path to sources
function _gpfGetSourcesPath () {
    var result = gpfSourcesPath,
        pathSep;
    /* istanbul ignore next */ // Handled the right way with NodeJS
    if ("undefined" === typeof result) {
        result = "";
    } else {
        if (_gpfDosPath) {
            pathSep = "\\";
        } else {
            pathSep = "/";
        }
        if (result.charAt(result.length - 1) !== pathSep) {
            result += pathSep;
        }
    }
    return result;
}

function _gpfLoadSources () { //jshint ignore:line
    /*jslint evil: true*/
    var sourcePath = _gpfGetSourcesPath(),
        sourceListContent = _gpfSyncReadForBoot(sourcePath + "sources.json"),
        _gpfSources,
        allContent = [],
        idx = 0,
        source;
    eval("_gpfSources = " + sourceListContent + ";"); //eslint-disable-line no-eval
    for (; idx < _gpfSources.length; ++idx) {
        source = _gpfSources[idx];
        if (source.load !== false) {
            allContent.push(_gpfSyncReadForBoot(sourcePath + source.name + ".js"));
        }
    }
    return allContent.join("\r\n");
}

/*jshint ignore:start*/ // Best way I found
eval(_gpfLoadSources()); //eslint-disable-line no-eval
/*jshint ignore:end*/

/*#endif*/

/**
 * Returns a string identifying the detected host
 *
 * @return {String}
 * - gpf.HOST_WSCRIPT for cscript and wscript
 * - gpf.HOST_NODEJS for nodejs
 * - gpf.HOST_PHANTOMJS for phantomjs
 * - gpf.HOST_BROWSER for any browser
 * - gpf.HOST_UNKNOWN if not detected
 */
gpf.host = function () {
    return _gpfHost;
};

// Returns the current version
gpf.version = function () {
    return _gpfVersion;
};
<|endoftext|>


<commit_before>/*
 * jemul8 - JavaScript x86 Emulator
 *
 * MODULE: Register class support
 *
 * ====
 *
 * Copyright 2013 jemul8.com (http://github.com/asmblah/jemul8)
 * Released under the MIT license
 * http://jemul8.com/MIT-LICENSE.txt
 */

/*jslint bitwise: true */
/*global define */
define([
	"js/util",
	"./decoder/register"
], function (
	util,
	DecoderRegister
) {
    "use strict";

	// Register (eg. CPU registers EAX, EBX) class constructor
	//	(NB: also used by I/O devices eg. CMOS)
	function Register(name, size) {
		DecoderRegister.call(this, name, size);

		if (!size) {
			size = 0;
		}

		this.value = 0;
		this.mask = util.generateMask(size);
	}

	util.inherit(Register).from(DecoderRegister);

	util.extend(Register.prototype, {
		clear: function () {
			this.set(0x00);
		},

		get: function () {
			return this.value;
		},

		// Returns a nicely formatted hex string, with register value, padded to its size
		getHexString: function () {
			var val = (this.get() >>> 0).toString(16).toUpperCase(),
				sizeHexChars = this.getSize() * 2,
				textLeadingZeroes = new Array(sizeHexChars - val.length + 1).join("0"),
				// Use spaces to right-align hex characters with the full 32-bit ones (8 chars)
				textLeadingSpaces = new Array(8 - sizeHexChars + 1).join(" ");

			return textLeadingSpaces + textLeadingZeroes + val;
		},

		set: function (val) {
			// Mask out bits of value outside Register's bit-width
			this.value = (val & this.mask) >>> 0;
		}
	});

	return Register;
});
<commit_msg>Moved jslint options to the methods they are actually needed<commit_after>/*
 * jemul8 - JavaScript x86 Emulator
 *
 * MODULE: Register class support
 *
 * ====
 *
 * Copyright 2013 jemul8.com (http://github.com/asmblah/jemul8)
 * Released under the MIT license
 * http://jemul8.com/MIT-LICENSE.txt
 */

/*global define */
define([
	"js/util",
	"./decoder/register"
], function (
	util,
	DecoderRegister
) {
    "use strict";

	// Register (eg. CPU registers EAX, EBX) class constructor
	//	(NB: also used by I/O devices eg. CMOS)
	function Register(name, size) {
		DecoderRegister.call(this, name, size);

		if (!size) {
			size = 0;
		}

		this.value = 0;
		this.mask = util.generateMask(size);
	}

	util.inherit(Register).from(DecoderRegister);

	util.extend(Register.prototype, {
		clear: function () {
			this.set(0x00);
		},

		get: function () {
			return this.value;
		},

		// Returns a nicely formatted hex string, with register value, padded to its size
		getHexString: function () {
            /*jslint bitwise: true */

			var val = (this.get() >>> 0).toString(16).toUpperCase(),
				sizeHexChars = this.getSize() * 2,
				textLeadingZeroes = new Array(sizeHexChars - val.length + 1).join("0"),
				// Use spaces to right-align hex characters with the full 32-bit ones (8 chars)
				textLeadingSpaces = new Array(8 - sizeHexChars + 1).join(" ");

			return textLeadingSpaces + textLeadingZeroes + val;
		},

		set: function (val) {
            /*jslint bitwise: true */

			// Mask out bits of value outside Register's bit-width
			this.value = (val & this.mask) >>> 0;
		}
	});

	return Register;
});
<|endoftext|>