# Emvi Dashboard

> Leidt uit de aanbestedingsstukken (leidraad, bijlagen, Nota's van Inlichtingen) het EMVI- of BPKV-gunningsmechanisme af (prijsformule, wegingen, oordeelsbanden, bodem- en plafondprijzen) en bouwt daarvan één standalone, offline werkend, interactief HTML-dashboard met per prijsveld een verkoopprijs- en kostprijsslider, kwaliteitsoordelen per criterium, een ROS-rekenhulp, geldigheidstoets, gevoeligheidsanalyse en een concurrentievergelijk dat toont wie op totaalscore wint. Gebruik deze skill wanneer de gebruiker vraagt om een EMVI-dashboard, BPKV-dashboard, prijsscore-rekenmodel, tenderprijs-simulator, gunningscalculator of inschrijfstrategie-tool voor een aanbesteding, of om "het effect van mijn prijs op de score" of "de wisselkoers tussen prijs en kwaliteit" door te rekenen, ook als de gebruiker alleen een TenderNed- of Mercell-link plakt met de vraag om het EMVI-mechanisme te modelleren.

- Skill: `martinwolve/emvi-dashboard` (Agent Skill)
- Install (CLI): `npx skillmds@latest add martinwolve/emvi-dashboard`
- Raw SKILL.md: https://api.skillmd.com/api/skills/martinwolve/emvi-dashboard/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: martinwolve (https://skillmd.com/u/martinwolve)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/martinwolve/emvi-dashboard

---


# EMVI Dashboard (universele versie)

Deze skill laat Claude uit de aanbestedingsstukken automatisch het EMVI- of BPKV-mechanisme afleiden en er een losstaand, interactief dashboard (het "EMVI Dashboard") van maken. De gebruiker varieert daarin per prijsveld een verkoopprijs en een kostprijs, kalibreert de kwaliteitsoordelen, leidt kostprijzen of verkoopprijzen af met een ROS-rekenhulp, vergelijkt de eigen inschrijving met een concurrent, en past de kolomverdeling zelf aan.

## 0. Parameters (vast ingesteld)

Deze skill heeft de volgende parameters vast ingesteld:

* KLEURENSCHEMA: modern, zakelijk, vlak; zie Stap 5 (geen bedrijfshuisstijl).
* TAAL VAN HET DASHBOARD: Nederlands.
* BRONDOCUMENTEN: staan in de projectkennis of zijn aan het gesprek toegevoegd. Ontbreken ze daar, dan haal je ze op via de door de gebruiker aangeleverde link naar het aanbestedingsplatform (bijvoorbeeld TenderNed of Mercell) met behulp van de daarvoor beschikbare skills en tools.
* OUTPUTNAAM: EMVI_dashboard_[project]_vJJJJMMDD.html (vervang [project] door de projectnaam en JJJJMMDD door de datum van oplevering).
* ROS-NIVEAUS: 5% / 10% / 20% (de knoppen van de ROS-rekenhulp; ROS = Return On Sales, marge als percentage van de omzet).

## 1. Rol en doel

Je bent tegelijk een senior tender- en pricingstrateeg met diepgaande kennis van Nederlandse en Europese aanbestedingen, en een ervaren front-end engineer. Je hebt toegang tot de aanbestedingsstukken in de projectkennis.

Controleer eerst of de aanbestedingsstukken (leidraad, bijlagen, Nota's van Inlichtingen) in de projectkennis aanwezig zijn. Zijn ze dat niet, dan:

1. gebruik je de link naar de aanbesteding die de gebruiker heeft gegeven, en vraag je om die link als die ontbreekt;
2. haal je het aanbestedingsdossier op met de skill die bij het platform hoort (de skill tenderned-tender voor tenderned.nl of de skill mercell-tender voor s2c.mercell.com) en de benodigde tools voor het ophalen en lezen van documenten;
3. zet je de opgehaalde documenten waar nodig om naar leesbare tekst (bijvoorbeeld met de skill documents-to-markdown) voordat je met Stap 1 begint;
4. meld je welke documenten je hebt opgehaald en welke ontbreken.

Werk pas met Stap 1 verder zodra de stukken beschikbaar zijn.

Je doel is om precies een losstaand HTML-bestand op te leveren: het EMVI Dashboard. Dit is een interactief dashboard waarin de gebruiker de commerciele en kwalitatieve aannames van een inschrijving kan varieren en direct het effect ziet op de prijsscore, de kwaliteitsscore, de totaalscore, de marge, de geldigheid en de uitkomst ten opzichte van een concurrent. Per prijsveld staan een verkoopprijs-slider en een kostprijs-slider; een ROS-rekenhulp rekent tussen beide om; een concurrentieblok toont wie op totaalscore wint.

Werk stap voor stap. Leid alle mechaniek af uit de daadwerkelijke stukken; verzin niets. Waar informatie ontbreekt of ambigu is, benoem je dat expliciet en formuleer je een transparante aanname.

## 2. Stap 1: analyseer de aanbesteding en leid het EMVI-model af

Extraheer uit de stukken de volgende gegevens, telkens met exacte bronverwijzing (documentnaam, paragraaf of pagina):

1. Gunningscriterium: BPKV, EMVI, laagste prijs of anders. Noteer de letterlijke formulering.
2. Kwaliteitscriteria: alle (sub)gunningscriteria met hun maximale punten of gewicht. Als er een beoordelingsschaal met kwalitatieve oordelen is (bijvoorbeeld Onvoldoende, Matig, Voldoende, Goed, Uitstekend), noteer je per criterium welk percentage of aantal punten bij elk oordeel hoort. Let op dat een oordeel per criterium een ander percentage kan opleveren.
3. Prijscriterium: het gewicht (punten of %) van prijs in de totaalbeoordeling.
4. Exacte prijsformule: schrijf de formule letterlijk uit. Classificeer daarna het formuletype, want dat bepaalt het dashboardgedrag. Herken minimaal:
   * Vaste referentie / lineaire interpolatie op vaste grenzen: score = (Pmax - Pinschrijving) / (Pmax - Pmin) x gewicht. Onafhankelijk van concurrenten.
   * Relatief ten opzichte van de laagste inschrijving: bijvoorbeeld score = (Plaagste / Peigen) x gewicht, of score = gewicht x (1 - (Peigen - Plaagste) / Plaagste). Hangt af van concurrentieprijzen.
   * Interpolatie tussen beste en slechtste inschrijver: score = (Phoogste - Peigen) / (Phoogste - Plaagste) x gewicht. Hangt af van het veld.
   * Gunning met fictieve korting (meerwaarde): kwaliteit vertaalt naar een fictief kortingsbedrag dat van de prijs wordt afgetrokken; gunning op laagste fictieve prijs.
   * Staffels of drempels en eventuele afvlakking.
5. Prijsinputs: welke prijsvelden de inschrijver invult en hoe die samen tot de beoordeelde prijs leiden. Dit kan zijn: een enkele inschrijfsom, een set eenheidsprijzen, of een set uurtarieven per functiegroep met een weging (gewogen gemiddelde). Noteer per input de exacte benaming, de eventuele weging, en hoe de aggregatie tot de beoordeelde prijs verloopt.
6. Randvoorwaarden: minima en maxima per prijsveld (bodem- en plafondprijzen), een eventuele bandbreedte op de geaggregeerde prijs, verplichte volgorde (bijvoorbeeld oplopende tarieven), en de gevolgen bij overschrijding (ongeldigheid, terzijdelegging).
7. Aard en looptijd: raamovereenkomst of eenmalige opdracht, looptijd, verlengingen, afnamegarantie.
8. Volume-indicatie: indicatieve uren, aantallen of omzetschattingen, indien gegeven.
9. Abnormaal lage inschrijving: een expliciet toetsingskader of drempel, indien aanwezig.
10. Prijsvastheid, indexatie, nacalculatie en benchmarking: bepalingen die de tariefstrategie over de looptijd beinvloeden.
11. Social Return en overige verplichte kosten die op de marge drukken (bijvoorbeeld all-in verrekening van bijkomende kosten).

Sluit Stap 1 af met een beknopte lijst van expliciete aannames en onzekerheden (ontbrekende volumes, ambigue formules, tegenstrijdigheden tussen paragrafen, en dergelijke).

## 3. Stap 2: bepaal de variabelen die de gebruiker bedient

Bepaal welke aannames de gebruiker interactief moet kunnen varieren. Neem in elk geval op, voor zover van toepassing:

* Per prijsveld twee gekoppelde sliders: een verkoopprijs en een kostprijs, op exact dezelfde schaal (zelfde minimum en maximum), zodat de sliderposities direct vergelijkbaar zijn. De bodemprijs geldt formeel voor de verkoopprijs; de kostprijs deelt de schaal voor de vergelijkbaarheid, en afgeleide waarden worden binnen die schaal geclampt. Bij een prijsstructuur met meerdere velden per functiegroep cluster je verkoop en kostprijs per groep. Bewaak de verplichte volgorde (bijvoorbeeld oplopende verkoopprijzen) uit de stukken.
* De kwaliteitsscore per criterium via de officiele oordeelsbanden (bijvoorbeeld een keuzelijst per criterium), met de juiste percentages per criterium.
* De kostprijs per prijsveld (niet blended), als eigen aanname, plus een ROS-rekenhulp (zie Stap 3) die verkoop- en kostprijzen in beide richtingen aan elkaar koppelt.
* Een concurrentievergelijk: invoervelden voor de kwaliteitsoordelen van een concurrerende inschrijving (per criterium) en een slider voor diens geaggregeerde prijs (binnen dezelfde band). Twee rollen:
   * Bij een relatief of veldafhankelijk formuletype zijn concurrentieprijzen sowieso nodig om de eigen prijsscore te kunnen berekenen; maak die afhankelijkheid expliciet.
   * Onafhankelijk van het formuletype toont het concurrentievergelijk wie op totaalscore wint (kwaliteit plus prijs), zodat de gebruiker de eigen positie kan aftasten.
* Optioneel: een werkelijke volume- of urenmix (arbitragepaneel) om naast de score-weging ook de werkelijke marge te tonen.

Markeer markttarieven, kostprijzen, kwaliteitsniveaus en concurrentie-invoer duidelijk als aannames die de gebruiker zelf kalibreert.

## 4. Stap 3: reken de mechaniek uit

Implementeer in het dashboard, live herrekenend bij elke wijziging:

* De geaggregeerde beoordelingsprijs volgens de gevonden aggregatiemethode (bijvoorbeeld het gewogen gemiddelde van de verkoopprijzen).
* De prijsscore volgens de exacte formule en het juiste formuletype.
* De kwaliteitsscore en de totaalscore.
* De ROS per prijsveld = (verkoopprijs - kostprijs) / verkoopprijs, getoond in een klein kader (badge) bij het veld, kleurgecodeerd (negatief, dun, gezond).
* De totale ROS op de geaggregeerde prijs, in een kader onder de prijsvelden, kleurgecodeerd.
* De marge = de totale ROS, eventueel verminderd met verplichte margedruk (bijvoorbeeld een Social Return-percentage, via een aan/uit-schakelaar), kleurgecodeerd (negatief, dun, gezond). Toon zichtbaar of de getoonde marge bruto of netto is.
* De ROS-rekenhulp met een richtingschakelaar waarvan altijd precies een richting actief is:
   * Verkoop naar kostprijs: kostprijs = verkoopprijs x (1 - ROS).
   * Kostprijs naar verkoop: verkoopprijs = kostprijs / (1 - ROS).
   De ROS-niveauknoppen (5% / 10% / 20%) passen de conversie in de gekozen richting toe op alle prijsvelden, waarbij afgeleide waarden binnen de sliderrange worden geclampt. De actieve markering van een ROS-knop vervalt zodra de gebruiker een prijs handmatig wijzigt of van richting wisselt.
* De geldigheidstoets: alle randvoorwaarden (bodem, plafond, bandbreedte op de geaggregeerde prijs, verplichte volgorde). Toon per overtreding een duidelijke melding en markeer de betreffende invoer. Een ongeldige inschrijving is een terzijdeleggingstoestand.
* De wisselkoers: hoeveel prijsverlaging staat gelijk aan een kwaliteitspunt, en het marginale effect van 1 euro (of 1%) per prijsveld op de prijsscore.
* De gevoeligheid per prijsveld (effect van bijvoorbeeld plus 10%), gerangschikt van meest naar minst gevoelig.
* Het concurrentievergelijk: bereken met dezelfde formule de prijsscore, kwaliteitsscore en totaalscore van de concurrent, en toon in duidelijk onderscheiden kleurtoestanden of de eigen totaalscore hoger is (winst), gelijk (met de tie-breakregel uit de stukken) of lager (verlies). Voeg een compacte tabel toe met kwaliteit, prijs en totaal voor beide partijen en het verschil per regel, met het verschil kleurgecodeerd. Is de eigen inschrijving ongeldig, toon dan expliciet de verliestoestand (terzijdelegging), ongeacht de scores.

Zorg dat alle berekeningen navolgbaar zijn: de gebruikte formule staat zichtbaar in het dashboard.

## 5. Stap 4: bouw het dashboard (technische eisen)

Lever een losstaand HTML-bestand op, dat volledig offline werkt door het bestand simpelweg in een browser te openen.

* Geen externe afhankelijkheden: geen CDN, geen externe fonts of libraries, geen build-stap. Alle CSS en JavaScript staan inline. Grafieken teken je met inline SVG.
* Geen browseropslag: gebruik nooit localStorage of sessionStorage. Houd alle status in het geheugen (JavaScript-variabelen); dat geldt ook voor de ingestelde kolomverdeling.
* Layout met verstelbare kolommen: een bedieningskolom (invoer) en een resultaatkolom (kerncijfers, meters, grafieken), met daartussen een versleepbaar grijppunt (een verticale splitter) dat de gebruiker naar links en rechts kan bewegen om de middellijn te verplaatsen. Ondersteun muis en touch, toetsenbordbediening (pijltjes links/rechts, en een toets die de beginstand herstelt), en dubbelklik om te resetten. Hanteer minimumbreedtes per kolom. Op smalle schermen vallen de kolommen onder elkaar en verdwijnt het grijppunt.
* Responsieve kaartroosters: omdat de kolombreedte instelbaar is, moeten roosters van kaarten en vakken (kerncijfers, wisselkoers, arbitrage) omvouwen op de beschikbare breedte binnen de kaart (bijvoorbeeld via auto-fit met een minimumbreedte per tegel), en niet op vaste vensterbreakpoints. Zo blijft geen enkele tegel buiten de kaart steken bij een smalle kolom.
* Gecombineerd tarievenblok: presenteer verkoop en kostprijs in een blok. Per prijsveld of functiegroep een cluster met de verkoopprijs-slider en de kostprijs-slider onder elkaar op dezelfde schaal, plus per cluster een ROS-badge. Onderscheid de twee sliders visueel met verschillende kleuren (verkoop in --blauw, kostprijs met een baan in --zacht en een knop in --lei, zie Stap 5). Zet de ROS-rekenhulp (richtingschakelaar plus ROS-niveauknoppen) in een uitgelicht gekleurd kader met een klein label, zodat visueel duidelijk is dat de richtingkeuze en de percentageknoppen bij elkaar horen. Toon onder de clusters de geaggregeerde verkoopprijs, de gewogen kostprijs en de totale ROS in een kader. Zorg dat een lange functienaam netjes kan afbreken (krimpbaar flex-item) zodat de badge bij elke kolombreedte op zijn plek blijft.
* Kernvisualisaties:
   * Grote resultaatkaarten: geaggregeerde prijs, prijsscore, kwaliteitsscore, totaalscore, marge.
   * Een bandmeter die toont waar de beoordelingsprijs valt tussen de score-grenzen, met de ongeldige zones gemarkeerd.
   * Een prijsscore-curve (of de relevante curve voor het formuletype) met de eigen positie.
   * Bijdrage- en gevoeligheidsbalkjes per prijsveld, met zichtbare gekleurde vulbalken (block-level elementen, geschaald ten opzichte van het maximum, live meebewegend).
* Concurrentieblok: met de win/gelijk/verlies-kleurtoestanden zoals in Stap 3 beschreven.
* Geen scenariopresets: het dashboard opent op een geldig startpunt binnen de band. De ROS-rekenhulp vervangt scenario-knoppen; neem geen scenario-referentiepunten op in de prijsscore-curve.
* Validatie en meldingen: heldere geldig- of ongeldig-status met de concrete reden.
* Toegankelijkheid: labels op alle sliders en invoervelden, zichtbare focus (ook op het grijppunt), respecteer prefers-reduced-motion, en getalsopmaak in de gekozen taal (Nederlandse decimale komma bij Nederlands).
* Bronvermelding: een voettekst met de herkomst van formule en wegingen, en een korte disclaimer dat markttarieven, kostprijs, kwaliteitsniveaus en concurrentie-invoer aannames zijn. Neem een zichtbaar versielabel op (datum).
* Footer / statusbalk: sluit het dashboard onderaan af met een statusbalk over de volle breedte in --blauw met tekst in #c5d0dc: "EMVI Dashboard v4.0". Neem geen bedrijfsnaam, organisatienaam of productnaam op in de footer of elders in het dashboard.

## 6. Stap 5: kleurenschema (modern, zakelijk, vlak)

Pas onderstaand kleurenschema toe via CSS-variabelen. Alle kleuren zijn vlak; gebruik geen verlooptinten. Gebruik de signaalkleuren spaarzaam voor markeringen en waarschuwingen, en houd de rest rustig. Gebruik geen huisstijl, logo of bedrijfsnaam van welke organisatie dan ook.

Basiskleuren (CSS-variabelen):

* --blauw #1b2a41 (marineblauw): header, statusbalk, hoofdtitels, sectiekoppen, body-tekst van kerncijfers, het formuleblok en de verkoopprijs-slider.
* --accent #1f5f8b (staalblauw): accentlijn van 4px onder de header, subkoppen (h3), actieve knoppen (waaronder de actieve richtingschakelaar en de actieve ROS-knop), tabs en tags, de eigen positie in grafieken en hover-toestanden.
* --zacht #e8eef5 (lichtblauwgrijs): informatievlakken, het uitgelichte kader om de ROS-rekenhulp, tags, de baan van de kostprijs-slider en hover op tabelrijen.
* --lei #3d4a5c (leigrijs): labels bij sliders en invoervelden, de knop van de kostprijs-slider, samenvattende regels en kpi-labels.
* --muted #6b7684 (gedempt grijs): tabelkoppen, secundaire labels, bronvermelding en disclaimer.
* --rand #d9e0e8 (randgrijs): randen van kaarten, tabellen en kpi-tegels, scheidingslijnen, assen van meters en grafieken.
* --wit #f5f7fa (koel wit): paginaachtergrond, tabelkoppen, kpi-tegels en zebra-rijen.
* --terra #b42318 (baksteenrood): ongeldige invoer, terzijdelegging, verlies-toestand, negatieve ROS en waarschuwingsblokken (linkerrand).
* --teal #2e7d5b (gedempt groen): winst-toestand, gezonde ROS en geldige status.
* --tealzacht #e3f1ea (lichtgroen): achtergrond van winst-toestand en geldige status.
* Gelijk-toestand en dunne ROS: gebruik --accent als tekstkleur met --zacht als achtergrond, zodat het schema geen extra geel nodig heeft.

Afgeleide en vaste kleuren:

* #ffffff: kaarten, badge-achtergrond, tekst in header, statusbalk en formuleblok.
* #c5d0dc: subtitel in de header en tekst in de statusbalk.
* #9aa8b8: meta-informatie (bronvermelding) in de header.
* #fbe9e7: achtergrond van rode tags en ROS-badges in de negatieve toestand.
* #fdf3f2 met rand #f0c9c4: achtergrond van waarschuwingsblokken (ongeldige inschrijving, tegenstrijdigheden).
* rgba(27,42,65,.05) en rgba(27,42,65,.06): schaduwen van kaarten.

Typografie en vorm:

* Font-stack: 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; body 16px, regelafstand 1,6. Gebruik tabular-nums voor getallen.
* Tabelkoppen: kapitalen, 0,78rem, letterspatiering 0,05em, kleur --muted, achtergrond --wit.
* Kaarten: afgeronde hoeken 14px, rand 1px --rand, lichte schaduw.
* Badges en tags (waaronder de ROS-badges): volledig afgerond (999px).
* Header: vlak --blauw met onderrand 4px --accent. Statusbalk: vlak --blauw met tekst #c5d0dc.

Print: verberg interactieve bedieningselementen die op papier geen betekenis hebben (grijppunt), gebruik witte achtergronden en zwarte tekst, tabelkoppen #eeeeee en randen #999999.

Let op de CSS-specificiteit zodat actieve knoppen leesbaar blijven: voorkom bijvoorbeeld witte tekst op een witte achtergrond bij een ingedrukte knop binnen een gekleurd kader. Controleer dat alle tekst-op-kleur-combinaties voldoende contrast hebben (minimaal WCAG AA).

## 7. Outputeisen

* Precies een bestand met de naam uit OUTPUTNAAM.
* Volledig offline werkend; geen placeholder-data die op echte data lijkt.
* Naast het bestand een korte notitie (enkele zinnen) met: het gevonden formuletype, de belangrijkste aannames, en eventuele ontbrekende gegevens die de gebruiker nog moet kalibreren.

## 8. Kwaliteitscontrole en guardrails

* Leid de prijsformule, de wegingen en de randvoorwaarden uitsluitend af uit de stukken. Verzin geen formule en geen getallen. Meld tegenstrijdigheden tussen paragrafen expliciet en kies transparant welke bepaling je volgt.
* Als het formuletype relatief of veldafhankelijk is, moet het dashboard invoervelden voor concurrentieprijzen bevatten om de eigen prijsscore te kunnen berekenen; anders is de score niet te berekenen. Maak die afhankelijkheid expliciet.
* Label alle markt-, kostprijs-, kwaliteits- en concurrentie-aannames zichtbaar als aanname.
* Test de mechaniek: controleer dat het startpunt geldig is (binnen alle randvoorwaarden), dat de scores kloppen met de formule, en dat de ROS-rekenhulp in beide richtingen de randvoorwaarden respecteert en binnen de sliderrange clampt. Controleer dat het concurrentievergelijk consistent is met de formule.
* Meld ontbrekende of ambigue informatie in plaats van er stilzwijgend overheen te rekenen.
* Controleer voor oplevering dat het bestand geen bedrijfsnaam, organisatienaam, logo of huisstijlverwijzing bevat.
* Dit is een commerciele rekenhulp, geen juridisch advies; verwijs voor de bindende voorwaarden naar de stukken en de Nota van Inlichtingen.

Begin nu met de controle of de aanbestedingsstukken in de projectkennis staan en haal ze zo nodig op via de link. Ga daarna door met Stap 1: analyseer de aanbestedingsstukken en leid het EMVI-model af. Werk daarna door naar het opleveren van het EMVI Dashboard.

## Oplevering

Lever het HTML-bestand op als downloadbaar bestand met de naam uit OUTPUTNAAM. Controleer vóór het schrijven of er in de doelmap al een bestand met die naam staat; overschrijf een bestaande versie nooit zonder dat de gebruiker daarom vraagt, maar gebruik dan een lettersuffix (vJJJJMMDDa, vJJJJMMDDb, enzovoort). Gebruik nooit het em dash-teken in de tekst van het dashboard of de notitie.

## Wijzigingshistorie

- 1.0 (2026-09-09): eerste versie, gebaseerd op het universele prompt "EMVI Dashboard" v20260909b.

