You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

585 lines
24 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
namespace app\calculator\logic;
use app\calculator\model\CalculatorCategoryPlace;
use app\calculator\model\CalculatorDetail;
use app\calculator\model\CalculatorPlace;
use app\calculator\model\CalculatorPosition;
use app\calculator\model\CalculatorRefractory;
use excel\Excel;
class Calculator extends Base
{
/**
* 获取其他场景查询场所列表
* @param int $category_id 分类 1--疏散距离查询2--安全出口数量查询3--楼梯类型查询4--防火间距查询
* @date 2023-01-19
*/
public function listOtherPlace($category_id)
{
$category_place_model = new CalculatorCategoryPlace();
$where = [
['uid', '=', $this->mid],
['is_publish', '=', 1],
['category_id', '=', $category_id]
];
$field = 'id,name';
$place_list = $category_place_model->getAllData($where, $field, 'id asc');
return sendSuccessArray([
// 场所列表
'place_list' => $place_list
]);
}
/**
* 其他场景获取场所详情
* @param int $place_id 场所ID
* @date 2023-01-19
*/
public function getOtherPlace($place_id)
{
$category_place_model = new CalculatorCategoryPlace();
$where = [
['id', '=', $place_id]
];
$field = 'id,category_id,name,content';
$detail = $category_place_model->getOneData($where, $field);
$detail['category_name'] = $detail->categoryName;
return sendSuccessArray([
// 场所详情
'detail' => $detail
]);
}
/**
* 计算器获取场所列表
* @date 2023-01-19
*/
public function listPlace()
{
$place_model = new CalculatorPlace();
$where = [
['uid', '=', $this->mid]
];
$field = 'id,name';
$place_list = $place_model->getAllData($where, $field, 'id asc');
return sendSuccessArray([
// 场所列表
'place_list' => $place_list
]);
}
/**
* 计算器获取场所列表
* @param int $place_id 场所ID
* @date 2023-01-19
*/
public function listPositionByPlace($place_id)
{
$position_model = new CalculatorPosition();
$detail_model = new CalculatorDetail();
// 获取下级位置ID
$place_ids = $detail_model
->where([
['uid', '=', $this->mid],
['place_id', '=', $place_id]
])
->distinct(true)->column('position_id');
// 获取下级位置列表
if (empty($place_ids)) {
$position_list = [];
} else {
$where = [
['uid', '=', $this->mid],
['id', 'in', $place_ids]
];
$field = 'id,name';
$position_list = $position_model->getAllData($where, $field, 'sort asc');
}
return sendSuccessArray([
// 位置列表
'position_list' => $position_list
]);
}
/**
* 计算器获取场所和位置确定的详情页
* @param int $place_id 场所ID
* @param int $position_id 位置ID
* @date 2023-01-19
*/
public function getPosition($place_id, $position_id)
{
$place_model = new CalculatorPlace();
$position_model = new CalculatorPosition();
$refractory_model = new CalculatorRefractory();
$detail_model = new CalculatorDetail();
// 获取下级耐火等级ID
$refractory_ids = $detail_model
->where([
['uid', '=', $this->mid],
['place_id', '=', $place_id],
['position_id', '=', $position_id]
])
->distinct(true)
->column('refractory_id');
// 耐火等级ID只有1个且为0时耐火等级id为空数组
if (count($refractory_ids) == 1 && $refractory_ids[0] == 0) {
$refractory_ids = [];
}
// 当场所和位置确定不了是否有耐火等级时
if (count($refractory_ids) > 1 && in_array(0, $refractory_ids)) {
return sendErrorArray(3001, '项目逻辑有误,场所和位置确定不了是否有耐火等级');
}
// 获取下级耐火等级列表
if (empty($refractory_ids)) {
$refractory_list = [];
} else {
$where = [
['uid', '=', $this->mid],
['id', 'in', $refractory_ids]
];
$field = 'id,name';
$refractory_list = $refractory_model->getAllData($where, $field, 'id asc');
}
// 获取计算方式 1--输入人数 2--输入面积
$calculation_type_array = $detail_model
->where([
['uid', '=', $this->mid],
['place_id', '=', $place_id],
['position_id', '=', $position_id]
])
->distinct(true)
->column('calculation_type');
if (count($calculation_type_array) != 1) {
return sendErrorArray(3002, '项目逻辑有误,场所和位置确定不了计算方式');
}
// 获取场所名称
$place_name = $place_model->getOneData([
['id', '=', $place_id]
], 'name');
// 获取位置名称
$position_name = $position_model->getOneData([
['id', '=', $position_id]
], 'name');
return sendSuccessArray([
// 场所ID
'place_id' => $place_id,
// 场所名称
'place_name' => $place_name,
// 位置名称
'position_name' => $position_name,
// 是否有耐火等级
'is_have_refractory' => empty($refractory_list) ? 0 : 1,
// 耐火等级列表
'refractory_list' => $refractory_list,
// 计算方式
'calculation_type' => $calculation_type_array[0]
]);
}
/**
* 查询结果前判断输入值是否有效
* @param int $place_id 场所ID
* @param int $position_id 位置ID
* @param int $refractory_id 耐火等级ID
* @param int $input_value 输入的值
* @date 2023-01-19
*/
public function isInputAvailable($place_id, $position_id, $refractory_id, $input_value)
{
$detail_model = new CalculatorDetail();
$where = [
['uid', '=', $this->mid],
['place_id', '=', $place_id],
['position_id', '=', $position_id]
];
if (!empty($refractory_id)) {
$where[] = ['refractory_id', '=', $refractory_id];
}
$field = 'calculation_type,min_input_value,max_input_value';
$detail = $detail_model->getAllData($where, $field, 'id asc');
// 按人数计算
if ($detail[0]['calculation_type'] == 1) {
// 只有一条数据
if (count($detail) == 1) {
$data = $detail[0];
if (!empty($data['min_input_value']) && $input_value < $data['min_input_value']) {
$message = '疏散人数最小数值为' . $data['min_input_value'];
return sendErrorArray(3001, $message);
}
if (!empty($data['max_input_value']) && $input_value > $data['max_input_value']) {
$message = '疏散人数最大数值为' . $data['max_input_value'];
return sendErrorArray(3002, $message);
}
// 有多条数据
} else {
$data = $detail->toArray();
// 获取最小值
$min_array = array_column($data, 'min_input_value');
// 对数值数组进行升序排序
sort($min_array);
$min_value = $min_array[0];
// 获取最大值
$max_array = array_column($data, 'max_input_value');
// 对数值数组进行降序排序
rsort($max_array);
$max_value = $max_array[0];
if ($input_value < $min_value) {
$message = '疏散人数最小数值为' . $min_value;
return sendErrorArray(3003, $message);
}
if ($input_value > $max_value) {
$message = '疏散人数最大数值为' . $max_value;
return sendErrorArray(3004, $message);
}
}
} else {
if ($input_value <= 0) {
return sendErrorArray(3005, '建筑面积请输入大于0的数值');
}
}
return sendSuccessArray();
}
/**
* 查询结果前判断输入值是否有效
* @param int $place_id 场所ID
* @param int $position_id 位置ID
* @param int $refractory_id 耐火等级ID
* @param int $input_value 输入的值
* @date 2023-01-19
*/
public function getCalculatorResult($place_id, $position_id, $refractory_id, $input_value)
{
$detail_model = new CalculatorDetail();
$where = [
['uid', '=', $this->mid],
['place_id', '=', $place_id],
['position_id', '=', $position_id]
];
if (!empty($refractory_id)) {
$where[] = ['refractory_id', '=', $refractory_id];
}
$field = 'place_id,position_id,refractory_id,calculation_type,min_evacuate_net_width,min_width,coefficient,personnel_density,min_area_limit,min_area_limit_personnel_density,max_area_limit,max_area_limit_personnel_density,min_input_value,max_input_value';
$detail_list = $detail_model->listDetail($where, $field);
// 只有一条数据
if (count($detail_list) == 1) {
$detail = $detail_list[0];
// 有多条数据
} else {
$detail_list = $detail_list->toArray();
foreach ($detail_list as $k => $v) {
if ($input_value >= $v['min_input_value'] && $input_value <= $v['max_input_value']) {
$detail = $v;
}
}
if (!isset($detail) || empty($detail)) {
return sendErrorArray(3001, '输入值有误');
}
}
$return_data = [
// 场所名称
'place_name' => $detail['place_name'],
// 备注
'remark' => $detail['remark'],
// 位置名称
'position_name' => $detail['position_name'],
// 耐火等级名称
'refractory_name' => empty($detail['refractory_name']) ? '' : $detail['refractory_name'],
// 计算方式
'calculation_type' => $detail['calculation_type'],
// 输入值
'input_value' => $input_value,
];
switch ($detail['calculation_type']) {
// 按人数计算
case 1:
// 有宽度最小值 输入参数示例值:13 2 '' 1000
if ($detail['min_width'] !== null) {
// 中间结果
$middle_value = round($input_value / 100 * $detail['min_evacuate_net_width'], 2);
// 最终结果
$finish_value = $middle_value > $detail['min_width'] ? $middle_value : $detail['min_width'];
// 计算结果的数值
$return_data['finish_value'] = $finish_value;
// 计算过程-公式
$return_data['formula'] = '取大值(疏散人数/100*百人最小疏散净宽度,宽度最小值)';
// 计算过程-其他参数值
$return_data['other_param'] = [
[
'param_name' => '百人最小疏散净宽度m',
'param_value' => $detail['min_evacuate_net_width']
],
[
'param_name' => '宽度最小值m',
'param_value' => $detail['min_width']
]
];
// 计算过程-公式替换
$return_data['formula_replace'] = 'MAX(' . $input_value . '/100*' . $detail['min_evacuate_net_width'] . ',' . $detail['min_width'] . ')';
// 计算过程-计算结果
$return_data['calculation_result'] = '宽度:' . $finish_value . 'm';
// 有系数 输入参数示例值:14 5 1 1000
} else if ($detail['coefficient'] !== null) {
// 最终结果
$finish_value = round($input_value * $detail['coefficient'] / 100 * $detail['min_evacuate_net_width'], 2);
// 计算结果的数值
$return_data['finish_value'] = $finish_value;
// 计算过程-公式
$return_data['formula'] = '疏散人数*系数/100*百人最小疏散净宽度';
// 计算过程-其他参数值
$return_data['other_param'] = [
[
'param_name' => '系数',
'param_value' => $detail['coefficient']
],
[
'param_name' => '百人最小疏散净宽度m',
'param_value' => $detail['min_evacuate_net_width']
]
];
// 计算过程-公式替换
$return_data['formula_replace'] = $input_value . '*' . $detail['coefficient'] . '/100*' . $detail['min_evacuate_net_width'];
// 计算过程-计算结果
$return_data['calculation_result'] = '宽度:' . $finish_value . 'm';
// 其他正常 输入参数示例值:1 2 1 1000
} else {
// 最终结果
$finish_value = round($input_value / 100 * $detail['min_evacuate_net_width'], 2);
// 计算结果的数值
$return_data['finish_value'] = $finish_value;
// 计算过程-公式
$return_data['formula'] = '疏散人数/100*百人最小疏散净宽度';
// 计算过程-其他参数值
$return_data['other_param'] = [
[
'param_name' => '百人最小疏散净宽度m',
'param_value' => $detail['min_evacuate_net_width']
]
];
// 计算过程-公式替换
$return_data['formula_replace'] = $input_value . '/100*' . $detail['min_evacuate_net_width'];
// 计算过程-计算结果
$return_data['calculation_result'] = '宽度:' . $finish_value . 'm';
}
break;
// 按面积计算
case 2:
// 有人员密度 输入参数示例值:16 5 1 1000
if (!empty($detail['personnel_density'])) {
// 人数
$people_number = round($input_value * $detail['personnel_density']);
// 最终结果
$finish_value = round($people_number / 100 * $detail['min_evacuate_net_width'], 2);
// 计算结果的数值
$return_data['finish_value'] = $finish_value;
// 计算过程-公式
$return_data['formula'] = '1.人数=输入面积*人员密度1' . "\n" . '2.宽度=人数/100*百人最小疏散净宽度';
// 计算过程-其他参数值
$return_data['other_param'] = [
[
'param_name' => '人员密度(人/m²',
'param_value' => $detail['personnel_density']
],
[
'param_name' => '百人最小疏散净宽度m',
'param_value' => $detail['min_evacuate_net_width']
]
];
// 计算过程-公式替换
$return_data['formula_replace'] = '人数=' . $input_value . '*' . $detail['personnel_density'] . "\n" . '宽度=' . $people_number . '/100*' . $detail['min_evacuate_net_width'];
// 计算过程-计算结果
$return_data['calculation_result'] = '人数:' . $people_number . "\n" . '宽度:' . $finish_value;
// 插直法 输入参数示例值:24 6 1 1000
} else {
if ($input_value <= $detail['min_area_limit']) {
$people_number = round($input_value * $detail['min_area_limit_personnel_density']);
// 计算过程-公式
$return_data['formula'] = '1.人数=输入面积*人员密度1' . "\n" . '2.宽度=人数/100*百人最小疏散净宽度';
// 计算过程-公式替换
$return_data['formula_replace'] = '人数=' .
$input_value . '*' . $detail['min_area_limit_personnel_density']
. "\n" . '宽度=' . $people_number . '/100*' . $detail['min_evacuate_net_width'];
} else if ($input_value >= $detail['max_area_limit']) {
// 计算过程-公式
$return_data['formula'] = '1.人数=输入面积*人员密度2' . "\n" . '2.宽度=人数/100*百人最小疏散净宽度';
$people_number = round($input_value * $detail['max_area_limit_personnel_density']);
// 计算过程-公式替换
$return_data['formula_replace'] = '人数=' .
$input_value . '*' . $detail['max_area_limit_personnel_density']
. "\n" . '宽度=' . $people_number . '/100*' . $detail['min_evacuate_net_width'];
} else {
$people_number = round($input_value * (
$detail['min_area_limit_personnel_density']
- ($input_value - $detail['min_area_limit'])
* ($detail['min_area_limit_personnel_density'] - $detail['max_area_limit_personnel_density'])
/ ($detail['max_area_limit'] - $detail['min_area_limit'])
));
// 计算过程-公式
$return_data['formula'] = '1.人数=输入面积*(人员密度1-(输入面积-面积限制1)* (人员密度1-人员密度2)/(面积限制2-面积限制1)) ' . "\n" . '2.宽度=人数/100*百人最小疏散净宽度';
// 计算过程-公式替换
$return_data['formula_replace'] = '人数=' .
$input_value . '*(' .
$detail['min_area_limit_personnel_density']
. '-(' . $input_value . '-' . $detail['min_area_limit'] . ')*(' .
$detail['min_area_limit_personnel_density'] . '- ' . $detail['max_area_limit_personnel_density'] . ')/(' .
$detail['max_area_limit'] . '-' . $detail['min_area_limit'] . '))'
. "\n" . '宽度=' . $people_number . '/100*' . $detail['min_evacuate_net_width'];
}
// 最终结果
$finish_value = round($people_number / 100 * $detail['min_evacuate_net_width'], 2);
// 计算结果的数值
$return_data['finish_value'] = $finish_value;
// 计算过程-其他参数值
$return_data['other_param'] = [
[
'param_name' => '面积限制1',
'param_value' => $detail['min_area_limit'] . '以下'
],
[
'param_name' => '人员密度1人/m²',
'param_value' => $detail['min_area_limit_personnel_density']
],
[
'param_name' => '面积限制2',
'param_value' => $detail['max_area_limit'] . '以上'
],
[
'param_name' => '人员密度2人/m²',
'param_value' => $detail['max_area_limit_personnel_density']
],
[
'param_name' => '百人最小疏散净宽度m',
'param_value' => $detail['min_evacuate_net_width']
]
];
// 计算过程-计算结果
$return_data['calculation_result'] = '人数:' . $people_number . "\n" . '宽度:' . $finish_value;
}
break;
// 其他
default:
break;
}
return sendSuccessArray($return_data);
}
/**
* 导入到数据库
* @date 2023-01-19
*/
public function importExcel()
{
$excel_class = new Excel();
$place_model = new CalculatorPlace();
$position_model = new CalculatorPosition();
$refractory_model = new CalculatorRefractory();
$detail_model = new CalculatorDetail();
// 场所名称以及对应ID
$place_array = $place_model->column('id', 'name');
// 位置名称以及对应ID
$position_array = $position_model->column('id', 'name');
// 耐火等级名称以及对应ID
$refractory_array = $refractory_model->column('id', 'name');
$file_path = './1.xlsx';
$result = $excel_class->getDataFromLocalFile($file_path);
$finish_data_list = [];
foreach ($result as $k => $v) {
// 位置
$position_name = $v['B'];
$data['position_id'] = $position_array[$position_name];
// 耐火等级
$refractory_name = $v['C'];
if (!empty($refractory_name)) {
$data['refractory_id'] = $refractory_array[$refractory_name];
} else {
$data['refractory_id'] = '';
}
// 最小疏散净宽度m/100人
$data['min_evacuate_net_width'] = $v['D'];
// 宽度最小值 calculation_type=1时用
$data['min_width'] = $v['E'];
// 系数 calculation_type=1时用
$data['coefficient'] = $v['F'];
// 人员密度
$data['personnel_density'] = $v['G'];
// 面积限制最小值 面积限制1
$data['min_area_limit'] = $v['H'];
// 最小面积限制时人员密度 人员密度1
$data['min_area_limit_personnel_density'] = $v['I'];
// 面积限制最大值 面积限制2
$data['max_area_limit'] = $v['J'];
// 最大面积限制时人员密度 人员密度2
$data['max_area_limit_personnel_density'] = $v['K'];
// 输入值的最小值
$data['min_input_value'] = $v['M'];
// 输入值的最大值
$data['max_input_value'] = $v['N'];
// 计算公式类型 1输入人数计算 2输入面积计算
$data['calculation_type'] = $v['O'];
// 场所用,分割开
$cur_line_palce_array = explode('', $v['A']);
foreach ($cur_line_palce_array as $k => $v) {
$finish_data_list[] = array_merge([
'place_id' => $place_array[$v]
], $data);
}
}
// dump($finish_data_list[0]);
// $detail_model->insertAll($finish_data_list);
return 'success';
}
}