448 lines
17 KiB
Python
448 lines
17 KiB
Python
import ast
|
||||
|
|
from datetime import datetime, timedelta, timezone
|
|||
|
|
import pandas as pd # 确保导入pandas用于类型检查
|
|||
|
|
|
|||
|
|
def process_incident_data(test_val):
|
|||
|
|
"""
|
|||
|
|
处理事故数据,去重、排序并提取指定字段。
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
test_val (dict): 包含 'status' 和 'data' 键的原始数据字典。
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
dict: 格式化后的数据,包含 'events' 键。
|
|||
|
|
"""
|
|||
|
|
unique_data_dict = {}
|
|||
|
|
for item in test_val:
|
|||
|
|
name = item.get("incident_name")
|
|||
|
|
if name and name not in unique_data_dict:
|
|||
|
|
unique_data_dict[name] = item
|
|||
|
|
|
|||
|
|
# 获取去重后的数据列表
|
|||
|
|
unique_data_list = list(unique_data_dict.values())
|
|||
|
|
|
|||
|
|
# 2. 根据 incident_time 升序排序
|
|||
|
|
# incident_time 是 GMT 格式字符串,可以直接排序
|
|||
|
|
sorted_data = sorted(unique_data_list, key=lambda x: x.get("incident_time", ""))
|
|||
|
|
|
|||
|
|
# 3. 提取指定字段并格式化时间
|
|||
|
|
id = 0
|
|||
|
|
processed_events_data = []
|
|||
|
|
for item in sorted_data:
|
|||
|
|
incident_time_str = item.get("incident_time")
|
|||
|
|
if not incident_time_str:
|
|||
|
|
# 如果 incident_time 为空或不存在,可以选择跳过或使用默认值
|
|||
|
|
# 这里我们跳过
|
|||
|
|
print(
|
|||
|
|
f"Warning: Missing 'incident_time' for item: {item.get('incident_name')}, skipping."
|
|||
|
|
)
|
|||
|
|
continue
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
# 🔥 仅修改这里:解析 GMT 格式时间 "Wed, 10 Apr 2024 16:00:00 GMT"
|
|||
|
|
if isinstance(incident_time_str, datetime):
|
|||
|
|
incident_datetime = incident_time_str
|
|||
|
|
else:
|
|||
|
|
# 解析 GMT 格式字符串 "Wed, 10 Apr 2024 16:00:00 GMT"
|
|||
|
|
incident_datetime = datetime.strptime(incident_time_str, "%a, %d %b %Y %H:%M:%S %Z")
|
|||
|
|
except ValueError as e:
|
|||
|
|
# 如果时间格式不正确,可以选择跳过或使用默认值
|
|||
|
|
# 这里我们跳过
|
|||
|
|
print(
|
|||
|
|
f"Warning: Invalid 'incident_time' format for item: {item.get('incident_name')}, value: {incident_time_str}, error: {e}. Skipping."
|
|||
|
|
)
|
|||
|
|
continue
|
|||
|
|
|
|||
|
|
# 格式化日期和时间(逻辑不变)
|
|||
|
|
date_str = incident_datetime.strftime("%Y-%m-%d")
|
|||
|
|
time_str = incident_datetime.strftime("%H:%M:%S")
|
|||
|
|
|
|||
|
|
# 创建新的字典,只包含需要的字段
|
|||
|
|
id += 1
|
|||
|
|
processed_item = {
|
|||
|
|
"id": id,
|
|||
|
|
"oneid": item.get("oneid", ""),
|
|||
|
|
"date": date_str,
|
|||
|
|
"time": time_str,
|
|||
|
|
"incident_name": item.get("incident_name", ""),
|
|||
|
|
"incident_description": item.get(
|
|||
|
|
"incident_description", ""
|
|||
|
|
),
|
|||
|
|
}
|
|||
|
|
processed_events_data.append(processed_item)
|
|||
|
|
|
|||
|
|
# 4. 构建最终返回的字典
|
|||
|
|
total_count = len(processed_events_data)
|
|||
|
|
result = {"data": processed_events_data, "total": total_count}
|
|||
|
|
|
|||
|
|
return result
|
|||
|
|
|
|||
|
|
|
|||
|
|
def process_incident_data1(test_val):
|
|||
|
|
"""
|
|||
|
|
处理事故数据,按照incident_time和incident_name去重,然后按incident_time排序。
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
test_val (list): 原始数据列表
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
dict: 格式化后的数据
|
|||
|
|
"""
|
|||
|
|
from datetime import datetime
|
|||
|
|
|
|||
|
|
# 1. 按照 incident_name 和 incident_time 组合去重
|
|||
|
|
unique_data_dict = {}
|
|||
|
|
for item in test_val:
|
|||
|
|
name = item.get("incident_name")
|
|||
|
|
time = item.get("incident_time")
|
|||
|
|
if name and time:
|
|||
|
|
# 使用组合键去重
|
|||
|
|
key = f"{name}_{time}"
|
|||
|
|
if key not in unique_data_dict:
|
|||
|
|
unique_data_dict[key] = item
|
|||
|
|
|
|||
|
|
# 获取去重后的数据列表
|
|||
|
|
unique_data_list = list(unique_data_dict.values())
|
|||
|
|
|
|||
|
|
# 2. 根据 incident_time 升序排序
|
|||
|
|
def parse_time(time_str):
|
|||
|
|
try:
|
|||
|
|
# 处理 "Sat, 08 Mar 2025 09:00:00 GMT" 格式
|
|||
|
|
return datetime.strptime(time_str, "%a, %d %b %Y %H:%M:%S %Z")
|
|||
|
|
except:
|
|||
|
|
# 处理 ISO 8601 格式作为备选
|
|||
|
|
try:
|
|||
|
|
return datetime.fromisoformat(time_str.replace("Z", "+00:00"))
|
|||
|
|
except:
|
|||
|
|
return datetime.min
|
|||
|
|
|
|||
|
|
sorted_data = sorted(unique_data_list, key=lambda x: parse_time(x.get("incident_time", "")))
|
|||
|
|
|
|||
|
|
# 3. 提取指定字段
|
|||
|
|
id = 0
|
|||
|
|
processed_events_data = []
|
|||
|
|
for item in sorted_data:
|
|||
|
|
incident_time_str = item.get("incident_time")
|
|||
|
|
if not incident_time_str:
|
|||
|
|
continue
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
incident_datetime = parse_time(incident_time_str)
|
|||
|
|
except:
|
|||
|
|
continue
|
|||
|
|
|
|||
|
|
# 格式化日期和时间
|
|||
|
|
date_str = incident_datetime.strftime("%Y-%m-%d")
|
|||
|
|
time_str = incident_datetime.strftime("%H:%M:%S")
|
|||
|
|
|
|||
|
|
# 创建新的字典
|
|||
|
|
id += 1
|
|||
|
|
processed_item = {
|
|||
|
|
"id": id,
|
|||
|
|
"oneid": item.get("oneid", ""),
|
|||
|
|
"date": date_str,
|
|||
|
|
"time": time_str,
|
|||
|
|
"incident_name": item.get("incident_name", ""),
|
|||
|
|
"incident_description": item.get("incident_description", ""),
|
|||
|
|
}
|
|||
|
|
processed_events_data.append(processed_item)
|
|||
|
|
|
|||
|
|
# 4. 构建最终返回的字典
|
|||
|
|
total_count = len(processed_events_data)
|
|||
|
|
result = {"data": processed_events_data, "total": total_count}
|
|||
|
|
|
|||
|
|
return result
|
|||
|
|
|
|||
|
|
def aggregate_and_sort_incidents(raw_data):
|
|||
|
|
"""
|
|||
|
|
按(idc_tickcount_ms + Incident__Name)聚合,整合同一组内的信号数据,消除视觉冗余
|
|||
|
|
1. 同一组只输出1条记录,包含公共信息+所有信号数据
|
|||
|
|
2. 按idc_tickcount_ms从小到大排序
|
|||
|
|
3. 保留所有关键数据(含mux_data解析)
|
|||
|
|
"""
|
|||
|
|
aggregate_dict = {}
|
|||
|
|
for item in raw_data:
|
|||
|
|
# 1. 处理聚合key:(idc_tickcount_ms整数, Incident__Name)
|
|||
|
|
try:
|
|||
|
|
tickcount_int = int(item.get("idc_tickcount_ms", "0"))
|
|||
|
|
except (ValueError, TypeError):
|
|||
|
|
tickcount_int = 0
|
|||
|
|
incident_name = item.get("incident_name", "unknown_incident")
|
|||
|
|
aggregate_key = (tickcount_int, incident_name)
|
|||
|
|
|
|||
|
|
# 2. 提取当前记录的关键数据(用于后续整合)
|
|||
|
|
# 处理数值:优先取int_value,无则取float_value,都无则为None
|
|||
|
|
# value = item.get("int_value") or item.get("float_value")
|
|||
|
|
int_value=item.get("int_value")
|
|||
|
|
float_value=item.get('float_value')
|
|||
|
|
if int_value is not None:
|
|||
|
|
value = int_value
|
|||
|
|
elif float_value is not None:
|
|||
|
|
value = float_value
|
|||
|
|
else:
|
|||
|
|
value = None
|
|||
|
|
|
|||
|
|
# 处理mux_data:若为JSON字符串,解析为字典(方便后续使用)
|
|||
|
|
mux_data = item.get("mux_data")
|
|||
|
|
if mux_data and mux_data != "null":
|
|||
|
|
try:
|
|||
|
|
mux_data = ast.literal_eval(mux_data)
|
|||
|
|
except (ValueError, SyntaxError):
|
|||
|
|
pass # 解析失败则保留原始字符串
|
|||
|
|
|
|||
|
|
# 3. 整合到聚合字典
|
|||
|
|
if aggregate_key not in aggregate_dict:
|
|||
|
|
# 首次遇到该key:初始化聚合结构(提取公共基础信息)
|
|||
|
|
aggregate_dict[aggregate_key] = {
|
|||
|
|
"base_info": { # 同一组的公共信息(只取第一条记录的)
|
|||
|
|
"oneid": item.get("oneid"),
|
|||
|
|
"ihd_version": item.get("ihd_version"),
|
|||
|
|
"incident_time": item.get("incident_time"),
|
|||
|
|
"speed": item.get("speed"),
|
|||
|
|
"gps_heading": item.get("gps_heading"),
|
|||
|
|
"incident_name": incident_name,
|
|||
|
|
"incident_description": item.get("incident_description"),
|
|||
|
|
"Trigger__condition": item.get("Trigger__condition"),
|
|||
|
|
"idc_tickcount_ms": item.get("idc_tickcount_ms"),
|
|||
|
|
"idc_tickcount_ms_int": tickcount_int,
|
|||
|
|
"gps_dr_position": item.get("gps_dr_position"),
|
|||
|
|
"incident_id": item.get("incident_id"),
|
|||
|
|
"longitude": item.get("longitude"),
|
|||
|
|
"latitude": item.get("latitude")
|
|||
|
|
},
|
|||
|
|
"signal_data": {} # 整合同一组的所有信号(key: 信号名,value: 信号数据)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# print('item.get("signal_name")',item.get('signal_name'))
|
|||
|
|
# 4. 将当前记录的信号数据添加到signal_data中
|
|||
|
|
# signal_key = item.get("key", "unknown_key")
|
|||
|
|
signal_key=item.get('signal_name')
|
|||
|
|
aggregate_dict[aggregate_key]["signal_data"][signal_key] = {
|
|||
|
|
"value": value,
|
|||
|
|
"mux_data": mux_data,
|
|||
|
|
"signal_ihd_id": item.get("signal_ihd_id"),
|
|||
|
|
"Decoding__value": item.get("Decoding__value"),
|
|||
|
|
"Meaning": item.get("meaning")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
sorted_data=sort_incidents_by_heading(list(aggregate_dict.values())) # 跨周期的
|
|||
|
|
|
|||
|
|
sorted_result = sorted(
|
|||
|
|
sorted_data,
|
|||
|
|
key=lambda x: x.get("idc_tickcount_ms_tmp", x["base_info"]["idc_tickcount_ms_int"])
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
return sorted_result
|
|||
|
|
|
|||
|
|
|
|||
|
|
def parse_coordinate(coord_str):
|
|||
|
|
"""
|
|||
|
|
解析坐标字符串为浮点数
|
|||
|
|
"""
|
|||
|
|
if coord_str is None:
|
|||
|
|
return None
|
|||
|
|
|
|||
|
|
if isinstance(coord_str, (int, float)):
|
|||
|
|
return float(coord_str)
|
|||
|
|
|
|||
|
|
if isinstance(coord_str, str):
|
|||
|
|
try:
|
|||
|
|
return float(coord_str)
|
|||
|
|
except ValueError:
|
|||
|
|
# 如果是 "[longitude, latitude]" 格式,提取第一个数字
|
|||
|
|
if coord_str.startswith('[') and coord_str.endswith(']'):
|
|||
|
|
try:
|
|||
|
|
coord_str_clean = coord_str.strip('[]')
|
|||
|
|
coords = coord_str_clean.split(',')
|
|||
|
|
if len(coords) >= 1:
|
|||
|
|
return float(coords[0].strip())
|
|||
|
|
except (ValueError, IndexError):
|
|||
|
|
pass
|
|||
|
|
return None
|
|||
|
|
|
|||
|
|
return None
|
|||
|
|
|
|||
|
|
|
|||
|
|
def sort_incidents_by_heading(raw_data):
|
|||
|
|
"""
|
|||
|
|
按__head方法的逻辑进行排序:根据GPS航向角排序并处理时间戳回绕
|
|||
|
|
"""
|
|||
|
|
import pandas as pd
|
|||
|
|
|
|||
|
|
# 将原始数据转换为DataFrame,并处理经纬度
|
|||
|
|
processed_data = []
|
|||
|
|
for item in raw_data:
|
|||
|
|
# 获取base_info
|
|||
|
|
base_info = item.get('base_info', {})
|
|||
|
|
|
|||
|
|
processed_item = item.copy() # 保持原始结构
|
|||
|
|
|
|||
|
|
# 解析经纬度和航向角,从base_info中获取
|
|||
|
|
longitude = parse_coordinate(base_info.get('longitude'))
|
|||
|
|
latitude = parse_coordinate(base_info.get('latitude'))
|
|||
|
|
gps_heading = parse_coordinate(base_info.get('gps_heading'))
|
|||
|
|
|
|||
|
|
# 添加到processed_item,用于排序
|
|||
|
|
processed_item['longitude'] = longitude if longitude is not None else 0.0
|
|||
|
|
processed_item['latitude'] = latitude if latitude is not None else 0.0
|
|||
|
|
processed_item['gps_heading'] = gps_heading if gps_heading is not None else 0.0
|
|||
|
|
processed_item['incident_time'] = base_info.get('incident_time', '')
|
|||
|
|
|
|||
|
|
# 确保时间戳是数值类型,从base_info中获取
|
|||
|
|
try:
|
|||
|
|
tickcount_ms = int(base_info.get('idc_tickcount_ms', 0))
|
|||
|
|
except (ValueError, TypeError):
|
|||
|
|
tickcount_ms = 0
|
|||
|
|
|
|||
|
|
processed_item['idc_tickcount_ms'] = tickcount_ms
|
|||
|
|
|
|||
|
|
processed_data.append(processed_item)
|
|||
|
|
|
|||
|
|
df = pd.DataFrame(processed_data)
|
|||
|
|
|
|||
|
|
# 确保所有相关列都是数值类型
|
|||
|
|
df['idc_tickcount_ms'] = pd.to_numeric(df['idc_tickcount_ms'], errors='coerce').fillna(0).astype(int)
|
|||
|
|
df['longitude'] = pd.to_numeric(df['longitude'], errors='coerce').fillna(0.0)
|
|||
|
|
df['latitude'] = pd.to_numeric(df['latitude'], errors='coerce').fillna(0.0)
|
|||
|
|
df['gps_heading'] = pd.to_numeric(df['gps_heading'], errors='coerce').fillna(0.0)
|
|||
|
|
|
|||
|
|
# 计算平均GPS航向角
|
|||
|
|
gps_heading = df["gps_heading"].mean()
|
|||
|
|
# print('gps_heading',gps_heading)
|
|||
|
|
|
|||
|
|
# 根据GPS航向角进行排序
|
|||
|
|
if (gps_heading >= 315):
|
|||
|
|
df.sort_values(by=['incident_time','latitude', 'longitude','idc_tickcount_ms'],
|
|||
|
|
ascending=[True, True, False, True], inplace=True)
|
|||
|
|
elif (gps_heading < 45):
|
|||
|
|
df.sort_values(by=['incident_time','latitude', 'longitude','idc_tickcount_ms'],
|
|||
|
|
ascending=[True, True, True, True], inplace=True)
|
|||
|
|
elif (gps_heading >= 45) and (gps_heading < 90):
|
|||
|
|
df.sort_values(by=['incident_time','longitude', 'latitude','idc_tickcount_ms'],
|
|||
|
|
ascending=[True, True, True, True], inplace=True)
|
|||
|
|
elif (gps_heading >= 90) and (gps_heading < 135):
|
|||
|
|
df.sort_values(by=['incident_time','longitude', 'latitude','idc_tickcount_ms'],
|
|||
|
|
ascending=[True, True, False, True], inplace=True)
|
|||
|
|
elif (gps_heading >= 135) and (gps_heading < 180):
|
|||
|
|
df.sort_values(by=['incident_time','latitude', 'longitude','idc_tickcount_ms'],
|
|||
|
|
ascending=[True, False, True, True], inplace=True)
|
|||
|
|
elif (gps_heading >= 180) and (gps_heading < 225):
|
|||
|
|
df.sort_values(by=['incident_time','latitude', 'longitude','idc_tickcount_ms'],
|
|||
|
|
ascending=[True, False, False, True], inplace=True)
|
|||
|
|
elif (gps_heading >= 225) and (gps_heading < 270):
|
|||
|
|
df.sort_values(by=['incident_time','longitude', 'latitude','idc_tickcount_ms'],
|
|||
|
|
ascending=[True, False, False, True], inplace=True)
|
|||
|
|
elif (gps_heading >= 270) and (gps_heading < 315):
|
|||
|
|
df.sort_values(by=['incident_time','longitude', 'latitude','idc_tickcount_ms'],
|
|||
|
|
ascending=[True, False, True, True], inplace=True)
|
|||
|
|
|
|||
|
|
# 处理时间戳回绕
|
|||
|
|
df['idc_tickcount_ms_tmp'] = df['idc_tickcount_ms'].copy()
|
|||
|
|
df.reset_index(inplace=True, drop=True)
|
|||
|
|
|
|||
|
|
# 确保数据类型一致
|
|||
|
|
df['idc_tickcount_ms'] = df['idc_tickcount_ms'].astype(int)
|
|||
|
|
|
|||
|
|
max_tickcount = df['idc_tickcount_ms'].max()
|
|||
|
|
loopcount = 65535 if max_tickcount < 65536 else 2097151
|
|||
|
|
period = 0
|
|||
|
|
|
|||
|
|
# 确保所有值都是整数
|
|||
|
|
df['idc_tickcount_ms'] = df['idc_tickcount_ms'].astype(int)
|
|||
|
|
|
|||
|
|
for i in range(1, len(df)):
|
|||
|
|
current_tick = int(df.loc[i, 'idc_tickcount_ms'])
|
|||
|
|
prev_tick = int(df.loc[i-1, 'idc_tickcount_ms'])
|
|||
|
|
if current_tick < prev_tick:
|
|||
|
|
period += 1
|
|||
|
|
df.loc[i, 'idc_tickcount_ms_tmp'] = current_tick + period * loopcount
|
|||
|
|
|
|||
|
|
# 按调整后的时间戳排序
|
|||
|
|
df.sort_values(by=["idc_tickcount_ms_tmp"], inplace=True)
|
|||
|
|
|
|||
|
|
# 转换回列表格式,移除临时添加的排序字段
|
|||
|
|
result = []
|
|||
|
|
for record in df.to_dict('records'):
|
|||
|
|
# 移除临时添加的排序字段
|
|||
|
|
cleaned_record = {k: v for k, v in record.items() if k not in ['longitude', 'latitude', 'gps_heading', 'incident_time']}
|
|||
|
|
result.append(cleaned_record)
|
|||
|
|
|
|||
|
|
# print(result)
|
|||
|
|
return result
|
|||
|
|
|
|||
|
|
|
|||
|
|
def aggregate_line_list(map_result):
|
|||
|
|
# 初始化聚合字典,key为idc_tickcount_ms_int,value为聚合后的数据
|
|||
|
|
aggregated_data = {}
|
|||
|
|
|
|||
|
|
# 遍历所有事件
|
|||
|
|
for item in map_result:
|
|||
|
|
base_info = item['base_info']
|
|||
|
|
# 提取需要的字段
|
|||
|
|
tickcount = item['idc_tickcount_ms_tmp']
|
|||
|
|
speed = base_info['speed']
|
|||
|
|
oneid = base_info['oneid']
|
|||
|
|
latitude = base_info['latitude']
|
|||
|
|
longitude = base_info['longitude']
|
|||
|
|
incident_name = base_info['incident_name']
|
|||
|
|
|
|||
|
|
# 聚合处理
|
|||
|
|
if tickcount not in aggregated_data:
|
|||
|
|
# 新的tickcount,初始化记录
|
|||
|
|
aggregated_data[tickcount] = {
|
|||
|
|
'idc_tickcount_ms_int': tickcount,
|
|||
|
|
'speed': speed,
|
|||
|
|
'oneid': oneid,
|
|||
|
|
'latitude': latitude,
|
|||
|
|
'longitude': longitude,
|
|||
|
|
'incident_names': [incident_name] # 用列表收集多个事件名称
|
|||
|
|
}
|
|||
|
|
else:
|
|||
|
|
# 已存在的tickcount,追加事件名称
|
|||
|
|
aggregated_data[tickcount]['incident_names'].append(incident_name)
|
|||
|
|
|
|||
|
|
# 转换为列表形式(按tickcount排序)
|
|||
|
|
result = sorted(aggregated_data.values(), key=lambda x: x['idc_tickcount_ms_int'])
|
|||
|
|
|
|||
|
|
return result
|
|||
|
|
|
|||
|
|
|
|||
|
|
def get_logging_list(map_list):
|
|||
|
|
result=[]
|
|||
|
|
id=0
|
|||
|
|
for item in map_list:
|
|||
|
|
# print(item)
|
|||
|
|
id+=1
|
|||
|
|
row_data={}
|
|||
|
|
row_data['id']=id
|
|||
|
|
base_info = item['base_info']
|
|||
|
|
# print("base_info['incident_time']",base_info['incident_time'])
|
|||
|
|
# dt = datetime.strptime(base_info['incident_time'], "%Y-%m-%d %H:%M:%S%z")
|
|||
|
|
dt = base_info['incident_time']
|
|||
|
|
if not isinstance(dt, datetime):
|
|||
|
|
# 只有是字符串时,才解析
|
|||
|
|
dt = datetime.strptime(dt, "%Y-%m-%d %H:%M:%S%z")
|
|||
|
|
|
|||
|
|
row_data['time']=dt.strftime("%H:%M:%S")
|
|||
|
|
|
|||
|
|
# row_data['coordinates']=base_info['longitude'][:12]+'.'+'\n'+base_info['latitude'][:12]
|
|||
|
|
row_data['coordinates'] = str(base_info['longitude'])[:12] + '\n' + str(base_info['latitude'])[:12]
|
|||
|
|
row_data['idc_tickcount_ms']=base_info['idc_tickcount_ms_int']
|
|||
|
|
row_data['speed']=base_info['speed']
|
|||
|
|
row_data['incident']={
|
|||
|
|
"name":base_info['incident_name'],
|
|||
|
|
"description":base_info['incident_description'],
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
row_data['signals']=[]
|
|||
|
|
for key,value in item["signal_data"].items():
|
|||
|
|
signals_name_value={}
|
|||
|
|
signals_name_value["name"]=key
|
|||
|
|
signals_name_value["value"]=value['value']
|
|||
|
|
signals_name_value["meaning"]=value['Meaning']
|
|||
|
|
row_data['signals'].append(signals_name_value)
|
|||
|
|
|
|||
|
|
result.append(row_data)
|
|||
|
|
|
|||
|
|
return result
|