<commit_before>/**!
* RedRaphael 1.0.0 - JavaScript Vector Library SVG Module
* Copyright (c) 2012-2013 FusionCharts Technologies <http://www.fusioncharts.com>
*
* Raphael 2.1.0 - JavaScript Vector Library SVG Module
* Copyright (c) 2008-2012 <NAME> <http://raphaeljs.com>
* Copyright © 2008-2012 Sencha Labs <http://sencha.com>
*
* Licensed under the MIT license.
*/
window.Raphael && window.Raphael.svg && function(R) {
    var has = "hasOwnProperty",
        Str = String,
        toFloat = parseFloat,
        toInt = parseInt,
        math = Math,
        mmax = math.max,
        abs = math.abs,
        pow = math.pow,
        sqrt = math.sqrt,
        separator = /[, ]+/,
        zeroStrokeFix = !!(/AppleWebKit/.test(R._g.win.navigator.userAgent) &&
                (!/Chrome/.test(R._g.win.navigator.userAgent) ||
                R._g.win.navigator.appVersion.match(/Chrome\/(\d+)\./)[1] < 29)),
        eve = R.eve,
        E = "",
        S = " ",
        xlink = "http://www.w3.org/1999/xlink",
        markers = {
            block: "M5,0 0,2.5 5,5z",
            classic: "M5,0 0,2.5 5,5 3.5,3 3.5,2z",
            diamond: "M2.5,0 5,2.5 2.5,5 0,2.5z",
            open: "M6,1 1,3.5 6,6",
            oval: "M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z"
        },
        markerCounter = {},
        updateReferenceUrl = function () {
            return R._url = R._g.win.location.href.replace(/#.*?$/, E);
        };

    R.toString = function() {
        return  "Your browser supports SVG.\nYou are running Rapha\xebl " + this.version;
    };

    // Code commented as resources will now be referenced using relative urls.
    // @todo Remove once we have acertained that there are no issues in any environment.
    // Automatic gradient and other reference update on state change
    // R._url = (/msie/i.test(navigator.userAgent) && !window.opera) ?
    //     E : updateReferenceUrl();
    // if (R._url && R._g.win.history.pushState) {
    //     R._g.win.history.pushState = (function () {
    //         var fn = R._g.win.history.pushState;
    //         return function () {
    //             var ret = fn.apply(R._g.win.history, arguments);
    //             return updateReferenceUrl(), ret;
    //         };
    //     }());
    //     R._g.win.addEventListener("popstate", updateReferenceUrl, false);
    // }
    R._url = E;

    var updateGradientReference = function (element, newGradient) {
        var gradient = element.gradient;

        if (gradient) {
            if (gradient === newGradient) {
                return; // no change
            }
            // else gradient is specified and it is not same as newGradient, implying a dereference
            gradient.refCount--;
            if (!gradient.refCount) {
                gradient.parentNode.removeChild(gradient);
            }
            delete element.gradient;
        }

        if (newGradient) { // add new gradient
            element.gradient = newGradient;
            newGradient.refCount++;
        }
    };

    var $ = R._createNode = function(el, attr) {
        if (attr) {
            if (typeof el == "string") {
                el = $(el);
            }
            for (var key in attr)
                if (attr[has](key)) {
                    if (key.substring(0, 6) == "xlink:") {
                        el.setAttributeNS(xlink, key.substring(6), Str(attr[key]));
                    } else {
                        el.setAttribute(key, Str(attr[key]));
                    }
                }
        } else {
            el = R._g.doc.createElementNS("http://www.w3.org/2000/svg", el);
        }
        return el;
    },
    gradientUnitNames = {
        userSpaceOnUse: 'userSpaceOnUse',
        objectBoundingBox: 'objectBoundingBox'
    },
    gradientSpreadNames = {
        pad: 'pad',
        redlect: 'reflect',
        repeat: 'repeat'
    },
    addGradientFill = function(element, gradient) {
        if (!element.paper || !element.paper.defs) {
            return 0;
        }

        var type = "linear",
            SVG = element.paper,
            id = (SVG.id + '-' + gradient).replace(/[\(\)\s%:,\xb0#]/g, "_"),
            fx = .5, fy = .5, r, cx, cy, units, spread,
            o = element.node,
            s = o.style,
            el = R._g.doc.getElementById(id);

        if (!el) {
            gradient = Str(gradient).replace(R._radial_gradient, function(all, opts) {
                type = "radial";
                opts = opts && opts.split(',') || [];
                units = opts[5];
                spread = opts[6];

                var _fx = opts[0],
                    _fy = opts[1],
                    _r = opts[2],
                    _cx = opts[3],
                    _cy = opts[4],
                    shifted = (_fx && _fy),
                    dir,
                    sqx;

                if (_r) {
                    r = /\%/.test(_r) ? _r : toFloat(_r);
                }

                if (units === gradientUnitNames.userSpaceOnUse) {
                    if (shifted) {
                        fx = _fx;
                        fy = _fy;
                    }
                    if (_cx && _cy) {
                        cx = _cx;
                        cy = _cy;
                        if (!shifted) {
                            fx = cx;
                            fy = cy;
                        }
                    }
                    return E;
                }

                if (shifted) {
                    fx = toFloat(_fx);
                    fy = toFloat(_fy);
                    dir = ((fy > .5) * 2 - 1);
                    (sqx = pow(fx - .5, 2)) + pow(fy - .5, 2) > .25 &&
                    (sqx < .25) && (fy = sqrt(.25 - sqx) * dir + .5) &&
                    fy !== .5 &&
                    (fy = fy.toFixed(5) - 1e-5 * dir);
                }
                if (_cx && _cy) {
                    cx = toFloat(_cx);
                    cy = toFloat(_cy);
                    dir = ((cy > .5) * 2 - 1);

                    (sqx = pow(cx - .5, 2)) + pow(cy - .5, 2) > .25 &&
                    (sqx < .25) && (cy = sqrt(.25 - sqx) * dir + .5) &&
                    cy !== .5 &&
                    (cy = cy.toFixed(5) - 1e-5 * dir);

                    if (!shifted) {
                        fx = cx;
                        fy = cy;
                    }
                }

                return E;
            });
            gradient = gradient.split(/\s*\-\s*/);
            if (type == "linear") {
                var angle = gradient.shift(),
                    specs = angle.match(/\((.*)\)/),
                    vector,
                    max;

                specs = specs && specs[1] && specs[1].split(/\s*\,\s*/);
                angle = -toFloat(angle);
                if (isNaN(angle)) {
                    return null;
                }
                if (specs && specs.length) {
                    if (specs[0] in gradientUnitNames) {
                        units = specs.shift();
                        (specs[0] in gradientSpreadNames) &&
                            (spread = specs.shift());
                    }
                    else {
                        specs[4] && (units = specs[4]);
                        specs[5] && (spread = specs[5]);
                    }

                    /** @todo apply angle rotation and validation */
                    vector = [
                        specs[0] || "0%", specs[1] || "0%",
                        specs[2] || "100%", specs[3] || "0%"
                    ];
                }
                else {
                    vector = [0, 0, math.cos(R.rad(angle)), math.sin(R.rad(angle))];
                    max = 1 / (mmax(abs(vector[2]), abs(vector[3])) || 1);
                    vector[2] *= max;
                    vector[3] *= max;
                    if (vector[2] < 0) {
                        vector[0] = -vector[2];
                        vector[2] = 0;
                    }
                    if (vector[3] < 0) {
                        vector[1] = -vector[3];
                        vector[3] = 0;
                    }
                }
            }
            var dots = R._parseDots(gradient);
            if (!dots) {
                return null;
            }

            el = $(type + "Gradient", {
                id: id
            });
            el.refCount = 0;
            (units in gradientUnitNames) &&
                    el.setAttribute('gradientUnits', Str(units));
            (spread in gradientSpreadNames) &&
                    el.setAttribute('spreadMethod', Str(spread));
            if (type === "radial") {
                (r !== undefined) && el.setAttribute('r', Str(r));

                if (cx !== undefined && cy !== undefined) {
                    el.setAttribute('cx', Str(cx));
                    el.setAttribute('cy', Str(cy));
                }
                el.setAttribute('fx', Str(fx));
                el.setAttribute('fy', Str(fy));
            }
            else {
                $(el, {
                    x1: vector[0],
                    y1: vector[1],
                    x2: vector[2],
                    y2: vector[3]
                });
            }

            for (var i = 0, ii = dots.length; i < ii; i++) {
                el.appendChild($("stop", {
                    offset: dots[i].offset ? dots[i].offset : i ? "100%" : "0%",
                    "stop-color": dots[i].color || "#fff",
                    //add stop opacity information
                    "stop-opacity": dots[i].opacity === undefined ? 1 : dots[i].opacity
                }));
            }
            SVG.defs.appendChild(el);
        }

        updateGradientReference(element, el);

        $(o, {
            fill: "url('" + R._url + "#" + id + "')",
            opacity: 1,
            "fill-opacity": 1
        });
        s.fill = E;
        s.opacity = 1;
        s.fillOpacity = 1;
        return 1;
    },
    updatePosition = function(o) {
        var bbox = o.getBBox(1);
        $(o.pattern, {
            patternTransform: o.matrix.invert() + " translate(" + bbox.x + "," + bbox.y + ")"
        });
    },
    addArrow = function(o, value, isEnd) {
        if (o.type == "path") {
            var values = Str(value).toLowerCase().split("-"),
            p = o.paper,
            se = isEnd ? "end" : "start",
            node = o.node,
            attrs = o.attrs,
            stroke = attrs["stroke-width"],
            i = values.length,
            type = "classic",
            from,
            to,
            dx,
            refX,
            attr,
            w = 3,
            h = 3,
            t = 5;
            while (i--) {
                switch (values[i]) {
                    case "block":
                    case "classic":
                    case "oval":
                    case "diamond":
                    case "open":
                    case "none":
                        type = values[i];
                        break;
                    case "wide":
                        h = 5;
                        break;
                    case "narrow":
                        h = 2;
                        break;
                    case "long":
                        w = 5;
                        break;
                    case "short":
                        w = 2;
                        break;
                }
            }
            if (type == "open") {
                w += 2;
                h += 2;
                t += 2;
                dx = 1;
                refX = isEnd ? 4 : 1;
                attr = {
                    fill: "none",
                    stroke: attrs.stroke
                };
            } else {
                refX = dx = w / 2;
                attr = {
                    fill: attrs.stroke,
                    stroke: "none"
                };
            }
            if (o._.arrows) {
                if (isEnd) {
                    o._.arrows.endPath && markerCounter[o._.arrows.endPath]--;
                    o._.arrows.endMarker && markerCounter[o._.arrows.endMarker]--;
                } else {
                    o._.arrows.startPath && markerCounter[o._.arrows.startPath]--;
                    o._.arrows.startMarker && markerCounter[o._.arrows.startMarker]--;
                }
            } else {
                o._.arrows = {};
            }
            if (type != "none") {
                var pathId = "raphael-marker-" + type,
                markerId = "raphael-marker-" + se + type + w + h + "-obj" + o.id;
                if (!R._g.doc.getElementById(pathId)) {
                    p.defs.appendChild($($("path"), {
                        "stroke-linecap": "round",
                        d: markers[type],
                        id: pathId
                    }));
                    markerCounter[pathId] = 1;
                } else {
                    markerCounter[pathId]++;
                }
                var marker = R._g.doc.getElementById(markerId),
                use;
                if (!marker) {
                    marker = $($("marker"), {
                        id: markerId,
                        markerHeight: h,
                        markerWidth: w,
                        orient: "auto",
                        refX: refX,
                        refY: h / 2
                    });
                    use = $($("use"), {
                        "xlink:href": "#" + pathId,
                        transform: (isEnd ? "rotate(180 " + w / 2 + " " + h / 2 + ") " : E) + "scale(" + w / t + "," + h / t + ")",
                        "stroke-width": (1 / ((w / t + h / t) / 2)).toFixed(4)
                    });
                    marker.appendChild(use);
                    p.defs.appendChild(marker);
                    markerCounter[markerId] = 1;
                } else {
                    markerCounter[markerId]++;
                    use = marker.getElementsByTagName("use")[0];
                }
                $(use, attr);
                var delta = dx * (type != "diamond" && type != "oval");
                if (isEnd) {
                    from = o._.arrows.startdx * stroke || 0;
                    to = R.getTotalLength(attrs.path) - delta * stroke;
                } else {
                    from = delta * stroke;
                    to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);
                }
                attr = {};
                attr["marker-" + se] = "url('" + R._url + "#" + markerId + "')";
                if (to || from) {
                    attr.d = R.getSubpath(attrs.path, from, to);
                }
                $(node, attr);
                o._.arrows[se + "Path"] = pathId;
                o._.arrows[se + "Marker"] = markerId;
                o._.arrows[se + "dx"] = delta;
                o._.arrows[se + "Type"] = type;
                o._.arrows[se + "String"] = value;
            } else {
                if (isEnd) {
                    from = o._.arrows.startdx * stroke || 0;
                    to = R.getTotalLength(attrs.path) - from;
                } else {
                    from = 0;
                    to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);
                }
                o._.arrows[se + "Path"] && $(node, {
                    d: R.getSubpath(attrs.path, from, to)
                });
                delete o._.arrows[se + "Path"];
                delete o._.arrows[se + "Marker"];
                delete o._.arrows[se + "dx"];
                delete o._.arrows[se + "Type"];
                delete o._.arrows[se + "String"];
            }
            for (attr in markerCounter)
                if (markerCounter[has](attr) && !markerCounter[attr]) {
                    var item = R._g.doc.getElementById(attr);
                    item && item.parentNode.removeChild(item);
                }
        }
    },
    dasharray = {
        "": [0],
        "none": [0],
        "-": [3, 1],
        ".": [1, 1],
        "-.": [3, 1, 1, 1],
        "-..": [3, 1, 1, 1, 1, 1],
        ". ": [1, 3],
        "- ": [4, 3],
        "--": [8, 3],
        "- .": [4, 3, 1, 3],
        "--.": [8, 3, 1, 3],
        "--..": [8, 3, 1, 3, 1, 3]
    },
    addDashes = function(o, value, params) {
        var predefValue = dasharray[Str(value).toLowerCase()];
        value = predefValue || ((value !== undefined) && [].concat(value));
        if (value) {
            var width = o.attrs["stroke-width"] || "1",
                    butt = {
                    round: width,
                    square: width,
                    butt: 0
                }[o.attrs["stroke-linecap"] || params["stroke-linecap"]] || 0,
                    i,
                    l = i = value.length;
            if (predefValue) {
                while (i--) {
                    value[i] = value[i] * width + ((i % 2) ? 1 : -1) * butt;
                }
            }
            else {
                for (i = 0; i < l; i += 2) {
                    value[i] -= butt;
                    value[i + 1] && (value[i + 1] += butt);
                    if (value[i] <= 0) {
                        value[i] = 0.1;
                    }
                }
            }
            if (R.is(value, 'array')) {
                $(o.node, {
                    "stroke-dasharray": value.join(",")
                });
            }
        }
    },

    applyCustomAttributes = function (o, attrs) {<commit_msg> When stroke-dasharray of an element in RedRaphael is using pre-defined directives, the corresponding values of the pre-defiend directives are being updated by mistake.  Introduced a new array in case of pre-defined to value to store the calculated values.<commit_after>/**!
* RedRaphael 1.0.0 - JavaScript Vector Library SVG Module
* Copyright (c) 2012-2013 FusionCharts Technologies <http://www.fusioncharts.com>
*
* Raphael 2.1.0 - JavaScript Vector Library SVG Module
* Copyright (c) 2008-2012 <NAME> <http://raphaeljs.com>
* Copyright © 2008-2012 Sencha Labs <http://sencha.com>
*
* Licensed under the MIT license.
*/
window.Raphael && window.Raphael.svg && function(R) {
    var has = "hasOwnProperty",
        Str = String,
        toFloat = parseFloat,
        toInt = parseInt,
        math = Math,
        mmax = math.max,
        abs = math.abs,
        pow = math.pow,
        sqrt = math.sqrt,
        separator = /[, ]+/,
        zeroStrokeFix = !!(/AppleWebKit/.test(R._g.win.navigator.userAgent) &&
                (!/Chrome/.test(R._g.win.navigator.userAgent) ||
                R._g.win.navigator.appVersion.match(/Chrome\/(\d+)\./)[1] < 29)),
        eve = R.eve,
        E = "",
        S = " ",
        xlink = "http://www.w3.org/1999/xlink",
        markers = {
            block: "M5,0 0,2.5 5,5z",
            classic: "M5,0 0,2.5 5,5 3.5,3 3.5,2z",
            diamond: "M2.5,0 5,2.5 2.5,5 0,2.5z",
            open: "M6,1 1,3.5 6,6",
            oval: "M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z"
        },
        markerCounter = {},
        updateReferenceUrl = function () {
            return R._url = R._g.win.location.href.replace(/#.*?$/, E);
        };

    R.toString = function() {
        return  "Your browser supports SVG.\nYou are running Rapha\xebl " + this.version;
    };

    // Code commented as resources will now be referenced using relative urls.
    // @todo Remove once we have acertained that there are no issues in any environment.
    // Automatic gradient and other reference update on state change
    // R._url = (/msie/i.test(navigator.userAgent) && !window.opera) ?
    //     E : updateReferenceUrl();
    // if (R._url && R._g.win.history.pushState) {
    //     R._g.win.history.pushState = (function () {
    //         var fn = R._g.win.history.pushState;
    //         return function () {
    //             var ret = fn.apply(R._g.win.history, arguments);
    //             return updateReferenceUrl(), ret;
    //         };
    //     }());
    //     R._g.win.addEventListener("popstate", updateReferenceUrl, false);
    // }
    R._url = E;

    var updateGradientReference = function (element, newGradient) {
        var gradient = element.gradient;

        if (gradient) {
            if (gradient === newGradient) {
                return; // no change
            }
            // else gradient is specified and it is not same as newGradient, implying a dereference
            gradient.refCount--;
            if (!gradient.refCount) {
                gradient.parentNode.removeChild(gradient);
            }
            delete element.gradient;
        }

        if (newGradient) { // add new gradient
            element.gradient = newGradient;
            newGradient.refCount++;
        }
    };

    var $ = R._createNode = function(el, attr) {
        if (attr) {
            if (typeof el == "string") {
                el = $(el);
            }
            for (var key in attr)
                if (attr[has](key)) {
                    if (key.substring(0, 6) == "xlink:") {
                        el.setAttributeNS(xlink, key.substring(6), Str(attr[key]));
                    } else {
                        el.setAttribute(key, Str(attr[key]));
                    }
                }
        } else {
            el = R._g.doc.createElementNS("http://www.w3.org/2000/svg", el);
        }
        return el;
    },
    gradientUnitNames = {
        userSpaceOnUse: 'userSpaceOnUse',
        objectBoundingBox: 'objectBoundingBox'
    },
    gradientSpreadNames = {
        pad: 'pad',
        redlect: 'reflect',
        repeat: 'repeat'
    },
    addGradientFill = function(element, gradient) {
        if (!element.paper || !element.paper.defs) {
            return 0;
        }

        var type = "linear",
            SVG = element.paper,
            id = (SVG.id + '-' + gradient).replace(/[\(\)\s%:,\xb0#]/g, "_"),
            fx = .5, fy = .5, r, cx, cy, units, spread,
            o = element.node,
            s = o.style,
            el = R._g.doc.getElementById(id);

        if (!el) {
            gradient = Str(gradient).replace(R._radial_gradient, function(all, opts) {
                type = "radial";
                opts = opts && opts.split(',') || [];
                units = opts[5];
                spread = opts[6];

                var _fx = opts[0],
                    _fy = opts[1],
                    _r = opts[2],
                    _cx = opts[3],
                    _cy = opts[4],
                    shifted = (_fx && _fy),
                    dir,
                    sqx;

                if (_r) {
                    r = /\%/.test(_r) ? _r : toFloat(_r);
                }

                if (units === gradientUnitNames.userSpaceOnUse) {
                    if (shifted) {
                        fx = _fx;
                        fy = _fy;
                    }
                    if (_cx && _cy) {
                        cx = _cx;
                        cy = _cy;
                        if (!shifted) {
                            fx = cx;
                            fy = cy;
                        }
                    }
                    return E;
                }

                if (shifted) {
                    fx = toFloat(_fx);
                    fy = toFloat(_fy);
                    dir = ((fy > .5) * 2 - 1);
                    (sqx = pow(fx - .5, 2)) + pow(fy - .5, 2) > .25 &&
                    (sqx < .25) && (fy = sqrt(.25 - sqx) * dir + .5) &&
                    fy !== .5 &&
                    (fy = fy.toFixed(5) - 1e-5 * dir);
                }
                if (_cx && _cy) {
                    cx = toFloat(_cx);
                    cy = toFloat(_cy);
                    dir = ((cy > .5) * 2 - 1);

                    (sqx = pow(cx - .5, 2)) + pow(cy - .5, 2) > .25 &&
                    (sqx < .25) && (cy = sqrt(.25 - sqx) * dir + .5) &&
                    cy !== .5 &&
                    (cy = cy.toFixed(5) - 1e-5 * dir);

                    if (!shifted) {
                        fx = cx;
                        fy = cy;
                    }
                }

                return E;
            });
            gradient = gradient.split(/\s*\-\s*/);
            if (type == "linear") {
                var angle = gradient.shift(),
                    specs = angle.match(/\((.*)\)/),
                    vector,
                    max;

                specs = specs && specs[1] && specs[1].split(/\s*\,\s*/);
                angle = -toFloat(angle);
                if (isNaN(angle)) {
                    return null;
                }
                if (specs && specs.length) {
                    if (specs[0] in gradientUnitNames) {
                        units = specs.shift();
                        (specs[0] in gradientSpreadNames) &&
                            (spread = specs.shift());
                    }
                    else {
                        specs[4] && (units = specs[4]);
                        specs[5] && (spread = specs[5]);
                    }

                    /** @todo apply angle rotation and validation */
                    vector = [
                        specs[0] || "0%", specs[1] || "0%",
                        specs[2] || "100%", specs[3] || "0%"
                    ];
                }
                else {
                    vector = [0, 0, math.cos(R.rad(angle)), math.sin(R.rad(angle))];
                    max = 1 / (mmax(abs(vector[2]), abs(vector[3])) || 1);
                    vector[2] *= max;
                    vector[3] *= max;
                    if (vector[2] < 0) {
                        vector[0] = -vector[2];
                        vector[2] = 0;
                    }
                    if (vector[3] < 0) {
                        vector[1] = -vector[3];
                        vector[3] = 0;
                    }
                }
            }
            var dots = R._parseDots(gradient);
            if (!dots) {
                return null;
            }

            el = $(type + "Gradient", {
                id: id
            });
            el.refCount = 0;
            (units in gradientUnitNames) &&
                    el.setAttribute('gradientUnits', Str(units));
            (spread in gradientSpreadNames) &&
                    el.setAttribute('spreadMethod', Str(spread));
            if (type === "radial") {
                (r !== undefined) && el.setAttribute('r', Str(r));

                if (cx !== undefined && cy !== undefined) {
                    el.setAttribute('cx', Str(cx));
                    el.setAttribute('cy', Str(cy));
                }
                el.setAttribute('fx', Str(fx));
                el.setAttribute('fy', Str(fy));
            }
            else {
                $(el, {
                    x1: vector[0],
                    y1: vector[1],
                    x2: vector[2],
                    y2: vector[3]
                });
            }

            for (var i = 0, ii = dots.length; i < ii; i++) {
                el.appendChild($("stop", {
                    offset: dots[i].offset ? dots[i].offset : i ? "100%" : "0%",
                    "stop-color": dots[i].color || "#fff",
                    //add stop opacity information
                    "stop-opacity": dots[i].opacity === undefined ? 1 : dots[i].opacity
                }));
            }
            SVG.defs.appendChild(el);
        }

        updateGradientReference(element, el);

        $(o, {
            fill: "url('" + R._url + "#" + id + "')",
            opacity: 1,
            "fill-opacity": 1
        });
        s.fill = E;
        s.opacity = 1;
        s.fillOpacity = 1;
        return 1;
    },
    updatePosition = function(o) {
        var bbox = o.getBBox(1);
        $(o.pattern, {
            patternTransform: o.matrix.invert() + " translate(" + bbox.x + "," + bbox.y + ")"
        });
    },
    addArrow = function(o, value, isEnd) {
        if (o.type == "path") {
            var values = Str(value).toLowerCase().split("-"),
            p = o.paper,
            se = isEnd ? "end" : "start",
            node = o.node,
            attrs = o.attrs,
            stroke = attrs["stroke-width"],
            i = values.length,
            type = "classic",
            from,
            to,
            dx,
            refX,
            attr,
            w = 3,
            h = 3,
            t = 5;
            while (i--) {
                switch (values[i]) {
                    case "block":
                    case "classic":
                    case "oval":
                    case "diamond":
                    case "open":
                    case "none":
                        type = values[i];
                        break;
                    case "wide":
                        h = 5;
                        break;
                    case "narrow":
                        h = 2;
                        break;
                    case "long":
                        w = 5;
                        break;
                    case "short":
                        w = 2;
                        break;
                }
            }
            if (type == "open") {
                w += 2;
                h += 2;
                t += 2;
                dx = 1;
                refX = isEnd ? 4 : 1;
                attr = {
                    fill: "none",
                    stroke: attrs.stroke
                };
            } else {
                refX = dx = w / 2;
                attr = {
                    fill: attrs.stroke,
                    stroke: "none"
                };
            }
            if (o._.arrows) {
                if (isEnd) {
                    o._.arrows.endPath && markerCounter[o._.arrows.endPath]--;
                    o._.arrows.endMarker && markerCounter[o._.arrows.endMarker]--;
                } else {
                    o._.arrows.startPath && markerCounter[o._.arrows.startPath]--;
                    o._.arrows.startMarker && markerCounter[o._.arrows.startMarker]--;
                }
            } else {
                o._.arrows = {};
            }
            if (type != "none") {
                var pathId = "raphael-marker-" + type,
                markerId = "raphael-marker-" + se + type + w + h + "-obj" + o.id;
                if (!R._g.doc.getElementById(pathId)) {
                    p.defs.appendChild($($("path"), {
                        "stroke-linecap": "round",
                        d: markers[type],
                        id: pathId
                    }));
                    markerCounter[pathId] = 1;
                } else {
                    markerCounter[pathId]++;
                }
                var marker = R._g.doc.getElementById(markerId),
                use;
                if (!marker) {
                    marker = $($("marker"), {
                        id: markerId,
                        markerHeight: h,
                        markerWidth: w,
                        orient: "auto",
                        refX: refX,
                        refY: h / 2
                    });
                    use = $($("use"), {
                        "xlink:href": "#" + pathId,
                        transform: (isEnd ? "rotate(180 " + w / 2 + " " + h / 2 + ") " : E) + "scale(" + w / t + "," + h / t + ")",
                        "stroke-width": (1 / ((w / t + h / t) / 2)).toFixed(4)
                    });
                    marker.appendChild(use);
                    p.defs.appendChild(marker);
                    markerCounter[markerId] = 1;
                } else {
                    markerCounter[markerId]++;
                    use = marker.getElementsByTagName("use")[0];
                }
                $(use, attr);
                var delta = dx * (type != "diamond" && type != "oval");
                if (isEnd) {
                    from = o._.arrows.startdx * stroke || 0;
                    to = R.getTotalLength(attrs.path) - delta * stroke;
                } else {
                    from = delta * stroke;
                    to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);
                }
                attr = {};
                attr["marker-" + se] = "url('" + R._url + "#" + markerId + "')";
                if (to || from) {
                    attr.d = R.getSubpath(attrs.path, from, to);
                }
                $(node, attr);
                o._.arrows[se + "Path"] = pathId;
                o._.arrows[se + "Marker"] = markerId;
                o._.arrows[se + "dx"] = delta;
                o._.arrows[se + "Type"] = type;
                o._.arrows[se + "String"] = value;
            } else {
                if (isEnd) {
                    from = o._.arrows.startdx * stroke || 0;
                    to = R.getTotalLength(attrs.path) - from;
                } else {
                    from = 0;
                    to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);
                }
                o._.arrows[se + "Path"] && $(node, {
                    d: R.getSubpath(attrs.path, from, to)
                });
                delete o._.arrows[se + "Path"];
                delete o._.arrows[se + "Marker"];
                delete o._.arrows[se + "dx"];
                delete o._.arrows[se + "Type"];
                delete o._.arrows[se + "String"];
            }
            for (attr in markerCounter)
                if (markerCounter[has](attr) && !markerCounter[attr]) {
                    var item = R._g.doc.getElementById(attr);
                    item && item.parentNode.removeChild(item);
                }
        }
    },
    dasharray = {
        "": [0],
        "none": [0],
        "-": [3, 1],
        ".": [1, 1],
        "-.": [3, 1, 1, 1],
        "-..": [3, 1, 1, 1, 1, 1],
        ". ": [1, 3],
        "- ": [4, 3],
        "--": [8, 3],
        "- .": [4, 3, 1, 3],
        "--.": [8, 3, 1, 3],
        "--..": [8, 3, 1, 3, 1, 3]
    },
    addDashes = function(o, value, params) {
        var predefValue = dasharray[Str(value).toLowerCase()];
        value = predefValue || ((value !== undefined) && [].concat(value));
        if (value) {
            var width = o.attrs["stroke-width"] || 1,
                    butt = {
                    round: width,
                    square: width,
                    butt: 0
                }[o.attrs["stroke-linecap"] || params["stroke-linecap"]] || 0,
                    i,
                    l = i = value.length,
                    calculatedValues;
            if (predefValue) {
                calculatedValues = [];
                while (i--) {
                    calculatedValues[i] = value[i] * width + ((i % 2) ? 1 : -1) * butt;
                    if (calculatedValues[i] <= 0) {
                        calculatedValues[i] = 0.1;
                    }
                }
            }
            else {
                for (i = 0; i < l; i += 2) {
                    value[i] -= butt;
                    value[i + 1] && (value[i + 1] += butt);
                    if (value[i] <= 0) {
                        value[i] = 0.1;
                    }
                }
                calculatedValues = value;
            }
            if (R.is(value, 'array')) {
                $(o.node, {
                    "stroke-dasharray": calculatedValues.join(",")
                });
            }
        }
    },

    applyCustomAttributes = function (o, attrs) {
{'fraction_non_alphanumeric': 0.14490271499564814, 'fraction_numerical': 0.016593199876463488, 'mean_word_length': 0.9485748673340992, 'pattern_counts': {'":': 58, '<': 28, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 6, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5357065', 'n_tokens_mistral': 10703, 'n_tokens_neox': 9679, 'n_words': 2153}