Alliance Credibility
Know an alliance well? Contribute to this measure using the link below. Every submission is reviewed before it enters the revised measure in the next annual update.
This table is for finding and comparing alliances; the credibility estimate and its credible intervals live on each alliance’s page. Tiers reflect expert coverage, not precision — gold/silver have expert ratings on file; bronze is LLM-only and provisional. Vintage: 2026-10-02.
median = vals => {
const s = [...vals].sort((a, b) => a - b), n = s.length;
return n % 2 ? s[(n - 1) / 2] : (s[n / 2 - 1] + s[n / 2]) / 2;
}
tierRank = ({gold: 0, silver: 1, bronze: 2})
// Best tier per alliance (D3: roll up to the best member tier for the home view).
bestTierByAlliance = {
const m = new Map();
for (const r of estimates) {
const cur = m.get(r.alliance_id);
if (cur === undefined || tierRank[r.confidence_tier] < tierRank[cur]) m.set(r.alliance_id, r.confidence_tier);
}
return m;
}
// Coarse alliance-level trajectory for the sparkline: median of the actor medians per year.
trajByAlliance = {
const byA = new Map();
for (const r of estimates) {
if (!byA.has(r.alliance_id)) byA.set(r.alliance_id, new Map());
const ym = byA.get(r.alliance_id);
if (!ym.has(r.year)) ym.set(r.year, []);
ym.get(r.year).push(r.irt_median);
}
const out = new Map();
for (const [aid, ym] of byA)
out.set(aid, [...ym.entries()].map(([year, v]) => ({year, val: median(v)})).sort((a, b) => a.year - b.year));
return out;
}
// Shared y-domain so sparkline shapes are comparable across rows.
yDomain = estimates.reduce((a, d) => [Math.min(a[0], d.irt_median), Math.max(a[1], d.irt_median)], [Infinity, -Infinity])
allianceSummary = meta.map(d => ({
atopid: d.atopid, name: d.name, members: d.members, n_members: d.n_members,
type: d.type, region: d.region, era: d.era, begyr: d.begyr, endyr: d.endyr,
tier: bestTierByAlliance.get(d.atopid) ?? "bronze",
traj: trajByAlliance.get(d.atopid) ?? []
}))filtered = allianceSummary.filter(d =>
tierFilter.includes(d.tier) &&
(regionFilter === "All" || d.region === regionFilter) &&
(search.trim() === "" ||
d.name.toLowerCase().includes(search.toLowerCase()) ||
d.members.some(m => m.toLowerCase().includes(search.toLowerCase())))
).sort((a, b) => a.name.localeCompare(b.name))sparkline = traj => traj.length < 2
? html`<span style="color:#ccc">—</span>`
: Plot.plot({
width: 130, height: 26, margin: 0,
x: {axis: null}, y: {domain: yDomain, axis: null},
marks: [Plot.line(traj, {x: "year", y: "val", stroke: "#1f5fa8", strokeWidth: 1, strokeOpacity: 0.85})]
})
tierBadge = t => {
const c = {gold: "#9a7400", silver: "#6b6b6b", bronze: "#9a9a9a"};
return html`<span style="background:${c[t]}22; color:${c[t]}; padding:1px 8px; border-radius:10px; font-size:0.76rem; font-weight:600">${t}</span>`;
}html`<div style="display:flex; flex-wrap:wrap; align-items:center; gap:0.5rem; margin:0.3rem 0">
<span style="color:#555; font-size:0.9rem; margin-right:0.4rem">Showing <b>${filtered.length}</b> of ${allianceSummary.length} alliances</span>
<a class="btn btn-sm btn-outline-primary" href="data/estimates.csv" download="${estimates[0].release}-estimates.csv">Download release data (CSV)</a>
<a class="btn btn-sm btn-outline-primary" href="codebook.html">Codebook</a>
</div>
<div style="color:#555; font-size:0.82rem; margin-bottom:0.6rem">Cite as: Alley, Joshua, and Brian Blankenship. 2026. <i>Alliance Credibility Data</i>, release cred-v2026.1. Harvard Dataverse. <a href="https://doi.org/10.7910/DVN/HEFN8Z">https://doi.org/10.7910/DVN/HEFN8Z</a>.</div>`html`<table style="border-collapse:collapse; width:100%; font-size:0.9rem">
<thead>
<tr style="border-bottom:2px solid #ccc; text-align:left">
<th style="padding:5px 8px">Alliance</th>
<th style="padding:5px 8px">Trajectory</th>
<th style="padding:5px 8px">Tier</th>
<th style="padding:5px 8px">Type</th>
<th style="padding:5px 8px">Region</th>
<th style="padding:5px 8px">Years</th>
<th style="padding:5px 8px; text-align:right">Members</th>
</tr>
</thead>
<tbody>
${filtered.map(d => html`<tr style="border-bottom:1px solid #eee">
<td style="padding:5px 8px"><a href="alliance.html?atopid=${d.atopid}">${d.name}</a></td>
<td style="padding:3px 8px">${sparkline(d.traj)}</td>
<td style="padding:5px 8px">${tierBadge(d.tier)}${d.tier === 'bronze' ? html` <span style="font-size:0.7rem; color:#a15c00">LLM-only</span>` : ''}</td>
<td style="padding:5px 8px">${d.type}</td>
<td style="padding:5px 8px">${d.region}</td>
<td style="padding:5px 8px; white-space:nowrap">${d.begyr}–${d.endyr}</td>
<td style="padding:5px 8px; text-align:right">${d.n_members}</td>
</tr>`)}
</tbody>
</table>`