EpiVerse
  • Repositories
  • Contributors
  • Community Health
    • Feedback
    • Source Code
    • github.com/reconhub
    • github.com/epiverse-trace
    • github.com/reconverse

On this page

  • Repositories
  • Network
  • Co-Contributors

Contributors and Maintainers

function sparkbar(max) {
  const colourScale = d3.scaleSequential(d3.interpolateCool)
    .domain([0, max]);

  return (x) => htl.html`<div style="
    background: ${colourScale(x)};
    color: black;
    width: ${100 * x / max}%;
    float: right;
    padding-right: 3px;
    box-sizing: border-box;
    overflow: visible;
    display: flex;
    justify-content: end;">${x.toFixed(2).toLocaleString("en-US")}`
}

function tooltip(title, expl) {
    const th = document.createElement("th");
    th.title = expl
    th.style.background = "#f0f8ff";
    th.textContent = title;

    th.addEventListener("mouseover", () => th.style.background = "#d0e8ff");
    th.addEventListener("mouseout", () => th.style.background = "#f0f8ff");

    return th;
}

function pkgfmt(pkg) {
    const th = document.createElement("th");
    th.title = "hover"
    th.style.background = "#f0f8ff";
    th.textContent = pkg;

    th.addEventListener("mouseover", () => th.style.background = "#d0e8ff");
    th.addEventListener("mouseout", () => th.style.background = "#f0f8ff");

    th.addEventListener("click", () => {
        localStorage.setItem("orgmetricsRepo", pkg);
        th.style.background="#a0f8ff";
        window.location.href="/repometrics-demo/repo.html";
    });

    return th;
}
repo_src = {
    return transpose(repo_src_in).map(row => ({
        ...row,
    }));
}
json_data = FileAttachment("results-json-data.json").json();
maintainer_pkgs = json_data['maintainer_pkgs'];
comaintainers = json_data['comaintainers'];
maintainers = Object.keys(maintainer_pkgs);
maintainerSet = localStorage.getItem("orgmetricsMaintainer") ||
    maintainers [Math.floor(Math.random() * maintainers.length)]
viewof maintainer = Inputs.select(
    maintainers,
    {
        multiple: false,
        value: maintainerSet,
        label: htl.html`<b>Maintainer:</b>`
    }
)
s = localStorage.setItem("orgmetricsMaintainer", maintainer.toString());
maintainer_gh_url =
    htl.html`<a href="https://github.com/${maintainer}" target="_blank"><i>${maintainer}</i></a>`
these_pkgs = maintainer_pkgs[maintainer] || null;

these_cos = comaintainers[maintainer] || null
these_cos_list = these_cos ?
these_cos.map(i => htl.html`
<div onclick=${() => localStorage.setItem('orgmetricsMaintainer', i)}>
<li><a href="/repometrics-demo/contributor.html">${i}</a></li>
</div>`) : htl.html`<li>No co-maintainers</li>`;
htl.html`<div><a href="https://github.com/${maintainer}" target="_blank">github.com/${maintainer}</a></div>`

Repositories

This is a sub-set of the main table on the Organization page, showing repository metrics aggregated across the four categories described there. Values are shown only for any repositories to which has contributed, and are scaled between 0 and 1 based on the distribution of values across the entire organization, with higher values always better than lower values.

metricsGroupedTable = {
    return transpose(metrics_table_in).map(row => ({
        ...row,
    }));
}
metricsTable = metricsGroupedTable.filter(i => these_pkgs.includes(i.package));
Inputs.table(metricsTable, {
    width: {
        package: 100,
        total: 200,
        development: 200,
        issues: 200,
        popularity: 200,
        meta: 200,
    },
    format: {
        package: d => pkgfmt(d),
        development: sparkbar(d3.max(metricsGroupedTable, d => d.development)),
        issues: sparkbar(d3.max(metricsGroupedTable, d => d.issues)),
        popularity: sparkbar(d3.max(metricsGroupedTable, d => d.popularity)),
        meta: sparkbar(d3.max(metricsGroupedTable, d => d.meta)),
        total: sparkbar(d3.max(metricsGroupedTable, d => d.total)),
    },
    header: {
        development: tooltip("Development", "Code development and maintenance metrics"),
        issues: tooltip("Issues", "GitHub issues and pull request activity"),
        popularity: tooltip("Popularity", "Project popularity on CRAN (where applicable) and GitHub"),
        meta: tooltip("Dependencies and releases", ""),
        total: tooltip("Overall", "Average across all four categories of metrics."),
    },
})

Network

