MediaWiki:Gadget-wix-interactive.js: Difference between revisions

Content deleted Content added
No edit summary
No edit summary
Line 14:
- "csm-rollforward" Horizontal waterfall: CSM opening → movements → closing
- "building-blocks" Stacked-bar initial recognition building blocks
- "impact-sort" Binary classification: CSM vs P&L scenario sorter
================================================================ */
 
Line 34 ⟶ 35:
'grouping-funnel': initGroupingFunnel,
'csm-rollforward': initCsmRollforward,
'building-blocks': initBuildingBlocks,
'impact-sort': initImpactSort
};
 
Line 3,234 ⟶ 3,236:
 
update();
}
 
 
/* ================================================================
IMPACT SORT — data-wix-module="impact-sort"
Binary classification exercise: does the scenario adjust the CSM
or hit P&L directly? Six shuffled cards, score tracking, and a
final results screen.
================================================================ */
 
function initImpactSort( container ) {
 
/* ── Scenario data ───────────────────────────────────────── */
 
var SCENARIOS = [
{ icon: '\uD83D\uDE97',
text: 'AXA Germany motor insurance: new winter data suggests total claims over the remaining coverage period will be <strong>\u20AC4.5M instead of \u20AC5M</strong> \u2014 a favourable change of \u20AC500,000.',
answer: 'csm',
correctHead: '\u2705 Correct \u2014 adjusts the CSM.',
correctBody: 'This change relates to claims expected over the <em>remaining</em> coverage period \u2014 service the insurer has <strong>not yet delivered</strong>. Because it concerns future service, the \u20AC500,000 favourable change increases the CSM, and will be released as profit gradually as coverage continues.',
wrongHead: '\u2717 Not quite \u2014 this one adjusts the CSM.',
wrongBody: 'Ask the key question: has the service already been provided? No \u2014 this change relates to claims expected over the <em>remaining</em> coverage period. Because it concerns future service, the \u20AC500,000 favourable change increases the CSM rather than appearing in P&L immediately.' },
{ icon: '\uD83D\uDE97',
text: 'AXA Germany motor insurance: revised data shows expected claims will <strong>rise by \u20AC500,000</strong> over the remaining coverage period (future claims, not yet incurred).',
answer: 'csm',
correctHead: '\u2705 Correct \u2014 adjusts the CSM.',
correctBody: 'Unfavourable changes about future service are absorbed by the CSM, just like favourable ones. The CSM decreases by \u20AC500,000. The CSM acts as a buffer in both directions \u2014 as long as it stays at or above zero.',
wrongHead: '\u2717 Not quite \u2014 this one adjusts the CSM.',
wrongBody: 'The change relates to claims that have <em>not yet been incurred</em> \u2014 it\u2019s about future service. Unfavourable changes about the future are absorbed by the CSM (decreasing it by \u20AC500,000), just as favourable ones increase it. The key: the service hasn\u2019t been provided yet.' },
{ icon: '\u26C8\uFE0F',
text: 'A severe hailstorm strikes Spain <strong>during the current reporting period</strong>. The insurer must increase its estimate of claims for damage that has already occurred.',
answer: 'pl',
correctHead: '\u2705 Correct \u2014 hits P&L directly.',
correctBody: 'The insurer was on risk when the storm happened \u2014 the service (providing coverage during that period) has <strong>already been delivered</strong>. Since this relates to current service, the full amount goes straight to insurance service expenses in the income statement. The CSM cannot absorb it.',
wrongHead: '\u2717 Not quite \u2014 this one hits P&L directly.',
wrongBody: 'Ask the key question: has the service already been provided? Yes \u2014 the insurer was on risk when the storm struck. This is current-period service, so the increase goes straight to insurance service expenses. The CSM only absorbs changes about <em>future</em> service.' },
{ icon: '\uD83D\uDD27',
text: 'A claim from a <strong>prior year</strong> is re-estimated upward because repair costs turned out to be higher than initially thought.',
answer: 'pl',
correctHead: '\u2705 Correct \u2014 hits P&L directly.',
correctBody: 'This relates to <strong>past service</strong> \u2014 the claim event already happened in a prior period. Any re-estimate of an already-incurred claim bypasses the CSM entirely and flows directly into insurance service expenses. The CSM only represents profit on service <em>still to come</em>.',
wrongHead: '\u2717 Not quite \u2014 this one hits P&L directly.',
wrongBody: 'The claim was incurred in a prior year \u2014 the service has long since been provided. Re-estimates of already-incurred claims relate to past service and go straight to the income statement. Remember: the CSM represents profit on service <em>still to come</em>, not service already delivered.' },
{ icon: '\uD83C\uDF0A',
text: 'Brittany, France: a January storm damages 200 roofs. Some homeowners don\u2019t report until March, but the insurer estimates the <strong>full cost of incurred claims including IBNR</strong>.',
answer: 'pl',
correctHead: '\u2705 Correct \u2014 hits P&L directly.',
correctBody: 'The claims are <strong>incurred</strong> in January, even if not yet reported. Once incurred, the liability relates to past service \u2014 the insurer was on risk during the storm. Any estimates or re-estimates of these claims go straight to the income statement. IBNR doesn\u2019t change this: incurred means the service has been provided.',
wrongHead: '\u2717 Not quite \u2014 this one hits P&L directly.',
wrongBody: 'The storm already happened \u2014 those 200 roofs were damaged while the insurer was on risk. Even though some claims are IBNR (incurred but not yet reported), they are still <em>incurred</em>, meaning the service has been provided. All incurred claim estimates bypass the CSM and go to P&L.' },
{ icon: '\uD83D\uDE97',
text: 'AXA Germany motor insurance: expected claims rise so dramatically that the <strong>CSM would go below zero</strong>. The change relates entirely to future service.',
answer: 'both',
correctHead: '\u2705 Correct \u2014 but there\u2019s a twist.',
wrongHead: '\u2717 It\u2019s actually a trick question \u2014 both answers are partially right.',
bothBody: 'This change relates to future service, so it <em>starts</em> by adjusting the CSM. But the CSM cannot go negative. The portion that brings the CSM to zero is absorbed normally; the <strong>excess</strong> spills over into P&L as an immediate loss. The group becomes onerous and a loss component is established. This is the one scenario where the answer is \u201Cboth\u201D \u2014 CSM first, then P&L for the overflow.' }
];
 
/* ── State ───────────────────────────────────────────────── */
 
var order = shuffle( makeRange( SCENARIOS.length ) );
var current = 0;
var correct = 0;
var wrong = 0;
var answered = false;
 
function makeRange( n ) { var a = []; for ( var i = 0; i < n; i++ ) a.push( i ); return a; }
 
function shuffle( arr ) {
for ( var i = arr.length - 1; i > 0; i-- ) {
var j = Math.floor( Math.random() * ( i + 1 ) );
var t = arr[i]; arr[i] = arr[j]; arr[j] = t;
}
return arr;
}
 
/* ── Build UI ────────────────────────────────────────────── */
 
wix.empty( container );
 
var wrapper = wix.el( 'div', { className: 'wix-eng-wrapper' } );
container.appendChild( wrapper );
 
/* Title */
wrapper.appendChild( wix.el( 'div', { className: 'wix-sim-title', textContent: 'Where Does the Impact Land?' } ) );
 
/* Decision rule */
wrapper.appendChild( wix.el( 'div', { className: 'wix-is-rule', innerHTML: '<strong>The key question:</strong> \u201CHas the service already been provided?\u201D If yes \u2192 P&L. If no \u2192 CSM.' } ) );
 
/* Progress bar */
var progFill = wix.el( 'div', { className: 'wix-progress-fill', style: { width: '0%' } } );
var progText = wix.el( 'span', { className: 'wix-is-badge', style: { border: 'none', padding: '0', background: 'none', color: '' } } );
var progBar = wix.el( 'div', { className: 'wix-progress-wrap', style: { marginBottom: '1rem' } }, [
wix.el( 'div', { className: 'wix-progress-track' }, [ progFill ] ),
progText
] );
wrapper.appendChild( progBar );
 
/* Score badges */
var badgeCorrect = wix.el( 'span', { className: 'wix-is-badge wix-is-badge--correct' } );
var badgeWrong = wix.el( 'span', { className: 'wix-is-badge wix-is-badge--wrong' } );
wrapper.appendChild( wix.el( 'div', { className: 'wix-is-score-row' }, [ badgeCorrect, badgeWrong ] ) );
 
/* Card stage */
var cardStage = wix.el( 'div' );
wrapper.appendChild( cardStage );
 
/* Choice buttons */
var btnCsm = wix.el( 'button', { className: 'wix-is-choice wix-is-choice--csm' }, [
wix.el( 'span', { className: 'wix-is-choice-icon', textContent: '\uD83D\uDD04' } ),
wix.el( 'span', { className: 'wix-is-choice-title', textContent: 'Adjusts the CSM' } ),
wix.el( 'span', { className: 'wix-is-choice-sub', textContent: 'Future service \u2014 profit recognised later' } )
] );
var btnPl = wix.el( 'button', { className: 'wix-is-choice wix-is-choice--pl' }, [
wix.el( 'span', { className: 'wix-is-choice-icon', textContent: '\uD83D\uDCC9' } ),
wix.el( 'span', { className: 'wix-is-choice-title', textContent: 'Hits P&L directly' } ),
wix.el( 'span', { className: 'wix-is-choice-sub', textContent: 'Current or past service \u2014 recognised now' } )
] );
var choicesEl = wix.el( 'div', { className: 'wix-is-choices' }, [ btnCsm, btnPl ] );
wrapper.appendChild( choicesEl );
 
/* Feedback */
var fbHead = wix.el( 'div', { className: 'wix-is-fb-head' } );
var fbBody = wix.el( 'div' );
var btnNext = wix.el( 'button', { className: 'wix-btn', textContent: 'Next scenario \u25B8', style: { marginTop: '0.6rem' } } );
var feedbackEl = wix.el( 'div', { className: 'wix-is-feedback wix-hidden' }, [ fbHead, fbBody, btnNext ] );
wrapper.appendChild( feedbackEl );
 
/* Final screen */
var finalIcon = wix.el( 'div', { className: 'wix-is-final-icon' } );
var finalTitle = wix.el( 'div', { className: 'wix-is-final-title' } );
var finalBody = wix.el( 'div', { className: 'wix-is-final-body' } );
var btnRestart = wix.el( 'button', { className: 'wix-btn wix-btn--outline', textContent: '\u21BA Try again' } );
var finalEl = wix.el( 'div', { className: 'wix-is-final wix-hidden' }, [ finalIcon, finalTitle, finalBody, btnRestart ] );
wrapper.appendChild( finalEl );
 
/* ── Render helpers ──────────────────────────────────────── */
 
function updateScores() {
badgeCorrect.textContent = '\u2713 ' + correct + ' correct';
badgeWrong.textContent = '\u2717 ' + wrong + ' wrong';
}
 
function renderCard() {
feedbackEl.className = 'wix-is-feedback wix-hidden';
answered = false;
 
if ( current >= order.length ) {
showFinal();
return;
}
 
var s = SCENARIOS[order[current]];
 
wix.empty( cardStage );
var card = wix.el( 'div', { className: 'wix-is-card' }, [
wix.el( 'div', { className: 'wix-is-card-num', textContent: 'Scenario ' + ( current + 1 ) + ' of ' + order.length } ),
wix.el( 'span', { className: 'wix-is-card-icon', textContent: s.icon } ),
wix.el( 'div', { className: 'wix-is-card-text', innerHTML: s.text } )
] );
cardStage.appendChild( card );
 
progFill.style.width = ( current / order.length * 100 ) + '%';
progText.textContent = current + ' / ' + order.length;
 
btnCsm.disabled = false;
btnPl.disabled = false;
choicesEl.className = 'wix-is-choices';
 
updateScores();
}
 
function handleAnswer( chosen ) {
if ( answered ) return;
answered = true;
 
var s = SCENARIOS[order[current]];
var isCorrect = s.answer === 'both' ? true : chosen === s.answer;
 
if ( isCorrect ) correct++; else wrong++;
updateScores();
 
/* Card border */
var card = cardStage.firstChild;
card.className = 'wix-is-card ' + ( isCorrect ? 'wix-is-card--correct' : 'wix-is-card--wrong' );
 
/* Feedback */
if ( s.answer === 'both' ) {
feedbackEl.className = 'wix-is-feedback wix-is-feedback--correct';
fbHead.textContent = chosen === 'csm' ? s.correctHead : s.wrongHead;
fbBody.innerHTML = s.bothBody;
} else if ( isCorrect ) {
feedbackEl.className = 'wix-is-feedback wix-is-feedback--correct';
fbHead.textContent = s.correctHead;
fbBody.innerHTML = s.correctBody;
} else {
feedbackEl.className = 'wix-is-feedback wix-is-feedback--wrong';
fbHead.textContent = s.wrongHead;
fbBody.innerHTML = s.wrongBody;
}
 
btnCsm.disabled = true;
btnPl.disabled = true;
 
btnNext.textContent = current >= order.length - 1 ? 'See results \u25B8' : 'Next scenario \u25B8';
}
 
function showFinal() {
wix.empty( cardStage );
choicesEl.className = 'wix-is-choices wix-hidden';
feedbackEl.className = 'wix-is-feedback wix-hidden';
progFill.style.width = '100%';
progText.textContent = order.length + ' / ' + order.length;
 
var pct = Math.round( correct / order.length * 100 );
finalIcon.textContent = pct === 100 ? '\uD83C\uDFC6' : pct >= 67 ? '\uD83D\uDC4F' : '\uD83D\uDCDA';
finalTitle.textContent = pct === 100 ? 'Perfect score!' : pct >= 67 ? 'Well done!' : 'Keep practising!';
finalBody.innerHTML = 'You got <strong>' + correct + ' out of ' + order.length + '</strong> correct (' + pct + '%).<br><br>' +
( pct === 100
? 'You\u2019ve nailed the future vs.\u00A0current/past service distinction \u2014 the key question IFRS\u00A017 asks at every re-estimate.'
: 'Remember the key question: <strong>\u201CHas the service already been provided?\u201D</strong> If yes, the change bypasses the CSM and goes straight to P&L. If no, it adjusts the CSM.' );
 
finalEl.className = 'wix-is-final';
}
 
function restart() {
order = shuffle( makeRange( SCENARIOS.length ) );
current = 0;
correct = 0;
wrong = 0;
finalEl.className = 'wix-is-final wix-hidden';
choicesEl.className = 'wix-is-choices';
renderCard();
}
 
/* ── Events ──────────────────────────────────────────────── */
 
btnCsm.addEventListener( 'click', function () { handleAnswer( 'csm' ); } );
btnPl.addEventListener( 'click', function () { handleAnswer( 'pl' ); } );
btnNext.addEventListener( 'click', function () { current++; renderCard(); } );
btnRestart.addEventListener( 'click', restart );
 
renderCard();
}