diff --git a/public/media/bingo/logos/europython-2002.png b/public/media/bingo/logos/europython-2002.png new file mode 100644 index 000000000..5f16056d4 Binary files /dev/null and b/public/media/bingo/logos/europython-2002.png differ diff --git a/public/media/bingo/logos/europython-2003.png b/public/media/bingo/logos/europython-2003.png new file mode 100644 index 000000000..efdd40682 Binary files /dev/null and b/public/media/bingo/logos/europython-2003.png differ diff --git a/public/media/bingo/logos/europython-2004.png b/public/media/bingo/logos/europython-2004.png new file mode 100644 index 000000000..0b0ada983 Binary files /dev/null and b/public/media/bingo/logos/europython-2004.png differ diff --git a/public/media/bingo/logos/europython-2005.png b/public/media/bingo/logos/europython-2005.png new file mode 100644 index 000000000..0b0ada983 Binary files /dev/null and b/public/media/bingo/logos/europython-2005.png differ diff --git a/public/media/bingo/logos/europython-2006.png b/public/media/bingo/logos/europython-2006.png new file mode 100644 index 000000000..40495659b Binary files /dev/null and b/public/media/bingo/logos/europython-2006.png differ diff --git a/public/media/bingo/logos/europython-2007.png b/public/media/bingo/logos/europython-2007.png new file mode 100644 index 000000000..8de384000 Binary files /dev/null and b/public/media/bingo/logos/europython-2007.png differ diff --git a/public/media/bingo/logos/europython-2008.png b/public/media/bingo/logos/europython-2008.png new file mode 100644 index 000000000..3812e03bc Binary files /dev/null and b/public/media/bingo/logos/europython-2008.png differ diff --git a/public/media/bingo/logos/europython-2009.png b/public/media/bingo/logos/europython-2009.png new file mode 100644 index 000000000..13f79dfee Binary files /dev/null and b/public/media/bingo/logos/europython-2009.png differ diff --git a/public/media/bingo/logos/europython-2010.png b/public/media/bingo/logos/europython-2010.png new file mode 100644 index 000000000..b1079a237 Binary files /dev/null and b/public/media/bingo/logos/europython-2010.png differ diff --git a/public/media/bingo/logos/europython-2011.png b/public/media/bingo/logos/europython-2011.png new file mode 100644 index 000000000..a1600c437 Binary files /dev/null and b/public/media/bingo/logos/europython-2011.png differ diff --git a/public/media/bingo/logos/europython-2012.png b/public/media/bingo/logos/europython-2012.png new file mode 100644 index 000000000..14e02013f Binary files /dev/null and b/public/media/bingo/logos/europython-2012.png differ diff --git a/public/media/bingo/logos/europython-2013.png b/public/media/bingo/logos/europython-2013.png new file mode 100644 index 000000000..19ce7b0d1 Binary files /dev/null and b/public/media/bingo/logos/europython-2013.png differ diff --git a/public/media/bingo/logos/europython-2014.png b/public/media/bingo/logos/europython-2014.png new file mode 100644 index 000000000..3ccfc9581 Binary files /dev/null and b/public/media/bingo/logos/europython-2014.png differ diff --git a/public/media/bingo/logos/europython-2015.png b/public/media/bingo/logos/europython-2015.png new file mode 100644 index 000000000..77a7dfe7f Binary files /dev/null and b/public/media/bingo/logos/europython-2015.png differ diff --git a/public/media/bingo/logos/europython-2016.png b/public/media/bingo/logos/europython-2016.png new file mode 100644 index 000000000..efbdbeefa Binary files /dev/null and b/public/media/bingo/logos/europython-2016.png differ diff --git a/public/media/bingo/logos/europython-2017.png b/public/media/bingo/logos/europython-2017.png new file mode 100644 index 000000000..374a1045b Binary files /dev/null and b/public/media/bingo/logos/europython-2017.png differ diff --git a/public/media/bingo/logos/europython-2018.png b/public/media/bingo/logos/europython-2018.png new file mode 100644 index 000000000..d4d80d5f0 Binary files /dev/null and b/public/media/bingo/logos/europython-2018.png differ diff --git a/public/media/bingo/logos/europython-2019.png b/public/media/bingo/logos/europython-2019.png new file mode 100644 index 000000000..852899652 Binary files /dev/null and b/public/media/bingo/logos/europython-2019.png differ diff --git a/public/media/bingo/logos/europython-2020.png b/public/media/bingo/logos/europython-2020.png new file mode 100644 index 000000000..6dbd8c2d3 Binary files /dev/null and b/public/media/bingo/logos/europython-2020.png differ diff --git a/public/media/bingo/logos/europython-2021.png b/public/media/bingo/logos/europython-2021.png new file mode 100644 index 000000000..e7168afbb Binary files /dev/null and b/public/media/bingo/logos/europython-2021.png differ diff --git a/public/media/bingo/logos/europython-2022.png b/public/media/bingo/logos/europython-2022.png new file mode 100644 index 000000000..0a3656e20 Binary files /dev/null and b/public/media/bingo/logos/europython-2022.png differ diff --git a/public/media/bingo/logos/europython-2022.svg b/public/media/bingo/logos/europython-2022.svg new file mode 100644 index 000000000..0a650fb42 --- /dev/null +++ b/public/media/bingo/logos/europython-2022.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/media/bingo/logos/europython-2023.svg b/public/media/bingo/logos/europython-2023.svg new file mode 100644 index 000000000..809a6721e --- /dev/null +++ b/public/media/bingo/logos/europython-2023.svg @@ -0,0 +1,280 @@ + \ No newline at end of file diff --git a/public/media/bingo/logos/europython-2024.png b/public/media/bingo/logos/europython-2024.png new file mode 100644 index 000000000..7168db599 Binary files /dev/null and b/public/media/bingo/logos/europython-2024.png differ diff --git a/public/media/bingo/logos/europython-2025.svg b/public/media/bingo/logos/europython-2025.svg new file mode 100644 index 000000000..e43745392 --- /dev/null +++ b/public/media/bingo/logos/europython-2025.svg @@ -0,0 +1 @@ + diff --git a/src/components/island/BingoCard.svelte b/src/components/island/BingoCard.svelte index a6d7f2cf2..b4f1a8e61 100644 --- a/src/components/island/BingoCard.svelte +++ b/src/components/island/BingoCard.svelte @@ -2,31 +2,31 @@ const STORAGE_KEY = 'ep-bingo-checked'; const editions = [ - { year: 2002, city: 'Charleroi', icon: '/media/bingo/charleroi.svg', bg: '#1003A3' }, - { year: 2003, city: 'Charleroi', icon: '/media/bingo/charleroi.svg', bg: '#1003A3' }, - { year: 2004, city: 'Gothenburg', icon: '/media/bingo/gothenburg.svg', bg: '#1003A3' }, - { year: 2005, city: 'Gothenburg', icon: '/media/bingo/gothenburg.svg', bg: '#1003A3' }, - { year: 2006, city: 'CERN, Geneva',icon: '/media/bingo/geneva.svg', bg: '#1003A3' }, - { year: 2007, city: 'Vilnius', icon: '/media/bingo/vilnius.svg', bg: '#1003A3' }, - { year: 2008, city: 'Vilnius', icon: '/media/bingo/vilnius.svg', bg: '#1003A3' }, - { year: 2009, city: 'Birmingham', icon: '/media/bingo/birmingham.svg', bg: '#1003A3' }, - { year: 2010, city: 'Birmingham', icon: '/media/bingo/birmingham.svg', bg: '#1003A3' }, - { year: 2011, city: 'Florence', icon: '/media/bingo/florence.svg', bg: '#1003A3' }, - { year: 2012, city: 'Florence', icon: '/media/bingo/florence.svg', bg: '#1003A3' }, - { year: 2013, city: 'Florence', icon: '/media/bingo/florence.svg', bg: '#1003A3' }, - { year: 2014, city: 'Berlin', icon: '/media/bingo/berlin.svg', bg: '#1003A3' }, - { year: 2015, city: 'Bilbao', icon: '/media/bingo/bilbao.svg', bg: '#1003A3' }, - { year: 2016, city: 'Bilbao', icon: '/media/bingo/bilbao.svg', bg: '#1003A3' }, - { year: 2017, city: 'Rimini', icon: '/media/bingo/rimini.svg', bg: '#1003A3' }, - { year: 2018, city: 'Edinburgh', icon: '/media/bingo/edinburgh.svg', bg: '#1003A3' }, - { year: 2019, city: 'Basel', icon: '/media/bingo/basel.svg', bg: '#1003A3' }, - { year: 2020, city: 'Online', icon: '/media/bingo/online.svg', bg: '#1003A3' }, - { year: 2021, city: 'Online', icon: '/media/bingo/online.svg', bg: '#1003A3' }, - { year: 2022, city: 'Dublin', icon: '/media/bingo/dublin.svg', bg: '#1003A3' }, - { year: 2023, city: 'Prague', icon: '/media/bingo/prague.svg', bg: '#1003A3' }, - { year: 2024, city: 'Prague', icon: '/media/bingo/prague.svg', bg: '#1003A3' }, - { year: 2025, city: 'Prague', icon: '/media/bingo/prague.svg', bg: '#1003A3' }, - { year: 2026, city: 'Kraków', icon: '/media/bingo/krakow.svg', bg: '#1003A3' }, + { year: 2002, city: 'Charleroi', icon: '/media/bingo/charleroi.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2002.png' }, + { year: 2003, city: 'Charleroi', icon: '/media/bingo/charleroi.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2003.png' }, + { year: 2004, city: 'Gothenburg', icon: '/media/bingo/gothenburg.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2004.png' }, + { year: 2005, city: 'Gothenburg', icon: '/media/bingo/gothenburg.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2005.png' }, + { year: 2006, city: 'CERN, Geneva',icon: '/media/bingo/geneva.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2006.png' }, + { year: 2007, city: 'Vilnius', icon: '/media/bingo/vilnius.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2007.png' }, + { year: 2008, city: 'Vilnius', icon: '/media/bingo/vilnius.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2008.png' }, + { year: 2009, city: 'Birmingham', icon: '/media/bingo/birmingham.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2009.png' }, + { year: 2010, city: 'Birmingham', icon: '/media/bingo/birmingham.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2010.png' }, + { year: 2011, city: 'Florence', icon: '/media/bingo/florence.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2011.png' }, + { year: 2012, city: 'Florence', icon: '/media/bingo/florence.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2012.png' }, + { year: 2013, city: 'Florence', icon: '/media/bingo/florence.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2013.png' }, + { year: 2014, city: 'Berlin', icon: '/media/bingo/berlin.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2014.png' }, + { year: 2015, city: 'Bilbao', icon: '/media/bingo/bilbao.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2015.png' }, + { year: 2016, city: 'Bilbao', icon: '/media/bingo/bilbao.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2016.png' }, + { year: 2017, city: 'Rimini', icon: '/media/bingo/rimini.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2017.png' }, + { year: 2018, city: 'Edinburgh', icon: '/media/bingo/edinburgh.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2018.png' }, + { year: 2019, city: 'Basel', icon: '/media/bingo/basel.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2019.png' }, + { year: 2020, city: 'Online', icon: '/media/bingo/online.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2020.png' }, + { year: 2021, city: 'Online', icon: '/media/bingo/online.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2021.png' }, + { year: 2022, city: 'Dublin', icon: '/media/bingo/dublin.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2022.png' }, + { year: 2023, city: 'Prague', icon: '/media/bingo/prague.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2023.svg' }, + { year: 2024, city: 'Prague', icon: '/media/bingo/prague.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2024.png' }, + { year: 2025, city: 'Prague', icon: '/media/bingo/prague.svg', bg: '#1003A3', logo: '/media/bingo/logos/europython-2025.svg' }, + { year: 2026, city: 'Kraków', icon: '/media/bingo/krakow.svg', bg: '#1003A3', logo: null }, ]; function loadChecked() { @@ -119,7 +119,7 @@ const cityColor = isLight ? 'rgba(0,0,0,0.4)' : 'rgba(255,255,255,0.6)'; const subtitleColor = isLight ? 'rgba(0,0,0,0.4)' : 'rgba(255,255,255,0.4)'; - // Preload SVG icons for checked cells (matches the flipped card-back shown on screen) + // Preload logos (or city icons for editions without a logo) for checked cells const images = await Promise.all( editions.map((ed, i) => { if (!checked[i]) return Promise.resolve(null); @@ -127,7 +127,7 @@ const img = new Image(); img.onload = () => resolve(img); img.onerror = () => resolve(null); - img.src = ed.icon; + img.src = ed.logo || ed.icon; }); }) ); @@ -162,35 +162,58 @@ const cx = x + 3, cy = y + 3, cw = CELL - 6, ch = CELL - 6; if (isChecked && images[i]) { - // Checked: bg colour + icon at 50% + year + city (matches card-back on screen) - ctx.fillStyle = ed.bg; - roundRect(ctx, cx, cy, cw, ch, 2); - ctx.fill(); - - ctx.strokeStyle = cellBorderChk; - ctx.lineWidth = 1.5; - ctx.setLineDash([]); - roundRect(ctx, cx, cy, cw, ch, 2); - ctx.stroke(); - - const iconSize = Math.round(cw * 0.5); - const ix = cx + Math.round((cw - iconSize) / 2); - const iy = cy + Math.round(ch * 0.08); - ctx.save(); - roundRect(ctx, cx, cy, cw, ch, 2); - ctx.clip(); - ctx.drawImage(images[i], ix, iy, iconSize, iconSize); - ctx.restore(); - - const cityY = iy + iconSize + Math.round(ch * 0.12); - ctx.fillStyle = 'white'; - ctx.font = `bold 13px system-ui, sans-serif`; - ctx.textAlign = 'center'; - ctx.fillText(ed.city, x + CELL / 2, cityY); - - ctx.fillStyle = 'rgba(255,255,255,0.7)'; - ctx.font = `12px system-ui, sans-serif`; - ctx.fillText(ed.year.toString(), x + CELL / 2, cityY + Math.round(ch * 0.14)); + if (ed.logo) { + // Logo editions: white background, logo fills the cell + ctx.fillStyle = 'white'; + roundRect(ctx, cx, cy, cw, ch, 2); + ctx.fill(); + + ctx.strokeStyle = cellBorderChk; + ctx.lineWidth = 1.5; + ctx.setLineDash([]); + roundRect(ctx, cx, cy, cw, ch, 2); + ctx.stroke(); + + const pad = Math.round(cw * 0.08); + const imgSize = cw - pad * 2; + const ix = cx + pad; + const iy = cy + pad; + ctx.save(); + roundRect(ctx, cx, cy, cw, ch, 2); + ctx.clip(); + ctx.drawImage(images[i], ix, iy, imgSize, imgSize); + ctx.restore(); + } else { + // 2026 fallback: dark bg + city icon + text (original behaviour) + ctx.fillStyle = ed.bg; + roundRect(ctx, cx, cy, cw, ch, 2); + ctx.fill(); + + ctx.strokeStyle = cellBorderChk; + ctx.lineWidth = 1.5; + ctx.setLineDash([]); + roundRect(ctx, cx, cy, cw, ch, 2); + ctx.stroke(); + + const iconSize = Math.round(cw * 0.5); + const ix = cx + Math.round((cw - iconSize) / 2); + const iy = cy + Math.round(ch * 0.08); + ctx.save(); + roundRect(ctx, cx, cy, cw, ch, 2); + ctx.clip(); + ctx.drawImage(images[i], ix, iy, iconSize, iconSize); + ctx.restore(); + + const cityY = iy + iconSize + Math.round(ch * 0.12); + ctx.fillStyle = 'white'; + ctx.font = `bold 13px system-ui, sans-serif`; + ctx.textAlign = 'center'; + ctx.fillText(ed.city, x + CELL / 2, cityY); + + ctx.fillStyle = 'rgba(255,255,255,0.7)'; + ctx.font = `12px system-ui, sans-serif`; + ctx.fillText(ed.year.toString(), x + CELL / 2, cityY + Math.round(ch * 0.14)); + } } else { // Unchecked: text card (matches the card-front on screen) ctx.fillStyle = isCurrent ? cellFillCur : cellFill; @@ -270,10 +293,14 @@ Now! {/if} -