KRAKKEMAT
Waar vriendschap en schaakplezier samenkomen
Word lid
iTip: Doorheen de site brengt het Krakkemat-logo je terug naar de startpagina.

KRAKKEMAT

SCHAAKCLUB VELDEGEM

Waar vriendschap en schaakplezier samenkomen

Bij onze club draait alles om het plezier en het leren van schaken, ongeacht je leeftijd of ervaringsniveau. Of je nu net begint of al wat ervaring hebt, je bent bij ons thuis.

Iedereen welkom

Iedereen welkom

Voor ervaren schakers én voor wie het spel wil ontdekken.

Gezellige clubavonden

Gezellige clubavonden

Samen schaken, praten en lachen in een warme open sfeer.

Toernooien en competitie

Toernooien & competitie

Voor wie uitdaging zoekt, organiseren we interne competities en toernooien.

Jeugd en ontwikkeling

Jeugd & ontwikkeling

We stimuleren jongeren om te groeien in schaakspel én vriendschap.

Ontdek onze club

Clubavonden

Clubavonden

2-wekelijks
op donderdag

Locatie

Locatie

LDC Veltershof
Koning Albertstraat 11
8210 Veldegem

Initiatie stap 1

Initiatie stap 1

Start om
17:30u

Initiatie stap 2

Initiatie stap
2 & 3

Start om
18:30u

Competitie

Competitie

Start om
19:30u

Online

Online

1x per maand
van september tot en met juni

Trainer Initiatielessen worden verzorgd door gediplomeerde schaaktrainers waarvan er binnen de club momenteel drie actief zijn.

Meer dan een schaakclub

Schaakclub Krakkemat Veldegem is een plek waar mensen samenkomen, leren van elkaar en vriendschappen opbouwen rond het schaakbord.

Of je nu komt om beter te worden, voor de gezelligheid of gewoon uit nieuwsgierigheid... Welkom!

Kom eens langs
Volgend Krakkemat event
—
——
Aanvang—uur
Volgend event

Nog geen event gepland

—
Bekijk volledige kalender

KRAKKEMAT

Seizoensoverzicht



2025 -2026

← Terug

Competitieanalyse wordt geladen...

Competitieanalyse na ronde 15

Pos
Naam
Punten
R1
R2
R3
R4
R5
R6
R7
R8
R9
R10
R11
R12
R13
R14
R15
Buc1
1
Vanbelleghem Rudy
25.0
+W12
+W15
+B27
+W16
+B6
-B19
=W9
=W2
+B4
-B3
+W11
-B5
+B7
+W13
-B14
99.5
2
Standaert Marnique
24.5
+W14
-W19
+B20
+W27
+B7
+B4
+W6
=B1
-B3
-W9
+W5
-B16
+W15
-B11
+B10
97.5
3
Pax Walter
23.5
-B19
+W30
BYE
BYE
+B17
+W10
+B13
+B6
+W2
+W1
+B4
-W11
+B5
=B9
+W16
86.5
4
Denolf Tom
23.0
-B6
-W9
+B7
+W13
+B5
-W2
-W16
+B15
-W1
+B12
-W3
+B17
-B8
+W10
+B20
95.0
5
Vanbelleghem Danny
23.0
-B15
+W21
BYE
+B12
-W4
BYE
+B17
+W7
-B9
+W6
-B2
+W1
-W3
+B8
+W23
83.0
6
Vandekerckhove Marc
22.0
+W4
+W7
-B19
+B9
-W1
+B15
-B2
-W3
-W11
-B5
+W12
+B13
+W20
BYE
+B21
94.0
7
Delhaye Brent
20.0
+W10
-B6
-W4
+B25
-W2
+B13
-W19
-B5
+W8
-B11
+B20
BYE
-W1
+B15
-W9
89.0
8
Beuselinck Luc
20.0
BYE
-W27
-B13
BYE
+B20
+W25
+W21
-B11
-B7
-W17
-B14
+B24
+W4
-W5
BYE
58.0
9
Loobuyck Linnert
19.0
BYE
+B4
+W10
-W6
+B11
+W18
=B1
-B19
+W5
+B2
BYE
BYE
BYE
=W3
+B7
79.0
10
Vandaele Ivan
18.0
-B7
+W31
-B9
+W28
-W15
-B3
-W11
+B18
-B12
-W13
-B17
+W21
BYE
-B4
-W2
77.5
11
Lanckriet Kyenzo
18.0
BYE
+B17
+W18
BYE
-W9
BYE
+B10
+W8
+B6
+W7
-B1
+B3
BYE
+W2
BYE
66.0
12
Degraeve Francky
17.5
-B1
+W13
-B16
-W5
-B18
BYE
+W28
+B14
+W10
-W4
-B6
=B15
+W23
BYE
BYE
65.5
13
Vandecasteele Wim
17.0
BYE
-B12
+W8
-B4
+B28
-W7
-W3
+B22
-W15
+B10
+W21
-W6
BYE
-B1
BYE
66.0
14
De Pauw Filip
16.5
-B2
-W20
BYE
+B34
BYE
-W17
+B31
-W12
-B21
BYE
+W8
=B18
+B22
BYE
+W1
47.0
15
De Wael Bart
15.5
+W5
-B1
BYE
+W20
+B10
-W6
BYE
-W4
+B13
BYE
-B16
=W12
-B2
-W7
BYE
70.0
16
Geldof Willem
15.0
+W17
+B18
+W12
-B1
-W19
BYE
+B4
BYE
BYE
BYE
+W15
+W2
BYE
BYE
-B3
60.0
17
Bourgeois Hendrik
15.0
-B16
-W11
+B26
BYE
-W3
+B14
-W5
BYE
BYE
+B8
+W10
-W4
BYE
+B21
BYE
58.0
18
Vandendriessche Tjorben
14.5
+B25
-W16
-B11
BYE
+W12
-B9
BYE
-W10
-B20
-W24
+B26
=W14
BYE
-B23
BYE
49.5
19
De Baenst Bruno
14.0
+W3
+B2
+W6
BYE
+B16
+W1
+B7
+W9
BYE
BYE
BYE
BYE
BYE
BYE
BYE
52.0
20
Wittevrongel Geert
14.0
BYE
+B14
-W2
-B15
-W8
BYE
+B22
BYE
+W18
+B21
-W7
BYE
-B6
BYE
-W4
53.0
21
Callens Donald
14.0
BYE
-B5
BYE
-W22
BYE
+W26
-B8
+B25
+W14
-W20
-B13
-B10
BYE
-W17
-W6
48.5
22
Ananina Bariyat Nadia
12.5
BYE
-B28
-W25
+B21
BYE
BYE
-W20
-W13
-B23
-B30
=W24
-B32
-W14
-B29
BYE
29.0
23
Devos Simon
9.0
BYE
BYE
BYE
BYE
BYE
BYE
+W24
BYE
+W22
BYE
BYE
-B25
-B12
+W18
-B5
22.5
24
Vandekerckhove Jan
9.0
BYE
BYE
BYE
BYE
BYE
BYE
-B23
+W26
BYE
+B18
=B22
-W8
BYE
BYE
=W25
15.5
25
Denys Paul
8.5
-W18
BYE
+B22
-W7
BYE
-B8
BYE
-W21
BYE
BYE
BYE
+W23
BYE
BYE
=B24
23.5
26
Vermeulen Tina
8.0
BYE
BYE
-W17
BYE
BYE
-B21
BYE
-B24
BYE
BYE
-W18
BYE
BYE
BYE
BYE
11.5
27
Verhaeghe Gerard
6.0
+W28
+B8
-W1
-B2
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
24.5
28
Desendere Paul
6.0
-B27
+W22
BYE
-B10
-W13
BYE
-B12
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
16.5
29
Kinds Koen
3.0
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
+W22
-B33
1.5
30
Bostoen Yentl
2.0
BYE
-B3
BYE
BYE
BYE
BYE
BYE
BYE
BYE
+W22
BYE
BYE
BYE
BYE
BYE
10.5
31
David Eddy
2.0
BYE
-B10
BYE
BYE
BYE
BYE
-W14
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
5.5
32
Maes Geert
2.0
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
+W22
BYE
BYE
BYE
0.0
33
Corneillie David
2.0
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
+W29
0.0
34
Hubert Monbailliu
1.0
BYE
BYE
BYE
-W14
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
0.0
35
Eneman Jochen
1.0
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
BYE
0.0

