Files
troxler-skat/generate_cards.js
2026-05-31 14:39:45 -05:00

149 lines
7.0 KiB
JavaScript

const fs = require('fs');
const path = require('path');
// Exakte Maße in Pixeln für 300 DPI (2 5/16" x 3 9/16" -> 2.3125" x 3.5625")
const width = 694;
const height = 1069;
const colors = {
Rot: '#E53935', // Trumpf (R)
Gelb: '#FDD835', // Gelb (G)
Gruen: '#43A047', // Grün (GR)
Schwarz: '#212121' // Schwarz (S)
};
// Zielordner anlegen
const outputDir = path.join(__dirname, 'karten_export_v2');
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir);
}
// Schleife durch Farben und Zahlen
for (const [colorName, hex] of Object.entries(colors)) {
const shortColor = colorName === 'Rot' ? 'R' : colorName === 'Gelb' ? 'G' : colorName === 'Gruen' ? 'GR' : 'S';
for (let num = 1; num <= 20; num++) {
// Offizieller Kartencode als Seriennummer anstelle des irritierenden Binärcodes
const cardCode = `TK-${shortColor}${num}`;
// Dynamische Generierung der vollkommen rotationssymmetrischen Symbole für die Mitte
let centerIcons = '';
if (colorName === 'Rot') {
// Symmetrisches Kronen-Paar für Trumpf
centerIcons = `
<g transform="translate(0, -22)">
<path d="M -20 12 L -24 -8 L -11 2 L 0 -15 L 11 2 L 24 -8 L 20 12 Z" fill="${hex}" />
<rect x="-20" y="14" width="40" height="4" fill="${hex}" rx="1" />
</g>
<g transform="rotate(180) translate(0, -22)">
<path d="M -20 12 L -24 -8 L -11 2 L 0 -15 L 11 2 L 24 -8 L 20 12 Z" fill="${hex}" />
<rect x="-20" y="14" width="40" height="4" fill="${hex}" rx="1" />
</g>
`;
} else if (colorName === 'Gruen') {
// Symmetrisches Pflanzen/Blatt-Paar für Grün
centerIcons = `
<g transform="translate(0, -22)">
<path d="M 0 12 Q -16 2 -14 -12 Q -9 -22 0 -25 Q 9 -22 14 -12 Q 16 2 0 12" fill="${hex}" />
<path d="M 0 12 Q -5 16 -10 20" fill="none" stroke="${hex}" stroke-width="3" stroke-linecap="round" />
</g>
<g transform="rotate(180) translate(0, -22)">
<path d="M 0 12 Q -16 2 -14 -12 Q -9 -22 0 -25 Q 9 -22 14 -12 Q 16 2 0 12" fill="${hex}" />
<path d="M 0 12 Q -5 16 -10 20" fill="none" stroke="${hex}" stroke-width="3" stroke-linecap="round" />
</g>
`;
} else if (colorName === 'Gelb') {
// Symmetrisches Sonnen/Sternen-Paar für Gelb
const sunRay = `<path d="M 0 -12 L 2.5 -19 L 0 -22 L -2.5 -19 Z" fill="${hex}" />`;
const singleSun = `
<circle cx="0" cy="0" r="8" fill="${hex}" />
${sunRay}
<g transform="rotate(45)">${sunRay}</g>
<g transform="rotate(90)">${sunRay}</g>
<g transform="rotate(135)">${sunRay}</g>
<g transform="rotate(180)">${sunRay}</g>
<g transform="rotate(225)">${sunRay}</g>
<g transform="rotate(270)">${sunRay}</g>
<g transform="rotate(315)">${sunRay}</g>
`;
centerIcons = `
<g transform="translate(0, -22)">${singleSun}</g>
<g transform="rotate(180) translate(0, -22)">${singleSun}</g>
`;
} else if (colorName === 'Schwarz') {
// Symmetrisches Admin/IT-Zahnrad-Paar für Schwarz
const singleGear = `
<rect x="-2.5" y="-14" width="5" height="28" fill="${hex}" rx="1"/>
<rect x="-2.5" y="-14" width="5" height="28" fill="${hex}" rx="1" transform="rotate(60)"/>
<rect x="-2.5" y="-14" width="5" height="28" fill="${hex}" rx="1" transform="rotate(120)"/>
<circle cx="0" cy="0" r="10" fill="${hex}"/>
<circle cx="0" cy="0" r="5" fill="#ffffff"/>
<circle cx="0" cy="0" r="1.5" fill="${hex}"/>
`;
centerIcons = `
<g transform="translate(0, -22)">${singleGear}</g>
<g transform="rotate(180) translate(0, -22)">${singleGear}</g>
`;
}
const svgContent = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}" width="${width}" height="${height}">
<defs>
<style>
.text { font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-weight: bold; fill: ${hex}; }
.corner-num { font-size: 65px; }
.card-code { font-size: 14px; fill: #888888; font-family: 'Helvetica Neue', Arial, sans-serif; letter-spacing: 1px; }
.center-num { font-size: 320px; letter-spacing: -10px; }
</style>
</defs>
<!-- Karten-Hintergrund -->
<rect width="${width}" height="${height}" rx="35" fill="#ffffff" />
<!-- Innerer Rand für sauberen Beschnitt und edle Optik -->
<rect x="25" y="25" width="${width - 50}" height="${height - 50}" rx="20" fill="none" stroke="${hex}" stroke-width="2" opacity="0.4" />
<!-- Ecken Oben (Links und Rechts sichtbar beim Fächern) -->
<text x="55" y="90" class="text corner-num">${num}</text>
<text x="55" y="112" class="card-code">${cardCode}</text>
<text x="${width - 55}" y="90" class="text corner-num" text-anchor="end">${num}</text>
<text x="${width - 55}" y="112" class="card-code" text-anchor="end">${cardCode}</text>
<!-- Ecken Unten (um 180 Grad rotiert für perfekte Symmetrie) -->
<g transform="translate(${width}, ${height}) rotate(180)">
<text x="55" y="90" class="text corner-num">${num}</text>
<text x="55" y="112" class="card-code">${cardCode}</text>
<text x="${width - 55}" y="90" class="text corner-num" text-anchor="end">${num}</text>
<text x="${width - 55}" y="112" class="card-code" text-anchor="end">${cardCode}</text>
</g>
<!-- Große Zahl Mitte Oben -->
<text x="${width / 2}" y="465" class="text center-num" text-anchor="middle">${num}</text>
<!-- Mittellinie und die gespiegelten Farb-Symbole -->
<g>
<line x1="80" y1="${height / 2}" x2="${width / 2 - 50}" y2="${height / 2}" stroke="${hex}" stroke-width="4" stroke-linecap="round" />
<line x1="${width / 2 + 50}" y1="${height / 2}" x2="${width - 80}" y2="${height / 2}" stroke="${hex}" stroke-width="4" stroke-linecap="round" />
<!-- Das exakt ausbalancierte Symbolzentrum -->
<g transform="translate(${width / 2}, ${height / 2})">
${centerIcons}
</g>
</g>
<!-- Große Zahl Mitte Unten (um 180 Grad rotiert) -->
<g transform="translate(${width}, ${height}) rotate(180)">
<text x="${width / 2}" y="465" class="text center-num" text-anchor="middle">${num}</text>
</g>
</svg>`;
// SVG Datei speichern
const fileName = `${colorName}_${String(num).padStart(2, '0')}.svg`;
fs.writeFileSync(path.join(outputDir, fileName), svgContent);
}
}
console.log('Erfolgreich! 80 vollkommen rotationssymmetrische SVG-Karten wurden im Ordner "karten_export_v2" generiert.');