Generate Political Compass SVG
Generate an SVG visualization of the political compass with the user's position plotted and save to file
Source Code
import fs from "fs";
const args = process.argv.slice(2);
const economicScore = parseFloat(args[0]);
const socialScore = parseFloat(args[1]);
const outputPath = args[2];
if (isNaN(economicScore) || economicScore < -10 || economicScore > 10) {
console.error("Error: economicScore must be a number between -10 and 10");
process.exit(1);
}
if (isNaN(socialScore) || socialScore < -10 || socialScore > 10) {
console.error("Error: socialScore must be a number between -10 and 10");
process.exit(1);
}
if (!outputPath) {
console.error("Error: outputPath is required");
process.exit(1);
}
// SVG dimensions
const size = 400;
const padding = 50;
const gridSize = size - padding * 2;
const center = size / 2;
// Convert scores to pixel coordinates
// Economic: -10 (left) to +10 (right) → padding to (size - padding)
// Social: -10 (libertarian/bottom) to +10 (authoritarian/top) → (size - padding) to padding
const userX = center + (economicScore / 10) * (gridSize / 2);
const userY = center - (socialScore / 10) * (gridSize / 2);
// Generate SVG
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${size} ${size}" width="${size}" height="${size}">
<defs>
<!-- Quadrant gradients -->
<linearGradient id="authLeft" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#dc2626;stop-opacity:0.4"/>
<stop offset="100%" style="stop-color:#dc2626;stop-opacity:0.15"/>
</linearGradient>
<linearGradient id="authRight" x1="100%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#2563eb;stop-opacity:0.4"/>
<stop offset="100%" style="stop-color:#2563eb;stop-opacity:0.15"/>
</linearGradient>
<linearGradient id="libLeft" x1="0%" y1="100%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#16a34a;stop-opacity:0.4"/>
<stop offset="100%" style="stop-color:#16a34a;stop-opacity:0.15"/>
</linearGradient>
<linearGradient id="libRight" x1="100%" y1="100%" x2="0%" y2="0%">
<stop offset="0%" style="stop-color:#eab308;stop-opacity:0.4"/>
<stop offset="100%" style="stop-color:#eab308;stop-opacity:0.15"/>
</linearGradient>
</defs>
<!-- Background -->
<rect width="${size}" height="${size}" fill="#fafafa"/>
<!-- Quadrants -->
<rect x="${padding}" y="${padding}" width="${gridSize / 2}" height="${gridSize / 2}" fill="url(#authLeft)"/>
<rect x="${center}" y="${padding}" width="${gridSize / 2}" height="${gridSize / 2}" fill="url(#authRight)"/>
<rect x="${padding}" y="${center}" width="${gridSize / 2}" height="${gridSize / 2}" fill="url(#libLeft)"/>
<rect x="${center}" y="${center}" width="${gridSize / 2}" height="${gridSize / 2}" fill="url(#libRight)"/>
<!-- Grid lines (light) -->
${[1, 2, 3, 4]
.map(
(i) => `
<line x1="${padding + (gridSize / 5) * i}" y1="${padding}" x2="${padding + (gridSize / 5) * i}" y2="${size - padding}" stroke="#d1d5db" stroke-width="0.5"/>
<line x1="${padding}" y1="${padding + (gridSize / 5) * i}" x2="${size - padding}" y2="${padding + (gridSize / 5) * i}" stroke="#d1d5db" stroke-width="0.5"/>`
)
.join("")}
<!-- Axes -->
<line x1="${padding}" y1="${center}" x2="${size - padding}" y2="${center}" stroke="#374151" stroke-width="2"/>
<line x1="${center}" y1="${padding}" x2="${center}" y2="${size - padding}" stroke="#374151" stroke-width="2"/>
<!-- Axis labels -->
<text x="${center}" y="${padding - 15}" text-anchor="middle" font-family="system-ui, sans-serif" font-size="12" font-weight="600" fill="#374151">AUTHORITARIAN</text>
<text x="${center}" y="${size - padding + 25}" text-anchor="middle" font-family="system-ui, sans-serif" font-size="12" font-weight="600" fill="#374151">LIBERTARIAN</text>
<text x="${padding - 10}" y="${center}" text-anchor="middle" font-family="system-ui, sans-serif" font-size="12" font-weight="600" fill="#374151" transform="rotate(-90 ${padding - 10} ${center})">ECONOMIC LEFT</text>
<text x="${size - padding + 10}" y="${center}" text-anchor="middle" font-family="system-ui, sans-serif" font-size="12" font-weight="600" fill="#374151" transform="rotate(90 ${size - padding + 10} ${center})">ECONOMIC RIGHT</text>
<!-- Quadrant ideology labels -->
<text x="${padding + gridSize / 4}" y="${padding + gridSize / 4 - 10}" text-anchor="middle" font-family="system-ui, sans-serif" font-size="10" fill="#991b1b" opacity="0.8">Authoritarian</text>
<text x="${padding + gridSize / 4}" y="${padding + gridSize / 4 + 5}" text-anchor="middle" font-family="system-ui, sans-serif" font-size="10" fill="#991b1b" opacity="0.8">Left</text>
<text x="${center + gridSize / 4}" y="${padding + gridSize / 4 - 10}" text-anchor="middle" font-family="system-ui, sans-serif" font-size="10" fill="#1e40af" opacity="0.8">Authoritarian</text>
<text x="${center + gridSize / 4}" y="${padding + gridSize / 4 + 5}" text-anchor="middle" font-family="system-ui, sans-serif" font-size="10" fill="#1e40af" opacity="0.8">Right</text>
<text x="${padding + gridSize / 4}" y="${center + gridSize / 4 - 10}" text-anchor="middle" font-family="system-ui, sans-serif" font-size="10" fill="#166534" opacity="0.8">Libertarian</text>
<text x="${padding + gridSize / 4}" y="${center + gridSize / 4 + 5}" text-anchor="middle" font-family="system-ui, sans-serif" font-size="10" fill="#166534" opacity="0.8">Left</text>
<text x="${center + gridSize / 4}" y="${center + gridSize / 4 - 10}" text-anchor="middle" font-family="system-ui, sans-serif" font-size="10" fill="#a16207" opacity="0.8">Libertarian</text>
<text x="${center + gridSize / 4}" y="${center + gridSize / 4 + 5}" text-anchor="middle" font-family="system-ui, sans-serif" font-size="10" fill="#a16207" opacity="0.8">Right</text>
<!-- User position dot -->
<circle cx="${userX}" cy="${userY}" r="12" fill="#1f2937" stroke="#ffffff" stroke-width="3"/>
<circle cx="${userX}" cy="${userY}" r="5" fill="#ffffff"/>
<!-- Coordinates label -->
<text x="${userX}" y="${userY + 25}" text-anchor="middle" font-family="system-ui, sans-serif" font-size="10" font-weight="600" fill="#1f2937">(${economicScore.toFixed(1)}, ${socialScore.toFixed(1)})</text>
<!-- Border -->
<rect x="${padding}" y="${padding}" width="${gridSize}" height="${gridSize}" fill="none" stroke="#374151" stroke-width="2"/>
</svg>`;
// Save SVG to file
fs.writeFileSync(outputPath, svg);
console.log("Generated political compass SVG visualization");
console.log(`User position: Economic ${economicScore.toFixed(1)}, Social ${socialScore.toFixed(1)}`);
console.log(`Saved to: ${outputPath}`);
console.log(JSON.stringify({
success: true,
path: outputPath,
economicScore: economicScore,
socialScore: socialScore
}));