<commit_before>(function (window, undefined) {
    "use strict";

    var mPainter = window.mPainter || {},
        _internal = {},
        _self;

    /**
     * Initialization
     */
    mPainter = function (options) {
        var defaults = {
                debug: false,
                id: "mysvg",
                cursor_id: "cursor",
                element_prefix: "element_",
                tool: "PAINT",

                start_trigger : ['mousedown', 'touchstart', 'MSPointerDown'],
                move_trigger  : ['mousemove', 'touchmove', 'MSPointerMove'],
                stop_trigger  : ['mouseup', 'touchend', 'touchcancel', 'MSPointerUp'],
            };
        this.options = _extend(defaults, options);

        _self = this;
        _internal = {
            el: _get(this.options.id),
            undo: [],
            redo: [],

            is_mousedown: false,
            first_draw: true,
            paint_start: undefined,
            paint_stack: {
                head: 0,
                elements: []
            },

            config: {
                element_index: 0,
                tool: this.options.tool,
                painter_radius: 3,
                opacity: 1,
                color: "#FF0000"  // red
            },

            // EVENTS: {
            //     "mousedown": _mouseDown,
            //     "mousemove": _mouseMove,
            //     "mouseup": _mouseUp,
            //     "mouseover": _mouseOver,
            //     "mouseout": _mouseOut
            // },

            TOOLS: {
                PAINT: "PAINT",
                LINE: "LINE"
            }

        };

        bindEvents();
    };

    mPainter.prototype = {

        setColor: function (color) {
            _internal.config.color = color;
        },

        setSize: function (radius) {
            _internal.config.painter_radius = radius;
        },

        setOpacity: function (opacity) {
            _internal.config.opacity = opacity;
        },

        setTool: function (tool_name) {
            if (_internal.TOOLS[tool_name]) {
                _internal.config.tool = _internal.TOOLS[tool_name];
            } else {
                throw "TOOL: " + tool_name + " is not available.";
            }
        },

        undo: function () {
            this.exec("undo");
        },

        redo: function () {
            this.exec("redo");
        },
        // TODO FIX: Function does not work
        saveImage: function () {
            // Create a canvas element
            var canvas = _get("mycanvas");
            var ctx = canvas.getContext("2d");

            var data = new XMLSerializer().serializeToString(_internal.el);
            var DOMURL = window.URL || window.webkitURL || window;
            // var img = new Image();
            var img = document.createElement('img');
            var svg = new Blob([data], {type: "image/svg+xml;charset=utf-8"});
            var url = DOMURL.createObjectURL(svg);
            img.onload = function () {
                ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
                // DOMURL.revokeObjectURL(url);
                var b64 = canvas.toDataURL("image/png");
            };
            img.src = url;
        },

        replay: function (callback) {
            var elements = _internal.paint_stack.elements,
                elements_length = elements.length,
                _raf = _requestAnimationFrame(),
                replay_time = time(),
                element_begin = 0,
                point_begin = 0,
                number_drew = 0,
                replay_points = [];

            clearPaint();
            var render = function () {
                var i, j, element_end,
                    before_time = _internal.paint_start + (time() - replay_time);
                // find element_end
                for (element_end = element_begin; element_end <= elements_length - 1; element_end++) {
                    var points = elements[element_end].points;
                    if (points[points.length - 1].timestamp > before_time) {
                        break;
                    }
                }
                if (element_end > elements_length - 1) {
                    element_end = elements_length - 1;
                }

                for (i = element_begin; i <= element_end; i++) {
                    var element = elements[i],
                        points_length = element.points.length;
                    for (j = point_begin; j < points_length; j++) {
                        var point = element.points[j];
                        if (point.timestamp > before_time) {
                            point_begin = j;
                            break;
                        }
                        replay_points.push(point);
                        draw(element.config, replay_points);
                        if (replay_points.length === points_length) {
                            point_begin = 0;
                            replay_points = [];
                            number_drew ++;
                            setElementOpacity(element.config);
                        }
                    }<commit_msg>[UPDATE] support undo/redo in replay functionality<commit_after>(function (window, undefined) {
    "use strict";

    var mPainter = window.mPainter || {},
        _internal = {},
        _self;

    /**
     * Initialization
     */
    mPainter = function (options) {
        var defaults = {
                debug: false,
                id: "mysvg",
                cursor_id: "cursor",
                element_prefix: "element_",
                tool: "PAINT",

                start_trigger : ['mousedown', 'touchstart', 'MSPointerDown'],
                move_trigger  : ['mousemove', 'touchmove', 'MSPointerMove'],
                stop_trigger  : ['mouseup', 'touchend', 'touchcancel', 'MSPointerUp'],
            };
        this.options = _extend(defaults, options);

        _self = this;
        _internal = {
            el: _get(this.options.id),
            undo: [],
            redo: [],

            is_mousedown: false,
            first_draw: true,
            paint_start: undefined,
            paint_stack: {
                head: 0,
                elements: []
            },

            config: {
                element_index: 0,
                tool: this.options.tool,
                painter_radius: 3,
                opacity: 1,
                color: "#FF0000"  // red
            },

            // EVENTS: {
            //     "mousedown": _mouseDown,
            //     "mousemove": _mouseMove,
            //     "mouseup": _mouseUp,
            //     "mouseover": _mouseOver,
            //     "mouseout": _mouseOut
            // },

            TOOLS: {
                PAINT: "PAINT",
                LINE: "LINE"
            }

        };

        bindEvents();
    };

    mPainter.prototype = {

        setColor: function (color) {
            _internal.config.color = color;
        },

        setSize: function (radius) {
            _internal.config.painter_radius = radius;
        },

        setOpacity: function (opacity) {
            _internal.config.opacity = opacity;
        },

        setTool: function (tool_name) {
            if (_internal.TOOLS[tool_name]) {
                _internal.config.tool = _internal.TOOLS[tool_name];
            } else {
                throw "TOOL: " + tool_name + " is not available.";
            }
        },

        undo: function () {
            this.exec("undo");
        },

        redo: function () {
            this.exec("redo");
        },
        // TODO FIX: Function does not work
        saveImage: function () {
            // Create a canvas element
            var canvas = _get("mycanvas");
            var ctx = canvas.getContext("2d");

            var data = new XMLSerializer().serializeToString(_internal.el);
            var DOMURL = window.URL || window.webkitURL || window;
            // var img = new Image();
            var img = document.createElement('img');
            var svg = new Blob([data], {type: "image/svg+xml;charset=utf-8"});
            var url = DOMURL.createObjectURL(svg);
            img.onload = function () {
                ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
                // DOMURL.revokeObjectURL(url);
                var b64 = canvas.toDataURL("image/png");
            };
            img.src = url;
        },

        replay: function (callback) {
            var elements = _internal.paint_stack.elements,
                elements_length = elements.length,
                _raf = _requestAnimationFrame(),
                replay_time = time(),
                deleted_time = 0,
                element_begin = 0,
                point_begin = 0,
                number_drew = 0,
                replay_points = [];

            clearPaint();
            var render = function () {
                var i, j, element_end,
                    before_time = _internal.paint_start + deleted_time + (time() - replay_time);
                // find element_end
                for (element_end = element_begin; element_end <= elements_length - 1; element_end++) {
                    var points = elements[element_end].points,
                        first_timestamp = points[0].timestamp,
                        last_timestamp = points[points.length - 1].timestamp;
                    if (elements[element_end].is_deleted === true) {
                        deleted_time += last_timestamp - first_timestamp;
                        console.log(deleted_time);
                        continue;
                    }
                    if (last_timestamp > before_time) {
                        break;
                    }
                }
                if (element_end > elements_length - 1) {
                    element_end = elements_length - 1;
                }

                for (i = element_begin; i <= element_end; i++) {
                    var element = elements[i],
                        points_length = element.points.length;
                    if (element.is_deleted === true) {
                        continue;
                    }
                    for (j = point_begin; j < points_length; j++) {
                        var point = element.points[j];
                        if (point.timestamp > before_time) {
                            point_begin = j;
                            break;
                        }
                        replay_points.push(point);
                        draw(element.config, replay_points);
                        if (replay_points.length === points_length) {
                            point_begin = 0;
                            replay_points = [];
                            number_drew ++;
                            setElementOpacity(element.config);
                        }
                    }
{'fraction_non_alphanumeric': 0.10670202066380177, 'fraction_numerical': 0.004205906555728262, 'mean_word_length': 1.1442854342285826, 'pattern_counts': {'":': 10, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5582841', 'n_tokens_mistral': 2903, 'n_tokens_neox': 2669, 'n_words': 568}