// 八字分析类(包含完整的特殊八字判断逻辑)
class BaziAnalyzer {
// 基础数据定义(保持不变)
public $heavenly_stems = ["甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"];
public $earthly_branches = ["子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"];
public $stem_elements = [
"甲" => "木", "乙" => "木", "丙" => "火", "丁" => "火",
"戊" => "土", "己" => "土", "庚" => "金", "辛" => "金",
"壬" => "水", "癸" => "水"
];
public $branch_elements = [
"子" => "水", "丑" => "湿土", "寅" => "木", "卯" => "木",
"辰" => "湿土", "巳" => "火", "午" => "火", "未" => "燥土",
"申" => "金", "酉" => "金", "戌" => "燥土", "亥" => "水"
];
public $generates = [
"木" => ["火"], "火" => ["土"], "土" => ["金"],
"金" => ["水"], "水" => ["木"], "湿土" => ["金", "水"],
"燥土" => ["火", "土"]
];
public $restrains = [
"木" => ["土", "湿土", "燥土"], "土" => ["水"],
"燥土" => ["金", "水", "湿土"], "湿土" => ["火", "土", "燥土"],
"水" => ["火"], "火" => ["金"], "金" => ["木"]
];
public $tomb_month_adjustment = [
// 辰月
"甲木辰月" => -0.5, "乙木辰月" => -0.5, "丙火辰月" => -0.5, "丁火辰月" => -0.5,
"戊土辰月" => -0.5, "己土辰月" => -0.5, "庚金辰月" => 0, "辛金辰月" => 0.5,
"壬水辰月" => 0.1, "癸水辰月" => 0.1,
// 丑月
"甲木丑月" => -0.5, "乙木丑月" => -0.5, "丙火丑月" => -0.5, "丁火丑月" => -0.5,
"戊土丑月" => -0.5, "己土丑月" => -0.5, "庚金丑月" => 0.5, "辛金丑月" => 0.5,
"壬水丑月" => 0, "癸水丑月" => 0.1,
// 未月
"甲木未月" => -0.5, "乙木未月" => -0.5, "丙火未月" => 0.1, "丁火未月" => 0.1,
"戊土未月" => 0.5, "己土未月" => 0.5, "庚金未月" => -0.5, "辛金未月" => -0.5,
"壬水未月" => -0.5, "癸水未月" => -0.5,
// 戌月
"甲木戌月" => -0.5, "乙木戌月" => -0.5, "丙火戌月" => 0, "丁火戌月" => 0.1,
"戊土戌月" => 0, "己土戌月" => 0.5, "庚金戌月" => -0.5, "辛金戌月" => -0.5,
"壬水戌月" => -0.5, "癸水戌月" => -0.5
];
public $opposing_branches = [
"子" => "午", "午" => "子", "丑" => "未", "未" => "丑",
"寅" => "申", "申" => "寅", "卯" => "酉", "酉" => "卯",
"辰" => "戌", "戌" => "辰", "巳" => "亥", "亥" => "巳"
];
public $combining_branches = [
"子" => "丑", "丑" => "子", "寅" => "亥", "亥" => "寅",
"卯" => "戌", "戌" => "卯", "辰" => "酉", "酉" => "辰",
"巳" => "申", "申" => "巳", "午" => "未", "未" => "午"
];
public $punishing_branches = [
"丑" => "戌", "戌" => "丑", "寅" => "巳", "巳" => "寅"
];
public $power_weights = [
"日支" => 7, "月干" => 6, "时干" => 5,
"月支" => 4, "年干" => 3, "时支" => 2, "年支" => 1
];
public $special_bazi_info = [];
public $reversal_info = [];
// 计算空亡地支(保持不变)
public function calculate_empty_branches($day_stem, $day_branch) {
$stem_num = array_search($day_stem, $this->heavenly_stems) + 1;
$branch_num = array_search($day_branch, $this->earthly_branches) + 1;
$xu_shou = $branch_num - ($stem_num - 1);
if ($xu_shou <= 0) $xu_shou += 12;
$kong_wang1 = $xu_shou + 10;
$kong_wang2 = $xu_shou + 11;
if ($kong_wang1 > 12) $kong_wang1 -= 12;
if ($kong_wang2 > 12) $kong_wang2 -= 12;
return [
$this->earthly_branches[$kong_wang1 - 1],
$this->earthly_branches[$kong_wang2 - 1]
];
}
// 检查地支相互作用(合、冲、刑、克、泄)
public function check_branch_interaction($branch1, $branch2) {
$element1 = $this->branch_elements[$branch1];
$element2 = $this->branch_elements[$branch2];
if (isset($this->opposing_branches[$branch1]) && $branch2 == $this->opposing_branches[$branch1]) return true;
if (isset($this->combining_branches[$branch1]) && $branch2 == $this->combining_branches[$branch1]) return true;
if (isset($this->punishing_branches[$branch1]) && $branch2 == $this->punishing_branches[$branch1]) return true;
if (isset($this->restrains[$element1]) && in_array($element2, $this->restrains[$element1])) return true;
if (isset($this->generates[$element2]) && in_array($element1, $this->generates[$element2])) return true;
return false;
}
// 检查地支合、冲、刑关系
public function check_branch_combine_oppose_punish($branch1, $branch2) {
if (isset($this->opposing_branches[$branch1]) && $branch2 == $this->opposing_branches[$branch1]) return true;
if (isset($this->combining_branches[$branch1]) && $branch2 == $this->combining_branches[$branch1]) return true;
if (isset($this->punishing_branches[$branch1]) && $branch2 == $this->punishing_branches[$branch1]) return true;
return false;
}
// 检查月支双伤(保持不变)
public function check_month_double_injury($bazi, $empty_branches) {
$year_branch = $bazi["year"]["branch"];
$month_branch = $bazi["month"]["branch"];
$day_branch = $bazi["day"]["branch"];
$hour_branch = $bazi["hour"]["branch"];
// 1. 先判断月支是否空亡,如果空亡,这个步骤跳过
if (in_array($month_branch, $empty_branches)) {
return false;
}
// 2. 如果日支和时支合、冲、刑关系,这个步骤跳过
// check_branch_interaction 已经包含了合、冲、刑、克、泄
if ($this->check_branch_combine_oppose_punish($day_branch, $hour_branch)) {
return false;
}
// 3. 月两次伤是月支同时受到年支和日支的克、泄、合、冲、刑的伤害
// 这里需要判断年支对月支的伤害,以及日支对月支的伤害
// check_branch_interaction($source_branch, $target_branch)
$year_hurts_month = $this->check_branch_interaction($year_branch, $month_branch);
$day_hurts_month = $this->check_branch_interaction($day_branch, $month_branch);
$main_condition = $year_hurts_month && $day_hurts_month;
// 4. 还有一种是辰、丑为月支,日支或者年支是其中一个或者两个都是金,也算两次伤
$special_case_chen_chou = false;
if (in_array($month_branch, ["辰", "丑"])) {
$day_branch_element = $this->branch_elements[$day_branch];
$year_branch_element = $this->branch_elements[$year_branch];
if ($day_branch_element == "金" || $year_branch_element == "金") {
$special_case_chen_chou = true;
}
}
return $main_condition || $special_case_chen_chou;
}
// 分析元素相互作用(保持不变)
public function analyze_element_interaction($day_element, $position_element, $branch = null) {
if ($position_element == "湿土") {
if ($day_element == "火") return "克";
if ($day_element == "金") return "泄";
if ($day_element == "水") return "帮";
if ($day_element == "木") return "耗";
} elseif ($position_element == "燥土") {
if ($day_element == "金") return "克";
if ($day_element == "水") return "克";
if ($day_element == "火") return "帮";
if ($day_element == "木") return "耗";
if ($day_element == "土") return "比";
}
if ($day_element == $position_element) return "比";
if (isset($this->generates[$position_element]) && in_array($day_element, $this->generates[$position_element])) return "生";
if (isset($this->generates[$day_element]) && in_array($position_element, $this->generates[$day_element])) return "泄";
if (isset($this->restrains[$position_element]) && in_array($day_element, $this->restrains[$position_element])) return "克";
if (isset($this->restrains[$day_element]) && in_array($position_element, $this->restrains[$day_element])) return "耗";
return "无";
}
// 获取元素关系(保持不变)
public function get_relation($element1, $element2) {
if ($element1 == $element2) return "比";
if (isset($this->generates[$element1]) && in_array($element2, $this->generates[$element1])) return "生";
if (isset($this->generates[$element2]) && in_array($element1, $this->generates[$element2])) return "泄";
if (isset($this->restrains[$element1]) && in_array($element2, $this->restrains[$element1])) return "克";
if (isset($this->restrains[$element2]) && in_array($element1, $this->restrains[$element2])) return "耗";
return "无";
}
// 判断是否为帮扶关系(保持不变)
private function is_helping($interaction) {
return in_array($interaction, ["比", "生"]);
}
// 判断是否为克制关系(保持不变)
private function is_constraining($interaction) {
return in_array($interaction, ["克", "耗", "泄"]);
}
// 判断位置是否受伤(保持不变)
private function is_position_injured($bazi, $position_type, $position_key, $empty_branches) {
$char = $bazi[$position_key][$position_type];
$element = ($position_type == "stem") ? $this->stem_elements[$char] : $this->branch_elements[$char];
if ($position_type == "branch" && in_array($char, $empty_branches)) return true;
$injured = false;
$all_positions = [];
foreach (["year", "month", "day", "hour"] as $pillar) {
foreach (["stem", "branch"] as $type) {
if ($pillar == $position_key && $type == $position_type) continue;
$all_positions[] = ["pillar" => $pillar, "type" => $type, "char" => $bazi[$pillar][$type]];
}
}
foreach ($all_positions as $pos) {
$other_element = ($pos["type"] == "stem") ? $this->stem_elements[$pos["char"]] : $this->branch_elements[$pos["char"]];
$relation = $this->get_relation($other_element, $element);
if (in_array($relation, ["克", "泄"])) {
$injured = true;
break;
}
}
if ($position_type == "branch" && !$injured) {
foreach ($all_positions as $pos) {
if ($pos["type"] != "branch") continue;
if (isset($this->opposing_branches[$char]) && $pos["char"] == $this->opposing_branches[$char]) {
$injured = true;
break;
}
if (isset($this->combining_branches[$char]) && $pos["char"] == $this->combining_branches[$char]) {
$injured = true;
break;
}
if (isset($this->punishing_branches[$char]) && $pos["char"] == $this->punishing_branches[$char]) {
$injured = true;
break;
}
}
}
if ($position_type == "branch" && in_array($char, ["辰", "丑", "未", "戌"]) && !$injured) {
$wood_clash_count = 0;
$has_combine_oppose = false;
foreach ($all_positions as $pos) {
if ($pos["type"] != "branch") continue;
if ($this->branch_elements[$pos["char"]] == "木") $wood_clash_count++;
if (isset($this->opposing_branches[$char]) && $pos["char"] == $this->opposing_branches[$char]) $has_combine_oppose = true;
if (isset($this->combining_branches[$char]) && $pos["char"] == $this->combining_branches[$char]) $has_combine_oppose = true;
}
if ($wood_clash_count >= 2 || $has_combine_oppose) $injured = true;
}
return $injured;
}
// 计算力量分配(保持不变)
public function calculate_power_distribution($bazi) {
$day_stem = $bazi["day"]["stem"];
$day_branch = $bazi["day"]["branch"];
$month_branch = $bazi["month"]["branch"];
$year_branch = $bazi["year"]["branch"];
$empty_branches = $this->calculate_empty_branches($day_stem, $day_branch);
// 同字空亡情况
if ($month_branch == $year_branch && in_array($month_branch, $empty_branches)) {
return ["month_stem" => 0.33, "day_branch" => 0.33, "hour_stem" => 0.33];
}
// 月令空亡情况
if (in_array($month_branch, $empty_branches)) {
return ["year_branch" => 0.3, "month_stem" => 0.23, "day_branch" => 0.23, "hour_stem" => 0.23];
}
// 检查月支双伤
$month_double_injured = $this->check_month_double_injury($bazi, $empty_branches);
if ($month_double_injured) {
return ["month_stem" => 0.33, "day_branch" => 0.33, "hour_stem" => 0.33];
}
// 墓库月处理(月不空亡且未受两次伤)
if (in_array($month_branch, ["辰", "丑", "未", "戌"])) {
if (in_array($month_branch, $empty_branches) || $month_double_injured) {
return $this->get_standard_power_distribution();
}
$day_element = $this->stem_elements[$day_stem];
$key = "{$day_stem}{$day_element}{$month_branch}月";
if (isset($this->tomb_month_adjustment[$key])) {
$adj = $this->tomb_month_adjustment[$key];
if ($adj == 0.5) {
return ["month_branch" => 0.5, "month_stem" => 0.17, "day_branch" => 0.17, "hour_stem" => 0.17];
} elseif ($adj == -0.5) {
return ["month_branch" => 0, "month_stem" => 0.17, "day_branch" => 0.17, "hour_stem" => 0.167];
} elseif ($adj == 0.1) {
return ["month_branch" => 0.1, "month_stem" => 0.3, "day_branch" => 0.3, "hour_stem" => 0.3];
} elseif ($adj == 0) {
return ["month_branch" => 0, "month_stem" => 0.33, "day_branch" => 0.33, "hour_stem" => 0.33];
}
}
}
// 标准模式
return $this->get_standard_power_distribution();
}
// 标准力量分配辅助函数(保持不变)
private function get_standard_power_distribution() {
return ["month_branch" => 0.5, "month_stem" => 0.17, "day_branch" => 0.17, "hour_stem" => 0.17];
}
// 计算日主旺衰(修正三元运算符嵌套)
public function calculate_strength($bazi, $power_distribution) {
$day_stem = $bazi["day"]["stem"];
$day_element = $this->stem_elements[$day_stem];
$help_strength = 0.0;
$strength_details = [];
$empty_branches = $this->calculate_empty_branches($day_stem, $bazi["day"]["branch"]);
// All 7 positions that have power_weights
$positions_to_analyze = [
"年干" => ["stem", "year"],
"年支" => ["branch", "year"],
"月干" => ["stem", "month"],
"月支" => ["branch", "month"],
"日支" => ["branch", "day"],
"时干" => ["stem", "hour"],
"时支" => ["branch", "hour"]
];
foreach ($positions_to_analyze as $pos_name => $pos_data) {
$type = $pos_data[0];
$pillar = $pos_data[1];
$char = $bazi[$pillar][$type];
$element = ($type == "stem") ? $this->stem_elements[$char] : $this->branch_elements[$char];
// Determine the power key based on position name
$power_key = "";
switch ($pos_name) {
case "年干": $power_key = "year_stem"; break;
case "年支": $power_key = "year_branch"; break;
case "月干": $power_key = "month_stem"; break;
case "月支": $power_key = "month_branch"; break;
case "日支": $power_key = "day_branch"; break;
case "时干": $power_key = "hour_stem"; break;
case "时支": $power_key = "hour_branch"; break;
}
$power = isset($power_distribution[$power_key]) ? $power_distribution[$power_key] : 0;
$interaction = $this->analyze_element_interaction($day_element, $element, ($type == "branch" ? $char : null));
if ($this->is_helping($interaction)) {
$help_strength += $power;
$effect = "增强";
} else {
$effect = "削弱";
}
$strength_details[$pos_name] = [
"effect" => $effect,
"percentage" => round($power * 100),
"relation" => $this->get_relation($element, $day_element),
"char" => $char,
"element" => $element
];
}
$help_percentage = round($help_strength * 100);
$status = $this->determine_bazi_status($help_percentage, $power_distribution, $strength_details, $empty_branches, $bazi);
return [
"status" => $status,
"help_strength" => $help_strength,
"strength_details" => $strength_details
];
}
// 判断八字旺衰状态(保持不变)
public function determine_bazi_status($help_percentage, $power_distribution, $strength_details, $empty_branches, $bazi) {
// 从旺格判断
if ($help_percentage >= 90) {
$this->special_bazi_info[] = "日主从旺";
return "从旺";
}
// 从弱格判断
if ($help_percentage <= 10) {
$this->special_bazi_info[] = "日主从弱";
return "从弱";
}
// 扶抑格判断
if ($help_percentage >= 50) {
return "身旺";
} else {
return "身弱";
}
}
// 辅助函数:判断两个位置是否相邻
private function are_adjacent($pos1, $pos2) {
$adjacent_map = [
"年干" => ["月干"],
"年支" => ["月支"],
"月干" => ["年干", "时干"],
"月支" => ["年支", "日支"],
"日干" => ["时干"], // 日干与时干相邻
"日支" => ["月支", "时支"],
"时干" => ["月干", "日干"],
"时支" => ["日支"]
];
return isset($adjacent_map[$pos1]) && in_array($pos2, $adjacent_map[$pos1]);
}
// 辅助函数:判断八字中是否存在与目标元素相同的五行(排除日干和目标元素自身)
private function has_same_element_in_bazi($bazi, $target_char, $target_pos_name) {
$target_element = null;
if (isset($this->stem_elements[$target_char])) {
$target_element = $this->stem_elements[$target_char];
} elseif (isset($this->branch_elements[$target_char])) {
$target_element = $this->branch_elements[$target_char];
}
if (!$target_element) return false;
$positions_to_check = [
"年干" => ["stem", "year"],
"年支" => ["branch", "year"],
"月干" => ["stem", "month"],
"月支" => ["branch", "month"],
"日干" => ["stem", "day"],
"日支" => ["branch", "day"],
"时干" => ["stem", "hour"],
"时支" => ["branch", "hour"]
];
foreach ($positions_to_check as $pos_name => $pos_data) {
if ($pos_name == $target_pos_name || ($pos_name == "日干" && $target_pos_name != "日干")) continue; // 排除自身和日干
$type = $pos_data[0];
$pillar = $pos_data[1];
$char = $bazi[$pillar][$type];
$element = ($type == "stem") ? $this->stem_elements[$char] : $this->branch_elements[$char];
// 特殊处理戊己土与辰丑未戌土
if (in_array($target_char, ['戊', '己']) && $target_element == "土") {
if (in_array($char, ['未', '戌']) && $this->branch_elements[$char] == "燥土") return true;
if (in_array($char, ['辰', '丑']) && $this->branch_elements[$char] == "湿土") continue; // 辰丑不以同五行论
} else if ($target_element == $element) {
return true;
}
}
return false;
}
// 新增方法:反断与指定天干相同五行且同柱的地支
private function reverse_same_element_branch($bazi, &$reversed_yong_ji, $stem_char, $initial_yong_ji, $stem_position) {
// 建立天干位置到同柱地支位置的映射
$branch_position_map = [
'年干' => '年支',
'月干' => '月支',
'时干' => '时支'
];
// 如果传入的天干位置不在映射表中(比如日干),则直接返回
if (!isset($branch_position_map[$stem_position])) {
return;
}
$branch_pos_name = $branch_position_map[$stem_position];
$pillar_key = str_replace('支', '', $branch_pos_name);
$pillar_key = lcfirst($pillar_key); // 转为小写开头的键名,如'year'
$branch_char = $bazi[$pillar_key]["branch"];
$branch_element = $this->branch_elements[$branch_char];
// 检查地支五行是否与天干相同(考虑燥土和湿土的特殊情况)
$is_same_element = false;
if (in_array($stem_char, ['戊', '己'])) {
// 未戌视为燥土,与戊己土相同
if (in_array($branch_char, ['未', '戌'])) {
$is_same_element = true;
}
} else {
// 普通情况,直接比较五行
$stem_element = $this->stem_elements[$stem_char];
if ($branch_element == $stem_element) {
$is_same_element = true;
}
}
// 如果五行相同,则进行反断
if ($is_same_element) {
// 检查这个地支位置在初始用忌神中是否存在
if (isset($initial_yong_ji[$branch_pos_name])) {
$original_type = $initial_yong_ji[$branch_pos_name]["type"];
$reversed_type = ($original_type == "用神") ? "忌神" : "用神";
// 修改这个地支位置的用忌神
$reversed_yong_ji[$branch_pos_name]["type"] = $reversed_type;
$this->reversal_info[] = "地支随天干反断:地支 {$branch_char}({$branch_pos_name})随天干 {$stem_char}({$stem_position})反断为 {$reversed_type}";
}
}
}
// 应用反断规则
public function apply_reversal_rules($bazi, $initial_yong_ji, $strength_result) {
$reversed_yong_ji = $initial_yong_ji;
$day_stem = $bazi["day"]["stem"];
$day_element = $this->stem_elements[$day_stem];
$empty_branches = $this->calculate_empty_branches($day_stem, $bazi["day"]["branch"]);
// 1. 扶抑反
if ($strength_result["status"] == "身旺" || $strength_result["status"] == "身弱") {
$positions_with_power = [];
foreach ($this->power_weights as $pos_name => $weight) {
if ($pos_name == "日干") continue; // 日干不参与反断
$pillar_key = '';
$type = '';
if (strpos($pos_name, '干') !== false) {
$type = 'stem';
$pillar_key = str_replace('干', '', $pos_name);
} elseif (strpos($pos_name, '支') !== false) {
$type = 'branch';
$pillar_key = str_replace('支', '', $pos_name);
}
$pillar_key = lcfirst($pillar_key);
if (isset($bazi[$pillar_key][$type])) {
$char = $bazi[$pillar_key][$type];
$element = ($type == 'stem') ? $this->stem_elements[$char] : $this->branch_elements[$char];
$current_type = $reversed_yong_ji[$pos_name]["type"];
if ($current_type == "忌神") {
$positions_with_power[$pos_name] = [
'char' => $char,
'element' => $element,
'weight' => $weight,
'type' => $type,
'pillar_key' => $pillar_key
];
}
}
}
// 找到力量最大的忌神
$strongest_jishi_pos = null;
$max_weight = -1;
foreach ($positions_with_power as $pos_name => $data) {
if ($data['weight'] > $max_weight) {
$max_weight = $data['weight'];
$strongest_jishi_pos = $pos_name;
}
}
if ($strongest_jishi_pos) {
$jishi_data = $positions_with_power[$strongest_jishi_pos];
$jishi_char = $jishi_data['char'];
$jishi_element = $jishi_data['element'];
$jishi_type = $jishi_data['type'];
$jishi_pillar_key = $jishi_data['pillar_key'];
$reversed_one = false;
// 检查是否有相邻且相同的字可以一起反断
$adjacent_found = false;
foreach ($positions_with_power as $other_pos_name => $other_data) {
if ($strongest_jishi_pos == $other_pos_name) continue;
// 检查是否相邻且字相同
if ($this->are_adjacent($strongest_jishi_pos, $other_pos_name) && $jishi_char == $other_data['char']) {
// 两个忌神一起反断
$reversed_yong_ji[$strongest_jishi_pos]["type"] = "用神";
$reversed_yong_ji[$other_pos_name]["type"] = "用神";
$this->reversal_info[] = "扶抑反:{$strongest_jishi_pos} ({$jishi_char}) 和 {$other_pos_name} ({$other_data['char']}) 相邻且相同,一起反断为用神";
$reversed_one = true;
$adjacent_found = true;
// 如果反断的是天干,则其五行相同的同柱地支也反断
if ($jishi_type == 'stem') {
$this->reverse_same_element_branch($bazi, $reversed_yong_ji, $jishi_char, $initial_yong_ji, $strongest_jishi_pos);
}
if ($other_data['type'] == 'stem') {
$this->reverse_same_element_branch($bazi, $reversed_yong_ji, $other_data['char'], $initial_yong_ji, $other_pos_name);
}
break; // 只反断一对
}
}
// 如果没有相邻且相同的字一起反断,则单独反断力量最大的忌神
if (!$adjacent_found) {
// 检查原局是否有同五行(日干的五行不算)
if ($this->has_same_element_in_bazi($bazi, $jishi_char, $strongest_jishi_pos)) {
$reversed_yong_ji[$strongest_jishi_pos]["type"] = "用神";
$this->reversal_info[] = "扶抑反:{$strongest_jishi_pos} ({$jishi_char}) 原局有同五行,反断为用神";
$reversed_one = true;
// 如果反断的是天干,则其五行相同的同柱地支也反断
if ($jishi_type == 'stem') {
$this->reverse_same_element_branch($bazi, $reversed_yong_ji, $jishi_char, $initial_yong_ji, $strongest_jishi_pos);
}
}
}
}
}
// 2. 从格反
if ($strength_result["status"] == "从旺" || $strength_result["status"] == "从弱") {
$positions_to_check = [
"年干" => ["stem", "year"],
"年支" => ["branch", "year"],
"月干" => ["stem", "month"],
"月支" => ["branch", "month"],
"日支" => ["branch", "day"],
"时干" => ["stem", "hour"],
"时支" => ["branch", "hour"]
];
foreach ($positions_to_check as $pos_name => $pos_data) {
if ($pos_name == "日干") continue; // 日干不参与反断
$type = $pos_data[0];
$pillar = $pos_data[1];
$char = $bazi[$pillar][$type];
$element = ($type == 'stem') ? $this->stem_elements[$char] : $this->branch_elements[$char];
$current_type = $reversed_yong_ji[$pos_name]["type"];
// 必须是用神
if ($current_type == "用神") {
// 检查是否同字且相连,且不能受任何克泄
foreach ($positions_to_check as $other_pos_name => $other_pos_data) {
if ($pos_name == $other_pos_name || $other_pos_name == "日干") continue;
$other_type = $other_pos_data[0];
$other_pillar = $other_pos_data[1];
$other_char = $bazi[$other_pillar][$other_type];
$other_element = ($other_type == 'stem') ? $this->stem_elements[$other_char] : $this->branch_elements[$other_char];
$other_current_type = $reversed_yong_ji[$other_pos_name]["type"];
if ($other_current_type == "用神" && $char == $other_char && $this->are_adjacent($pos_name, $other_pos_name)) {
// 检查是否受克泄
$is_constrained = false;
// 遍历所有其他位置,检查是否有克泄关系
foreach ($positions_to_check as $check_pos_name => $check_pos_data) {
if ($check_pos_name == $pos_name || $check_pos_name == $other_pos_name || $check_pos_name == "日干") continue;
$check_type = $check_pos_data[0];
$check_pillar = $check_pos_data[1];
$check_char = $bazi[$check_pillar][$check_type];
$check_element = ($check_type == 'stem') ? $this->stem_elements[$check_char] : $this->branch_elements[$check_char];
$relation_to_char = $this->get_relation($check_element, $element);
$relation_to_other_char = $this->get_relation($check_element, $other_element);
if (in_array($relation_to_char, ["克", "泄"]) || in_array($relation_to_other_char, ["克", "泄"])) {
$is_constrained = true;
break;
}
}
if (!$is_constrained) {
// 反断这对用神
$reversed_yong_ji[$pos_name]["type"] = "忌神";
$reversed_yong_ji[$other_pos_name]["type"] = "忌神";
$this->reversal_info[] = "从格反:{$pos_name} ({$char}) 和 {$other_pos_name} ({$other_char}) 相邻且相同,且不受克泄,反断为忌神";
// 如果反断的是天干,则其五行相同的同柱地支也反断
if ($type == 'stem') {
$this->reverse_same_element_branch($bazi, $reversed_yong_ji, $char, $initial_yong_ji, $pos_name);
}
if ($other_type == 'stem') {
$this->reverse_same_element_branch($bazi, $reversed_yong_ji, $other_char, $initial_yong_ji, $other_pos_name);
}
// 避免重复处理,跳过内部循环
continue 2;
}
}
}
}
}
}
// 3. 时干反
$hour_stem_char = $bazi["hour"]["stem"];
$hour_stem_element = $this->stem_elements[$hour_stem_char];
$month_branch_char = $bazi["month"]["branch"];
$hour_branch_char = $bazi["hour"]["branch"];
$month_branch_element = $this->branch_elements[$month_branch_char];
$hour_branch_element = $this->branch_elements[$hour_branch_char];
$is_hour_stem_weaker_than_month = in_array($this->get_relation($month_branch_element, $hour_stem_element), ["克", "耗", "泄"]);
$is_hour_stem_weaker_than_hour_branch = in_array($this->get_relation($hour_branch_element, $hour_stem_element), ["克", "耗", "泄"]);
$has_no_same_element = !$this->has_same_element_in_bazi($bazi, $hour_stem_char, "时干");
$month_branch_empty = in_array($month_branch_char, $empty_branches);
$hour_branch_empty = in_array($hour_branch_char, $empty_branches);
if ($is_hour_stem_weaker_than_month &&
$is_hour_stem_weaker_than_hour_branch &&
$has_no_same_element &&
!$month_branch_empty && // 月空或时支空、时干不反
!$hour_branch_empty) {
$original_type = $reversed_yong_ji["时干"]["type"];
$reversed_type = ($original_type == "用神") ? "忌神" : "用神";
$reversed_yong_ji["时干"]["type"] = $reversed_type;
$this->reversal_info[] = "时干反:时干 ({$hour_stem_char}) 满足反断条件,反断为 {$reversed_type}";
// 如果时干反断,则其五行相同的同柱地支(时支)也反断
$this->reverse_same_element_branch($bazi, $reversed_yong_ji, $hour_stem_char, $initial_yong_ji, "时干");
}
return $reversed_yong_ji;
}
}
// 计算初步用神忌神(保持不变)
private function get_default_status($help_percentage) {
if ($help_percentage >= 80) return "从旺";
if ($help_percentage >= 50) return "身旺";
if ($help_percentage >= 20) return "身弱";
return "从弱";
}
// 分析八字(保持不变)
public function analyze_bazi($bazi) {
$power_distribution = $this->calculate_power_distribution($bazi);
$strength_result = $this->calculate_strength($bazi, $power_distribution);
$initial_yong_ji = $this->calculate_initial_yong_ji($bazi, $strength_result);
$reversed_yong_ji = $this->apply_reversal_rules($bazi, $initial_yong_ji, $strength_result);
return [
"power_distribution" => $power_distribution,
"strength_result" => $strength_result,
"initial_yong_ji" => $initial_yong_ji,
"yong_ji" => $reversed_yong_ji,
"reversal_info" => $this->reversal_info,
"special_bazi_info" => $this->special_bazi_info,
"empty_branches" => $this->calculate_empty_branches($bazi["day"]["stem"], $bazi["day"]["branch"])
];
}
}
// 处理前端请求
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// 接收前端发送的JSON数据
$request_data = json_decode(file_get_contents('php://input'), true);
if (!$request_data) {
http_response_code(400);
echo json_encode(["error" => "无效的请求数据"]);
exit;
}
// 验证八字数据完整性
$required_fields = ["year_stem", "year_branch", "month_stem", "month_branch", "day_stem", "day_branch", "hour_stem", "hour_branch"];
foreach ($required_fields as $field) {
if (!isset($request_data[$field]) || empty($request_data[$field])) {
http_response_code(400);
echo json_encode(["error" => "缺少必要的八字信息:{$field}"]);
exit;
}
}
// 构造八字数据格式
$bazi = [
"year" => ["stem" => $request_data["year_stem"], "branch" => $request_data["year_branch"]],
"month" => ["stem" => $request_data["month_stem"], "branch" => $request_data["month_branch"]],
"day" => ["stem" => $request_data["day_stem"], "branch" => $request_data["day_branch"]],
"hour" => ["stem" => $request_data["hour_stem"], "branch" => $request_data["hour_branch"]]
];
// 执行八字分析
$analyzer = new BaziAnalyzer();
$result = $analyzer->analyze_bazi($bazi);
// 返回JSON结果
header('Content-Type: application/json');
echo json_encode($result);
exit;
}
?>