<commit_before>function getRewardBarTooltipManager(canvas, chartData){
    var ttm = {};

    ttm.chartData = chartData;
    ttm.canvas = canvas;

    ttm.generateTooltips= function(){
        this.chartData.positionTooltips();
        for (var i in this.chartData.actionRewardNames){
            var actionRewardName = this.chartData.actionRewardNames[i];
            var rewardBar = this.chartData.actionRewardForNameMap[actionRewardName];
            var tooltipText = "Value of " + rewardBar.name + " is " + Math.floor(rewardBar.value);
            rewardBar.tooltipID = createTooltipDiv(tooltipText, rewardBar, this.canvas);
        }
    }
    ttm.generateValueTooltips = function () {
        this.chartData.positionValueTooltips();
        for (var i in this.chartData.actionRewardNames) {
            var actionRewardName = this.chartData.actionRewardNames[i];
            var rewardBar = this.chartData.actionRewardForNameMap[actionRewardName];
            rewardBar.tooltipValueID = createValueTooltipDiv(Math.floor(rewardBar.value), rewardBar, this.canvas);
        }
    }
    ttm.generateValueTooltips();
    ttm.generateTooltips();

    canvas.onmousemove = function(e){
        var x = e.offsetX;
        var y = e.offsetY;
        var actionRewardName = chartData.getActionBarNameForCoordinates(x, y);
        if (actionRewardName == "None"){
            ttm.hideAllToolTips();
        }
        else {
            if (ttm.isToolTipShowingForRewardBar(actionRewardName)){
                // do nothing, it's already showing
            }
            else {
                ttm.hideAllToolTips();
                ttm.showTooltipForRewardBar(actionRewardName);

                ttm.showSimilarBarValues(actionRewardName);
            }
        }
    }

    ttm.isToolTipShowingForRewardBar = function(actionRewardName){
        var rewardBar = chartData.actionRewardForNameMap[actionRewardName];
        var ttVisibility = $("#tooltip-container-" + rewardBar.fullName).css("visibility");
        return (ttVisibility == "visible");
    }
    ttm.hideAllToolTips = function(){
        for (var i in this.chartData.actionRewardNames){
            var rewardBar = chartData.actionRewardForNameMap[this.chartData.actionRewardNames[i]];
            var toolContainerID = document.getElementById("tooltip-container-" + rewardBar.fullName);
            toolContainerID.style.visibility = "hidden";
        }
    }
    ttm.showTooltipForRewardBar = function(actionRewardName){
        var rewardBar = chartData.actionRewardForNameMap[actionRewardName];
        var toolContainerID = document.getElementById("tooltip-container-" + rewardBar.fullName);
        toolContainerID.style.visibility = "visible";
    }
    ttm.showSimilarBarValues = function (actionRewardName) {
        var rewardBarName = actionRewardName.split(".")[1];
        for (var i=0; i < chartData.actions.length; i++) {
            var action = "Attack Q" + Number(i + 1) + ".";
            var similarBar = action + rewardBarName;
            var rewardBar = chartData.actionRewardForNameMap[similarBar];
            $("#" + rewardBar.tooltipValueID).css("visibility","visible");
        }
    }
    return ttm;
}

function createTooltipDiv(text, rewardBar, canvas) {
    var canvas_bounds = canvas.getBoundingClientRect();
    var x = rewardBar.tooltipOriginX + canvas_bounds.left;
    var y = rewardBar.tooltipOriginY  + canvas_bounds.top;

    var tooltipContainer = document.createElement("div");
    tooltipContainer.setAttribute("id", "tooltip-container-" + rewardBar.fullName);
    tooltipContainer.setAttribute("style", "position:absolute;left:" + (x + 9) + "px;top:" + y + "px;visibility:hidden");

    var id = convertNameToLegalId("tooltip-" + rewardBar.fullName);
    var ttDiv = document.createElement("div");
    ttDiv.setAttribute("id",id);
    ttDiv.setAttribute("style", 'width:100px;white-space: pre-wrap;' + 
    'padding:4px;background-color:#00aabb;' + 
    'z-index:' + zIndexMap["tooltip"] + ';' + 
    'color:black;font-family:Arial;' + 
    'border-radius:.4em;');
    ttDiv.innerHTML = text;

    tooltipContainer.append(ttDiv)

    $("#explanations-rewards").append(tooltipContainer);

    arrow = document.createElement("div");
    arrow.setAttribute("id", "arrow-" + rewardBar.fullName);
    var ttDivFromDOM = document.getElementById(id);
    var ttDivHeight = ttDivFromDOM.clientHeight;
    ttDivHeight = (ttDivHeight / 2) + 10;
    arrow.setAttribute("style", "position:relative;left:-10px;top:-" + ttDivHeight + "px;width:0; height:0; border-top: 10px solid transparent; border-bottom: 10px solid transparent; border-right:10px solid #00aabb;");
    tooltipContainer.appendChild(arrow);

    //$("#tooltip-container-" + rewardBar.fullName).css("top", (y - ttDivHeight) + "px");

    return id;
}

