PageSourceSearch

https://www.zeb.co.jp/wp-content/cache/autoptimize/js/autoptimize_single_5cc11dadf0e8e98283ef85d25ac25ed0.js

js zeb.co.jp collected 2026-10-07 08:08:02 UTC 56,875 bytes, 108 lines download raw bytes

1(function(){'use strict';if(typeof window!=='undefined'&&window.Chart&&window.ChartDataLabels){try{window.Chart.register(window.ChartDataLabels);}catch(e){}}
2var RF_DEFS=[{key:'rh',ja:'水力',cat:'renew',cssVar:'--rf-hydro',hex:'#1e88e5'},{key:'rt',ja:'火力',cat:'nonren',cssVar:'--rf-thermal',hex:'#ef4444'},{key:'rn',ja:'原子力',cat:'nonren',cssVar:'--rf-nuclear',hex:'#a855f7'},{key:'rw',ja:'風力',cat:'renew',cssVar:'--rf-wind',hex:'#06b6d4'},{key:'rg',ja:'地熱',cat:'renew',cssVar:'--rf-geothermal',hex:'#92400e'},{key:'rs',ja:'太陽光',cat:'renew',cssVar:'--rf-solar',hex:'#f59e0b'},{key:'rb',ja:'バイオマス',cat:'renew',cssVar:'--rf-biomass',hex:'#16a34a'},{key:'rc',ja:'蓄電池',cat:'storage',cssVar:'--rf-battery',hex:'#6366f1'},{key:'ro',ja:'その他',cat:'other',cssVar:'--rf-other',hex:'#94a3b8'},];var RF_KEYS=RF_DEFS.map(function(s){return s.key;});var RF_BY_KEY={};RF_DEFS.forEach(function(s){RF_BY_KEY[s.key]=s;});var PRESETS=[{id:'all',label:'すべて',keys:RF_KEYS.slice()},{id:'renew',label:'再エネのみ',keys:RF_DEFS.filter(function(s){return s.cat==='renew';}).map(function(s){return s.key;})},{id:'nonren',label:'非再エネのみ',keys:RF_DEFS.filter(function(s){return s.cat==='nonren';}).map(function(s){return s.key;})},{id:'solar',label:'太陽光のみ',keys:['rs']},{id:'none',label:'すべて解除',keys:[]},];var VOLT_COLORS={low:'#06b6d4',high:'#f97316'};var VOLT_LABELS={low:'低圧',high:'特別高圧/高圧'};var state={overview:null,tab:'national',selectedPref:null,selectedRegion:'all',prefDetailCache:{},charts:{},prefYear:null,muniYear:null,detailPref:null,detailMuni:'',selectedRf:RF_KEYS.slice(),prefTableSort:{col:'name',dir:'asc'},muniTableSort:{col:'rf',dir:'desc'},};var KARTE_GAP_PREFS_2022=['tokushima','kagawa','ehime','kochi'];function hasMuniDataGap(pkey,year){return year===2022&&KARTE_GAP_PREFS_2022.indexOf(pkey)>=0;}
3function renderSortIndicator(active,dir){if(!active)return'<span class="erf-sort-arrow">⇅</span>';return'<span class="erf-sort-arrow active">'+(dir==='asc'?'▲':'▼')+'</span>';}
4function applyTableSort(items,sort,getValue){var dir=sort.dir==='desc'?-1:1;items.sort(function(a,b){var av=getValue(a,sort.col);var bv=getValue(b,sort.col);if(av==null&&bv==null)return 0;if(av==null)return 1;if(bv==null)return-1;if(typeof av==='string'||typeof bv==='string'){return String(av).localeCompare(String(bv),'ja')*dir;}
5return(av-bv)*dir;});}
6function onHeaderClick(sort,col,defaultDirForNumeric){if(sort.col===col){sort.dir=sort.dir==='asc'?'desc':'asc';}else{sort.col=col;sort.dir=defaultDirForNumeric||'desc';}}
7function fmt(v,digits){if(v==null||isNaN(v))return'-';digits=digits==null?0:digits;return Number(v).toLocaleString('ja-JP',{maximumFractionDigits:digits,minimumFractionDigits:digits});}
8function fmtEnergy(v_thousand_kwh){if(v_thousand_kwh==null||isNaN(v_thousand_kwh))return'-';var v_mwh=v_thousand_kwh;var sign=v_mwh<0?'-':'';var av=Math.abs(v_mwh);if(av>=1e6)return sign+(av/1e6).toFixed(2)+' TWh';if(av>=1e3)return sign+(av/1e3).toFixed(2)+' GWh';return sign+Math.round(av)+' MWh';}
9function fmtAxisEnergy(v){if(v==null||isNaN(v))return'';var sign=v<0?'-':'';var av=Math.abs(v);if(av>=1e6)return sign+(av/1e6).toFixed(1)+'TWh';if(av>=1e3)return sign+(av/1e3).toFixed(1)+'GWh';return sign+Math.round(av)+'MWh';}
10function growth(curr,base){if(!base||base===0||curr==null)return null;return(curr/base-1)*100;}
11function growthClass(g){return g==null?'':(g>=0?'pos':'neg');}
12function fmtGrowth(g){if(g==null)return'-';return(g>=0?'+':'')+g.toFixed(2)+'%';}
13function destroyChart(id){if(state.charts[id]){state.charts[id].destroy();delete state.charts[id];}}
14function isTopmostInStack(c){if(!c||!c.chart||!c.chart.data)return false;var ds=c.chart.data.datasets;var meIdx=c.datasetIndex;var di=c.dataIndex;if(meIdx==null||di==null)return false;var me=ds[meIdx];if(!me)return false;var myStack=me.stack;var myVal=me.data?me.data[di]:null;if(myVal==null||myVal===0)return false;for(var i=meIdx+1;i<ds.length;i++){var o=ds[i];if(!o||o.stack!==myStack)continue;var v=o.data?o.data[di]:null;if(v!=null&&v!==0)return false;}
15return true;}
16function stackTotalAt(c){if(!c||!c.chart||!c.chart.data)return 0;var ds=c.chart.data.datasets;var me=ds[c.datasetIndex];if(!me)return 0;var myStack=me.stack;var idx=c.dataIndex;var sum=0;for(var i=0;i<ds.length;i++){var o=ds[i];if(!o||o.stack!==myStack)continue;var v=o.data?o.data[idx]:null;if(v!=null)sum+=v;}
17return sum;}
18function ajaxJson(action,params){var fd=new FormData();fd.append('action',action);fd.append('_nonce',ERF.nonce);Object.keys(params||{}).forEach(function(k){fd.append(k,params[k]);});return fetch(ERF.ajaxUrl,{method:'POST',body:fd,credentials:'same-origin'}).then(function(r){if(!r.ok){return r.json().then(function(j){throw new Error(j&&j.data?j.data:('HTTP '+r.status));},function(){throw new Error('HTTP '+r.status);});}
19return r.json();});}
20function sumRfSelected(row){if(!row)return 0;var s=0;state.selectedRf.forEach(function(k){var v=row[k];if(v!=null)s+=v;});return s;}
21function sumDemand(row){if(!row)return 0;return(row.dl||0)+(row.dh||0);}
22function renderHeader(ov){var years=ov.years;var lastYear=years[years.length-1];var firstYear=years[0];var nat_last=ov.national[String(lastYear)];var muniRange=ov.muni_years[0]+'-'+ov.muni_years[ov.muni_years.length-1];return''+'<div class="msd-header">'+'<div class="msd-header-left">'+'<div class="msd-header-badge">ELECTRICITY REVERSE-FLOW '+ov.meta.year_range+'</div>'+'<h2 class="msd-header-title">'+'市区町村別 電力逆潮流ダッシュボード'+'<span class="msd-beta-badge">β版</span>'+'</h2>'+'<p class="msd-header-sub">'+'全国 '+ov.meta.pref_count+' 都道府県・'+ov.meta.muni_count+' 市区町村について、'+'<b>電力逆潮流(発電実績)</b>と <b>需要との差分</b> を <b>電源9種別</b>(水力/火力/原子力/風力/地熱/太陽光/バイオマス/蓄電池/その他)で表示します。'+'対象期間は<b>全国・都道府県が '+firstYear+'〜'+lastYear+'年度</b>(電力調査統計 02-2/03-2 = 都道府県別発電実績/需要実績)、'+'<b>市区町村別が '+muniRange+'年度</b>
22(同 6-2/6-1)です。'+'</p>'+'</div>'+'<div class="msd-header-right">'+'<div class="msd-header-stat">'+'<span class="msd-header-stat-label">全国 発電実績合計 ('+lastYear+')</span>'+'<span class="msd-header-stat-value">'+fmtEnergy(nat_last.rT)+'</span>'+'<div class="msd-header-stat-sub">太陽光 '+fmtEnergy(nat_last.rs)+' / 火力 '+fmtEnergy(nat_last.rt)+'</div>'+'</div>'+'<div class="msd-header-stat">'+'<span class="msd-header-stat-label">需要との差 ('+lastYear+')</span>'+'<span class="msd-header-stat-value">'+fmtEnergy((nat_last.dl+nat_last.dh)-nat_last.rT)+'</span>'+'<div class="msd-header-stat-sub">需要 − 逆潮流</div>'+'</div>'+'</div>'+'</div>';}
23function renderBetaNotice(ov){return''+'<div class="msd-beta-notice">'+'<div class="msd-beta-notice-head">'+'<span class="msd-beta-notice-tag">β版</span>'+'<span class="msd-beta-notice-title">本ダッシュボードは試験公開(β版)です</span>'+'</div>'+'<ul class="msd-beta-notice-list">'+'<li><b>需要</b>は電力調査統計の <b>03-2 都道府県別電力需要実績</b>(2016-2024年度)の値を使用しています。</li>'+'<li><b>火力/水力/原子力/地熱/バイオマス/蓄電池/その他</b>は電力調査統計の <b>02-2 都道府県別発電実績</b>(2016-2024年度)の値を使用しています。「廃棄物」列はバイオマスに統合しています。<b>蓄電池</b>列は 2023 年度から追加されているため、それ以前は 0 として表示されます。</li>'+'<li><b>太陽光・風力</b>は、02-2 が事業者所属の発電所のみを対象とし FIT 由来の住宅・産業 PV を含まないため、<b>2022 年度以降は 6-2 市町村別逆潮流量の合算</b>を、<b>2021 年度以前は 自治体カルテ 再エネ推計</b>(環境省「自治体排出量カルテ」:容量×設備利用率の推計発電量)を採用しています。2021/2022 年度の境界で出典が切り替わるため、わずかな不連続が生じる場合があります。</li>'+'<li><b>市区町村別/個票(単一市区町村)</b>は <b>6-2 市町村別逆潮流量</b>・<b>6-1 市町村別需要電力量</b>(2022-2024年度)を使用。事業者数の少ない区分はα(非開示)として 0 扱いになります。</li>'+'<li class="msd-beta-warn-row"><b>【2022年度 四国4県のデータ欠落】</b> 2022年度の 6-2 市町村別逆潮流量では、<b>徳島県・高知県・香川県・愛媛県(四国電力エリア)</b>の市区町村別 再エネ逆潮流データ(太陽光・風力・水力・バイオマス等)が <b>欠落</b> しています(2023年度は正常値)。このため:<br> - <b>これら4県の 2022 年度の市区町村別・個票(単一市区町村)の再エネ値はほぼ 0</b> となります。<br> - <b>全国の太陽光・風力 2022 年度</b>も上記分(合計約 4 TWh)が欠落しており、実態より小さめに出ます。2022→2023 の急増の一部はこの欠落復旧によるものです。</li>'+'<li>表示中の数値は今後の精査により <b>予告なく変更される場合があります</b>。判断の根拠としては元統計と併せてご確認ください。</li>'+'</ul>'+'</div>';}
24function renderTabs(){return''+'<div class="msd-tabs">'+'<button class="msd-tab active" data-tab="national">全国推移</button>'+'<button class="msd-tab" data-tab="prefecture">都道府県別</button>'+'<button class="msd-tab" data-tab="municipality">市区町村別</button>'+'<button class="msd-tab" data-tab="detail">個票</button>'+'</div>';}
25function renderSourceFilter(){var presets=PRESETS.map(function(p){var act=matchPreset(p)?' active':'';return'<button class="erf-preset'+act+'" data-preset="'+p.id+'">'+p.label+'</button>';}).join('');var chks=RF_DEFS.map(function(s){var ck=state.selectedRf.indexOf(s.key)>=0?' checked':'';return''+'<label class="erf-source-chk">'+'<input type="checkbox" data-src="'+s.key+'"'+ck+'>'+'<span class="erf-source-swatch" style="background:'+s.hex+';"></span>'+
26s.ja+'</label>';}).join('');return''+'<div class="erf-filter" data-role="rf-filter">'+'<div class="erf-filter-head">'+'<h4 class="erf-filter-title">電源種別フィルタ</h4>'+'<div class="erf-filter-presets">'+presets+'</div>'+'</div>'+'<div class="erf-sources">'+chks+'</div>'+'</div>';}
27function matchPreset(p){if(p.keys.length!==state.selectedRf.length)return false;var sortedA=p.keys.slice().sort();var sortedB=state.selectedRf.slice().sort();for(var i=0;i<sortedA.length;i++)if(sortedA[i]!==sortedB[i])return false;return true;}
28function updateFilterUiActive(){var el=document.querySelector('[data-role="rf-filter"]');if(!el)return;el.querySelectorAll('.erf-preset').forEach(function(b){var p=PRESETS.find(function(x){return x.id===b.dataset.preset;});b.classList.toggle('active',p&&matchPreset(p));});el.querySelectorAll('input[type=checkbox][data-src]').forEach(function(cb){cb.checked=state.selectedRf.indexOf(cb.dataset.src)>=0;});}
29function renderTabNational(){return''+'<div class="msd-tab-panel active" data-panel="national">'+'<div class="msd-kpi cols-3" data-role="kpi-national"></div>'+'<div class="msd-row cols-1">'+'<div class="msd-chart-box">'+'<h3>全国・電力逆潮流 推移 <span class="msd-chart-note">(電源種別積み上げ)</span></h3>'+'<div class="msd-chart-canvas-wrap tall">'+'<canvas id="erf-chart-nat-rf"></canvas>'+'</div>'+'</div>'+'</div>'+'<div class="msd-row cols-1">'+'<div class="msd-chart-box">'+'<h3>全国・電力需要と逆潮流の差 <span class="msd-chart-note">(プラス側: 需要 電圧区分積み上げ / マイナス側: 逆潮流 電源種別積み上げ / 下段: 需要−逆潮流)</span></h3>'+'<div class="erf-butterfly">'+'<div class="erf-butterfly-main">'+'<canvas id="erf-chart-nat-butterfly"></canvas>'+'</div>'+'<div class="erf-butterfly-diff">'+'<canvas id="erf-chart-nat-diff"></canvas>'+'</div>'+'</div>'+'</div>'+'</div>'+'</div>';}
30function renderKpiNational(ov){var years=ov.years;var first=years[0],last=years[years.length-1];var n_first=ov.national[String(first)];var n_last=ov.national[String(last)];var rfLast=sumRfSelected(n_last);var rfFirst=sumRfSelected(n_first);var rfTotalLast=n_last.rT;var renewLast=['rh','rw','rg','rs','rb'].reduce(function(s,k){return s+(n_last[k]||0);},0);var renewRatio=rfTotalLast?renewLast/rfTotalLast*100:null;var demandLast=sumDemand(n_last);var diff=demandLast-rfLast;var cards=[{key:'rf-total',label:'選択電源 逆潮流 ('+last+')',value:fmtEnergy(rfLast),sub:'全電源合計: '+fmtEnergy(rfTotalLast),g:growth(rfLast,rfFirst),gLbl:first+'→'+last},{key:'rf-renewable',label:'再エネ比率 ('+last+')',value:renewRatio==null?'-':fmt(renewRatio,1)+' %',sub:'再エネ: '+fmtEnergy(renewLast),g:null},{key:'diff',label:'需要 − 選択電源 逆潮流 ('+last+')',value:fmtEnergy(diff),sub:'需要 '+fmtEnergy(demandLast)+' − 逆潮流 '+fmtEnergy(rfLast),g:null},];var html=cards.map(function(c){var growthHtml='';if(c.g!=null){growthHtml='<div class="msd-kpi-growth '+growthClass(c.g)+'">'+fmtGrowth(c.g)+' ('+c.gLbl+')</div>';}
31return''+'<div class="msd-kpi-card kpi-'+c.key+'">'+'<div class="msd-kpi-label">'+c.label+'</div>'+'<div class="msd-kpi-value">'+c.value+'</div>'+'<div class="msd-kpi-sub">'+c.sub+'</div>'+
32growthHtml+'</div>';}).join('');document.querySelector('[data-role="kpi-national"]').innerHTML=html;}
33function drawNationalRfStack(ov,ctxId,valueFn,yTitle,axisFmt,tooltipFmt){var ctx=document.getElementById(ctxId);if(!ctx)return;destroyChart(ctxId);var years=ov.years;var datasets=RF_DEFS.filter(function(s){return state.selectedRf.indexOf(s.key)>=0;}).map(function(s){return{label:s.ja,data:years.map(function(y){return valueFn(ov.n
33ational[String(y)],s.key);}),backgroundColor:s.hex+'d0',borderColor:s.hex,borderWidth:1,stack:'rf'};});state.charts[ctxId]=new Chart(ctx,{type:'bar',data:{labels:years,datasets:datasets},options:{responsive:true,maintainAspectRatio:false,interaction:{mode:'index',intersect:false},layout:{padding:{top:24}},plugins:{legend:{position:'top'},datalabels:{display:isTopmostInStack,anchor:'end',align:'end',offset:2,clip:false,font:{weight:'700',size:11},color:'#0f172a',formatter:function(v,c){return tooltipFmt(stackTotalAt(c));}},tooltip:{callbacks:{label:function(c){return c.dataset.label+': '+tooltipFmt(c.parsed.y);},footer:function(items){var sum=items.reduce(function(s,i){return s+i.parsed.y;},0);return'合計: '+tooltipFmt(sum);}}}},scales:{x:{stacked:true,title:{display:true,text:'年度'}},y:{stacked:true,title:{display:true,text:yTitle},ticks:{callback:function(v){return axisFmt(v);}}}}}});}
34function drawNationalRf(ov){drawNationalRfStack(ov,'erf-chart-nat-rf',function(n,k){return n[k]||0;},'電力逆潮流 (MWh / GWh / TWh)',function(v){return fmtAxisEnergy(v);},function(v){return fmtEnergy(v);});}
35function drawNationalButterfly(ov){var years=ov.years;var mainCtx=document.getElementById('erf-chart-nat-butterfly');if(!mainCtx)return;destroyChart('erf-chart-nat-butterfly');var demandDatasets=[{label:'需要(低圧)',stack:'demand',data:years.map(function(y){return ov.national[String(y)].dl;}),backgroundColor:VOLT_COLORS.low+'cc',borderColor:VOLT_COLORS.low,borderWidth:1,},{label:'需要('+VOLT_LABELS.high+')',stack:'demand',data:years.map(function(y){return ov.national[String(y)].dh;}),backgroundColor:VOLT_COLORS.high+'cc',borderColor:VOLT_COLORS.high,borderWidth:1,}];var rfDatasets=RF_DEFS.filter(function(s){return state.selectedRf.indexOf(s.key)>=0;}).map(function(s){return{label:'逆潮流('+s.ja+')',stack:'rf',data:years.map(function(y){return-(ov.national[String(y)][s.key]||0);}),backgroundColor:s.hex+'d0',borderColor:s.hex,borderWidth:1,};});state.charts['erf-chart-nat-butterfly']=new Chart(mainCtx,{type:'bar',data:{labels:years,datasets:demandDatasets.concat(rfDatasets)},options:{responsive:true,maintainAspectRatio:false,interaction:{mode:'index',intersect:false},layout:{padding:{top:40,bottom:40}},plugins:{legend:{position:'top',labels:{boxWidth:12,font:{size:11}}},datalabels:{display:isTopmostInStack,anchor:'end',align:function(c){return stackTotalAt(c)>=0?'end':'start';},offset:2,clip:false,font:{weight:'700',size:11},color:function(c){return stackTotalAt(c)>=0?'#9a3412':'#15803d';},formatter:function(v,c){return fmtEnergy(Math.abs(stackTotalAt(c)));}},tooltip:{callbacks:{label:function(c){return c.dataset.label+': '+fmtEnergy(Math.abs(c.parsed.y));}}}},scales:{x:{stacked:true,title:{display:true,text:'年度'}},y:{stacked:true,title:{display:true,text:'↑需要  /  逆潮流↓ (MWh / GWh / TWh)'},ticks:{callback:function(v){return fmtAxisEnergy(Math.abs(v));}},grid:{color:function(c){return c.tick.value===0?'#1e293b':'rgba(0,0,0,0.05)';},lineWidth:function(c){return c.tick.value===0?2:1;}}}}}});var diffCtx=document.getElementById('erf-chart-nat-diff');if(!diffCtx)return;destroyChart('erf-chart-nat-diff');var diffData=years.map(function(y){var n=ov.national[String(y)];return sumDemand(n)-sumRfSelected(n);});var diffColors=diffData.map(function(d){return d>=0?VOLT_COLORS.high+'cc':'rgba(22,163,74,0.8)';});var diffBorders=diffData.map(function(d){return d>=0?VOLT_COLORS.high:'#15803d';});state.charts['erf-chart-nat-diff']=new Chart(diffCtx,{type:'bar',data:{labels:years,datasets:[{label:'需要 − 逆潮流',data:diffData,backgroundColor:diffColors,borderColor:diffBorders,borderWidth:1}]},options:{responsive:true,maintainAspectRatio:false,layout:{padding:{top:28,bottom:28}},plugins:{legend:{display:false},datalabels:{display:true,anchor:function(c){return c.dataset.data[c.dataIndex]>=0?'end':'start';},align:function(c){return c.dataset.data[c.dataIndex]>=0?'top':'bottom';},offset:4,clip:false,font:{weight:'700',size:11},color:function(c){return c.dataset.data[c.dataIndex]>=0?'#9a3412':'#15803d';},formatter:function(v){return fmtEnergy(v);}},tooltip:{callbacks:{label:function(c){return'需要 − 逆潮流: '+fmtEnergy(c.parsed.y);}}
35}},scales:{x:{title:{display:true,text:'年度'}},y:{title:{display:true,text:'需要 − 逆潮流 (MWh/GWh/TWh)'},ticks:{callback:function(v){return fmtAxisEnergy(v);}},grid:{color:function(c){return c.tick.value===0?'#1e293b':'rgba(0,0,0,0.05)';},lineWidth:function(c){return c.tick.value===0?2:1;}}}}}});}
36function renderTabPrefecture(ov){var years=ov.years;var yearBtns=years.map(function(y){var act=(y===state.prefYear)?' active':'';return'<button class="'+act.trim()+'" data-year="'+y+'">'+y+'</button>';}).join('');return''+'<div class="msd-tab-panel" data-panel="prefecture">'+'<div class="msd-controls">'+'<div class="msd-control-group">'+'<label>表示年度</label>'+'<div class="erf-year-tabs" data-role="pref-year">'+yearBtns+'</div>'+'</div>'+'</div>'+'<div class="msd-row cols-1">'+'<div class="msd-chart-box">'+'<h3><span data-role="pref-rf-title">都道府県別 電力逆潮流</span> <span class="msd-chart-note">(電源種別積み上げ, 降順)</span></h3>'+'<div class="msd-chart-canvas-wrap pref-h">'+'<canvas id="erf-chart-pref-rf"></canvas>'+'</div>'+'</div>'+'</div>'+'<div class="msd-row cols-1">'+'<div class="msd-chart-box">'+'<h3><span data-role="pref-butterfly-title">都道府県別 需要と逆潮流の差</span> <span class="msd-chart-note">(プラス側: 需要 電圧区分積み上げ / マイナス側: 逆潮流 電源種別積み上げ)</span></h3>'+'<div class="erf-butterfly">'+'<div class="erf-butterfly-main" style="height:1200px;">'+'<canvas id="erf-chart-pref-butterfly"></canvas>'+'</div>'+'<div class="erf-butterfly-diff" style="height:1200px;">'+'<canvas id="erf-chart-pref-diff"></canvas>'+'</div>'+'</div>'+'</div>'+'</div>'+'<div class="msd-row cols-1">'+'<div class="msd-chart-box">'+'<h3>都道府県別 数値表 <span class="msd-chart-note">('+'<span data-role="pref-table-year"></span>'+'年度)</span></h3>'+'<div class="msd-heatmap-wrap" data-role="pref-table"></div>'+'<div class="msd-disclaimer" style="margin-top:14px;">'+'<b>ヒント:</b> 行ラベル(都道府県名)をクリックすると、市区町村別タブへ移動し当該都道府県のランキングを表示します。'+'</div>'+'</div>'+'</div>'+'</div>';}
37function prefList(ov){return Object.keys(ov.prefectures).map(function(k){return{key:k,ja:ov.prefectures[k].ja,en:ov.prefectures[k].en};});}
38function drawPrefStack(ov,ctxId,valueFn,axisTitle,axisFmt,tooltipFmt){var ctx=document.getElementById(ctxId);if(!ctx)return;destroyChart(ctxId);var prefs=prefList(ov);var yr=String(state.prefYear);var totals=prefs.map(function(p){var d=ov.prefecture[yr][p.key];var tot=0;state.selectedRf.forEach(function(k){tot+=valueFn(d,k)||0;});return{p:p,total:tot};});totals.sort(function(a,b){return b.total-a.total;});var sortedPrefs=totals.map(function(t){return t.p;});var datasets=RF_DEFS.filter(function(s){return state.selectedRf.indexOf(s.key)>=0;}).map(function(s){return{label:s.ja,data:sortedPrefs.map(function(p){return valueFn(ov.prefecture[yr][p.key],s.key);}),backgroundColor:s.hex+'d0',borderColor:s.hex,borderWidth:1,stack:'rf'};});state.charts[ctxId]=new Chart(ctx,{type:'bar',data:{labels:sortedPrefs.map(function(p){return p.ja;}),datasets:datasets},options:{responsive:true,maintainAspectRatio:false,indexAxis:'y',interaction:{mode:'index',axis:'y',intersect:false},layout:{padding:{right:80}},plugins:{legend:{position:'top',labels:{boxWidth:12,font:{size:11}}},datalabels:{display:isTopmostInStack,anchor:'end',align:'end',offset:4,clip:false,font:{weight:'700',size:10},color:'#0f172a',formatter:function(v,c){return tooltipFmt(stackTotalAt(c));}},tooltip:{callbacks:{label:function(c){return c.dataset.label+': '+tooltipFmt(c.parsed.x);},footer:function(items){var sum=items.reduce(function(s,i){return s+i.parsed.x;},0);return'合計: '+tooltipFmt(sum);}}}},scales:{x:{stacked:true,title:{display:true,text:axisTitle},ticks:{callback:function(v){return axisFmt(v);}}},y:{stacked:true,ticks:{font:{size:12},autoSkip:false}}}}});}
39function drawPrefRf(ov){document.querySelector('[data-role="pref-rf-title"]').textContent='都道府県別 電力逆潮流 ('+state.prefYear+'年度)';drawPrefStack(ov,'erf-chart-pref-rf',function(d,k){return d[k]||0;},'電力逆潮流 (MWh / GWh / TWh)',function(v){return fmtAxisEnergy(v);},function(v){return fmtEnergy(v);});}
40function drawPrefButterfly(ov){document.querySelector('[data-role="pref-butterfly-title"]').textContent='都道府県別 需要と逆潮流の差 ('+state.prefYear+'年度)';var prefs=prefList(ov);var yr=String(state.prefYear);var mainCtx=document.getElementById('erf-chart-pref-butterfly');if(!mainCtx)return;
40destroyChart('erf-chart-pref-butterfly');var labels=prefs.map(function(p){return p.ja;});var demandDs=[{label:'需要(低圧)',stack:'demand',data:prefs.map(function(p){return ov.prefecture[yr][p.key].dl;}),backgroundColor:VOLT_COLORS.low+'cc',borderColor:VOLT_COLORS.low,borderWidth:1,},{label:'需要('+VOLT_LABELS.high+')',stack:'demand',data:prefs.map(function(p){return ov.prefecture[yr][p.key].dh;}),backgroundColor:VOLT_COLORS.high+'cc',borderColor:VOLT_COLORS.high,borderWidth:1,}];var rfDs=RF_DEFS.filter(function(s){return state.selectedRf.indexOf(s.key)>=0;}).map(function(s){return{label:'逆潮流('+s.ja+')',stack:'rf',data:prefs.map(function(p){return-(ov.prefecture[yr][p.key][s.key]||0);}),backgroundColor:s.hex+'d0',borderColor:s.hex,borderWidth:1,};});state.charts['erf-chart-pref-butterfly']=new Chart(mainCtx,{type:'bar',data:{labels:labels,datasets:demandDs.concat(rfDs)},options:{responsive:true,maintainAspectRatio:false,indexAxis:'y',interaction:{mode:'index',axis:'y',intersect:false},layout:{padding:{left:70,right:70}},plugins:{legend:{position:'top',labels:{boxWidth:12,font:{size:11}}},datalabels:{display:isTopmostInStack,anchor:'end',align:function(c){return stackTotalAt(c)>=0?'end':'start';},offset:4,clip:false,font:{weight:'700',size:10},color:function(c){return stackTotalAt(c)>=0?'#9a3412':'#15803d';},formatter:function(v,c){return fmtEnergy(Math.abs(stackTotalAt(c)));}},tooltip:{callbacks:{label:function(c){return c.dataset.label+': '+fmtEnergy(Math.abs(c.parsed.x));}}}},scales:{x:{stacked:true,title:{display:true,text:'←逆潮流  /  需要→ (MWh / GWh / TWh)'},ticks:{callback:function(v){return fmtAxisEnergy(Math.abs(v));}},grid:{color:function(c){return c.tick.value===0?'#1e293b':'rgba(0,0,0,0.05)';},lineWidth:function(c){return c.tick.value===0?2:1;}}},y:{stacked:true,ticks:{font:{size:12},autoSkip:false}}}}});var diffCtx=document.getElementById('erf-chart-pref-diff');if(!diffCtx)return;destroyChart('erf-chart-pref-diff');var diffData=prefs.map(function(p){var d=ov.prefecture[yr][p.key];return sumDemand(d)-sumRfSelected(d);});var diffColors=diffData.map(function(d){return d>=0?VOLT_COLORS.high+'cc':'rgba(22,163,74,0.8)';});var diffBorders=diffData.map(function(d){return d>=0?VOLT_COLORS.high:'#15803d';});state.charts['erf-chart-pref-diff']=new Chart(diffCtx,{type:'bar',data:{labels:labels,datasets:[{label:'需要 − 逆潮流',data:diffData,backgroundColor:diffColors,borderColor:diffBorders,borderWidth:1}]},options:{responsive:true,maintainAspectRatio:false,indexAxis:'y',interaction:{mode:'index',axis:'y',intersect:false},layout:{padding:{left:70,right:70}},plugins:{legend:{display:false},datalabels:{display:function(c){var v=c.dataset.data[c.dataIndex];return v!=null&&v!==0;},anchor:'end',align:function(c){return(c.dataset.data[c.dataIndex]||0)>=0?'end':'start';},offset:4,clip:false,font:{weight:'700',size:10},color:function(c){return(c.dataset.data[c.dataIndex]||0)>=0?'#9a3412':'#15803d';},formatter:function(v){return fmtEnergy(v);}},tooltip:{callbacks:{label:function(c){return'需要 − 逆潮流: '+fmtEnergy(c.parsed.x);}}}},scales:{x:{title:{display:true,text:'需要 − 逆潮流 (MWh / GWh / TWh)'},ticks:{callback:function(v){return fmtAxisEnergy(v);}},grid:{color:function(c){return c.tick.value===0?'#1e293b':'rgba(0,0,0,0.05)';},lineWidth:function(c){return c.tick.value===0?2:1;}}},y:{ticks:{font:{size:12},autoSkip:false}}}}});}
41function renderPrefTable(ov){var wrap=document.querySelector('[data-role="pref-table"]');var yEl=document.querySelector('[data-role="pref-table-year"]');if(!wrap)return;if(yEl)yEl.textContent=state.prefYear;var prefs=prefList(ov);var yr=String(state.prefYear);var rows=prefs.map(function(p){var d=ov.prefecture[yr][p.key];var rf=sumRfSelected(d);var demand=sumDemand(d);return{p:p,d:d,name:p.ja,rf:rf,rT:d.rT,demand:demand,diff:demand-rf};});applyTableSort(rows,state.prefTableSort,function(r,col){return r[col];});var s=state.prefTableSort;var sortableTh=function(col,label,align){var ta=align||'right';return'<th class="msd-sortable" data-sort-col="'+col+'" style="text-align:'+ta+';cursor:pointer;">'+
42label+' '+renderSortIndicator(s.col===col,s.dir)+'</th>';};var html='<table class="msd-heatmap"><thead><tr>'+
43sortableTh('name','都道府県','left')+
44sortableTh('rf','選択電源 逆潮流')+
45sortableTh('rT','合計 逆潮流')+
46sortableTh('demand','合計 需要')+
47sortableTh('diff','需要 − 選択電源 逆潮流')+'</tr></thead><tbody>';rows.forEach(function(r){var gap=hasMuniDataGap(r.p.key,state.prefYear);var marker=gap?'<span class="erf-gap-mark" title="2022年度 6-2 で再エネ逆潮流データが欠落しているため、太陽光・風力の値が実態より小さくなっています">⚠</span>':'';html+='<tr data-pref="'+r.p.key+'"'+(gap?' class="msd-row-gap"':'')+'>'+'<th title="クリックで市区町村別タブへ">'+r.name+marker+'</th>'+'<td class="msd-growth-cell">'+fmtEnergy(r.rf)+'</td>'+'<td class="msd-growth-cell">'+fmtEnergy(r.rT)+'</td>'+'<td class="msd-growth-cell">'+fmtEnergy(r.demand)+'</td>'+'<td class="msd-growth-cell" style="color:'+(r.diff>=0?'#9a3412':'#15803d')+';font-weight:600;">'+fmtEnergy(r.diff)+'</td>'+'</tr>';});html+='</tbody></table>';wrap.innerHTML=html;wrap.querySelectorAll('th[data-sort-col]').forEach(function(th){th.addEventListener('click',function(){var col=th.dataset.sortCol;onHeaderClick(state.prefTableSort,col,col==='name'?'asc':'desc');renderPrefTable(ov);});});
47wrap.querySelectorAll('tr[data-pref] th').forEach(function(th){th.addEventListener('click',function(e){e.stopPropagation();var pkey=th.parentNode.getAttribute('data-pref');switchTab('municipality');var sel=document.querySelector('[data-role="muni-pref-select"]');if(sel){sel.value=pkey;sel.dispatchEvent(new Event('change'));}});});}
48function renderTabMunicipality(ov){var prefs=prefList(ov);var opts=prefs.map(function(p){return'<option value="'+p.key+'">'+p.ja+'</option>';}).join('');var years=ov.muni_years;var yearBtns=years.map(function(y){var act=(y===state.muniYear)?' active':'';return'<button class="'+act.trim()+'" data-year="'+y+'">'+y+'年度</button>';}).join('');return''+'<div class="msd-tab-panel" data-panel="municipality">'+'<div class="msd-controls" style="margin-bottom:18px;">'+'<div class="msd-control-group">'+'<label>都道府県を選択</label>'+'<select class="msd-select" data-role="muni-pref-select">'+'<option value="">— 選択してください —</option>'+
49opts+'</select>'+'</div>'+'<div class="msd-control-group">'+'<label>表示年度</label>'+'<div class="erf-year-tabs" data-role="muni-year">'+yearBtns+'</div>'+'</div>'+'</div>'+'<div data-role="muni-content">'+'<div class="msd-loading" style="padding:80px 0;">都道府県を選択してください。</div>'+'</div>'+'</div>';}
50function loadPrefecture(pkey){if(state.prefDetailCache[pkey])return Promise.resolve(state.prefDetailCache[pkey]);return ajaxJson('erf_get_prefecture',{pref:pkey}).then(function(json){state.prefDetailCache[pkey]=json;return json;});}
51function filteredMkeys(detail){var all=Object.keys(detail.munis);if(!detail.regions||state.selectedRegion==='all')return all;return all.filter(function(k){return detail.munis[k].region===state.selectedRegion;});}
52function renderMuniContent(pkey){var detail=state.prefDetailCache[pkey];var regionsHtml='';if(detail&&detail.regions){var btns='<button data-region="all" class="active">全道</button>';Object.keys(detail.regions).forEach(function(rk){btns+='<button data-region="'+rk+'">'+detail.regions[rk]+'</button>';});regionsHtml=''+'<div class="msd-controls" data-role="region-filter">'+'<div class="msd-control-group">'+'<label>地域</label>'+'<div class="msd-mode-btns" data-role="region">'+btns+'</div>'+'</div>'+'<div style="font-size:12px;color:var(--msd-sub);">道南=渡島・檜山 / 道央=石狩・後志・空知・胆振・日高 / 道北=上川・留萌・宗谷 / 道東=オホーツク・十勝・釧路・根室</div>'+'</div>';}
53var gapBanner=(KARTE_GAP_PREFS_2022.indexOf(pkey)>=0)?'<div class="erf-gap-banner" data-role="muni-gap-banner" style="display:none;">'+'<b>⚠ データ欠落のお知らせ:</b> 2022 年度の電力調査統計 6-2 では、本県の市区町村別 再エネ逆潮流データ(太陽光・風力・水力・バイオマス等)が <b>欠落</b> しています。2022 年度の表示値は実態より小さく出ます(2023 年度以降は正常)。'+'</div>':'';var html=regionsHtml+gapBanner+'<div class="msd-row cols-1">'+'<div class="msd-chart-box">'+'<h3><span data-role="muni-rf-title">市区町村別 電力逆潮流</span> <span class="msd-chart-note">(上位30, 電源種別積み上げ)</span></h3>'+'<div class="msd-chart-canvas-wrap muni-h">'+'<canvas id="erf-chart-muni-rf"></canvas>'+'</div>'+'</div>'+'</div>'+'<div class="msd-row cols-1">'+'<div class="msd-chart-box">'+'<h3><span data-role="muni-butterfly-title">市区町村別 需要と逆潮流の差</span> <span class="msd-chart-note">(上位30, プラス側: 需要 電圧区分積み上げ / マイナス側: 逆潮流 電源種別積み上げ)</span></h3>'+'<div class="erf-butterfly">'+'<div class="erf-butterfly-main" style="height:900px;">'+'<canvas id="erf-chart-muni-butterfly"></canvas>'+'</div>'+'<div class="erf-butterfly-diff" style="height:900px;">'+'<canvas id="erf-chart-muni-diff"></canvas>'+'</div>'+'</div>'+'</div>'+'</div>'+'<div class="msd-row cols-1">'+'<div class="msd-chart-box">'+'<h3>市区町村ランキング <span class="msd-chart-note">('+'<span data-role="muni-table-year"></span>'+'年度, 選択電源 逆潮流 降順)</span></h3>'+'<div data-role="muni-rank-table" style="max-height:600px;overflow-y:auto;"></div>'+'</div>'+'</div>'+'<div class="msd-disclaimer" style="margin-top:14px;">'+'<b>ご注意:</b> 火力発電所や大規模太陽光発電所が立地する自治体では逆潮流量が極端に大きくなることがあります。建物の床面積を伴わない発電設備の影響です。'+'<
53/div>';document.querySelector('[data-role="muni-content"]').innerHTML=html;}
54function drawMuniStack(detail,ctxId,valueFn,axisTitle,axisFmt,tooltipFmt,topN){var ctx=document.getElementById(ctxId);if(!ctx)return;destroyChart(ctxId);var yr=String(state.muniYear);var mkeys=filteredMkeys(detail);var data=detail.data[yr]||{};var rows=mkeys.map(function(m){var d=data[m];if(!d)return null;var tot=0;state.selectedRf.forEach(function(k){tot+=valueFn(d,k)||0;});return{m:m,name:detail.munis[m].ja,total:tot,row:d};}).filter(Boolean);rows.sort(function(a,b){return b.total-a.total;});if(topN&&rows.length>topN)rows=rows.slice(0,topN);var datasets=RF_DEFS.filter(function(s){return state.selectedRf.indexOf(s.key)>=0;}).map(function(s){return{label:s.ja,data:rows.map(function(r){return valueFn(r.row,s.key);}),backgroundColor:s.hex+'d0',borderColor:s.hex,borderWidth:1,stack:'rf'};});state.charts[ctxId]=new Chart(ctx,{type:'bar',data:{labels:rows.map(function(r){return r.name;}),datasets:datasets},options:{responsive:true,maintainAspectRatio:false,indexAxis:'y',interaction:{mode:'index',axis:'y',intersect:false},layout:{padding:{right:80}},plugins:{legend:{position:'top',labels:{boxWidth:12,font:{size:11}}},datalabels:{display:isTopmostInStack,anchor:'end',align:'end',offset:4,clip:false,font:{weight:'700',size:10},color:'#0f172a',formatter:function(v,c){return tooltipFmt(stackTotalAt(c));}},tooltip:{callbacks:{label:function(c){return c.dataset.label+': '+tooltipFmt(c.parsed.x);},footer:function(items){var sum=items.reduce(function(s,i){return s+i.parsed.x;},0);return'合計: '+tooltipFmt(sum);}}}},scales:{x:{stacked:true,title:{display:true,text:axisTitle},ticks:{callback:function(v){return axisFmt(v);}}},y:{stacked:true,ticks:{font:{size:12},autoSkip:false}}}}});return rows;}
55function drawMuniRf(detail){document.querySelector('[data-role="muni-rf-title"]').textContent='市区町村別 電力逆潮流 ('+state.muniYear+'年度, 上位30)';drawMuniStack(detail,'erf-chart-muni-rf',function(d,k){return d[k]||0;},'電力逆潮流 (MWh / GWh / TWh)',function(v){return fmtAxisEnergy(v);},function(v){return fmtEnergy(v);},30);}
56function drawMuniButterfly(detail){document.querySelector('[data-role="muni-butterfly-title"]').textContent='市区町村別 需要と逆潮流の差 ('+state.muniYear+'年度, 選択電源 逆潮流 降順上位30)';var yr=String(state.muniYear);var mkeys=filteredMkeys(detail);var data=detail.data[yr]||{};var rows=mkeys.map(function(m){var d=data[m];if(!d)return null;return{m:m,name:detail.munis[m].ja,row:d,rf:sumRfSelected(d)};}).filter(Boolean);rows.sort(function(a,b){return b.rf-a.rf;});rows=rows.slice(0,30);var labels=rows.map(function(r){return r.name;});var demandDs=[{label:'需要(低圧)',stack:'demand',data:rows.map(function(r){return r.row.dl;}),backgroundColor:VOLT_COLORS.low+'cc',borderColor:VOLT_COLORS.low,borderWidth:1,},{label:'需要('+VOLT_LABELS.high+')',stack:'demand',data:rows.map(function(r){return r.row.dh;}),backgroundColor:VOLT_COLORS.high+'cc',borderColor:VOLT_COLORS.high,borderWidth:1,}];var rfDs=RF_DEFS.filter(function(s){return state.selectedRf.indexOf(s.key)>=0;}).map(function(s){return{label:'逆潮流('+s.ja+')',stack:'rf',data:rows.map(function(r){return-(r.row[s.key]||0);}),backgroundColor:s.hex+'d0',borderColor:s.hex,borderWidth:1,};});var mainCtx=document.getElementById('erf-chart-muni-butterfly');if(!mainCtx)return;destroyChart('erf-chart-muni-butterfly');state.charts['erf-chart-muni-butterfly']=new Chart(mainCtx,{type:'bar',data:{labels:labels,datasets:demandDs.concat(rfDs)},options:{responsive:true,maintainAspectRatio:false,indexAxis:'y',interaction:{mode:'index',axis:'y',intersect:false},layout:{padding:{left:70,right:70}},plugins:{legend:{position:'top',labels:{boxWidth:12,font:{size:11}}},datalabels:{display:isTopmostInStack,anchor:'end',align:function(c){return stackTotalAt(c)>=0?'end':'start';},offset:4,clip:false,font:{weight:'700',size:10},color:function(c){return stackTotalAt(c)>=0?'#9a3412':'#15803d';},formatter:function(v,c){return fmtEnergy(Math.abs(stackTotalAt(c)));}},tooltip:{callbacks:{label:function(c){return c.dataset.label+': '+fmtEnergy(Math.abs(c.parsed.x));}}}},scales:{x:{stacked:true,title:{display:true,text:'←逆潮流  /  需要→ (MWh / GWh / TWh)'},ticks:{callback:function(v){return fmtAxisEnergy(Math.abs(v));}},grid:{color:function(c){return c.tick.value===0?'#1e293b':'rgba(0,0,0,0.05)';},lineWidth:function(c){return c.tick.value===0?2:1;}}},y:{stacked:true,ticks:{font:{size:12},autoSkip:false}}}}});var diffData=rows.map(function(r){return sumDemand(r.row)-r.rf;});var diffColors=diffData.map(function(d){return d>=0?VOLT_COLORS.high+'cc':'rgba(22,163,74,0.8)';});var diffBorders=diffData.map(function(d){return d>=0?VOLT_COLORS.high:'#15803d';});var diffCtx=document.getElementById('erf-chart-muni-diff');if(!diffCtx)return;
56destroyChart('erf-chart-muni-diff');state.charts['erf-chart-muni-diff']=new Chart(diffCtx,{type:'bar',data:{labels:labels,datasets:[{label:'需要 − 逆潮流',data:diffData,backgroundColor:diffColors,borderColor:diffBorders,borderWidth:1}]},options:{responsive:true,maintainAspectRatio:false,indexAxis:'y',interaction:{mode:'index',axis:'y',intersect:false},layout:{padding:{left:70,right:70}},plugins:{legend:{display:false},datalabels:{display:function(c){var v=c.dataset.data[c.dataIndex];return v!=null&&v!==0;},anchor:'end',align:function(c){return(c.dataset.data[c.dataIndex]||0)>=0?'end':'start';},offset:4,clip:false,font:{weight:'700',size:10},color:function(c){return(c.dataset.data[c.dataIndex]||0)>=0?'#9a3412':'#15803d';},formatter:function(v){return fmtEnergy(v);}},tooltip:{callbacks:{label:function(c){return'需要 − 逆潮流: '+fmtEnergy(c.parsed.x);}}}},scales:{x:{title:{display:true,text:'需要 − 逆潮流 (MWh / GWh / TWh)'},ticks:{callback:function(v){return fmtAxisEnergy(v);}},grid:{color:function(c){return c.tick.value===0?'#1e293b':'rgba(0,0,0,0.05)';},lineWidth:function(c){return c.tick.value===0?2:1;}}},y:{ticks:{font:{size:12},autoSkip:false}}}}});}
57function renderMuniRankTable(detail){var wrap=document.querySelector('[data-role="muni-rank-table"]');var yEl=document.querySelector('[data-role="muni-table-year"]');if(!wrap)return;if(yEl)yEl.textContent=state.muniYear;var yr=String(state.muniYear);var mkeys=filteredMkeys(detail);var data=detail.data[yr]||{};var rows=mkeys.map(function(m){var d=data[m];if(!d)return null;var rf=sumRfSelected(d);var demand=sumDemand(d);return{m:m,name:detail.munis[m].ja,row:d,rf:rf,rT:d.rT||0,demand:demand,diff:demand-rf};}).filter(Boolean);applyTableSort(rows,state.muniTableSort,function(r,col){return r[col];});var s=state.muniTableSort;var sortableTh=function(col,label,align){var ta=align||'right';return'<th class="msd-sortable" data-sort-col="'+col+'" style="text-align:'+ta+';cursor:pointer;">'+
58label+' '+renderSortIndicator(s.col===col,s.dir)+'</th>';};var html='<table class="msd-heatmap"><thead><tr>'+'<th style="text-align:center;">#</th>'+
59sortableTh('name','市区町村','left')+
60sortableTh('rf','選択電源 逆潮流')+
61sortableTh('rT','合計 逆潮流')+
62sortableTh('demand','合計 需要')+
63sortableTh('diff','需要 − 選択電源 逆潮流')+'</tr></thead><tbody>';rows.forEach(function(r,i){html+='<tr>'+'<td style="text-align:center;font-weight:700;color:var(--msd-accent);">'+(i+1)+'</td>'+'<th>'+r.name+'</th>'+'<td class="msd-growth-cell">'+fmtEnergy(r.rf)+'</td>'+'<td class="msd-growth-cell">'+fmtEnergy(r.rT)+'</td>'+'<td class="msd-growth-cell">'+fmtEnergy(r.demand)+'</td>'+'<td class="msd-growth-cell" style="color:'+(r.diff>=0?'#9a3412':'#15803d')+';font-weight:600;">'+fmtEnergy(r.diff)+'</td>'+'</tr>';});html+='</tbody></table>';wrap.innerHTML=html;wrap.querySelectorAll('th[data-sort-col]').forEach(function(th){th.addEventListener('click',function(){var col=th.dataset.sortCol;onHeaderClick(state.muniTableSort,col,col==='name'?'asc':'desc');renderMuniRankTable(detail);});});}
64function renderTabDetail(ov){var prefs=prefList(ov);var opts=prefs.map(function(p){return'<option value="'+p.key+'">'+p.ja+'</option>';}).join('');return''+'<div class="msd-tab-panel" data-panel="detail">'+'<div class="msd-controls" style="margin-bottom:18px;">'+'<div class="msd-control-group">'+'<label>都道府県</label>'+'<select class="msd-select" data-role="detail-pref-select">'+'<option value="">— 選択してください —</option>'+
65opts+'</select>'+'</div>'+'<div class="msd-control-group">'+'<label>市区町村</label>'+'<select class="msd-select" data-role="detail-muni-select" disabled>'+'<option value="">— 県全体 —</option>'+'</select>'+'</div>'+'</div>'+'<div data-role="detail-content">'+'<div class="msd-loading" style="padding:80px 0;">都道府県を選択してください。</div>'+'</div>'+'</div>';}
66function renderDetailContent(){var gapBanner=(KARTE_GAP_PREFS_2022.indexOf(state.detailPref)>=0)?'<div class="erf-gap-banner">'+'<b>⚠ データ欠落のお知らせ:</b> 本県は 2022 年度の電力調査統計 6-2 で市区町村別の再エネ逆潮流データが <b>欠落</b> しているため、'+'本ダッシュボードでは <b>2022 年度の太陽光・風力</b>(市区町村合算由来)が実態より小さく表示されます。'+'2023 年度以降は正常です。'+'<
66/div>':'';var html=gapBanner+'<div class="msd-kpi cols-3" data-role="kpi-detail"></div>'+'<div class="msd-row cols-1">'+'<div class="msd-chart-box">'+'<h3><span data-role="detail-rf-title">電力逆潮流 推移</span> <span class="msd-chart-note">(電源種別積み上げ)</span></h3>'+'<div class="msd-chart-canvas-wrap tall">'+'<canvas id="erf-chart-detail-rf"></canvas>'+'</div>'+'</div>'+'</div>'+'<div class="msd-row cols-1">'+'<div class="msd-chart-box">'+'<h3><span data-role="detail-butterfly-title">電力需要と逆潮流の差</span> <span class="msd-chart-note">(プラス側: 需要 電圧区分積み上げ / マイナス側: 逆潮流 電源種別積み上げ / 下段: 需要−逆潮流)</span></h3>'+'<div class="erf-butterfly">'+'<div class="erf-butterfly-main">'+'<canvas id="erf-chart-detail-butterfly"></canvas>'+'</div>'+'<div class="erf-butterfly-diff">'+'<canvas id="erf-chart-detail-diff"></canvas>'+'</div>'+'</div>'+'</div>'+'</div>';document.querySelector('[data-role="detail-content"]').innerHTML=html;}
67function getDetailRow(year){var ov=state.overview;if(!state.detailPref)return null;var yr=String(year);if(!state.detailMuni){return ov.prefecture[yr][state.detailPref]||null;}
68var detail=state.prefDetailCache[state.detailPref];if(!detail)return null;return(detail.data[yr]||{})[state.detailMuni]||null;}
69function detailDisplayName(){var ov=state.overview;if(!state.detailPref)return'';var prefJa=ov.prefectures[state.detailPref].ja;if(!state.detailMuni)return prefJa+'(県全体)';var detail=state.prefDetailCache[state.detailPref];if(!detail||!detail.munis[state.detailMuni])return prefJa;return prefJa+' '+detail.munis[state.detailMuni].ja;}
70function detailYears(){var ov=state.overview;if(!ov)return[];return state.detailMuni?ov.muni_years.slice():ov.years.slice();}
71function renderKpiDetail(){var ov=state.overview;var years=detailYears();var first=years[0],last=years[years.length-1];var r_first=getDetailRow(first);var r_last=getDetailRow(last);if(!r_last)return;var rfLast=sumRfSelected(r_last);var rfFirst=r_first?sumRfSelected(r_first):null;var rfTotalLast=r_last.rT;var renewLast=['rh','rw','rg','rs','rb'].reduce(function(s,k){return s+(r_last[k]||0);},0);var renewRatio=rfTotalLast?renewLast/rfTotalLast*100:null;var demandLast=sumDemand(r_last);var diff=demandLast-rfLast;var cards=[{key:'rf-total',label:'選択電源 逆潮流 ('+last+')',value:fmtEnergy(rfLast),sub:'全電源合計: '+fmtEnergy(rfTotalLast),g:growth(rfLast,rfFirst),gLbl:first+'→'+last},{key:'rf-renewable',label:'再エネ比率 ('+last+')',value:renewRatio==null?'-':fmt(renewRatio,1)+' %',sub:'再エネ: '+fmtEnergy(renewLast),g:null},{key:'diff',label:'需要 − 選択電源 逆潮流 ('+last+')',value:fmtEnergy(diff),sub:'需要 '+fmtEnergy(demandLast)+' − 逆潮流 '+fmtEnergy(rfLast),g:null},];var html=cards.map(function(c){var growthHtml='';if(c.g!=null){growthHtml='<div class="msd-kpi-growth '+growthClass(c.g)+'">'+fmtGrowth(c.g)+' ('+c.gLbl+')</div>';}
72return''+'<div class="msd-kpi-card kpi-'+c.key+'">'+'<div class="msd-kpi-label">'+c.label+'</div>'+'<div class="msd-kpi-value">'+c.value+'</div>'+'<div class="msd-kpi-sub">'+c.sub+'</div>'+
73growthHtml+'</div>';}).join('');document.querySelector('[data-role="kpi-detail"]').innerHTML=html;}
74function drawDetailRf(){var ov=state.overview;var ctx=document.getElementById('erf-chart-detail-rf');if(!ctx)return;destroyChart('erf-chart-detail-rf');var years=detailYears();var name=detailDisplayName();var titleEl=document.querySelector('[data-role="detail-rf-title"]');if(titleEl)titleEl.textContent=name+' — 電力逆潮流 推移';var datasets=RF_DEFS.filter(function(s){return state.selectedRf.indexOf(s.key)>=0;}).map(function(s){return{label:s.ja,data:years.map(function(y){var r=getDetailRow(y);return r?(r[s.key]||0):null;}),backgroundColor:s.hex+'d0',borderColor:s.hex,borderWidth:1,stack:'rf'};});state.charts['erf-chart-detail-rf']=new Chart(ctx,{type:'bar',data:{labels:years,datasets:datasets},options:{responsive:true,maintainAspectRatio:false,interaction:{mode:'index',intersect:false},layout:{padding:{top:24}},plugins:{legend:{position:'top'},datalabels:{display:isTopmostInStack,anchor:'end',align:'end',offset:2,clip:false,font:{weight:'700',size:11},color:'#0f172a',formatter:function(v,c){return fmtEnergy(stackTotalAt(c));}}
74,tooltip:{callbacks:{label:function(c){return c.dataset.label+': '+fmtEnergy(c.parsed.y);},footer:function(items){var sum=items.reduce(function(s,i){return s+i.parsed.y;},0);return'合計: '+fmtEnergy(sum);}}}},scales:{x:{stacked:true,title:{display:true,text:'年度'}},y:{stacked:true,title:{display:true,text:'電力逆潮流 (MWh / GWh / TWh)'},ticks:{callback:function(v){return fmtAxisEnergy(v);}}}}}});}
75function drawDetailButterfly(){var ov=state.overview;var years=detailYears();var name=detailDisplayName();var titleEl=document.querySelector('[data-role="detail-butterfly-title"]');if(titleEl)titleEl.textContent=name+' — 電力需要と逆潮流の差';var mainCtx=document.getElementById('erf-chart-detail-butterfly');if(!mainCtx)return;destroyChart('erf-chart-detail-butterfly');var demandDatasets=[{label:'需要(低圧)',stack:'demand',data:years.map(function(y){var r=getDetailRow(y);return r?r.dl:null;}),backgroundColor:VOLT_COLORS.low+'cc',borderColor:VOLT_COLORS.low,borderWidth:1,},{label:'需要('+VOLT_LABELS.high+')',stack:'demand',data:years.map(function(y){var r=getDetailRow(y);return r?r.dh:null;}),backgroundColor:VOLT_COLORS.high+'cc',borderColor:VOLT_COLORS.high,borderWidth:1,}];var rfDatasets=RF_DEFS.filter(function(s){return state.selectedRf.indexOf(s.key)>=0;}).map(function(s){return{label:'逆潮流('+s.ja+')',stack:'rf',data:years.map(function(y){var r=getDetailRow(y);return r?-(r[s.key]||0):null;}),backgroundColor:s.hex+'d0',borderColor:s.hex,borderWidth:1,};});state.charts['erf-chart-detail-butterfly']=new Chart(mainCtx,{type:'bar',data:{labels:years,datasets:demandDatasets.concat(rfDatasets)},options:{responsive:true,maintainAspectRatio:false,interaction:{mode:'index',intersect:false},layout:{padding:{top:40,bottom:40}},plugins:{legend:{position:'top',labels:{boxWidth:12,font:{size:11}}},datalabels:{display:isTopmostInStack,anchor:'end',align:function(c){return stackTotalAt(c)>=0?'end':'start';},offset:4,clip:false,font:{weight:'700',size:11},color:function(c){return stackTotalAt(c)>=0?'#9a3412':'#15803d';},formatter:function(v,c){return fmtEnergy(Math.abs(stackTotalAt(c)));}},tooltip:{callbacks:{label:function(c){return c.dataset.label+': '+fmtEnergy(Math.abs(c.parsed.y));}}}},scales:{x:{stacked:true,title:{display:true,text:'年度'}},y:{stacked:true,title:{display:true,text:'↑需要  /  逆潮流↓ (MWh / GWh / TWh)'},ticks:{callback:function(v){return fmtAxisEnergy(Math.abs(v));}},grid:{color:function(c){return c.tick.value===0?'#1e293b':'rgba(0,0,0,0.05)';},lineWidth:function(c){return c.tick.value===0?2:1;}}}}}});var diffCtx=document.getElementById('erf-chart-detail-diff');if(!diffCtx)return;destroyChart('erf-chart-detail-diff');var diffData=years.map(function(y){var r=getDetailRow(y);if(!r)return null;return sumDemand(r)-sumRfSelected(r);});var diffColors=diffData.map(function(d){return d==null?'#94a3b8':(d>=0?VOLT_COLORS.high+'cc':'rgba(22,163,74,0.8)');});var diffBorders=diffData.map(function(d){return d==null?'#64748b':(d>=0?VOLT_COLORS.high:'#15803d');});state.charts['erf-chart-detail-diff']=new Chart(diffCtx,{type:'bar',data:{labels:years,datasets:[{label:'需要 − 逆潮流',data:diffData,backgroundColor:diffColors,borderColor:diffBorders,borderWidth:1}]},options:{responsive:true,maintainAspectRatio:false,layout:{padding:{top:28,bottom:28}},plugins:{legend:{display:false},datalabels:{display:true,anchor:function(c){var v=c.dataset.data[c.dataIndex];return v>=0?'end':'start';},align:function(c){var v=c.dataset.data[c.dataIndex];return v>=0?'top':'bottom';},offset:4,clip:false,font:{weight:'700',size:11},color:function(c){var v=c.dataset.data[c.dataIndex];return v>=0?'#9a3412':'#15803d';},formatter:function(v){return v==null?'-':fmtEnergy(v);}},tooltip:{callbacks:{label:function(c){return'需要 − 逆潮流: '+fmtEnergy(c.parsed.y);}}}},scales:{x:{title:{display:true,text:'年度'}},y:{title:{display:true,text:'需要 − 逆潮流 (MWh/GWh/TWh)'},ticks:{callback:function(v){return fmtAxisEnergy(v);}},grid:{color:function(c){return c.tick.value===0?'#1e293b':'rgba(0,0,0,0.05)';},lineWidth:function(c){return c.tick.value===0?2:1;}}}}}});}
76function refreshDetailCharts(){if(!state.detailPref)return;renderKpiDetail();drawDetailRf();drawDetailButterfly();}
77function populateDetailMuniSelect(){var sel=document.querySelector('[data-role="detail-muni-select"]');
77if(!sel)return;if(!state.detailPref){sel.innerHTML='<option value="">— 県全体 —</option>';sel.disabled=true;return;}
78var detail=state.prefDetailCache[state.detailPref];if(!detail){sel.disabled=true;return;}
79var opts='<option value="">— 県全体 —</option>';Object.keys(detail.munis).forEach(function(mk){opts+='<option value="'+mk+'">'+detail.munis[mk].ja+'</option>';});sel.innerHTML=opts;sel.disabled=false;sel.value=state.detailMuni||'';}
80function selectDetailPref(pkey){state.detailPref=pkey||null;state.detailMuni='';var content=document.querySelector('[data-role="detail-content"]');if(!pkey){if(content)content.innerHTML='<div class="msd-loading" style="padding:80px 0;">都道府県を選択してください。</div>';populateDetailMuniSelect();return;}
81if(content)content.innerHTML='<div class="msd-loading" style="padding:80px 0;">読み込み中...</div>';loadPrefecture(pkey).then(function(){populateDetailMuniSelect();renderDetailContent();refreshDetailCharts();}).catch(function(err){if(content)content.innerHTML='<div class="msd-error">'+(err.message||'エラー')+'</div>';});}
82function switchTab(tabName){state.tab=tabName;document.querySelectorAll('.msd-tab').forEach(function(t){t.classList.toggle('active',t.dataset.tab===tabName);});document.querySelectorAll('.msd-tab-panel').forEach(function(p){p.classList.toggle('active',p.dataset.panel===tabName);});if(tabName==='national')renderNational(state.overview);else if(tabName==='prefecture')renderPrefecture(state.overview);else if(tabName==='municipality')renderMunicipality(state.overview);else if(tabName==='detail')renderDetail(state.overview);}
83function renderDetail(ov){if(state.detailPref)refreshDetailCharts();}
84function renderNational(ov){renderKpiNational(ov);drawNationalRf(ov);drawNationalButterfly(ov);}
85function renderPrefecture(ov){if(state.prefYear==null)state.prefYear=ov.years[ov.years.length-1];drawPrefRf(ov);drawPrefButterfly(ov);renderPrefTable(ov);}
86function renderMunicipality(ov){if(state.muniYear==null)state.muniYear=ov.muni_years[ov.muni_years.length-1];}
87function refreshMuniCharts(){if(!state.selectedPref)return;var detail=state.prefDetailCache[state.selectedPref];if(!detail)return;var banner=document.querySelector('[data-role="muni-gap-banner"]');if(banner){banner.style.display=hasMuniDataGap(state.selectedPref,state.muniYear)?'':'none';}
88drawMuniRf(detail);drawMuniButterfly(detail);renderMuniRankTable(detail);}
89function refreshAllCharts(){if(!state.overview)return;if(state.tab==='national')renderNational(state.overview);else if(state.tab==='prefecture')renderPrefecture(state.overview);else if(state.tab==='municipality')refreshMuniCharts();else if(state.tab==='detail')refreshDetailCharts();}
90function attachEvents(root){root.addEventListener('click',function(e){var tabBtn=e.target.closest('.msd-tab');if(tabBtn){switchTab(tabBtn.dataset.tab);return;}
91var pre=e.target.closest('.erf-preset');if(pre){var preset=PRESETS.find(function(p){return p.id===pre.dataset.preset;});if(preset){state.selectedRf=preset.keys.slice();updateFilterUiActive();refreshAllCharts();}
92return;}
93var py=e.target.closest('[data-role="pref-year"] button');if(py){state.prefYear=parseInt(py.dataset.year,10);document.querySelectorAll('[data-role="pref-year"] button').forEach(function(b){b.classList.toggle('active',b.dataset.year===py.dataset.year);});renderPrefecture(state.overview);return;}
94var my=e.target.closest('[data-role="muni-year"] button');if(my){state.muniYear=parseInt(my.dataset.year,10);document.querySelectorAll('[data-role="muni-year"] button').forEach(function(b){b.classList.toggle('active',b.dataset.year===my.dataset.year);});refreshMuniCharts();return;}
95var rb=e.target.closest('[data-role="region"] button');if(rb){state.selectedRegion=rb.dataset.region;document.querySelectorAll('[data-role="region"] button').forEach(function(b){b.classList.toggle('active',b.dataset.region===rb.dataset.region);});refreshMuniCharts();return;}});root.addEventListener('change',function(e){var cb=e.target.closest('input[type=checkbox][data-src]');if(cb){var k=cb.dataset.src;var idx=state.selectedRf.indexOf(k);if(cb.checked&&idx<0)state.selectedRf.push(k);else if(!cb.checked&&idx>=0)state.selectedRf.splice(idx,1);updateFilterUiActive();refreshAllCharts();return;}
96var sel=e.target.closest('[data-role="muni-pref-select"]');
96if(sel){var pkey=sel.value;if(!pkey){state.selectedPref=null;document.querySelector('[data-role="muni-content"]').innerHTML='<div class="msd-loading" style="padding:80px 0;">都道府県を選択してください。</div>';return;}
97state.selectedPref=pkey;state.selectedRegion='all';document.querySelector('[data-role="muni-content"]').innerHTML='<div class="msd-loading" style="padding:80px 0;">読み込み中...</div>';loadPrefecture(pkey).then(function(){renderMuniContent(pkey);refreshMuniCharts();}).catch(function(err){document.querySelector('[data-role="muni-content"]').innerHTML='<div class="msd-error">'+(err.message||'エラー')+'</div>';});return;}
98var dSel=e.target.closest('[data-role="detail-pref-select"]');if(dSel){selectDetailPref(dSel.value);return;}
99var dMuniSel=e.target.closest('[data-role="detail-muni-select"]');if(dMuniSel){state.detailMuni=dMuniSel.value||'';refreshDetailCharts();return;}});}
100function init(){var root=document.getElementById('erf-dashboard');if(!root)return;ajaxJson('erf_get_overview',{}).then(function(ov){state.overview=ov;state.prefYear=ov.years[ov.years.length-1];state.muniYear=ov.muni_years[ov.muni_years.length-1];var html=renderHeader(ov)+
101renderBetaNotice(ov)+
102renderTabs()+
103renderSourceFilter()+
104renderTabNational()+
105renderTabPrefecture(ov)+
106renderTabMunicipality(ov)+
107renderTabDetail(ov);root.innerHTML=html;attachEvents(root);switchTab('national');}).catch(function(err){root.innerHTML='<div class="msd-error">データ取得に失敗しました: '+(err.message||err)+'</div>';});}
108if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',init);}else{init();}})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.