KRAKKEMAT

Seizoensoverzicht

2026 - 2027

← Terug

De competitie is nog jong

Er zijn momenteel nog onvoldoende speelrondes afgewerkt om zinvolle analyses te tonen.

Vanaf ronde 5 verschijnen hier automatisch statistieken, trends en opmerkelijke prestaties uit de competitie.

KRAKKEMAT

Ledenpaswoord

KRAKKEMAT

Onlinegenerator

Maak online activiteiten voor de kalender.

Eventgegevens

Preview

ONLINE EVENT
Nog geen event
Vul de gegevens in om een preview te zien.
✓ Event opgeslagen

Online club

Krakkemat @ Chess.com

Krakkemat Online

Waar vriendschap en schaakplezier samenkomen.

Vriendschap

We spelen om samen plezier te maken.

Schaakplezier

Resultaten zijn belangrijk, maar plezier komt op de eerste plaats.

Iedereen welkom

Van beginner tot ervaren speler, iedereen mag meedoen.

Respect

We behandelen elkaar met respect, online én aan het bord.

Sportiviteit

Winnen is mooi, maar fair play nog belangrijker.

Volgend online toernooi
Online kalender

Geplande online toernooien

Online archief

Online spelen

Toernooivormen & info

KRAKKEMAT

Wie is wie

Een handig overzicht van de online handles van de leden.

Handle Handle
Naam lid Naam lid

KRAKKEMAT

Stappenmethode

Oplossingen

← Terug

Blog

Schaakbord
20 mei 2026NieuwsKrakkemat

Nieuwe blogpagina voor Krakkemat

We bouwen aan een stijlvolle blog waar nieuws, tornooien en clubverhalen een vaste plek krijgen.

Online shop

Deze aanmelding helpt ons om je betaling aan de juiste persoon te koppelen. Een bezoek aan de online shop verplicht je uiteraard niet tot een aankoop.

Betaal je jouw lidgeld? Vergeet dan nadien ook niet om op de homepagina op de knop 'Word lid' te klikken en de vragenlijst in te vullen.
Betaal je voor iemand anders? Vermeld hieronder dan de naam van die persoon.
Bestel je een T-shirt of Polo? Vergeet dan niet om hieronder eerst de maat te vermelden.

Shop

Online betaalgemak

Contact

We helpen je graag verder en verwelkomen je met plezier in onze club.

Veltershof Veldegem

LDC Veltershof
Koning Albertstraat 11
8210 Veldegem

