FeatureService.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <?php
  2. namespace App\Services;
  3. use App\Feature;
  4. Class FeatureService
  5. {
  6. public function getMapArray()
  7. {
  8. $features = Feature::query()->get();
  9. $map = [];
  10. foreach ($features as $feature){
  11. $map[$feature->id] = ["type"=>$feature->type,"logic"=>$feature->logic,"describe"=>$feature->describe];
  12. }
  13. return $map;
  14. }
  15. public function translationFeature($str)
  16. {
  17. if (!$str)return null;
  18. $result = [];
  19. preg_match_all('/\d+|[\&\|\(\)]/',$str,$result); //初次匹配以数字&|()为分隔符生成数组
  20. $sign = 0; //为第二次切割做起点标记
  21. $model = [];//第二次切割数组
  22. $ids = [];//记录出现的特征ID,统一查询
  23. foreach ($result[0] as $index => &$str){
  24. if (is_numeric($str)){
  25. $model[] = array_slice($result[0],$sign,($index-$sign)+1);
  26. $sign = $index+1;
  27. $ids[] = $str;
  28. continue;
  29. }
  30. if ($index == count($result[0])-1 && $str == ')'){
  31. $model[] = [")"];
  32. }
  33. }//以数字为标准切割策略组
  34. $features = Feature::query()->find($ids);//查询出现的特征
  35. $featureMap = [];
  36. foreach ($features as $index => $feature){
  37. $featureMap[$feature->id] = $index;
  38. }//为查询的特征重组为key-val形式数组留做引用
  39. foreach ($model as $index => &$m){
  40. $arr = [
  41. "strategyGroupStartSign" => false,//是否为策略组起点,这将在解析时解析为 (
  42. "calculation" => "",//运算规则,目前仅有 &,| 翻译后填入
  43. "type"=>"", //特征类型
  44. "id"=>"", //特征ID
  45. "logic"=>"", //特征逻辑
  46. "describe"=>"", //特征信息
  47. "strategyGroupEndSign" => false,//是否为策略组终点,这将在解析时解析为 )
  48. ];//最终对象组模型,策略组将几组特征组合引用
  49. foreach ($m as $str){
  50. if (is_numeric($str)){//填入特征信息
  51. if (isset($featureMap[$str])){
  52. $arr["type"] = $features[$featureMap[$str]]->type;
  53. $arr["id"] = $features[$featureMap[$str]]->id;
  54. $arr["logic"] = $features[$featureMap[$str]]->logic;
  55. $arr["describe"] = $features[$featureMap[$str]]->describe;
  56. }
  57. continue;
  58. }
  59. switch ($str){//特殊字符的翻译
  60. case "(":
  61. $arr["strategyGroupStartSign"] = true;
  62. break;
  63. case ")":
  64. $model[$index-1]["strategyGroupEndSign"] = true;
  65. break;
  66. case "&":
  67. $arr["calculation"] = "并且";
  68. break;
  69. case "|":
  70. $arr["calculation"] = "或";
  71. break;
  72. }
  73. }
  74. if (!$arr["id"]){
  75. unset($model[$index]);
  76. continue;
  77. }
  78. $m = $arr;//变更当前指针为翻译结果
  79. }
  80. return $model;
  81. }
  82. public function analysisFeature($features)
  83. {
  84. $str = "";
  85. $map = [];
  86. foreach ($features as &$feature){
  87. if (!$feature["type"] || !$feature["logic"] || !$feature["describe"])continue;
  88. $f = Feature::query()->firstOrCreate([
  89. "type"=>$feature["type"], //特征类型
  90. "logic"=>$feature["logic"], //特征逻辑
  91. "describe"=>$feature["describe"], //特征信息
  92. ]);
  93. $feature["id"] = $f->id;
  94. $map[$feature["id"]] = $f;
  95. if ($feature["calculation"] == '并且')$str .= '&';
  96. else $str .= '|';
  97. if ($feature["strategyGroupStartSign"])$str .= "(";
  98. $str .= $feature["id"];
  99. if ($feature["strategyGroupEndSign"])$str .= ")";
  100. }
  101. return ['feature'=>$str,"map"=>$map];
  102. }
  103. public function formatFeature(array $features, $value, $columnMapping = null)
  104. {
  105. if (!$features)return $value;
  106. preg_match_all('/\d+|[\&\|\(\)]/',$value,$result);
  107. foreach ($result[0] as &$str){
  108. if (is_numeric($str) && isset($features[$str])){
  109. $column = $features[$str]["type"];
  110. $logic = $features[$str]["logic"];
  111. $describe = $features[$str]["describe"];
  112. if ($columnMapping){
  113. $column = $columnMapping[$column] ?? $column;
  114. switch ($logic){
  115. case "包含":
  116. $logic = " like ";
  117. $describe = "%".$describe."%";
  118. break;
  119. case "不包含":
  120. $logic = " not like ";
  121. $describe = "%".$describe."%";
  122. break;
  123. case "等于":
  124. $logic = " = ";
  125. break;
  126. }
  127. $str = $column.$logic.$describe;
  128. }else $str = $features[$str]["type"].' '.$features[$str]["logic"].' '.$features[$str]["describe"];
  129. }
  130. if ($str == "&"){
  131. if ($columnMapping) $str = " and ";
  132. else $str = " 并且 ";
  133. }
  134. if ($str == "|"){
  135. if ($columnMapping) $str = " or ";
  136. else $str = " 或 ";
  137. }
  138. }
  139. return implode("",$result[0]);
  140. }
  141. public function matchFeature($value, $columnMapping, $matchObject) :bool
  142. {
  143. preg_match_all('/\d+/',$value,$ids);
  144. if ($ids[0])$fs = Feature::query()->whereIn("id",$ids[0])->get();
  145. else return false;
  146. $features = [];
  147. foreach ($fs as $f){
  148. $features[$f->id] = $f;
  149. }
  150. preg_match_all('/\d+|[\&\|\(\)]/',$value,$result);
  151. foreach ($result[0] as &$str) {
  152. if (is_numeric($str) && isset($features[$str])) {
  153. $column = $features[$str]["type"];
  154. $logic = $features[$str]["logic"];
  155. $describe = $features[$str]["describe"];
  156. $value = isset($columnMapping[$column]) ? $matchObject[$columnMapping[$column]] : '';
  157. switch ($logic) {
  158. case "包含":
  159. $str = mb_strpos($value,$describe) === false ? 'false' : 'true';
  160. break;
  161. case "不包含":
  162. $str = mb_strpos($value,$describe) === false ? 'true' : 'false';
  163. break;
  164. case "等于":
  165. $str = $value == $describe ? 'true' : 'false';
  166. break;
  167. }
  168. continue;
  169. }
  170. if ($str == "&") {
  171. $str = '&&';
  172. continue;
  173. }
  174. if ($str == "|") {
  175. $str = '||';
  176. }
  177. }
  178. $is = implode("",$result[0]);
  179. return eval("return $is;");
  180. }
  181. }