Files
geograsim/App/tile-test.html
T
Adminator 33fae37838 User Management + Didaktisches Handbuch + Stadt-Editor + Emoji-Kacheln
User Management (Backend):
- schema-v2.sql: students, licenses, student_results, activity_log Tabellen
- auth.php: Lehrer-Registrierung/Login, Schueler-Login, Status-Check
- classes.php: CRUD fuer Klassenverwaltung (mit Join-Code-Generator)
- students.php: Schueler erstellen (einzeln + Batch), bearbeiten, loeschen
- modules.php: Modulfreigabe pro Klasse (locked/free/teacher_started)

Didaktisches Handbuch:
- handbuch.html: Vollstaendiger Lehrpersonen-Guide
- 6 Module detailliert beschrieben (Lernziele, Kompetenzen)
- Vor/Nach-Fragen fuer jede Simulation
- Empfohlener Unterrichtsablauf (45-min-Einheit)
- Differenzierungshinweise, Bewertungsempfehlungen

Stadt-Editor:
- stadt-editor.html: Funktionierendes 8x8 Raster mit Kachel-Platzierung
- 15 Emoji-Gebaude-Kacheln (Kirche, Moschee, Wohngebiet, Fabrik, etc.)
- Spielplatz: Rutsche+Karussell statt schwebende Koepfe
- Hochhaeuser: 6 Gebaeude in 2 Reihen

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 01:52:55 +02:00