Open in Google Maps

Telefonisch contact

Voorzitter Luc Beuselinck0472 25 34 61
Secretaris Danny Vanbelleghem0478 24 18 65

Kalender

Een overzicht van onze komende clubactiviteiten.

KRAKKEMAT

Kalenderbeheer

Voeg activiteiten toe, wijzig bestaande activiteiten of verwijder ze. Wijzigingen zijn onmiddellijk zichtbaar op de website.

Preview

Nog geen preview.

Bestaande activiteiten

Laden...
Activiteiten worden geladen...

Privacyverklaring

Hoe KRAKKEMAT Schaakclub Veldegem omgaat met persoonsgegevens, foto’s, contactgegevens en privacy.

1. Wie zijn wij?

KRAKKEMAT Schaakclub Veldegem hecht veel belang aan de bescherming van uw persoonsgegevens en respecteert uw privacy.

Deze privacyverklaring legt uit welke gegevens wij verzamelen, waarom wij dit doen en hoe wij hiermee omgaan.

Verantwoordelijke voor de verwerking:
KRAKKEMAT Schaakclub Veldegem
E-mail: [email protected]

2. Welke persoonsgegevens verzamelen wij?

Afhankelijk van uw contact met onze club kunnen wij volgende gegevens verzamelen:

▸ naam en voornaam
▸ e-mailadres
▸ telefoonnummer
▸ adresgegevens
▸ geboortedatum
▸ gegevens ingevuld via contactformulieren
▸ lidmaatschapsgegevens
▸ foto’s genomen tijdens clubactiviteiten

3. Waarom verwerken wij deze gegevens?

Uw gegevens worden uitsluitend gebruikt voor:

▸ beheer van lidmaatschappen
▸ communicatie met leden en bezoekers
▸ organisatie van clubactiviteiten en tornooien
▸ beantwoorden van vragen via het contactformulier
▸ verzenden van praktische informatie
▸ publiceren van sfeerbeelden van clubactiviteiten
▸ verbeteren van de werking van onze website

4. Op basis waarvan verwerken wij uw gegevens?

Wij verwerken persoonsgegevens op basis van:

▸ uw toestemming
▸ de uitvoering van een overeenkomst, zoals een lidmaatschap
▸ het gerechtvaardigd belang van de vereniging
▸ wettelijke verplichtingen

5. Hoe lang bewaren wij uw gegevens?

Persoonsgegevens worden niet langer bewaard dan noodzakelijk voor de doeleinden waarvoor ze verzameld werden.

6. Delen wij gegevens met derden?

Wij delen persoonsgegevens enkel indien noodzakelijk, bijvoorbeeld met:

▸ hostingproviders van de website
▸ e-maildiensten
▸ schaakfederaties indien vereist voor tornooien of aansluiting

7. Gebruik van foto’s

Deze foto’s kunnen gebruikt worden:

▸ op onze website
▸ op sociale media

Wij proberen steeds respectvol om te gaan met beeldmateriaal. Indien u niet wenst dat foto’s waarop u herkenbaar bent gepubliceerd worden, kan u ons steeds contacteren via [email protected].

8. Cookies

Onze website maakt geen gebruik van analytische of externe cookies.

9. Uw rechten

U heeft steeds het recht om:

▸ uw gegevens in te kijken
▸ foutieve gegevens te laten aanpassen
▸ gegevens te laten verwijderen
▸ bezwaar te maken tegen verwerking
▸ uw toestemming in te trekken

U kan hiervoor contact opnemen via [email protected].

10. Beveiliging van gegevens

Wij nemen passende technische en organisatorische maatregelen om persoonsgegevens te beschermen tegen verlies, misbruik of ongeoorloofde toegang.

11. Externe links

Onze website kan links bevatten naar externe websites. Wij zijn niet verantwoordelijk voor het privacybeleid van andere websites.

12. Wijzigingen aan deze privacyverklaring

KRAKKEMAT Schaakclub Veldegem behoudt zich het recht voor deze privacyverklaring aan te passen indien nodig.

Contact

Voor vragen over deze privacyverklaring of over de verwerking van persoonsgegevens kan u steeds contact opnemen via onze contactpagina.

KRAKKEMAT

Desktop omgeving

Deze beheeromgeving is enkel beschikbaar op desktopapparaten.

Gebruik een computer of laptop

Om fouten te vermijden zijn de beheertools, generators en databankfuncties niet beschikbaar op gsm of tablet.

Terug naar home

KRAKKEMAT

Spelerslijst

Beheer de spelerslijst voor competitiebeheer, PGN Tool en live registratie.

Speler toevoegen / wijzigen

Spelerslijst

0 spelers
Spelerslijst laden...

KRAKKEMAT

Competitie-instellingen

Beheer de instellingen voor clubcompetities, blitzavonden en tornooien.

Competitie toevoegen / wijzigen

Competitie-instellingen worden normaal slechts één keer aangemaakt. Na export moeten ze vervangen worden in "kmsot competitie data" op #homehtml en daarna moet de website opnieuw gepubliceerd worden.

Wanneer "Op ELO" gekozen wordt maar minstens één actieve speler ELO 0 heeft, schakelt de pairing automatisch over naar willekeurig.

Competities

0 competities
Nog geen competities toegevoegd.
✓ Competitie-instellingen werden naar het klembord geschreven

KRAKKEMAT

Rondevoorbereider

Kies de competitie, ronde, datum, aanwezigen en eventuele bye vóór de pairing.

