function assemble_season(DateTime $date, array $astro) { /* --------------------------------------------- * 0. 辞書の読み込み * --------------------------------------------- */ $zassetsu_dict = json_decode(file_get_contents(__DIR__ . '/../data/zassetsu.json'), true); $sekku_dict = json_decode(file_get_contents(__DIR__ . '/../data/sekku.json'), true); $flowers_dict = json_decode(file_get_contents(__DIR__ . '/../data/flowers.json'), true); $birds_dict = json_decode(file_get_contents(__DIR__ . '/../data/birds-new.json'), true); $memories_dict = json_decode(file_get_contents(__DIR__ . '/../data/memories.json'), true); $birds_poem_dict = json_decode(file_get_contents(__DIR__ . '/../data/poem/birds-poem.json'), true); $sekki_index = json_decode(file_get_contents(get_stylesheet_directory() . '/data/sekki-index.json'), true); $kou_index = json_decode(file_get_contents(get_stylesheet_directory() . '/data/kou-index.json'), true); $kou_yomi_dict = json_decode(file_get_contents(get_stylesheet_directory() . '/data/kou-yomi.json'), true); $poem_kou = json_decode(file_get_contents(get_stylesheet_directory() . '/data/poem/poem-kou.json'), true); $flowers_poem_dict = json_decode(file_get_contents(__DIR__ . '/../data/poem/flowers-poem.json'), true); /* --------------------------------------------- * A. 今日の節気 * --------------------------------------------- */ $sekki_dates_all = loadSekkiData(); $year = (int)$date->format('Y'); $today_ts = $date->getTimestamp(); $today_sekki = null; $next_sekki = null; if (isset($sekki_dates_all[$year])) { foreach ($sekki_dates_all[$year] as $name => $mdhm) { $start_ts = (new DateTime($mdhm))->getTimestamp(); if ($start_ts <= $today_ts) { $today_sekki = $name; } elseif (!$next_sekki) { $next_sekki = $name; } } } /* --------------------------------------------- * B. 候 * --------------------------------------------- */ $days = 0; if ($today_sekki && isset($sekki_dates_all[$year][$today_sekki])) { $sekki_start = new DateTime($sekki_dates_all[$year][$today_sekki]); $days = (int)$date->diff($sekki_start)->format('%a'); } $kou_index_in_sekki = min(2, floor($days / 5)); $sekki_data = $sekki_index[$today_sekki] ?? null; $sekki_icon = $sekki_data['icon'] ?? 'sekki-1'; $sekki_id = intval(str_replace('sekki-', '', $sekki_icon)); $kou_number = $sekki_id * 3 + $kou_index_in_sekki; $kou_icon = sprintf("kou-%02d", $kou_number); $kou_name = $kou_index[$kou_icon] ?? null; $kou_poem_raw = $kou_name && isset($poem_kou[$kou_name]) ? $poem_kou[$kou_name] : []; $kou_yomi = $kou_yomi_dict[$kou_name] ?? ''; $kou_poem_long = function_exists('build_kou_long') ? build_kou_long($kou_poem_raw) : ''; $poem_short_data = json_decode(file_get_contents(__DIR__ . '/../data/poem/koupoem-short.json'), true); $season = []; $season['sekki'] = [ 'name' => $today_sekki, 'icon' => $sekki_icon, 'desc' => $sekki_data['desc'] ?? '' ]; $season['kou'] = [ 'name' => $kou_name, 'yomi' => $kou_yomi, 'icon' => $kou_icon, 'poem_long' => $kou_poem_long, 'poem_short' => $poem_short_data[$kou_name] ?? '' ]; /* --------------------------------------------- * C. 花・鳥の抽選(最優先でここ) * --------------------------------------------- */ $solar_month = (int)$date->format('n'); $month_key = $solar_month . '月'; $flowers = $flowers_dict[$month_key] ?? []; $birds = $birds_dict[(string)$solar_month] ?? []; $flower_name = !empty($flowers) ? $flowers[array_rand($flowers)] : null; $bird_name = null; if (!empty($birds)) { $b = $birds[array_rand($birds)]; $bird_name = is_array($b) ? ($b['name'] ?? null) : $b; } /* --------------------------------------------- * D. 鳥の詩辞書整形(抽選後に必ずここ) * --------------------------------------------- */ if (isset($birds_poem_dict[(string)$solar_month])) { $birds_poem_dict = $birds_poem_dict[(string)$solar_month]; } $birds_poem_dict_converted = []; foreach ($birds_poem_dict as $item) { if (!empty($item['keyword'])) { $birds_poem_dict_converted[$item['keyword']] = [ 'myth' => $item['myth'] ?? '', 'appearance' => $item['appearance'] ?? '', 'description'=> $item['description'] ?? '', ]; } } $birds_poem_dict = $birds_poem_dict_converted; /* --------------------------------------------- * E. 鳥の詩抽出 * --------------------------------------------- */ $bird_poem = $birds_poem_dict[$bird_name] ?? [ 'myth' => '', 'appearance' => '', 'description'=> $bird_name ? "{$bird_name}が季節の気配をそっと運ぶ。" : '' ]; $season['bird'] = [ 'name' => $bird_name, 'myth' => $bird_poem['myth'], 'appearance' => $bird_poem['appearance'], 'description' => $bird_poem['description'], ]; /* --------------------------------------------- * F. 花の詩抽出 * --------------------------------------------- */ $flower_poem = $flower_name && isset($flowers_poem_dict[$flower_name]) ? $flowers_poem_dict[$flower_name] : [ 'myth' => '', 'appearance' => '', 'description'=> $flower_name ? "{$flower_name}が季節をそっと彩る。" : '' ]; $season['flower'] = [ 'name' => $flower_name, 'myth' => $flower_poem['myth'], 'appearance' => $flower_poem['appearance'], 'description' => $flower_poem['description'], ]; /* --------------------------------------------- * G. 旧暦 * --------------------------------------------- */ $k = function_exists('calc_kyureki') ? calc_kyureki($date) : ['wafuu' => '', 'month' => 1, 'day' => 1]; $month_reading = [ '睦月'=>'むつき','如月'=>'きさらぎ','弥生'=>'やよい','卯月'=>'うづき', '皐月'=>'さつき','水無月'=>'みなづき','文月'=>'ふづき','葉月'=>'はづき', '長月'=>'ながつき','神無月'=>'かんなづき','霜月'=>'しもつき','師走'=>'しわす' ]; $age = $astro['moon']['age_float'] ?? null; $season['kyureki'] = [ 'date' => function_exists('formatKyurekiDate') ? formatKyurekiDate($k) : '', 'month_name' => $k['wafuu'] ?? '', 'reading' => $month_reading[$k['wafuu'] ?? ''] ?? '', 'month_num' => $k['month'] ?? 1, 'day_num' => $k['day'] ?? 1, 'is_leap' => $k['is_leap'] ?? false, 'is_saku' => ($age !== null && $age < 0.5), 'is_mochi' => ($age !== null && abs($age - 15) < 0.5), ]; /* --------------------------------------------- * H. 五節句 * --------------------------------------------- */ $today_sekku = null; if (is_array($sekku_dict)) { foreach ($sekku_dict as $s) { if (($s['month'] == $solar_month && $s['day'] == (int)$date->format('j')) || ($s['month'] == ($k['month'] ?? 1) && $s['day'] == ($k['day'] ?? 1))) { $today_sekku = $s; } } } $season['sekku'] = $today_sekku; /* --------------------------------------------- * I. 行事判定 * --------------------------------------------- */ $astro['kyureki'] = $season['kyureki']; $season['events'] = assemble_season_events($date, $astro); /* --------------------------------------------- * J. 季の気配 * --------------------------------------------- */ if ($flower_name && $bird_name) { $season['feel'] = "{$k['wafuu']}の空気がいつしか満ち、{$flower_name}の花にいやされ、\n" . "{$bird_name}達の気配に心弾む。"; } else { $season['feel'] = "{$k['wafuu']}の空気が静かに満ち、いつしか花や鳥の気配に包まれる。"; } /* --------------------------------------------- * K. 記憶 * --------------------------------------------- */ $memories_today = array_filter($memories_dict ?? [], fn($m) => ($m['month'] ?? 0) == $solar_month); $season['memory'] = $memories_today ? $memories_today[array_rand($memories_today)] : null; return $season; }