490 lines
18 KiB
HTML

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kachel-Test — Gebäude</title>
<style>
body { margin:0; display:flex; align-items:flex-start; justify-content:center; min-height:100vh; background:#e0e0d8; gap:10px; flex-wrap:wrap; font-family:Inter,sans-serif; padding:15px; }
.tile { display:flex; flex-direction:column; align-items:center; gap:2px; }
.tile span { font-size:9px; color:#666; }
</style>
</head>
<body>
<div class="tile"><canvas id="t01" width="200" height="200"></canvas><span>Kirche</span></div>
<div class="tile"><canvas id="t02" width="200" height="200"></canvas><span>Moschee</span></div>
<div class="tile"><canvas id="t03" width="200" height="200"></canvas><span>Wohngebiet</span></div>
<div class="tile"><canvas id="t04" width="200" height="200"></canvas><span>Fabrik</span></div>
<div class="tile"><canvas id="t05" width="200" height="200"></canvas><span>Spital</span></div>
<div class="tile"><canvas id="t06" width="200" height="200"></canvas><span>Feuerwehr</span></div>
<div class="tile"><canvas id="t07" width="200" height="200"></canvas><span>Polizei</span></div>
<div class="tile"><canvas id="t08" width="200" height="200"></canvas><span>Schule</span></div>
<div class="tile"><canvas id="t09" width="200" height="200"></canvas><span>Supermarkt</span></div>
<div class="tile"><canvas id="t10" width="200" height="200"></canvas><span>Park</span></div>
<script>
var SZ = 200
var RW = SZ * 0.4, M = SZ / 2, HR = RW / 2
var LW = 2
var GREEN = '#b8ccaa', ROAD = '#2e2e2e', WHITE = '#fff'
var DASH = [SZ*0.07, SZ*0.05]
var DOFF = -SZ*0.035
// === Strassen-Grundfunktionen ===
function base(id) {
var c = document.getElementById(id).getContext('2d')
c.fillStyle = GREEN; c.fillRect(0,0,SZ,SZ)
return c
}
function drawRoadNS(c, x) {
// Vertikale Strasse bei x-Mitte = x
c.fillStyle = ROAD; c.fillRect(x-HR, 0, RW, SZ)
c.strokeStyle = WHITE; c.lineWidth = LW
c.beginPath(); c.moveTo(x-HR,0); c.lineTo(x-HR,SZ); c.stroke()
c.beginPath(); c.moveTo(x+HR,0); c.lineTo(x+HR,SZ); c.stroke()
c.setLineDash(DASH); c.lineDashOffset = DOFF
c.beginPath(); c.moveTo(x,0); c.lineTo(x,SZ); c.stroke()
c.setLineDash([]); c.lineDashOffset = 0
}
function drawRoadEW(c, y) {
c.fillStyle = ROAD; c.fillRect(0, y-HR, SZ, RW)
c.strokeStyle = WHITE; c.lineWidth = LW
c.beginPath(); c.moveTo(0,y-HR); c.lineTo(SZ,y-HR); c.stroke()
c.beginPath(); c.moveTo(0,y+HR); c.lineTo(SZ,y+HR); c.stroke()
c.setLineDash(DASH); c.lineDashOffset = DOFF
c.beginPath(); c.moveTo(0,y); c.lineTo(SZ,y); c.stroke()
c.setLineDash([]); c.lineDashOffset = 0
}
function drawStubN(c) {
// Sackgasse von oben — kurzer Stummel
var stubY = 4
c.fillStyle = ROAD; c.fillRect(M-HR, 0, RW, stubY)
c.beginPath(); c.arc(M, stubY, HR, 0, Math.PI); c.fill()
c.strokeStyle = WHITE; c.lineWidth = LW
c.beginPath(); c.moveTo(M-HR,0); c.lineTo(M-HR,stubY); c.stroke()
c.beginPath(); c.moveTo(M+HR,0); c.lineTo(M+HR,stubY); c.stroke()
c.beginPath(); c.arc(M, stubY, HR, 0, Math.PI); c.stroke()
}
function drawStubS(c) {
var stubY = SZ - 4
c.fillStyle = ROAD; c.fillRect(M-HR, stubY, RW, 4)
c.beginPath(); c.arc(M, stubY, HR, Math.PI, 0); c.fill()
c.strokeStyle = WHITE; c.lineWidth = LW
c.beginPath(); c.moveTo(M-HR,SZ); c.lineTo(M-HR,stubY); c.stroke()
c.beginPath(); c.moveTo(M+HR,SZ); c.lineTo(M+HR,stubY); c.stroke()
c.beginPath(); c.arc(M, stubY, HR, Math.PI, 0); c.stroke()
}
function drawStubE(c) {
var stubX = SZ - 4
c.fillStyle = ROAD; c.fillRect(stubX, M-HR, 4, RW)
c.beginPath(); c.arc(stubX, M, HR, Math.PI*1.5, Math.PI*0.5); c.fill()
c.strokeStyle = WHITE; c.lineWidth = LW
c.beginPath(); c.moveTo(SZ,M-HR); c.lineTo(stubX,M-HR); c.stroke()
c.beginPath(); c.moveTo(SZ,M+HR); c.lineTo(stubX,M+HR); c.stroke()
c.beginPath(); c.arc(stubX, M, HR, Math.PI*1.5, Math.PI*0.5); c.stroke()
}
function drawStubW(c) {
var stubX = 4
c.fillStyle = ROAD; c.fillRect(0, M-HR, 4, RW)
c.beginPath(); c.arc(stubX, M, HR, Math.PI*0.5, Math.PI*1.5); c.fill()
c.strokeStyle = WHITE; c.lineWidth = LW
c.beginPath(); c.moveTo(0,M-HR); c.lineTo(stubX,M-HR); c.stroke()
c.beginPath(); c.moveTo(0,M+HR); c.lineTo(stubX,M+HR); c.stroke()
c.beginPath(); c.arc(stubX, M, HR, Math.PI*0.5, Math.PI*1.5); c.stroke()
}
// === Gebaeude-Hilfszeichnung ===
function drawBuilding(c, x, y, w, h, color, label) {
// Gebaeude als Rechteck mit Farbe + Label
c.fillStyle = color
c.fillRect(x, y, w, h)
c.strokeStyle = 'rgba(0,0,0,0.15)'; c.lineWidth = 1
c.strokeRect(x, y, w, h)
// Dach-Effekt (dunklere Oberkante)
c.fillStyle = 'rgba(0,0,0,0.08)'
c.fillRect(x, y, w, 4)
// Label
if (label) {
c.fillStyle = 'rgba(255,255,255,0.9)'
c.font = 'bold 10px Inter, sans-serif'
c.textAlign = 'center'; c.textBaseline = 'middle'
c.fillText(label, x + w/2, y + h/2)
}
}
function drawHouse(c, x, y, w, h) {
// Kleines Haus mit Dach
c.fillStyle = '#d4a574'
c.fillRect(x, y + h*0.35, w, h*0.65)
// Dach
c.fillStyle = '#8B4513'
c.beginPath()
c.moveTo(x - 2, y + h*0.35)
c.lineTo(x + w/2, y)
c.lineTo(x + w + 2, y + h*0.35)
c.closePath()
c.fill()
// Fenster
c.fillStyle = '#a8d0e0'
c.fillRect(x + w*0.2, y + h*0.5, w*0.25, h*0.2)
// Tuer
c.fillStyle = '#6a4a3a'
c.fillRect(x + w*0.55, y + h*0.55, w*0.2, h*0.4)
}
function drawTree(c, x, y, sz) {
c.fillStyle = '#5a4020'
c.fillRect(x + sz*0.4, y + sz*0.5, sz*0.2, sz*0.5)
c.fillStyle = '#3a8a2a'
c.beginPath(); c.arc(x + sz*0.5, y + sz*0.4, sz*0.4, 0, Math.PI*2); c.fill()
}
// ============================================================
// 1. KIRCHE — Sackgasse S, grosses Gebaeude
// ============================================================
;(function(){
var c = base('t01')
drawStubS(c)
// Grosses Kirchengebaeude
drawBuilding(c, 30, 15, 140, 110, '#c8b090', '')
// Turm
c.fillStyle = '#a08060'
c.fillRect(80, 5, 40, 60)
// Kreuz oben
c.strokeStyle = '#5a4a3a'; c.lineWidth = 3
c.beginPath(); c.moveTo(100, 2); c.lineTo(100, 18); c.stroke()
c.beginPath(); c.moveTo(92, 10); c.lineTo(108, 10); c.stroke()
// Tuer
c.fillStyle = '#5a3a2a'
c.beginPath(); c.arc(100, 125, 15, Math.PI, 0); c.fill()
c.fillRect(85, 115, 30, 15)
// Label
c.fillStyle = '#5a4a3a'; c.font = 'bold 11px Inter,sans-serif'; c.textAlign = 'center'
c.fillText('Kirche', 100, 85)
})()
// ============================================================
// 2. MOSCHEE — Sackgasse N + S (zwei Zufahrten)
// ============================================================
;(function(){
var c = base('t02')
drawStubN(c)
drawStubS(c)
// Gebaeude
drawBuilding(c, 25, 35, 150, 90, '#d8c8a8', '')
// Kuppel
c.fillStyle = '#c0a878'
c.beginPath(); c.arc(100, 50, 35, Math.PI, 0); c.fill()
// Halbmond
c.fillStyle = '#e8d8a0'; c.font = '18px serif'; c.textAlign = 'center'
c.fillText('☪', 100, 42)
// Minarett
c.fillStyle = '#b8a878'
c.fillRect(150, 25, 12, 70)
c.fillRect(147, 22, 18, 6)
// Label
c.fillStyle = '#6a5a3a'; c.font = 'bold 10px Inter,sans-serif'
c.fillText('Moschee', 100, 100)
})()
// ============================================================
// 3. WOHNGEBIET — Gerade N-S, Haeuser links und rechts
// ============================================================
;(function(){
var c = base('t03')
drawRoadNS(c, M)
// Haeuser links
drawHouse(c, 8, 20, 30, 30)
drawHouse(c, 12, 70, 28, 28)
drawHouse(c, 6, 120, 32, 30)
// Haeuser rechts
drawHouse(c, 160, 15, 30, 28)
drawHouse(c, 162, 65, 28, 30)
drawHouse(c, 158, 115, 32, 28)
drawHouse(c, 164, 160, 26, 26)
})()
// ============================================================
// 4. FABRIK — Kurve (N→E), Fabrik im gruenen Bereich (unten-links)
// ============================================================
;(function(){
var c = base('t04')
// Kurve N→E
var px = M+HR, py = M-HR
c.fillStyle = ROAD
c.fillRect(M-HR, 0, RW, py)
c.fillRect(px, M-HR, SZ-px, RW)
c.beginPath(); c.moveTo(px,py); c.arc(px,py,RW,Math.PI,Math.PI*0.5,true); c.closePath(); c.fill()
// Raender
c.strokeStyle=WHITE;c.lineWidth=LW
c.beginPath();c.arc(px,py,RW,Math.PI,Math.PI*0.5,true);c.stroke()
c.beginPath();c.moveTo(M+HR,0);c.lineTo(M+HR,py);c.stroke()
c.beginPath();c.moveTo(px,M-HR);c.lineTo(SZ,M-HR);c.stroke()
c.beginPath();c.moveTo(M-HR,0);c.lineTo(M-HR,py);c.stroke()
c.beginPath();c.moveTo(px,M+HR);c.lineTo(SZ,M+HR);c.stroke()
// Mittellinie
c.setLineDash(DASH);c.lineDashOffset=DOFF
c.beginPath();c.moveTo(M,0);c.lineTo(M,py);c.arc(px,py,HR,Math.PI,Math.PI*0.5,true);c.lineTo(SZ,M);c.stroke()
c.setLineDash([]);c.lineDashOffset=0
// Fabrik unten-links
drawBuilding(c, 10, 130, 70, 55, '#8a8a8a', '')
// Schornstein
c.fillStyle = '#6a6a6a'
c.fillRect(55, 110, 12, 20)
c.fillRect(30, 115, 10, 15)
// Rauch
c.fillStyle = 'rgba(100,100,100,0.25)'
c.beginPath(); c.arc(61, 105, 6, 0, Math.PI*2); c.fill()
c.beginPath(); c.arc(58, 96, 5, 0, Math.PI*2); c.fill()
// Label
c.fillStyle = '#fff'; c.font = 'bold 10px Inter,sans-serif'; c.textAlign = 'center'
c.fillText('Fabrik', 45, 160)
})()
// ============================================================
// 5. SPITAL — Sackgasse E + W (zwei Zufahrten seitlich)
// ============================================================
;(function(){
var c = base('t05')
drawStubE(c)
drawStubW(c)
// Grosses Gebaeude
drawBuilding(c, 20, 15, 160, 80, '#e8e0d0', '')
// Rotes Kreuz
c.fillStyle = '#cc3333'
c.fillRect(90, 30, 20, 50)
c.fillRect(75, 42, 50, 20)
// Label
c.fillStyle = '#6a3a3a'; c.font = 'bold 11px Inter,sans-serif'; c.textAlign = 'center'
c.fillText('Spital', 100, 120)
// Rettungswagen-Parkplatz
c.fillStyle = '#7a7a7a'; c.fillRect(30, 100, 50, 25)
c.fillStyle = '#ddd'; c.font = '16px serif'
c.fillText('🚑', 55, 117)
})()
// ============================================================
// 6. FEUERWEHR — Sackgasse S
// ============================================================
;(function(){
var c = base('t06')
drawStubS(c)
// Gebaeude
drawBuilding(c, 25, 10, 150, 100, '#cc4444', '')
// Tore (2 Garagen)
c.fillStyle = '#8a2a2a'
c.fillRect(40, 70, 45, 40)
c.fillRect(105, 70, 45, 40)
// Tor-Linien
c.strokeStyle = '#6a1a1a'; c.lineWidth = 1
for (var i = 0; i < 5; i++) { c.beginPath(); c.moveTo(40, 75+i*7); c.lineTo(85, 75+i*7); c.stroke() }
for (var i = 0; i < 5; i++) { c.beginPath(); c.moveTo(105, 75+i*7); c.lineTo(150, 75+i*7); c.stroke() }
// Label
c.fillStyle = '#fff'; c.font = 'bold 11px Inter,sans-serif'; c.textAlign = 'center'
c.fillText('Feuerwehr', 100, 45)
// Schlauchturm
c.fillStyle = '#aa3333'
c.fillRect(160, 15, 15, 55)
})()
// ============================================================
// 7. POLIZEI — Sackgasse N
// ============================================================
;(function(){
var c = base('t07')
drawStubN(c)
// Gebaeude
drawBuilding(c, 20, 50, 160, 85, '#4a6a9a', '')
// Stern/Abzeichen
c.fillStyle = '#c0d0e8'; c.font = '24px serif'; c.textAlign = 'center'
c.fillText('⭐', 100, 85)
// Label
c.fillStyle = '#fff'; c.font = 'bold 11px Inter,sans-serif'
c.fillText('Polizei', 100, 115)
// Parkplatz
c.fillStyle = '#7a7a7a'; c.fillRect(30, 145, 60, 20)
c.fillStyle = '#ddd'; c.font = '14px serif'
c.fillText('🚔', 60, 160)
})()
// ============================================================
// 8. SCHULE — Gerade E-W, Gebaeude oben
// ============================================================
;(function(){
var c = base('t08')
drawRoadEW(c, M)
// Schulgebaeude oben
drawBuilding(c, 15, 10, 170, 60, '#e0c888', '')
// Fensterreihe
c.fillStyle = '#a8d0e0'
for (var i = 0; i < 5; i++) c.fillRect(25 + i*34, 25, 22, 18)
// Label
c.fillStyle = '#5a4a2a'; c.font = 'bold 11px Inter,sans-serif'; c.textAlign = 'center'
c.fillText('Schule', 100, 58)
// Schulhof unten (Wiese ist schon gruen, ein paar Details)
drawTree(c, 30, 145, 20)
drawTree(c, 140, 150, 18)
c.fillStyle = '#aaa'; c.fillRect(70, 155, 50, 3) // Bank
})()
// ============================================================
// 9. SUPERMARKT — Gerade N-S, Gebaeude rechts mit Parkplatz
// ============================================================
;(function(){
var c = base('t09')
drawRoadNS(c, M)
// Supermarkt rechts
drawBuilding(c, 140, 20, 55, 80, '#e0d0a0', '')
// Label
c.fillStyle = '#5a4a2a'; c.font = 'bold 9px Inter,sans-serif'; c.textAlign = 'center'
c.fillText('Super-', 167, 50)
c.fillText('markt', 167, 62)
// Parkplatz
c.fillStyle = '#8a8a8a'
c.fillRect(140, 110, 55, 40)
// Parkplatz-Linien
c.strokeStyle = '#aaa'; c.lineWidth = 1
for (var i = 0; i < 4; i++) { c.beginPath(); c.moveTo(152+i*12, 110); c.lineTo(152+i*12, 150); c.stroke() }
// Einkaufswagen
c.fillStyle = '#ddd'; c.font = '12px serif'
c.fillText('🛒', 167, 135)
})()
// ============================================================
// 10. PARK — Sackgasse N, viel Gruen
// ============================================================
;(function(){
var c = base('t10')
drawStubN(c)
// Baeume
drawTree(c, 15, 40, 28)
drawTree(c, 60, 55, 24)
drawTree(c, 130, 35, 30)
drawTree(c, 155, 80, 22)
drawTree(c, 25, 120, 26)
drawTree(c, 100, 110, 20)
drawTree(c, 150, 140, 24)
// Teich
c.fillStyle = 'rgba(60,140,200,0.4)'
c.beginPath(); c.ellipse(80, 140, 30, 18, 0.1, 0, Math.PI*2); c.fill()
c.strokeStyle = 'rgba(60,140,200,0.3)'; c.lineWidth = 1; c.stroke()
// Bank
c.fillStyle = '#8a7050'
c.fillRect(95, 82, 20, 6)
c.fillRect(95, 82, 3, 10)
c.fillRect(112, 82, 3, 10)
// Weg (kleiner Pfad)
c.strokeStyle = 'rgba(160,140,100,0.4)'; c.lineWidth = 3; c.setLineDash([4,3])
c.beginPath(); c.moveTo(M, 10); c.quadraticCurveTo(60, 80, 80, 140); c.stroke()
c.setLineDash([])
// Label
c.fillStyle = 'rgba(0,0,0,0.35)'; c.font = 'bold 11px Inter,sans-serif'; c.textAlign = 'center'
c.fillText('Park', 100, 175)
})()
// ============================================================
// EMOJI-VERSIONEN (Gegenversuch)
// ============================================================
var emojiTiles = [
{id:'e01', label:'Kirche', stub:'S', emoji:'⛪', size:95},
{id:'e02', label:'Moschee', stub:'NS', emoji:'🕌', size:85},
{id:'e03', label:'Wohngebiet', road:'NS', emojis:[
{e:'🏠',x:-0.32,y:-0.3,s:32},{e:'🏡',x:-0.3,y:0,s:30},{e:'🏠',x:-0.32,y:0.28,s:28},
{e:'🏘️',x:0.32,y:-0.25,s:30},{e:'🏠',x:0.3,y:0.05,s:32},{e:'🏡',x:0.32,y:0.3,s:28}]},
{id:'e04', label:'Fabrik', stub:'S', emoji:'🏭', size:85},
{id:'e05', label:'Spital', stub:'EW', emoji:'🏥', size:75, extra:[{e:'🚑',x:0,y:0.3,s:32}]},
{id:'e06', label:'Feuerwehr', stub:'S', bg:'rgba(200,50,40,0.12)', emojis:[
{e:'🏠',x:0,y:-0.15,s:60},{e:'🚒',x:-0.2,y:0.22,s:40},{e:'🚒',x:0.2,y:0.22,s:40}]},
{id:'e07', label:'Polizei', stub:'N', emoji:'🚔', size:45, extra:[{e:'🏢',x:0,y:0.15,s:55}]},
{id:'e08', label:'Schule', road:'EW', emoji:'🏫', size:60, yoff:-0.28},
{id:'e09', label:'Supermarkt', road:'NS', emoji:'🏪', size:55, xoff:0.3, extra:[
{e:'🚗',x:0.22,y:0.25,s:26},{e:'🚙',x:0.35,y:0.15,s:24},{e:'🚗',x:0.22,y:0.38,s:22}]},
{id:'e10', label:'Park', stub:'N', emojis:[
{e:'🌳',x:-0.3,y:-0.1,s:32},{e:'🌳',x:-0.1,y:-0.1,s:32},{e:'🌳',x:0.1,y:-0.1,s:32},{e:'🌳',x:0.3,y:-0.1,s:32},
{e:'🌳',x:-0.2,y:0.1,s:28},{e:'🌳',x:0,y:0.1,s:28},{e:'🌳',x:0.2,y:0.1,s:28},
{e:'🌷',x:-0.35,y:0.3,s:16},{e:'🌷',x:-0.2,y:0.32,s:14},{e:'🌷',x:-0.05,y:0.3,s:16},
{e:'🌷',x:0.1,y:0.32,s:14},{e:'🌷',x:0.25,y:0.3,s:16},{e:'🌷',x:0.38,y:0.32,s:14}]},
{id:'e11', label:'Rathaus', stub:'S', emoji:'🏛️', size:85},
{id:'e13', label:'Tankstelle', road:'NS', emojis:[
{e:'⛽',x:0.28,y:-0.2,s:32},{e:'⛽',x:0.28,y:0,s:32},{e:'⛽',x:0.28,y:0.2,s:32},
{e:'🚗',x:0.38,y:-0.15,s:26},{e:'🚙',x:0.38,y:0.15,s:26}]},
{id:'e14', label:'Spielplatz', stub:'N', emojis:[
{e:'🛝',x:-0.2,y:0,s:42},{e:'🎠',x:0.2,y:0,s:36},{e:'⚽',x:0,y:0.25,s:22},
{e:'🌳',x:-0.35,y:0.3,s:26},{e:'🌳',x:0.35,y:0.3,s:26}]},
{id:'e15', label:'Bauernhof', stub:'EW', emojis:[
{e:'🏠',x:0,y:-0.05,s:55},
{e:'🌾',x:-0.35,y:-0.3,s:24},{e:'🌾',x:-0.2,y:-0.3,s:24},{e:'🌾',x:-0.05,y:-0.3,s:24},
{e:'🌾',x:0.1,y:-0.3,s:24},{e:'🌾',x:0.25,y:-0.3,s:24},{e:'🌾',x:0.4,y:-0.3,s:24},
{e:'🐄',x:-0.25,y:0.28,s:30},{e:'🐔',x:0.15,y:0.3,s:22},{e:'🐔',x:0.28,y:0.28,s:22}]},
{id:'e16', label:'Hochhäuser', road:'NS', emojis:[
{e:'🏢',x:0.22,y:-0.2,s:38},{e:'🏢',x:0.32,y:-0.2,s:38},{e:'🏢',x:0.42,y:-0.2,s:38},
{e:'🏢',x:0.22,y:0.15,s:38},{e:'🏢',x:0.32,y:0.15,s:38},{e:'🏢',x:0.42,y:0.15,s:38}]},
]
// Erzeuge HTML fuer Emoji-Tiles
var hr = document.createElement('div')
hr.style.cssText = 'width:100%;text-align:center;color:#888;font-size:11px;margin:8px 0;border-top:1px solid #ccc;padding-top:6px'
hr.textContent = '▼ Emoji-Versionen ▼'
document.body.appendChild(hr)
emojiTiles.forEach(function(t) {
var div = document.createElement('div')
div.className = 'tile'
var cv = document.createElement('canvas')
cv.width = 200; cv.height = 200; cv.id = t.id
var span = document.createElement('span')
span.textContent = t.label
div.appendChild(cv); div.appendChild(span)
document.body.appendChild(div)
var c = cv.getContext('2d')
c.fillStyle = GREEN; c.fillRect(0, 0, SZ, SZ)
// Hintergrundfarbe (z.B. rot fuer Feuerwehr)
if (t.bg) { c.fillStyle = t.bg; c.fillRect(0, 0, SZ, SZ) }
// Strasse
if (t.road === 'NS') drawRoadNS(c, M)
if (t.road === 'EW') drawRoadEW(c, M)
if (t.stub) {
if (t.stub.indexOf('N') >= 0) drawStubN(c)
if (t.stub.indexOf('S') >= 0) drawStubS(c)
if (t.stub.indexOf('E') >= 0) drawStubE(c)
if (t.stub.indexOf('W') >= 0) drawStubW(c)
}
// Emojis
c.textAlign = 'center'; c.textBaseline = 'middle'
if (t.emoji) {
c.font = (t.size || 50) + 'px serif'
c.fillText(t.emoji, M + (t.xoff || 0) * SZ, M + (t.yoff || 0) * SZ)
}
if (t.emojis) {
t.emojis.forEach(function(em) {
c.font = (em.s || 24) + 'px serif'
c.fillText(em.e, M + em.x * SZ, M + em.y * SZ)
})
}
if (t.extra) {
t.extra.forEach(function(em) {
c.font = (em.s || 24) + 'px serif'
c.fillText(em.e, M + (em.x||0) * SZ, M + (em.y||0) * SZ)
})
}
// Keine Beschriftung auf der Kachel
})
</script>
</body>
</html>