[{"data":1,"prerenderedAt":1949},["ShallowReactive",2],{"content-/pl-waterfall-redesign":3,"all-pages-for-dir":1928,"related-/pl-waterfall-redesign":1929,"og-image-/pl-waterfall-redesign":1948},{"id":4,"title":5,"body":6,"category":1914,"concepts":1914,"description":1915,"extension":1916,"meta":1917,"navigation":666,"ogImage":1914,"path":1918,"project_name":1914,"published":1919,"publishedAt":1920,"seo":1921,"source":1914,"stem":1922,"tags":1923,"todo":1914,"unpublished":1919,"updatedAt":1920,"__hash__":1927},"pages/2025-12/2025-12-26/pl-waterfall-redesign.md","P/L Waterfallチャート構造変更案",{"type":7,"value":8,"toc":1881},"minimark",[9,13,17,22,26,33,36,55,60,63,66,77,80,84,91,95,196,199,217,219,223,229,240,244,290,293,301,304,338,340,343,347,550,553,573,575,578,581,624,630,633,644,650,652,655,719,723,730,750,756,763,769,780,787,798,800,804,807,810,816,819,823,829,832,835,840,926,930,990,994,1000,1027,1307,1311,1314,1320,1699,1704,1710,1721,1725,1798,1801,1848,1851,1877],[10,11,5],"h1",{"id":12},"pl-waterfallチャート構造変更案",[14,15,16],"p",{},"P/L WaterfallチャートのJリーグ財務データページにおける構造を変更する。",[18,19,21],"h2",{"id":20},"背景問題点","背景・問題点",[23,24,25],"h3",{"id":25},"特別損益が漏れている",[14,27,28,32],{},[29,30,31],"strong",{},"特別利益・特別損失がチャートに含まれていない","のが現在のP/L Waterfallチャートの問題である。",[14,34,35],{},"例: V・ファーレン長崎の場合",[37,38,39,43,46,49,52],"ul",{},[40,41,42],"li",{},"営業損失: ▲1,225百万円",[40,44,45],{},"営業外: 33百万円（ネット値で表示）",[40,47,48],{},"税引前利益: 8百万円",[40,50,51],{},"法人税等: 6百万円",[40,53,54],{},"純利益: 2百万円",[14,56,57],{},[29,58,59],{},"営業損失▲1,225 + 営業外33 = ▲1,192 なのに税引前利益が8となっている",[14,61,62],{},"→ 特別利益が約1,200百万円あるはずだが、チャートに表示されていない",[23,64,65],{"id":65},"その他の問題",[37,67,68,71,74],{},[40,69,70],{},"税引前利益を表示しているが、要素が多くなりすぎている",[40,72,73],{},"バーの数が7本と多く、横幅を取る",[40,75,76],{},"営業外はネット値で表示されており、収益・費用の内訳が見えない",[78,79],"hr",{},[18,81,83],{"id":82},"before現在の構造","Before（現在の構造）",[14,85,86],{},[87,88],"img",{"alt":89,"src":90},"現在のP/L Waterfall","/2025-12/2025-12-26/image.png",[23,92,94],{"id":93},"現在のバー構成-7本","現在のバー構成: 7本",[96,97,98,114],"table",{},[99,100,101],"thead",{},[102,103,104,108,111],"tr",{},[105,106,107],"th",{},"#",[105,109,110],{},"バー",[105,112,113],{},"内容",[115,116,117,129,140,151,165,175,186],"tbody",{},[102,118,119,123,126],{},[120,121,122],"td",{},"1",[120,124,125],{},"売上高",[120,127,128],{},"積み上げ棒（スポンサー/入場料/配分金/その他）",[102,130,131,134,137],{},[120,132,133],{},"2",[120,135,136],{},"営業費用",[120,138,139],{},"積み上げ棒（人件費/試合関連/運営費/その他/販管費）",[102,141,142,145,148],{},[120,143,144],{},"3",[120,146,147],{},"営業利益/損失",[120,149,150],{},"結果バー",[102,152,153,156,159],{},[120,154,155],{},"4",[120,157,158],{},"営業外",[120,160,161,164],{},[29,162,163],{},"ネット値","（営業外収益 - 営業外費用）",[102,166,167,170,173],{},[120,168,169],{},"5",[120,171,172],{},"税引前利益/損失",[120,174,150],{},[102,176,177,180,183],{},[120,178,179],{},"6",[120,181,182],{},"法人税等",[120,184,185],{},"単一バー",[102,187,188,191,194],{},[120,189,190],{},"7",[120,192,193],{},"純利益/損失",[120,195,150],{},[23,197,198],{"id":198},"問題点まとめ",[200,201,202,208,211,214],"ol",{},[40,203,204,207],{},[29,205,206],{},"特別利益・特別損失が完全に欠落"," → 数値の整合性が取れない",[40,209,210],{},"営業外がネット値 → 内訳が見えない",[40,212,213],{},"バーが7本 → 横幅を取りすぎ",[40,215,216],{},"税引前利益 → 中間値で冗長",[78,218],{},[18,220,222],{"id":221},"after変更後の構造","After（変更後の構造）",[14,224,225],{},[87,226],{"alt":227,"src":228},"alt text","/2025-12/2025-12-26/image-2.png",[230,231,236],"pre",{"className":232,"code":234,"language":235},[233],"language-text","┌─────────┐   ┌─────────┐\n│ 売上高  │   │営業費用 │\n│(積み上げ)│   │(積み上げ)│\n│         │   │         │\n│スポンサー│   │ 人件費  │\n│ 入場料  │   │試合関連 │\n│ 配分金  │   │ 運営費  │\n│ その他  │   │ その他  │\n│         │   │ 販管費  │\n└────┬────┘   └────┬────┘\n     │              │\n     └──────┬───────┘\n            ▼\n     ┌─────────┐\n     │営業利益 │\n     │/営業損失│\n     └────┬────┘\n          │\n          ▼\n┌─────────┐       ┌─────────┐\n│営業外等 │       │営業外等 │\n│ 収益   │       │ 費用   │\n│(積み上げ)│       │(積み上げ)│\n│         │       │         │\n│営業外収益│       │営業外費用│\n│特別利益 │       │特別損失 │\n│法人税還付│       │法人税等 │\n└────┬────┘       └────┬────┘\n     │                   │\n     └─────────┬─────────┘\n               ▼\n        ┌─────────┐\n        │ 純利益  │\n        │/純損失  │\n        └─────────┘\n","text",[237,238,234],"code",{"__ignoreMap":239},"",[23,241,243],{"id":242},"変更後のバー数-6本","変更後のバー数: 6本",[200,245,246,249,252,254,271,287],{},[40,247,248],{},"売上高（積み上げ棒）",[40,250,251],{},"営業費用（積み上げ棒）",[40,253,147],{},[40,255,256,259,260],{},[29,257,258],{},"営業外等収益","（積み上げ棒）← NEW\n",[37,261,262,265,268],{},[40,263,264],{},"営業外収益",[40,266,267],{},"特別利益",[40,269,270],{},"法人税還付（マイナスの場合）",[40,272,273,259,276],{},[29,274,275],{},"営業外等費用",[37,277,278,281,284],{},[40,279,280],{},"営業外費用",[40,282,283],{},"特別損失",[40,285,286],{},"法人税等（プラスの場合）",[40,288,289],{},"純利益/純損失",[23,291,292],{"id":292},"削除される要素",[37,294,295],{},[40,296,297,300],{},[298,299,172],"del",{},"（不要）",[23,302,303],{"id":303},"変更のポイント",[200,305,306,312,318,332],{},[40,307,308,311],{},[29,309,310],{},"特別損益の追加",": 特別利益・特別損失を明示的に表示",[40,313,314,317],{},[29,315,316],{},"積み上げ棒の活用",": 営業外と特別と法人税を積み上げて表示",[40,319,320,323,324],{},[29,321,322],{},"法人税の分岐処理",":\n",[37,325,326,329],{},[40,327,328],{},"法人税等がプラス → 費用側に積み上げ",[40,330,331],{},"法人税等がマイナス（還付）→ 収益側に積み上げ",[40,333,334,337],{},[29,335,336],{},"要素の削減",": 税引前利益を削除し、シンプルに",[78,339],{},[18,341,342],{"id":342},"データ構造の確認",[23,344,346],{"id":345},"更新後のpldetaileddata型2025-12-26実装完了","更新後のPLDetailedData型（2025-12-26実装完了）",[230,348,352],{"className":349,"code":350,"language":351,"meta":239,"style":239},"language-typescript shiki shiki-themes vitesse-light vitesse-light","interface PLDetailedData {\n  revenue: number               // 売上高\n  costOfRevenue: number         // 売上原価（チーム人件費等）\n  grossProfit: number           // 売上総利益\n  sgaExpenses: number           // 販管費\n  operatingIncome: number       // 営業利益\n  nonOperatingIncome: number    // 営業外収益\n  nonOperatingExpenses: number  // 営業外費用\n  ordinaryIncome: number        // 経常利益 ← NEW\n  extraordinaryIncome: number   // 特別利益 ← NEW\n  extraordinaryLoss: number     // 特別損失 ← NEW\n  preTaxIncome: number          // 税引前利益\n  taxes: number                 // 法人税等\n  netIncome: number             // 純利益\n}\n","typescript",[237,353,354,371,388,401,414,427,440,453,466,479,492,505,518,531,544],{"__ignoreMap":239},[355,356,359,363,367],"span",{"class":357,"line":358},"line",1,[355,360,362],{"class":361},"stQ0i","interface",[355,364,366],{"class":365},"sSkh3"," PLDetailedData",[355,368,370],{"class":369},"shFtX"," {\n",[355,372,374,378,381,384],{"class":357,"line":373},2,[355,375,377],{"class":376},"s4oTP","  revenue",[355,379,380],{"class":369},": ",[355,382,383],{"class":365},"number",[355,385,387],{"class":386},"sxvE3","               // 売上高\n",[355,389,391,394,396,398],{"class":357,"line":390},3,[355,392,393],{"class":376},"  costOfRevenue",[355,395,380],{"class":369},[355,397,383],{"class":365},[355,399,400],{"class":386},"         // 売上原価（チーム人件費等）\n",[355,402,404,407,409,411],{"class":357,"line":403},4,[355,405,406],{"class":376},"  grossProfit",[355,408,380],{"class":369},[355,410,383],{"class":365},[355,412,413],{"class":386},"           // 売上総利益\n",[355,415,417,420,422,424],{"class":357,"line":416},5,[355,418,419],{"class":376},"  sgaExpenses",[355,421,380],{"class":369},[355,423,383],{"class":365},[355,425,426],{"class":386},"           // 販管費\n",[355,428,430,433,435,437],{"class":357,"line":429},6,[355,431,432],{"class":376},"  operatingIncome",[355,434,380],{"class":369},[355,436,383],{"class":365},[355,438,439],{"class":386},"       // 営業利益\n",[355,441,443,446,448,450],{"class":357,"line":442},7,[355,444,445],{"class":376},"  nonOperatingIncome",[355,447,380],{"class":369},[355,449,383],{"class":365},[355,451,452],{"class":386},"    // 営業外収益\n",[355,454,456,459,461,463],{"class":357,"line":455},8,[355,457,458],{"class":376},"  nonOperatingExpenses",[355,460,380],{"class":369},[355,462,383],{"class":365},[355,464,465],{"class":386},"  // 営業外費用\n",[355,467,469,472,474,476],{"class":357,"line":468},9,[355,470,471],{"class":376},"  ordinaryIncome",[355,473,380],{"class":369},[355,475,383],{"class":365},[355,477,478],{"class":386},"        // 経常利益 ← NEW\n",[355,480,482,485,487,489],{"class":357,"line":481},10,[355,483,484],{"class":376},"  extraordinaryIncome",[355,486,380],{"class":369},[355,488,383],{"class":365},[355,490,491],{"class":386},"   // 特別利益 ← NEW\n",[355,493,495,498,500,502],{"class":357,"line":494},11,[355,496,497],{"class":376},"  extraordinaryLoss",[355,499,380],{"class":369},[355,501,383],{"class":365},[355,503,504],{"class":386},"     // 特別損失 ← NEW\n",[355,506,508,511,513,515],{"class":357,"line":507},12,[355,509,510],{"class":376},"  preTaxIncome",[355,512,380],{"class":369},[355,514,383],{"class":365},[355,516,517],{"class":386},"          // 税引前利益\n",[355,519,521,524,526,528],{"class":357,"line":520},13,[355,522,523],{"class":376},"  taxes",[355,525,380],{"class":369},[355,527,383],{"class":365},[355,529,530],{"class":386},"                 // 法人税等\n",[355,532,534,537,539,541],{"class":357,"line":533},14,[355,535,536],{"class":376},"  netIncome",[355,538,380],{"class":369},[355,540,383],{"class":365},[355,542,543],{"class":386},"             // 純利益\n",[355,545,547],{"class":357,"line":546},15,[355,548,549],{"class":369},"}\n",[23,551,552],{"id":552},"追加されたフィールド",[37,554,555,561,567],{},[40,556,557,560],{},[237,558,559],{},"ordinaryIncome: number"," // 経常利益",[40,562,563,566],{},[237,564,565],{},"extraordinaryIncome: number"," // 特別利益",[40,568,569,572],{},[237,570,571],{},"extraordinaryLoss: number","   // 特別損失",[78,574],{},[18,576,577],{"id":577},"関連テストコード",[23,579,580],{"id":580},"既存テスト",[96,582,583,592],{},[99,584,585],{},[102,586,587,590],{},[105,588,589],{},"ファイル",[105,591,113],{},[115,593,594,604,614],{},[102,595,596,601],{},[120,597,598],{},[237,599,600],{},"jleague-balance.test.ts",[120,602,603],{},"BSの貸借一致テスト（資産 = 負債 + 純資産）",[102,605,606,611],{},[120,607,608],{},[237,609,610],{},"jleague-variance.test.ts",[120,612,613],{},"営業利益増減ウォーターフォールの計算テスト",[102,615,616,621],{},[120,617,618],{},[237,619,620],{},"waterfall-integrity.test.ts",[120,622,623],{},"一般企業用PLの整合性テスト（Jリーグ用ではない）",[23,625,627,629],{"id":626},"jleague-variancetestts-の検証内容",[237,628,610],{}," の検証内容",[14,631,632],{},"営業利益増減チャートの計算ロジックを検証:",[37,634,635,638,641],{},[40,636,637],{},"前年営業利益 + 収益増減 - 費用増減 = 当期営業利益",[40,639,640],{},"費用増加 → マイナス影響（赤バー）",[40,642,643],{},"費用減少 → プラス影響（緑バー）",[14,645,646,649],{},[29,647,648],{},"注意",": このテストは「営業利益増減」のみを検証しており、P/L Waterfall全体の特別損益は検証していない。",[78,651],{},[18,653,654],{"id":654},"実装タスク",[200,656,659,673,686,699,709],{"className":657},[658],"contains-task-list",[40,660,663,668,669,672],{"className":661},[662],"task-list-item",[664,665],"input",{"checked":666,"disabled":666,"type":667},true,"checkbox"," データソース確認: Jリーグ経営情報開示に特別損益が含まれている（",[237,670,671],{},"j-league-data.json","に既存）",[40,674,676,678,679,682,683],{"className":675},[662],[664,677],{"checked":666,"disabled":666,"type":667}," データ型更新: ",[237,680,681],{},"PLDetailedData"," に特別損益フィールドを追加 → ",[237,684,685],{},"types/financial.ts",[40,687,689,691,692,695,696],{"className":688},[662],[664,690],{"checked":666,"disabled":666,"type":667}," データ変換関数更新: ",[237,693,694],{},"convertToPLDetailed()"," で特別損益を含めるよう修正 → ",[237,697,698],{},"composables/jleague/useJLeagueData.ts",[40,700,702,704,705,708],{"className":701},[662],[664,703],{"checked":666,"disabled":666,"type":667}," チャートコンポーネント更新: ",[237,706,707],{},"JLeaguePLWaterfallSection.vue"," の描画ロジック変更",[40,710,712,714,715,718],{"className":711},[662],[664,713],{"checked":666,"disabled":666,"type":667}," テスト追加: ",[237,716,717],{},"tests/pl-detailed-data.test.ts"," でPLDetailedDataの整合性テストを実装",[23,720,722],{"id":721},"実装済み変更2025-12-26","実装済み変更（2025-12-26）",[14,724,725,729],{},[29,726,727],{},[237,728,685],{},":",[37,731,732,738,744],{},[40,733,734,737],{},[237,735,736],{},"ordinaryIncome"," (経常利益) 追加",[40,739,740,743],{},[237,741,742],{},"extraordinaryIncome"," (特別利益) 追加",[40,745,746,749],{},[237,747,748],{},"extraordinaryLoss"," (特別損失) 追加",[14,751,752,729],{},[29,753,754],{},[237,755,698],{},[37,757,758],{},[40,759,760,762],{},[237,761,694],{}," 関数で上記フィールドを生データから変換",[14,764,765,729],{},[29,766,767],{},[237,768,717],{},[37,770,771,774,777],{},[40,772,773],{},"PLDetailedDataの整合性テスト",[40,775,776],{},"特別損益の反映: 267/267 (100.0%) 成功",[40,778,779],{},"V・ファーレン長崎など特別利益が大きいケースでの検証",[14,781,782,729],{},[29,783,784],{},[237,785,786],{},"components/jleague/JLeaguePLWaterfallSection.vue",[37,788,789,792,795],{},[40,790,791],{},"バー構成を7本から6本に変更",[40,793,794],{},"営業外等収益・営業外等費用の積み上げ棒を追加",[40,796,797],{},"引き出し線による小セグメントのラベル表示を実装（詳細は下記）",[78,799],{},[18,801,803],{"id":802},"積み上げ棒グラフの小セグメント対応引き出し線","積み上げ棒グラフの小セグメント対応（引き出し線）",[14,805,806],{},"各セグメントの高さが小さい場合に積み上げ棒グラフでラベルがセグメント内に収まらない問題がある。この問題を「引き出し線（Leader Line）」で解決した。",[23,808,809],{"id":809},"問題",[230,811,814],{"className":812,"code":813,"language":235},[233],"┌─────────┐\n│ 人件費  │ ← 高さ十分：ラベルが入る\n│  1,382  │\n├─────────┤\n│試合関連 │ ← 高さ不足：ラベルが潰れる\n├─────────┤\n│ 運営費  │ ← 高さ不足\n├─────────┤\n│ その他  │ ← 高さ不足\n├─────────┤\n│ 販管費  │\n│   817   │\n└─────────┘\n",[237,815,813],{"__ignoreMap":239},[14,817,818],{},"28px未満のセグメントの高さでは、ラベル（項目名+金額）が物理的に入らない。",[23,820,822],{"id":821},"解決策-引き出し線","解決策: 引き出し線",[230,824,827],{"className":825,"code":826,"language":235},[233],"          ┌─────────┐\n          │ 人件費  │\n          │  1,382  │\n          ├────●────┤\n試合関連 137 ──┤         │\n  運営費 365 ──●         │\n  その他 207 ──┤         │\n          ├────●────┤\n          │ 販管費  │\n          │   817   │\n          └─────────┘\n",[237,828,826],{"__ignoreMap":239},[14,830,831],{},"引き出し線で小さいセグメントはバーの外にラベルを表示する。",[23,833,834],{"id":834},"実装詳細",[836,837,839],"h4",{"id":838},"_1-セグメントインターフェース","1. セグメントインターフェース",[230,841,843],{"className":349,"code":842,"language":351,"meta":239,"style":239},"interface Segment {\n  label: string\n  value: number\n  color: string\n  y: number       // セグメントのY座標\n  height: number  // セグメントの高さ\n  labelY?: number // 引き出し線ラベルの調整済みY座標\n}\n",[237,844,845,854,864,874,883,895,907,922],{"__ignoreMap":239},[355,846,847,849,852],{"class":357,"line":358},[355,848,362],{"class":361},[355,850,851],{"class":365}," Segment",[355,853,370],{"class":369},[355,855,856,859,861],{"class":357,"line":373},[355,857,858],{"class":376},"  label",[355,860,380],{"class":369},[355,862,863],{"class":365},"string\n",[355,865,866,869,871],{"class":357,"line":390},[355,867,868],{"class":376},"  value",[355,870,380],{"class":369},[355,872,873],{"class":365},"number\n",[355,875,876,879,881],{"class":357,"line":403},[355,877,878],{"class":376},"  color",[355,880,380],{"class":369},[355,882,863],{"class":365},[355,884,885,888,890,892],{"class":357,"line":416},[355,886,887],{"class":376},"  y",[355,889,380],{"class":369},[355,891,383],{"class":365},[355,893,894],{"class":386},"       // セグメントのY座標\n",[355,896,897,900,902,904],{"class":357,"line":429},[355,898,899],{"class":376},"  height",[355,901,380],{"class":369},[355,903,383],{"class":365},[355,905,906],{"class":386},"  // セグメントの高さ\n",[355,908,909,912,915,917,919],{"class":357,"line":442},[355,910,911],{"class":376},"  labelY",[355,913,914],{"class":361},"?",[355,916,380],{"class":369},[355,918,383],{"class":365},[355,920,921],{"class":386}," // 引き出し線ラベルの調整済みY座標\n",[355,923,924],{"class":357,"line":455},[355,925,549],{"class":369},[836,927,929],{"id":928},"_2-引き出し線の表示条件","2. 引き出し線の表示条件",[230,931,933],{"className":349,"code":932,"language":351,"meta":239,"style":239},"// 高さ28px以上: セグメント内にラベル表示\n// 高さ28px未満: 引き出し線でバー外にラベル表示\nconst needsLeaderLine = (seg: Segment) => seg.height \u003C 28\n",[237,934,935,940,945],{"__ignoreMap":239},[355,936,937],{"class":357,"line":358},[355,938,939],{"class":386},"// 高さ28px以上: セグメント内にラベル表示\n",[355,941,942],{"class":357,"line":373},[355,943,944],{"class":386},"// 高さ28px未満: 引き出し線でバー外にラベル表示\n",[355,946,947,950,954,957,960,963,965,968,971,974,977,980,983,986],{"class":357,"line":390},[355,948,949],{"class":361},"const ",[355,951,953],{"class":952},"senZ8","needsLeaderLine",[355,955,956],{"class":369}," =",[355,958,959],{"class":369}," (",[355,961,962],{"class":376},"seg",[355,964,380],{"class":369},[355,966,967],{"class":365},"Segment",[355,969,970],{"class":369},")",[355,972,973],{"class":369}," =>",[355,975,976],{"class":376}," seg",[355,978,979],{"class":369},".",[355,981,982],{"class":376},"height",[355,984,985],{"class":369}," \u003C",[355,987,989],{"class":988},"sM54T"," 28\n",[836,991,993],{"id":992},"_3-引き出し線の配置","3. 引き出し線の配置",[230,995,998],{"className":996,"code":997,"language":235},[233],"        バー\n    ┌─────────┐\n    │         │\n    │    ●────┼── ラベル\n    │   3/4   │\n    └─────────┘\n         ↑\n    黒丸の位置\n",[237,999,997],{"__ignoreMap":239},[37,1001,1002,1008,1018],{},[40,1003,1004,1007],{},[29,1005,1006],{},"黒丸の位置",": バー幅の3/4地点（中央より右寄り）",[40,1009,1010,1013,1014,1017],{},[29,1011,1012],{},"線の終点",": バー幅の1/2地点から少し左（",[237,1015,1016],{},"bar.x + bar.width / 2 - 3","）",[40,1019,1020,1023,1024,1017],{},[29,1021,1022],{},"ラベル位置",": 線の終点からさらに左（",[237,1025,1026],{},"bar.x + bar.width / 2 - 6",[230,1028,1030],{"className":349,"code":1029,"language":351,"meta":239,"style":239},"// 引き出し線の描画\n\u003Cline\n  :x1=\"bar.x + bar.width * 3/4\"  // 黒丸（右寄り）\n  :y1=\"seg.y + seg.height / 2\"\n  :x2=\"bar.x + bar.width / 2 - 3\" // 線の終点\n  :y2=\"seg.labelY\"\n/>\n\u003Ccircle\n  :cx=\"bar.x + bar.width * 3/4\"\n  :cy=\"seg.y + seg.height / 2\"\n  r=\"2.5\"\n  fill=\"#333\"\n/>\n\u003Ctext\n  :x=\"bar.x + bar.width / 2 - 6\"  // ラベル位置\n  :y=\"seg.labelY\"\n  text-anchor=\"end\"\n>\n  {{ seg.label }} {{ seg.value }}\n\u003C/text>\n",[237,1031,1032,1037,1045,1070,1087,1105,1121,1129,1136,1151,1166,1180,1194,1200,1207,1225,1241,1262,1267,1296],{"__ignoreMap":239},[355,1033,1034],{"class":357,"line":358},[355,1035,1036],{"class":386},"// 引き出し線の描画\n",[355,1038,1039,1042],{"class":357,"line":373},[355,1040,1041],{"class":369},"\u003C",[355,1043,1044],{"class":376},"line\n",[355,1046,1047,1051,1054,1057,1061,1065,1067],{"class":357,"line":390},[355,1048,1050],{"class":1049},"sG7-3","  :",[355,1052,1053],{"class":376},"x1",[355,1055,1056],{"class":369},"=",[355,1058,1060],{"class":1059},"sMJiu","\"",[355,1062,1064],{"class":1063},"sdGka","bar.x + bar.width * 3/4",[355,1066,1060],{"class":1059},[355,1068,1069],{"class":386},"  // 黒丸（右寄り）\n",[355,1071,1072,1074,1077,1079,1081,1084],{"class":357,"line":403},[355,1073,1050],{"class":1049},[355,1075,1076],{"class":376},"y1",[355,1078,1056],{"class":369},[355,1080,1060],{"class":1059},[355,1082,1083],{"class":1063},"seg.y + seg.height / 2",[355,1085,1086],{"class":1059},"\"\n",[355,1088,1089,1091,1094,1096,1098,1100,1102],{"class":357,"line":416},[355,1090,1050],{"class":1049},[355,1092,1093],{"class":376},"x2",[355,1095,1056],{"class":369},[355,1097,1060],{"class":1059},[355,1099,1016],{"class":1063},[355,1101,1060],{"class":1059},[355,1103,1104],{"class":386}," // 線の終点\n",[355,1106,1107,1109,1112,1114,1116,1119],{"class":357,"line":429},[355,1108,1050],{"class":1049},[355,1110,1111],{"class":376},"y2",[355,1113,1056],{"class":369},[355,1115,1060],{"class":1059},[355,1117,1118],{"class":1063},"seg.labelY",[355,1120,1086],{"class":1059},[355,1122,1123,1126],{"class":357,"line":442},[355,1124,1125],{"class":361},"/",[355,1127,1128],{"class":369},">\n",[355,1130,1131,1133],{"class":357,"line":455},[355,1132,1041],{"class":369},[355,1134,1135],{"class":376},"circle\n",[355,1137,1138,1140,1143,1145,1147,1149],{"class":357,"line":468},[355,1139,1050],{"class":1049},[355,1141,1142],{"class":376},"cx",[355,1144,1056],{"class":369},[355,1146,1060],{"class":1059},[355,1148,1064],{"class":1063},[355,1150,1086],{"class":1059},[355,1152,1153,1155,1158,1160,1162,1164],{"class":357,"line":481},[355,1154,1050],{"class":1049},[355,1156,1157],{"class":376},"cy",[355,1159,1056],{"class":369},[355,1161,1060],{"class":1059},[355,1163,1083],{"class":1063},[355,1165,1086],{"class":1059},[355,1167,1168,1171,1173,1175,1178],{"class":357,"line":494},[355,1169,1170],{"class":376},"  r",[355,1172,1056],{"class":369},[355,1174,1060],{"class":1059},[355,1176,1177],{"class":1063},"2.5",[355,1179,1086],{"class":1059},[355,1181,1182,1185,1187,1189,1192],{"class":357,"line":507},[355,1183,1184],{"class":376},"  fill",[355,1186,1056],{"class":369},[355,1188,1060],{"class":1059},[355,1190,1191],{"class":1063},"#333",[355,1193,1086],{"class":1059},[355,1195,1196,1198],{"class":357,"line":520},[355,1197,1125],{"class":361},[355,1199,1128],{"class":369},[355,1201,1202,1204],{"class":357,"line":533},[355,1203,1041],{"class":369},[355,1205,1206],{"class":376},"text\n",[355,1208,1209,1211,1214,1216,1218,1220,1222],{"class":357,"line":546},[355,1210,1050],{"class":1049},[355,1212,1213],{"class":376},"x",[355,1215,1056],{"class":369},[355,1217,1060],{"class":1059},[355,1219,1026],{"class":1063},[355,1221,1060],{"class":1059},[355,1223,1224],{"class":386},"  // ラベル位置\n",[355,1226,1228,1230,1233,1235,1237,1239],{"class":357,"line":1227},16,[355,1229,1050],{"class":1049},[355,1231,1232],{"class":376},"y",[355,1234,1056],{"class":369},[355,1236,1060],{"class":1059},[355,1238,1118],{"class":1063},[355,1240,1086],{"class":1059},[355,1242,1244,1247,1250,1253,1255,1257,1260],{"class":357,"line":1243},17,[355,1245,1246],{"class":376},"  text",[355,1248,1249],{"class":361},"-",[355,1251,1252],{"class":376},"anchor",[355,1254,1056],{"class":369},[355,1256,1060],{"class":1059},[355,1258,1259],{"class":1063},"end",[355,1261,1086],{"class":1059},[355,1263,1265],{"class":357,"line":1264},18,[355,1266,1128],{"class":369},[355,1268,1270,1273,1275,1277,1280,1283,1286,1288,1290,1293],{"class":357,"line":1269},19,[355,1271,1272],{"class":369},"  {{",[355,1274,976],{"class":376},[355,1276,979],{"class":369},[355,1278,1279],{"class":376},"label",[355,1281,1282],{"class":369}," }}",[355,1284,1285],{"class":369}," {{",[355,1287,976],{"class":376},[355,1289,979],{"class":369},[355,1291,1292],{"class":376},"value",[355,1294,1295],{"class":369}," }}\n",[355,1297,1299,1301,1303,1305],{"class":357,"line":1298},20,[355,1300,1041],{"class":369},[355,1302,1125],{"class":361},[355,1304,235],{"class":376},[355,1306,1128],{"class":369},[836,1308,1310],{"id":1309},"_4-ラベル重なり防止アルゴリズム","4. ラベル重なり防止アルゴリズム",[14,1312,1313],{},"小セグメントが複数ある場合、ラベルが重なる問題を解決する。",[14,1315,1316,1319],{},[29,1317,1318],{},"方針",": 下から上に向かって調整（上方向にスペースがあるため）",[230,1321,1323],{"className":349,"code":1322,"language":351,"meta":239,"style":239},"function adjustSegmentLabelPositions(segments: Segment[], minGap: number = 14): void {\n  // 初期位置: 各セグメントの中央\n  for (const seg of segments) {\n    seg.labelY = seg.y + seg.height / 2\n  }\n\n  // 引き出し線が必要なセグメントのみ対象\n  const leaderSegments = segments.filter(seg => seg.height \u003C 28)\n  if (leaderSegments.length \u003C= 1) return\n\n  // 下から上に向かって調整\n  // 一番下のラベルは元の位置を維持、上のラベルを上方向にずらす\n  for (let i = leaderSegments.length - 2; i >= 0; i--) {\n    const curr = leaderSegments[i]\n    const below = leaderSegments[i + 1]\n\n    const gap = below.labelY - curr.labelY\n    if (gap \u003C minGap) {\n      // 重なりを解消：現在のラベルを上にずらす\n      curr.labelY = below.labelY - minGap\n    }\n  }\n}\n",[237,1324,1325,1366,1371,1393,1426,1431,1436,1441,1478,1504,1508,1513,1518,1567,1587,1609,1613,1638,1655,1660,1683,1689,1694],{"__ignoreMap":239},[355,1326,1327,1330,1333,1336,1339,1341,1343,1346,1349,1351,1353,1355,1358,1361,1364],{"class":357,"line":358},[355,1328,1329],{"class":361},"function",[355,1331,1332],{"class":952}," adjustSegmentLabelPositions",[355,1334,1335],{"class":369},"(",[355,1337,1338],{"class":376},"segments",[355,1340,380],{"class":369},[355,1342,967],{"class":365},[355,1344,1345],{"class":369},"[],",[355,1347,1348],{"class":376}," minGap",[355,1350,380],{"class":369},[355,1352,383],{"class":365},[355,1354,956],{"class":369},[355,1356,1357],{"class":988}," 14",[355,1359,1360],{"class":369},"):",[355,1362,1363],{"class":365}," void",[355,1365,370],{"class":369},[355,1367,1368],{"class":357,"line":373},[355,1369,1370],{"class":386},"  // 初期位置: 各セグメントの中央\n",[355,1372,1373,1377,1379,1381,1383,1386,1389,1391],{"class":357,"line":390},[355,1374,1376],{"class":1375},"sHkkW","  for",[355,1378,959],{"class":369},[355,1380,949],{"class":361},[355,1382,962],{"class":376},[355,1384,1385],{"class":361}," of",[355,1387,1388],{"class":376}," segments",[355,1390,970],{"class":369},[355,1392,370],{"class":369},[355,1394,1395,1398,1400,1403,1405,1407,1409,1411,1414,1416,1418,1420,1423],{"class":357,"line":403},[355,1396,1397],{"class":376},"    seg",[355,1399,979],{"class":369},[355,1401,1402],{"class":376},"labelY",[355,1404,956],{"class":369},[355,1406,976],{"class":376},[355,1408,979],{"class":369},[355,1410,1232],{"class":376},[355,1412,1413],{"class":361}," +",[355,1415,976],{"class":376},[355,1417,979],{"class":369},[355,1419,982],{"class":376},[355,1421,1422],{"class":361}," /",[355,1424,1425],{"class":988}," 2\n",[355,1427,1428],{"class":357,"line":416},[355,1429,1430],{"class":369},"  }\n",[355,1432,1433],{"class":357,"line":429},[355,1434,1435],{"emptyLinePlaceholder":666},"\n",[355,1437,1438],{"class":357,"line":442},[355,1439,1440],{"class":386},"  // 引き出し線が必要なセグメントのみ対象\n",[355,1442,1443,1446,1449,1451,1453,1455,1458,1460,1462,1464,1466,1468,1470,1472,1475],{"class":357,"line":455},[355,1444,1445],{"class":361},"  const ",[355,1447,1448],{"class":376},"leaderSegments",[355,1450,956],{"class":369},[355,1452,1388],{"class":376},[355,1454,979],{"class":369},[355,1456,1457],{"class":952},"filter",[355,1459,1335],{"class":369},[355,1461,962],{"class":376},[355,1463,973],{"class":369},[355,1465,976],{"class":376},[355,1467,979],{"class":369},[355,1469,982],{"class":376},[355,1471,985],{"class":369},[355,1473,1474],{"class":988}," 28",[355,1476,1477],{"class":369},")\n",[355,1479,1480,1483,1485,1487,1489,1493,1496,1499,1501],{"class":357,"line":468},[355,1481,1482],{"class":1375},"  if",[355,1484,959],{"class":369},[355,1486,1448],{"class":376},[355,1488,979],{"class":369},[355,1490,1492],{"class":1491},"sz8Xr","length",[355,1494,1495],{"class":369}," \u003C=",[355,1497,1498],{"class":988}," 1",[355,1500,970],{"class":369},[355,1502,1503],{"class":1375}," return\n",[355,1505,1506],{"class":357,"line":481},[355,1507,1435],{"emptyLinePlaceholder":666},[355,1509,1510],{"class":357,"line":494},[355,1511,1512],{"class":386},"  // 下から上に向かって調整\n",[355,1514,1515],{"class":357,"line":507},[355,1516,1517],{"class":386},"  // 一番下のラベルは元の位置を維持、上のラベルを上方向にずらす\n",[355,1519,1520,1522,1524,1527,1530,1532,1535,1537,1539,1542,1544,1547,1550,1553,1556,1558,1560,1563,1565],{"class":357,"line":520},[355,1521,1376],{"class":1375},[355,1523,959],{"class":369},[355,1525,1526],{"class":361},"let ",[355,1528,1529],{"class":376},"i",[355,1531,956],{"class":369},[355,1533,1534],{"class":376}," leaderSegments",[355,1536,979],{"class":369},[355,1538,1492],{"class":1491},[355,1540,1541],{"class":361}," - ",[355,1543,133],{"class":988},[355,1545,1546],{"class":369},";",[355,1548,1549],{"class":376}," i",[355,1551,1552],{"class":369}," >=",[355,1554,1555],{"class":988}," 0",[355,1557,1546],{"class":369},[355,1559,1549],{"class":376},[355,1561,1562],{"class":361},"--",[355,1564,970],{"class":369},[355,1566,370],{"class":369},[355,1568,1569,1572,1575,1577,1579,1582,1584],{"class":357,"line":533},[355,1570,1571],{"class":361},"    const ",[355,1573,1574],{"class":376},"curr",[355,1576,956],{"class":369},[355,1578,1534],{"class":376},[355,1580,1581],{"class":369},"[",[355,1583,1529],{"class":376},[355,1585,1586],{"class":369},"]\n",[355,1588,1589,1591,1594,1596,1598,1600,1602,1605,1607],{"class":357,"line":546},[355,1590,1571],{"class":361},[355,1592,1593],{"class":376},"below",[355,1595,956],{"class":369},[355,1597,1534],{"class":376},[355,1599,1581],{"class":369},[355,1601,1529],{"class":376},[355,1603,1604],{"class":361}," + ",[355,1606,122],{"class":988},[355,1608,1586],{"class":369},[355,1610,1611],{"class":357,"line":1227},[355,1612,1435],{"emptyLinePlaceholder":666},[355,1614,1615,1617,1620,1622,1625,1627,1629,1631,1633,1635],{"class":357,"line":1243},[355,1616,1571],{"class":361},[355,1618,1619],{"class":376},"gap",[355,1621,956],{"class":369},[355,1623,1624],{"class":376}," below",[355,1626,979],{"class":369},[355,1628,1402],{"class":376},[355,1630,1541],{"class":361},[355,1632,1574],{"class":376},[355,1634,979],{"class":369},[355,1636,1637],{"class":376},"labelY\n",[355,1639,1640,1643,1645,1647,1649,1651,1653],{"class":357,"line":1264},[355,1641,1642],{"class":1375},"    if",[355,1644,959],{"class":369},[355,1646,1619],{"class":376},[355,1648,985],{"class":369},[355,1650,1348],{"class":376},[355,1652,970],{"class":369},[355,1654,370],{"class":369},[355,1656,1657],{"class":357,"line":1269},[355,1658,1659],{"class":386},"      // 重なりを解消：現在のラベルを上にずらす\n",[355,1661,1662,1665,1667,1669,1671,1673,1675,1677,1680],{"class":357,"line":1298},[355,1663,1664],{"class":376},"      curr",[355,1666,979],{"class":369},[355,1668,1402],{"class":376},[355,1670,956],{"class":369},[355,1672,1624],{"class":376},[355,1674,979],{"class":369},[355,1676,1402],{"class":376},[355,1678,1679],{"class":361}," -",[355,1681,1682],{"class":376}," minGap\n",[355,1684,1686],{"class":357,"line":1685},21,[355,1687,1688],{"class":369},"    }\n",[355,1690,1692],{"class":357,"line":1691},22,[355,1693,1430],{"class":369},[355,1695,1697],{"class":357,"line":1696},23,[355,1698,549],{"class":369},[14,1700,1701],{},[29,1702,1703],{},"なぜ「下から上」なのか？",[230,1705,1708],{"className":1706,"code":1707,"language":235},[233],"売上高バー（大きい）\n┌─────────┐\n│         │  ← この空間にラベルを展開できる\n│         │\n├─────────┤\n│ seg1    │ ← 上に押し上げられる\n├─────────┤\n│ seg2    │ ← 上に押し上げられる\n├─────────┤\n│ seg3    │ ← 元の位置を維持（アンカー）\n└─────────┘\n    ↓\n  ゼロライン ← これより下に出ると見切れる\n",[237,1709,1707],{"__ignoreMap":239},[37,1711,1712,1715,1718],{},[40,1713,1714],{},"売上高の方が大きいため、上方向にスペースがある",[40,1716,1717],{},"下方向に押し出すとチャート領域外に出てしまう",[40,1719,1720],{},"一番下のセグメントを基準（アンカー）にして上に展開",[836,1722,1724],{"id":1723},"_5-バー種類別のラベル表示設定","5. バー種類別のラベル表示設定",[96,1726,1727,1739],{},[99,1728,1729],{},[102,1730,1731,1733,1736],{},[105,1732,110],{},[105,1734,1735],{},"ラベル表示",[105,1737,1738],{},"引き出し線",[115,1740,1741,1751,1759,1769,1780,1790],{},[102,1742,1743,1745,1748],{},[120,1744,125],{},[120,1746,1747],{},"表示",[120,1749,1750],{},"左側",[102,1752,1753,1755,1757],{},[120,1754,136],{},[120,1756,1747],{},[120,1758,1750],{},[102,1760,1761,1763,1766],{},[120,1762,147],{},[120,1764,1765],{},"表示（バー上）",[120,1767,1768],{},"なし",[102,1770,1771,1773,1778],{},[120,1772,258],{},[120,1774,1775],{},[29,1776,1777],{},"非表示",[120,1779,1750],{},[102,1781,1782,1784,1788],{},[120,1783,275],{},[120,1785,1786],{},[29,1787,1777],{},[120,1789,1750],{},[102,1791,1792,1794,1796],{},[120,1793,193],{},[120,1795,1765],{},[120,1797,1768],{},[14,1799,1800],{},"合計値を表示する意味がないため営業外等収益・営業外等費用はバー上のラベルを非表示とし、内訳のみ引き出し線で表示。",[230,1802,1804],{"className":349,"code":1803,"language":351,"meta":239,"style":239},"interface BarData {\n  // ...\n  hideLabel?: boolean  // trueの場合、バー上のラベル非表示\n}\n\n// 営業外等収益・費用では hideLabel: true を設定\n",[237,1805,1806,1815,1820,1835,1839,1843],{"__ignoreMap":239},[355,1807,1808,1810,1813],{"class":357,"line":358},[355,1809,362],{"class":361},[355,1811,1812],{"class":365}," BarData",[355,1814,370],{"class":369},[355,1816,1817],{"class":357,"line":373},[355,1818,1819],{"class":386},"  // ...\n",[355,1821,1822,1825,1827,1829,1832],{"class":357,"line":390},[355,1823,1824],{"class":376},"  hideLabel",[355,1826,914],{"class":361},[355,1828,380],{"class":369},[355,1830,1831],{"class":365},"boolean",[355,1833,1834],{"class":386},"  // trueの場合、バー上のラベル非表示\n",[355,1836,1837],{"class":357,"line":403},[355,1838,549],{"class":369},[355,1840,1841],{"class":357,"line":416},[355,1842,1435],{"emptyLinePlaceholder":666},[355,1844,1845],{"class":357,"line":429},[355,1846,1847],{"class":386},"// 営業外等収益・費用では hideLabel: true を設定\n",[23,1849,1850],{"id":1850},"設計上の考慮点",[200,1852,1853,1859,1865,1871],{},[40,1854,1855,1858],{},[29,1856,1857],{},"一貫性",": 全ての引き出し線を左側から出す（統一感）",[40,1860,1861,1864],{},[29,1862,1863],{},"可読性",": 黒丸を右寄りに配置し、線とラベルが売上高バーと被らないようにする",[40,1866,1867,1870],{},[29,1868,1869],{},"スペース活用",": 上方向にラベルを展開し、チャート領域内に収める",[40,1872,1873,1876],{},[29,1874,1875],{},"1項目の場合",": セグメントが1つだけの場合は真横に表示（自然な配置）",[1878,1879,1880],"style",{},"html pre.shiki code .stQ0i, html code.shiki .stQ0i{--shiki-default:#AB5959;--shiki-dark:#AB5959}html pre.shiki code .sSkh3, html code.shiki .sSkh3{--shiki-default:#2E8F82;--shiki-dark:#2E8F82}html pre.shiki code .shFtX, html code.shiki .shFtX{--shiki-default:#999999;--shiki-dark:#999999}html pre.shiki code .s4oTP, html code.shiki .s4oTP{--shiki-default:#B07D48;--shiki-dark:#B07D48}html pre.shiki code .sxvE3, html code.shiki .sxvE3{--shiki-default:#A0ADA0;--shiki-dark:#A0ADA0}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .senZ8, html code.shiki .senZ8{--shiki-default:#59873A;--shiki-dark:#59873A}html pre.shiki code .sM54T, html code.shiki .sM54T{--shiki-default:#2F798A;--shiki-dark:#2F798A}html pre.shiki code .sG7-3, html code.shiki .sG7-3{--shiki-default:#393A34;--shiki-dark:#393A34}html pre.shiki code .sMJiu, html code.shiki .sMJiu{--shiki-default:#B5695977;--shiki-dark:#B5695977}html pre.shiki code .sdGka, html code.shiki .sdGka{--shiki-default:#B56959;--shiki-dark:#B56959}html pre.shiki code .sHkkW, html code.shiki .sHkkW{--shiki-default:#1E754F;--shiki-dark:#1E754F}html pre.shiki code .sz8Xr, html code.shiki .sz8Xr{--shiki-default:#998418;--shiki-dark:#998418}",{"title":239,"searchDepth":373,"depth":373,"links":1882},[1883,1887,1891,1896,1900,1905,1908],{"id":20,"depth":373,"text":21,"children":1884},[1885,1886],{"id":25,"depth":390,"text":25},{"id":65,"depth":390,"text":65},{"id":82,"depth":373,"text":83,"children":1888},[1889,1890],{"id":93,"depth":390,"text":94},{"id":198,"depth":390,"text":198},{"id":221,"depth":373,"text":222,"children":1892},[1893,1894,1895],{"id":242,"depth":390,"text":243},{"id":292,"depth":390,"text":292},{"id":303,"depth":390,"text":303},{"id":342,"depth":373,"text":342,"children":1897},[1898,1899],{"id":345,"depth":390,"text":346},{"id":552,"depth":390,"text":552},{"id":577,"depth":373,"text":577,"children":1901},[1902,1903],{"id":580,"depth":390,"text":580},{"id":626,"depth":390,"text":1904},"jleague-variance.test.ts の検証内容",{"id":654,"depth":373,"text":654,"children":1906},[1907],{"id":721,"depth":390,"text":722},{"id":802,"depth":373,"text":803,"children":1909},[1910,1911,1912,1913],{"id":809,"depth":390,"text":809},{"id":821,"depth":390,"text":822},{"id":834,"depth":390,"text":834},{"id":1850,"depth":390,"text":1850},null,"JリーグページのP/L Waterfallチャートの構造変更（ビフォー・アフター比較）","md",{},"/pl-waterfall-redesign",false,"2025-12-26T00:00:00.000Z",{"title":5,"description":1915},"2025-12/2025-12-26/pl-waterfall-redesign",[1924,1925,1926],"design","jleague","financial-quiz","jcAfOrHOM-HMyEAou5AsOafWBJjoEHNoahHeBDFfU00",[],[1930,1934,1937,1941,1945],{"title":1931,"path":1932,"publishedAt":1933},"GitHub Actionsデプロイエラー - Jリーグクラブページ500エラー","/github-actions-deploy-error","2025-12-31T00:00:00.000Z",{"title":1935,"path":1936,"publishedAt":1933},"TableOfContents メトロラインデザイン仕様","/toc-metro-line-design",{"title":1938,"path":1939,"publishedAt":1940},"純資産増減ウォーターフォール実装計画","/net-assets-waterfall-plan","2025-12-27T00:00:00.000Z",{"title":1942,"path":1943,"publishedAt":1944},"Jリーグクラブ財務データ可視化 - 実装計画","/jleague-financial-data-structure","2025-12-25T00:00:00.000Z",{"title":1946,"path":1947,"publishedAt":1944},"Jリーグ経営情報の見方ガイド","/jleague-financial-metrics-guide","https://log.eurekapu.com/og/blog/pl-waterfall-redesign.png?v=2025-12-26T00%3A00%3A00.000Z&title=P%2FL%20Waterfall%E3%83%81%E3%83%A3%E3%83%BC%E3%83%88%E6%A7%8B%E9%80%A0%E5%A4%89%E6%9B%B4%E6%A1%88&author=Kei%20Komatsu&sig=65c4f4f0eb6b9c08",1785654978991]