diff --git a/app/eva_common.py b/app/eva_common.py index 0bbd0ec..dddfebf 100644 --- a/app/eva_common.py +++ b/app/eva_common.py @@ -1886,60 +1886,65 @@ def get_prev_cross(nodeid, area_id, roads_dir_dict): return src_cross +def _to_int_list(nums, mask): + """把非'-'位转成int,再微调±1使总和=100,只动最大位。""" + # 先全部转int + nums = [int(v) if not mask[i] else v for i, v in enumerate(nums)] + # 有效位下标 + valid = [i for i, m in enumerate(mask) if not m] + if len(valid) < 2: # 单有效或全'-'无需调 + return nums + s = sum(nums[i] for i in valid) + if s == 100: + return nums + # 差±1 + delta = s - 100 + idx_big = max(valid, key=nums.__getitem__) # 仍只动最大位 + nums[idx_big] -= delta + return nums + + def fix_to_100(a, b, c): nums = [a, b, c] - dash_mask = [v == '-' for v in nums] - valid_idx = [i for i, m in enumerate(dash_mask) if not m] + mask = [v == '-' for v in nums] + valid_idx = [i for i, m in enumerate(mask) if not m] # ----- 全 '-' ----- - if len(valid_idx) == 0: + if not valid_idx: return nums[:] # ----- 仅 1 个有效 ----- if len(valid_idx) == 1: - vi = valid_idx[0] - nums[vi] = 100 - return nums + nums[valid_idx[0]] = 100 + return _to_int_list(nums, mask) # ----- 2 个有效 ----- if len(valid_idx) == 2: i0, i1 = valid_idx v0, v1 = nums[i0], nums[i1] - - # 只有出现 100 或 0 才强制随机拆分 if 100 in (v0, v1) or 0 in (v0, v1): r1 = random.randint(1, 3) r2 = 100 - r1 - # 原 100 的下标放较大值,原 0 的下标放较小值 - if v0 == 100 or v1 == 100: # 谁 100 谁拿大的 + # 原100位放较大值,原0位放较小值 + if v0 == 100 or v1 == 100: idx_100 = i0 if v0 == 100 else i1 idx_zro = i1 if v0 == 100 else i0 nums[idx_100] = max(r1, r2) nums[idx_zro] = min(r1, r2) - else: # 谁 0 谁拿小的 + else: idx_zro = i0 if v0 == 0 else i1 - idx_nz = i1 if v0 == 0 else i0 + idx_nz = i1 if v0 == 0 else i0 nums[idx_zro] = min(r1, r2) - nums[idx_nz] = max(r1, r2) - return nums - - # 正常值:等比缩放(下标不变) + nums[idx_nz] = max(r1, r2) + return _to_int_list(nums, mask) # 这里已int,但保险再调一次 + # 正常值:等比缩放 s = v0 + v1 - if s == 100: - return nums - delta = s - 100 # 正=超出,负=不足 - # 从值更大的下标里扣掉 delta - idx_big = i0 if v0 >= v1 else i1 - nums[idx_big] -= delta - # Rounding 可能导致差 1,再微调一次(仍只动同一下标) - delta2 = sum(nums[i] for i in valid_idx) - 100 - nums[idx_big] -= delta2 - return nums + nums[i0] = v0 * 100 / s + nums[i1] = v1 * 100 / s + return _to_int_list(nums, mask) # ----- 3 个有效 ----- - # 先处理 0/100(只动原 100 或原 0 的下标) if 100 in nums or 0 in nums: - # 100 存在:拆成两份 1~3,只动 100 位与 0 位 if 100 in nums: idx_100 = nums.index(100) zeros = [i for i in range(3) if nums[i] == 0] @@ -1948,27 +1953,23 @@ def fix_to_100(a, b, c): nums[zeros[0]] = r1 nums[zeros[1]] = r2 nums[idx_100] = 0 # 先清零,再走下面统一处理 - # 现在只剩 0 需要修正 zeros = [i for i in range(3) if nums[i] == 0] - if len(zeros) == 1: # 单 0:用 1~3 填充 + if len(zeros) == 1: nums[zeros[0]] = random.randint(1, 3) - elif len(zeros) == 2: # 双 0:随机拆分 100,只动 0 位 + elif len(zeros) == 2: r1 = random.randint(1, 3) r2 = 100 - r1 nums[zeros[0]] = r1 nums[zeros[1]] = r2 - return nums + return _to_int_list(nums, mask) - # 原本无 0/100:等比缩放,只动最大下标 + # 正常缩放 s = sum(nums) if s == 100: - return nums + return [int(v) for v in nums] for i in range(3): - nums[i] = max(1, int(round(nums[i] * 100 / s))) - delta = sum(nums) - 100 - idx_max = max(range(3), key=nums.__getitem__) - nums[idx_max] -= delta - return nums + nums[i] = max(1, round(nums[i] * 100 / s)) + return _to_int_list(nums, mask) def query_cross_delay_info_controller_export_excel(road_flow_delay_infos, road_flow_turn_rate):