function createValueTooltipDiv (text, rewardBar, canvas) {<commit_msg>Fixed the tooltip y-position so the speech bubble always looks like it's touching the bar<commit_after>function getRewardBarTooltipManager(canvas, chartData){
    var ttm = {};

    ttm.chartData = chartData;
    ttm.canvas = canvas;

    ttm.generateTooltips= function(){
        this.chartData.positionTooltips();
        for (var i in this.chartData.actionRewardNames){
            var actionRewardName = this.chartData.actionRewardNames[i];
            var rewardBar = this.chartData.actionRewardForNameMap[actionRewardName];
            var tooltipText = "Value of " + rewardBar.name + " is " + Math.floor(rewardBar.value);
            rewardBar.tooltipID = createTooltipDiv(tooltipText, rewardBar, this.canvas);
        }
    }
    ttm.generateValueTooltips = function () {
        this.chartData.positionValueTooltips();
        for (var i in this.chartData.actionRewardNames) {
            var actionRewardName = this.chartData.actionRewardNames[i];
            var rewardBar = this.chartData.actionRewardForNameMap[actionRewardName];
            rewardBar.tooltipValueID = createValueTooltipDiv(Math.floor(rewardBar.value), rewardBar, this.canvas);
        }
    }
    ttm.generateValueTooltips();
    ttm.generateTooltips();

    canvas.onmousemove = function(e){
        var x = e.offsetX;
        var y = e.offsetY;
        var actionRewardName = chartData.getActionBarNameForCoordinates(x, y);
        if (actionRewardName == "None"){
            ttm.hideAllToolTips();
        }
        else {
            if (ttm.isToolTipShowingForRewardBar(actionRewardName)){
                // do nothing, it's already showing
            }
            else {
                ttm.hideAllToolTips();
                ttm.showTooltipForRewardBar(actionRewardName);

                ttm.showSimilarBarValues(actionRewardName);
            }
        }
    }

    ttm.isToolTipShowingForRewardBar = function(actionRewardName){
        var rewardBar = chartData.actionRewardForNameMap[actionRewardName];
        var ttVisibility = $("#tooltip-container-" + rewardBar.fullName).css("visibility");
        return (ttVisibility == "visible");
    }
    ttm.hideAllToolTips = function(){
        for (var i in this.chartData.actionRewardNames){
            var rewardBar = chartData.actionRewardForNameMap[this.chartData.actionRewardNames[i]];
            var toolContainerID = document.getElementById("tooltip-container-" + rewardBar.fullName);
            toolContainerID.style.visibility = "hidden";
        }
    }
    ttm.showTooltipForRewardBar = function(actionRewardName){
        var rewardBar = chartData.actionRewardForNameMap[actionRewardName];
        var toolContainerID = document.getElementById("tooltip-container-" + rewardBar.fullName);
        toolContainerID.style.visibility = "visible";
    }
    ttm.showSimilarBarValues = function (actionRewardName) {
        var rewardBarName = actionRewardName.split(".")[1];
        for (var i=0; i < chartData.actions.length; i++) {
            var action = "Attack Q" + Number(i + 1) + ".";
            var similarBar = action + rewardBarName;
            var rewardBar = chartData.actionRewardForNameMap[similarBar];
            $("#" + rewardBar.tooltipValueID).css("visibility","visible");
        }
    }
    return ttm;
}

function createTooltipDiv(text, rewardBar, canvas) {
    var canvas_bounds = canvas.getBoundingClientRect();
    var x = rewardBar.tooltipOriginX + canvas_bounds.left;
    var y = rewardBar.tooltipOriginY  + canvas_bounds.top;

    var tooltipContainer = document.createElement("div");
    tooltipContainer.setAttribute("id", "tooltip-container-" + rewardBar.fullName);
    tooltipContainer.setAttribute("style", "position:absolute;left:" + (x + 13) + "px;top:" + y + "px;visibility:hidden");

    var id = convertNameToLegalId("tooltip-" + rewardBar.fullName);
    var ttDiv = document.createElement("div");
    ttDiv.setAttribute("id",id);
    ttDiv.setAttribute("style", 'width:100px;white-space: pre-wrap;' + 
    'padding:4px;background-color:#00aabb;' + 
    'z-index:' + zIndexMap["tooltip"] + ';' + 
    'color:black;font-family:Arial;' + 
    'border-radius:.4em;');
    ttDiv.innerHTML = text;

    tooltipContainer.append(ttDiv)

    $("#explanations-rewards").append(tooltipContainer);

    arrow = document.createElement("div");
    arrow.setAttribute("id", "arrow-" + rewardBar.fullName);
    var ttDivFromDOM = document.getElementById(id);
    var ttDivHeight = ttDivFromDOM.clientHeight;
    ttDivHeight = (ttDivHeight / 2) + 10;
    arrow.setAttribute("style", "position:relative;left:-10px;top:-" + ttDivHeight + "px;width:0; height:0; border-top: 10px solid transparent; border-bottom: 10px solid transparent; border-right:10px solid #00aabb;");
    tooltipContainer.appendChild(arrow);

    var ttContainerDiv = document.getElementById("tooltip-container-" + rewardBar.fullName);
    ttContainerDiv.style.top = Number(y - (ttDivFromDOM.clientHeight / 2)) + "px";

    return id;
}

function createValueTooltipDiv (text, rewardBar, canvas) {
{'fraction_non_alphanumeric': 0.12236669690555388, 'fraction_numerical': 0.005442999697611128, 'mean_word_length': 3.2060194997880456, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, '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': '6806859', 'n_tokens_mistral': 2995, 'n_tokens_neox': 2906, 'n_words': 500}