Rondegegevens

Kies een competitie om de rondecontrole uit te voeren.

Status

Aanwezig0
Afwezig0
Bye0
Te pairen0

Bye

Bij een oneven aantal aanwezige spelers moet één speler bye krijgen. Als de competitie dit vereist, kunnen enkel bestuursleden bye krijgen.

Geen bye nodig zolang het aantal aanwezige spelers even is.
✓ Actie uitgevoerd

Aanwezige spelers

Nog geen aanwezige spelers aangeduid.

Afwezige spelers

0 spelers
Geen spelers geladen.
window.kmRoundSetupApp = (function(){ "use strict"; const app = {}; app.STORAGE_KEY = "kmRoundSetup"; app.PLAYERS_URL = "https://api.krakkemat.be/spelers-lezen.php"; app.COMPETITIONS_URL = "https://api.krakkemat.be/competities-lezen.php"; app.ROUNDS_URL = "https://api.krakkemat.be/rondes-lezen.php"; /*================================================== DATA ==================================================*/ app.players = []; app.competitions = []; app.rounds = []; app.presentPlayers = []; app.absentPlayers = []; app.byePlayer = null; /*================================================== ELEMENTEN ==================================================*/ app.el = { competition: document.getElementById("kmRoundCompetition"), round: document.getElementById("kmRoundNumber"), date: document.getElementById("kmRoundDate"), controlMessage: document.getElementById("kmRoundControlMessage"), presentCount: document.getElementById("kmRoundPresentCount"), absentCount: document.getElementById("kmRoundAbsentCount"), byeCount: document.getElementById("kmRoundByeCount"), pairingCount: document.getElementById("kmRoundPairingCount"), presentList: document.getElementById("kmRoundPresentList"), absentList: document.getElementById("kmRoundAbsentList"), byeSelect: document.getElementById("kmRoundByePlayer"), byeMessage: document.getElementById("kmRoundByeMessage"), search: document.getElementById("kmRoundPlayerSearch"), playerCount: document.getElementById("kmRoundPlayerCount"), nextRoundBtn: document.getElementById("kmNextRoundBtn"), saveBtn: document.getElementById("kmSaveRoundSetupBtn"), clearBtn: document.getElementById("kmClearRoundSetupBtn"), saveMessage: document.getElementById("kmRoundSaveMessage") }; /*================================================== LADEN ==================================================*/ app.loadPlayers = async function(){ try{ const response = await fetch( app.PLAYERS_URL, { method: "GET", cache: "no-store" } ); if(!response.ok){ throw new Error( "HTTP " + response.status ); } const data = await response.json(); if( !data || !Array.isArray(data.players) ){ throw new Error( "Ongeldige spelersdata" ); } app.players = data.players .filter(function(player){ return player.active === true; }) .slice(); return true; }catch(error){ console.error( "Rondevoorbereider: spelers laden mislukt:", error ); app.players = []; if(app.el.controlMessage){ app.el.controlMessage.textContent = "De spelerslijst kon niet geladen worden."; } return false; } }; app.loadCompetitions = async function(){ try{ const response = await fetch( app.COMPETITIONS_URL, { method: "GET", cache: "no-store" } ); if(!response.ok){ throw new Error( "HTTP " + response.status ); } const data = await response.json(); if( !data || !Array.isArray(data.competitions) ){ throw new Error( "Ongeldige competitiedata" ); } app.competitions = data.competitions.slice(); return true; }catch(error){ console.error( "Rondevoorbereider: competities laden mislukt:", error ); app.competitions = []; if(app.el.controlMessage){ app.el.controlMessage.textContent = "De competitie-instellingen konden niet geladen worden."; } return false; } }; app.loadRounds = async function(){ try{ const response = await fetch( app.ROUNDS_URL, { method: "GET", cache: "no-store" } ); if(!response.ok){ throw new Error( "HTTP " + response.status ); } const data = await response.json(); if( !data || !Array.isArray(data.rounds) ){ throw new Error( "Ongeldige rondehistoriek" ); } app.rounds = data.rounds.slice(); return true; }catch(error){ console.error( "Rondevoorbereider: rondehistoriek laden mislukt:", error ); app.rounds = []; if(app.el.controlMessage){ app.el.controlMessage.textContent = "De rondehistoriek kon niet geladen worden."; } return false; } }; /*================================================== COMPETITIES ==================================================*/ app.fillCompetitionSelect = function(){ const select = app.el.competition; select.innerHTML = ''; app.competitions.forEach(function(comp){ const option = document.createElement("option"); option.value = comp.id; option.textContent = comp.name; select.appendChild(option); }); }; /*================================================== RONDECONTROLE ==================================================*/ app.getLastRound = function(competitionId){ let last = 0; app.rounds.forEach(function(round){ const roundCompetitionId = String( round.competitionId ?? round.c ?? "" ); const roundNumber = Number( round.round ?? round.r ?? 0 ); if( roundCompetitionId === competitionId && roundNumber > last ){ last = roundNumber; } }); return last; }; app.updateRoundControl = function(){ const competitionId = app.el.competition.value; if(!competitionId){ app.el.controlMessage.textContent = "Kies eerst een competitie."; return; } const comp = app.getCompetition(); if(!comp){ app.el.controlMessage.textContent = "Competitie niet gevonden."; return; } const historicalLast = app.getLastRound( competitionId ); const singleDay = app.isSingleDayCompetition(comp); /*================================================== LANGDURIGE COMPETITIE Enige bron voor vorige rondes: window.kmCompetitionRounds ==================================================*/ if(!singleDay){ const expected = historicalLast + 1; if(!app.readRound()){ app.writeRound( expected ); } const current = app.readRound(); if(current === expected){ app.el.controlMessage.textContent = historicalLast > 0 ? "Laatste gespeelde ronde is " + historicalLast + ". Volgende ronde is " + expected + "." : "Dit is de eerste ronde van deze competitie."; return; } if(current <= historicalLast){ app.el.controlMessage.textContent = "FOUT: ronde " + current + " bestaat reeds in de gepubliceerde historiek."; return; } app.el.controlMessage.textContent = "FOUT: volgende ronde moet ronde " + expected + " zijn."; return; } /*================================================== 1 DAG / BLITZ Hier mag de lokale voorbereiding wel mee bepalen waar de avond gebleven is. ==================================================*/ let savedRound = 0; try{ const raw = localStorage.getItem( app.STORAGE_KEY ); const saved = raw ? JSON.parse(raw) : null; if( saved && saved.competitionId === competitionId ){ savedRound = Number(saved.round) || 0; } }catch(e){} const lastKnown = Math.max( historicalLast, savedRound ); const expected = lastKnown + 1; if(!app.readRound()){ app.writeRound( expected ); } const current = app.readRound(); if( savedRound > 0 && current === savedRound ){ app.el.controlMessage.textContent = "Ronde " + current + " is de huidige ronde van deze blitz/ééndagscompetitie."; return; } if(current === expected){ app.el.controlMessage.textContent = "Volgende ronde is correct (" + expected + ")."; return; } if(current <= historicalLast){ app.el.controlMessage.textContent = "FOUT: ronde " + current + " bestaat reeds in de historiek."; return; } app.el.controlMessage.textContent = "FOUT: volgende ronde moet ronde " + expected + " zijn."; }; app.escapeHtml = function(value){ return String(value); }; return app; })();
(function(){ "use strict"; const app = window.kmRoundSetupApp; if(!app) return; /*================================================== HELPERS SPELERS ==================================================*/ app.playerName = function(player){ return [ player.lastName || "", player.firstName || "" ].join(" ").trim(); }; app.sortPlayers = function(list){ return list.slice().sort(function(a,b){ const an = String(a.lastName || "").localeCompare(String(b.lastName || ""),"nl"); if(an !== 0) return an; return String(a.firstName || "").localeCompare(String(b.firstName || ""),"nl"); }); }; app.getPlayerById = function(id){ return app.players.find(function(player){ return player.id === id; }) || null; }; app.isPresent = function(id){ return app.presentPlayers.indexOf(id) >= 0; }; app.isBye = function(id){ return app.byePlayer === id; }; app.getCompetition = function(){ const id = app.el.competition.value; return app.competitions.find(function(comp){ return comp.id === id; }) || null; }; /*================================================== RONDEVELD UITLEZEN / SCHRIJVEN ==================================================*/ app.getRoundField = function(){ const fields = Array.from( document.querySelectorAll( 'input#kmRoundNumber, input[type="number"][id="kmRoundNumber"]' ) ); /* Neem bij voorkeur het zichtbare rondeveld. */ const visibleField = fields.find(function(field){ return field.offsetParent !== null; }); /* Anders terugvallen op het oorspronkelijk gekoppelde veld. */ return ( visibleField || fields[0] || app.el.round || null ); }; app.readRound = function(){ const field = app.getRoundField(); if(!field){ return 0; } return ( Number(field.value) || 0 ); }; app.writeRound = function(value){ const field = app.getRoundField(); if(!field){ return; } field.value = value === null || value === undefined ? "" : String(value); }; /*================================================== COMPETITIETYPE ==================================================*/ app.isSingleDayCompetition = function(comp){ return !!( comp && comp.competitionMode === "singleDay" ); }; app.updateCompetitionModeUi = function(){ const comp = app.getCompetition(); const singleDay = app.isSingleDayCompetition(comp); if(!app.el.nextRoundBtn){ return; } /* Geen competitie gekozen: knop niet tonen. */ if(!comp){ app.el.nextRoundBtn.style.display = "none"; return; } /* 1 dag / blitz: Volgende ronde is beschikbaar. Langdurig: Volgende ronde bestaat functioneel niet. */ app.el.nextRoundBtn.style.display = singleDay ? "" : "none"; }; /*================================================== AANWEZIG / AFWEZIG ==================================================*/ app.setAllAbsent = function(){ app.presentPlayers = []; app.byePlayer = null; app.renderPlayers(); }; app.addPresent = function(id){ if(app.presentPlayers.indexOf(id) < 0){ app.presentPlayers.push(id); } app.renderPlayers(); }; app.removePresent = function(id){ app.presentPlayers = app.presentPlayers.filter(function(playerId){ return playerId !== id; }); if(app.byePlayer === id){ app.byePlayer = null; } app.renderPlayers(); }; /*================================================== BYE ==================================================*/ app.getByeCandidates = function(){ const comp = app.getCompetition(); let candidates = app.presentPlayers .map(app.getPlayerById) .filter(Boolean); if(comp && comp.byeBoardOnly){ candidates = candidates.filter(function(player){ return !!player.boardMember; }); } return app.sortPlayers(candidates); }; app.updateByeSelect = function(){ const select = app.el.byeSelect; const comp = app.getCompetition(); const presentCount = app.presentPlayers.length; select.innerHTML = ''; if(presentCount % 2 === 0){ app.byePlayer = null; app.el.byeMessage.textContent = "Geen bye nodig: het aantal aanwezige spelers is even."; select.disabled = true; return; } const candidates = app.getByeCandidates(); candidates.forEach(function(player){ const option = document.createElement("option"); option.value = player.id; option.textContent = app.playerName(player); select.appendChild(option); }); select.disabled = false; if(app.byePlayer){ const valid = candidates.some(function(player){ return player.id === app.byePlayer; }); if(!valid){ app.byePlayer = null; } } select.value = app.byePlayer || ""; if(candidates.length === 0){ app.el.byeMessage.textContent = "FOUT: er is een bye nodig, maar er is geen geldige bye-speler beschikbaar."; return; } if(comp && comp.byeBoardOnly){ app.el.byeMessage.textContent = "Er is een bye nodig. Volgens deze competitie mogen enkel bestuursleden bye krijgen."; }else{ app.el.byeMessage.textContent = "Er is een bye nodig. Kies één aanwezige speler."; } }; /*================================================== RENDER SPELERS ==================================================*/ app.createPlayerRow = function(player,type){ const isPresent = type === "present"; const row = document.createElement("div"); row.className = "km-round-player-row"; const btn = document.createElement("button"); btn.type = "button"; btn.className = isPresent ? "km-round-player-btn is-remove" : "km-round-player-btn"; btn.textContent = isPresent ? "−" : "+"; if(isPresent){ btn.setAttribute("data-remove-present",player.id); }else{ btn.setAttribute("data-add-present",player.id); } const middle = document.createElement("div"); const name = document.createElement("div"); name.className = "km-round-player-name"; name.textContent = app.playerName(player); const meta = document.createElement("div"); meta.className = "km-round-player-meta"; meta.innerHTML = player.boardMember ? "Bestuurslid" : " "; middle.appendChild(name); middle.appendChild(meta); const status = document.createElement("div"); status.className = "km-round-player-meta"; status.textContent = app.isBye(player.id) ? "Bye" : (isPresent ? "Aanwezig" : "Afwezig"); row.appendChild(btn); row.appendChild(middle); row.appendChild(status); return row; }; app.renderPresentList = function(){ app.el.presentList.innerHTML = ""; const present = app.sortPlayers( app.presentPlayers .map(app.getPlayerById) .filter(Boolean) ); if(present.length === 0){ const empty = document.createElement("div"); empty.className = "km-empty-state"; empty.textContent = "Nog geen aanwezige spelers aangeduid."; app.el.presentList.appendChild(empty); return; } present.forEach(function(player){ app.el.presentList.appendChild( app.createPlayerRow(player,"present") ); }); }; app.renderAbsentList = function(){ app.el.absentList.innerHTML = ""; const q = app.el.search.value.trim().toLowerCase(); const absent = app.sortPlayers( app.players.filter(function(player){ return !app.isPresent(player.id); }) ).filter(function(player){ if(!q) return true; return app.playerName(player).toLowerCase().includes(q); }); app.el.playerCount.textContent = absent.length === 1 ? "1 afwezige speler" : absent.length + " afwezige spelers"; if(absent.length === 0){ const empty = document.createElement("div"); empty.className = "km-empty-state"; empty.textContent = "Geen afwezige spelers gevonden."; app.el.absentList.appendChild(empty); return; } let currentLetter = ""; absent.forEach(function(player){ const rawLetter = String(player.lastName || player.firstName || "?").trim(); const letter = rawLetter ? rawLetter.charAt(0).toUpperCase() : "?"; if(letter !== currentLetter){ currentLetter = letter; const letterEl = document.createElement("div"); letterEl.className = "km-round-letter"; letterEl.textContent = letter; app.el.absentList.appendChild(letterEl); } app.el.absentList.appendChild( app.createPlayerRow(player,"absent") ); }); }; app.updateCounts = function(){ const presentCount = app.presentPlayers.length; const absentCount = app.players.length - presentCount; const byeCount = app.byePlayer ? 1 : 0; const pairingCount = presentCount - byeCount; app.el.presentCount.textContent = presentCount; app.el.absentCount.textContent = absentCount; app.el.byeCount.textContent = byeCount; app.el.pairingCount.textContent = pairingCount; /*---------------------------------- VISUELE PAIRINGSTATUS ----------------------------------*/ const pairingCard = app.el.pairingCount ? app.el.pairingCount.closest( ".km-round-status-card" ) : null; if(pairingCard){ pairingCard.classList.remove( "is-pairing-ok", "is-pairing-error" ); /* Nog geen spelers: neutrale toestand. */ if(presentCount === 0){ return; } /* Geldig: minstens twee spelers te pairen en een even aantal. */ if( pairingCount >= 2 && pairingCount % 2 === 0 ){ pairingCard.classList.add( "is-pairing-ok" ); return; } /* Oneven / nog geen geldige bye: actie vereist. */ pairingCard.classList.add( "is-pairing-error" ); } }; app.renderPlayers = function(){ app.updateByeSelect(); app.renderPresentList(); app.renderAbsentList(); app.updateCounts(); }; /*================================================== EVENTS SPELERS ==================================================*/ app.bindPlayerEvents = function(){ app.el.absentList.addEventListener("click",function(e){ const btn = e.target.closest("[data-add-present]"); if(!btn) return; app.addPresent(btn.getAttribute("data-add-present")); }); app.el.presentList.addEventListener("click",function(e){ const btn = e.target.closest("[data-remove-present]"); if(!btn) return; app.removePresent(btn.getAttribute("data-remove-present")); }); app.el.byeSelect.addEventListener("change",function(){ app.byePlayer = app.el.byeSelect.value || null; app.renderPlayers(); }); app.el.search.addEventListener("input",function(){ app.renderAbsentList(); }); }; })();
(function(){ "use strict"; const app = window.kmRoundSetupApp; if(!app) return; /*================================================== DATUM UITLEZEN ==================================================*/ app.readDate = function(){ const fields = Array.from( document.querySelectorAll( 'input#kmRoundDate, input[type="date"][id="kmRoundDate"]' ) ); /* Neem eerst een zichtbaar ingevuld datumveld. */ const visibleField = fields.find(function(field){ return ( field.value && field.offsetParent !== null ); }); /* Anders eender welk ingevuld datumveld. */ const filledField = visibleField || fields.find(function(field){ return !!field.value; }); /* Laatste terugval: het oorspronkelijk gekoppelde veld. */ const field = filledField || app.el.date; return field ? String(field.value || "").trim() : ""; }; /*================================================== RONDENUMMER UITLEZEN ==================================================*/ app.readRound = function(){ const fields = Array.from( document.querySelectorAll( 'input#kmRoundNumber, input[type="number"][id="kmRoundNumber"]' ) ); const visibleField = fields.find(function(field){ return ( field.value && field.offsetParent !== null ); }); const filledField = visibleField || fields.find(function(field){ return !!field.value; }); const field = filledField || app.el.round; return field ? Number(field.value) || 0 : 0; }; /*================================================== VALIDATIE ==================================================*/ app.validate = function(){ const comp = app.getCompetition(); if(!comp){ alert("Kies eerst een competitie."); return false; } if(!app.readRound()){ alert("Vul een ronde in."); return false; } const selectedDate = app.readDate(); if(!selectedDate){ alert("Vul een datum in."); return false; } const historicalLast = app.getLastRound( comp.id ); const current = app.readRound(); const singleDay = app.isSingleDayCompetition(comp); /*---------------------------------- LANGDURIG ----------------------------------*/ if(!singleDay){ const expected = historicalLast + 1; if(current !== expected){ alert( "Deze ronde sluit niet aan op de gepubliceerde historiek. " + "Verwachte ronde: " + expected + "." ); return false; } /*---------------------------------- 1 DAG / BLITZ ----------------------------------*/ }else{ let savedRound = 0; try{ const raw = localStorage.getItem( app.STORAGE_KEY ); const saved = raw ? JSON.parse(raw) : null; if( saved && saved.competitionId === comp.id ){ savedRound = Number(saved.round) || 0; } }catch(e){} const expected = Math.max( historicalLast, savedRound ) + 1; const isSavedPreparation = savedRound > 0 && current === savedRound; const isNextRound = current === expected; if( !isSavedPreparation && !isNextRound ){ alert( "Deze ronde sluit niet aan op de blitzhistoriek. " + "Verwachte ronde: " + expected + "." ); return false; } } if(app.presentPlayers.length < 2){ alert("Duid minstens twee aanwezige spelers aan."); return false; } if(app.presentPlayers.length % 2 === 1 && !app.byePlayer){ alert("Er is een oneven aantal aanwezigen. Kies eerst een bye-speler."); return false; } const pairingCount = app.presentPlayers.length - (app.byePlayer ? 1 : 0); if(pairingCount < 2){ alert("Er blijven te weinig spelers over om te pairen."); return false; } if(pairingCount % 2 !== 0){ alert("Het aantal te pairen spelers moet even zijn."); return false; } if(app.byePlayer){ const bye = app.getPlayerById(app.byePlayer); if(!bye){ alert("De gekozen bye-speler bestaat niet meer."); return false; } if(app.presentPlayers.indexOf(app.byePlayer) < 0){ alert("De gekozen bye-speler is niet aanwezig."); return false; } if(comp.byeBoardOnly && !bye.boardMember){ alert("Volgens deze competitie mag enkel een bestuurslid bye krijgen."); return false; } } return true; }; /*================================================== BEWAREN ==================================================*/ app.getPairingPlayers = function(){ return app.presentPlayers.filter(function(id){ return id !== app.byePlayer; }); }; app.buildSetup = function(){ return { competitionId:app.el.competition.value, round:app.readRound(), date:app.readDate(), presentPlayers:app.presentPlayers.slice(), absentPlayers:app.players .filter(function(player){ return app.presentPlayers.indexOf(player.id) < 0; }) .map(function(player){ return player.id; }), byePlayer:app.byePlayer, pairingPlayers:app.getPairingPlayers() }; }; app.saveSetup = function(){ if(!app.validate()) return; const setup = app.buildSetup(); localStorage.setItem( app.STORAGE_KEY, JSON.stringify(setup) ); window.dispatchEvent( new CustomEvent( "km:round-setup-saved", { detail:setup } ) ); const pairingWindow = window.open( window.location.origin + window.location.pathname + "#pairing", "_blank" ); if(!pairingWindow){ alert( "Het pairingtabblad kon niet worden geopend. Sta pop-ups toe voor deze website." ); } }; app.loadSetup = function(){ try{ const raw = localStorage.getItem( app.STORAGE_KEY ); if(!raw) return; const setup = JSON.parse(raw); if( !setup || typeof setup !== "object" ){ return; } const comp = app.competitions.find(function(item){ return ( item.id === setup.competitionId ); }); /* Een langdurige competitie wordt NOOIT hersteld vanuit localStorage. De rondevoorbereider start daar uitsluitend vanuit de gepubliceerde websitegegevens. */ if( !comp || !app.isSingleDayCompetition(comp) ){ return; } /* Alleen voor een ééndagscompetitie/blitz mag de lokale voorbereiding terugkomen. */ app.el.competition.value = setup.competitionId || ""; if(setup.round){ app.writeRound( setup.round ); } if(setup.date){ app.el.date.value = setup.date; } if( Array.isArray( setup.presentPlayers ) ){ app.presentPlayers = setup.presentPlayers.filter(function(id){ return !!app.getPlayerById(id); }); } if( setup.byePlayer && app.getPlayerById( setup.byePlayer ) ){ app.byePlayer = setup.byePlayer; } }catch(e){} }; app.clearSetup = function(){ if(!confirm("Rondevoorbereiding wissen?")){ return; } localStorage.removeItem(app.STORAGE_KEY); app.presentPlayers = []; app.byePlayer = null; app.el.competition.value = ""; app.writeRound(""); app.el.date.value = ""; app.updateCompetitionModeUi(); app.updateRoundControl(); app.renderPlayers(); }; /*================================================== VOLGENDE RONDE ==================================================*/ app.startNextRound = function(){ const comp = app.getCompetition(); if(!comp){ alert("Kies eerst een competitie."); return; } /* Bepaal de laatst gekende ronde uit: 1. de gepubliceerde/lokale historiek; 2. de laatst bewaarde rondevoorbereiding. */ const historicalLast = app.getLastRound(comp.id); let savedRound = 0; try{ const raw = localStorage.getItem(app.STORAGE_KEY); const saved = raw ? JSON.parse(raw) : null; if( saved && saved.competitionId === comp.id ){ savedRound = Number(saved.round) || 0; } }catch(e){} /* De volgende ronde is altijd één hoger dan de hoogste gekende ronde. */ const nextRound = Math.max( historicalLast, savedRound, app.readRound() ) + 1; /*---------------------------------- Maximum aantal rondes controleren ----------------------------------*/ const maxRounds = Number(comp.maxRounds); if( Number.isFinite(maxRounds) && maxRounds > 0 && nextRound > maxRounds ){ alert( "Deze competitie bestaat uit maximaal " + maxRounds + " rondes." ); return; } app.writeRound( nextRound ); /* Bye moet per ronde opnieuw gekozen worden. */ app.byePlayer = null; app.el.search.value = ""; app.updateRoundControl(); app.renderPlayers(); const setup = app.buildSetup(); localStorage.setItem( app.STORAGE_KEY, JSON.stringify(setup) ); /* Duidelijke bevestiging tonen. */ app.el.saveMessage.textContent = "✓ Ronde " + nextRound + " is voorbereid"; app.el.saveMessage.classList.add( "show" ); setTimeout(function(){ app.el.saveMessage.classList.remove( "show" ); },1800); /* Terug naar de rondegegevens, zodat het nieuwe rondenummer zichtbaar is. */ const roundSection = app.el.round.closest(".km-section"); if(roundSection){ roundSection.scrollIntoView({ behavior:"smooth", block:"start" }); } }; /*================================================== EVENTS ALGEMEEN ==================================================*/ app.bindMainEvents = function(){ app.el.competition.addEventListener( "change", function(){ const comp = app.getCompetition(); app.writeRound(""); app.updateCompetitionModeUi(); /* Bij een langdurige competitie wordt iedere speelavond opnieuw aanwezigheid opgenomen vanaf nul. */ if( comp && !app.isSingleDayCompetition(comp) ){ app.presentPlayers = []; app.byePlayer = null; app.el.search.value = ""; } app.updateRoundControl(); app.renderPlayers(); } ); document.addEventListener( "input", function(event){ if( event.target && event.target.id === "kmRoundNumber" ){ app.updateRoundControl(); } } ); app.el.nextRoundBtn.addEventListener( "click", app.startNextRound ); app.el.saveBtn.addEventListener( "click", app.saveSetup ); app.el.clearBtn.addEventListener( "click", app.clearSetup ); }; /*================================================== INIT ==================================================*/ app.init = async function(){ const playersLoaded = await app.loadPlayers(); if(!playersLoaded){ console.error( "Rondevoorbereider: spelerslijst kon niet geladen worden." ); return; } const competitionsLoaded = await app.loadCompetitions(); if(!competitionsLoaded){ console.error( "Rondevoorbereider: competitie-instellingen konden niet geladen worden." ); return; } const roundsLoaded = await app.loadRounds(); if(!roundsLoaded){ console.error( "Rondevoorbereider: rondehistoriek kon niet geladen worden." ); return; } app.fillCompetitionSelect(); app.loadSetup(); app.updateCompetitionModeUi(); app.updateRoundControl(); app.renderPlayers(); app.bindPlayerEvents(); app.bindMainEvents(); }; app.init(); })();

KRAKKEMAT

Pairinggenerator

Genereer de pairing, registreer de resultaten, bereken de rangschikking en bewaar de ronde.

Rondevoorbereiding

De rondevoorbereiding wordt geladen.

REPERTOIRE

Mijn persoonlijke openingstrainer

Wit

Nog geen witte openingen.

Zwart

Nog geen zwarte openingen.

KRAKKEMAT

Competitiebeheer

Beheer spelers, competitie-instellingen, rondes, pairings, uitslagen en rangschikking.