co_pkgs = these_cos ? these_cos.map(i => maintainer_pkgs[i]).flat() : [];
pkgs_expanded_full = [
    ...these_pkgs,
    ...co_pkgs
];
// Reduce to unique pkgs:
pkgs_expanded = [...new Set(pkgs_expanded_full)];

co_nodes = these_cos ?
    these_cos.map(item => ({ id: item, group: "Co-maintainer", size: 6 })) : [];
nodes = [
    { id: maintainer, group: "Maintainer", size: 10 },
    ...pkgs_expanded.map(item => ({
        id: item,
        group: these_pkgs.includes(item) ? "packages" : "otherPackages",
        size: these_pkgs.includes(item) ? 8 : 4,
    })),
    ...co_nodes
];

// edges are mappings from co-maintainers to all packages. First collect list
// of all packages from co-maintainers:
these_co_pkgs = these_cos ? these_cos.reduce((acc, key) => {
    if (maintainer_pkgs.hasOwnProperty(key)) {
        if (!these_pkgs.includes(key)) {
            acc[key] = maintainer_pkgs[key];
        }
    }
    return acc;
}, {}) : [];
// Then flatten that to (source, target) pairs of (maintainer, package):
these_co_pkgs_flat = Object.entries(these_co_pkgs).flatMap(([source, targets]) =>
    targets.map(target => ({ source, target }))
);
links = [
    ...these_pkgs.map(item => ({
        source: maintainer, target: item, value: 4
    })),
    ...these_co_pkgs_flat.map(item => ({
        source: item.source, target: item.target, value: 2
    }))
];
import {Swatches} from "@d3/color-legend"
Swatches(chart.scales.color)
strength = -400;

chart = {

    const width = 928;
    const height = 600;

    const types = Array.from(new Set(nodes.map(d => d.group)));

    const color = d3.scaleOrdinal(types, d3.schemeCategory10);

    const simulation = d3.forceSimulation(nodes)
        .force("link", d3.forceLink(links).id(d => d.id))
        .force("charge", d3.forceManyBody().strength(strength))
        .force("x", d3.forceX())
        .force("y", d3.forceY());

    const svg = d3.create("svg")
        .attr("viewBox", [-width / 2, -height / 2, width, height])
        .attr("width", width)
        .attr("height", height)
        .attr("style", "max-width: 100%; height: auto; font: 14px sans-serif;");

    const link = svg.append("g")
        .attr("fill", "none")
        .attr("stroke-width", 1.5)
        .selectAll("path")
        .data(links)
        .join("path")
            .attr("stroke", "gray")
            .attr("stroke-width", d => d.value);

    const node = svg.append("g")
        .selectAll("g")
        .data(nodes)
        .join("g")
            .call(drag(simulation));

    node.append("circle")
        .attr("stroke", "white")
        .attr("stroke-width", 1.5)
        .data(nodes)
        .join("circle")
            .attr("fill", d => color(d.group))
            .attr("r", d => d.size);

    node.append("text")
        .attr("x", 8)
        .attr("y", "0.31em")
        .text(d => d.id)
        .html(d => d.group === "Co-maintainer" ?
            `<a href="/repometrics-demo/contributor.html"
                onclick="localStorage.setItem('orgmetricsMaintainer', '${d.id}')">${d.id}</a>` :
            ((d.group === "packages" || d.group === "otherPackages") ?
                `<a href="/repometrics-demo/repo.html"
                    onclick="localStorage.setItem('orgmetricsRepo', '${d.id}')">${d.id}</a>` :
            d.id))
        .clone(true).lower()
            .attr("fill", "none")
            .attr("stroke", "white")
            .attr("stroke-width", 3);

    simulation.on("tick", () => {
        link.attr("d", linkArc);
        node.attr("transform", d => `translate(${d.x},${d.y})`);
    });

    invalidation.then(() => simulation.stop());

    return Object.assign(svg.node(), {scales: {color}});
}
function linkArc(d) {
    const r = Math.hypot(d.target.x - d.source.x, d.target.y - d.source.y);
    return `
    M${d.source.x},${d.source.y}
    A${r},${r} 0 0,1 ${d.target.x},${d.target.y}
    `;
}
drag = simulation => {

    function dragstarted(event, d) {
        if (!event.active) simulation.alphaTarget(0.3).restart();
        d.fx = d.x;
        d.fy = d.y;
    }

    function dragged(event, d) {
        d.fx = event.x;
        d.fy = event.y;
    }

    function dragended(event, d) {
        if (!event.active) simulation.alphaTarget(0);
        d.fx = null;
        d.fy = null;
    }

    return d3.drag()
        .on("start", dragstarted)
        .on("drag", dragged)
        .on("end", dragended);
}

Co-Contributors

htl.html`<ul>${these_cos_list}</ul>`
 
Cookie Preferences