WbwLookupController.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Models\UserDict;
  4. use App\Models\DictInfo;
  5. use App\Models\WbwTemplate;
  6. use App\Models\Channel;
  7. use App\Models\WbwAnalysis;
  8. use Illuminate\Http\Request;
  9. use App\Tools\CaseMan;
  10. use Illuminate\Support\Facades\Log;
  11. use Illuminate\Support\Facades\Cache;
  12. use App\Http\Api\DictApi;
  13. class WbwLookupController extends Controller
  14. {
  15. private $dictList = [
  16. '85dcc61c-c9e1-4ae0-9b44-cd6d9d9f0d01',//社区汇总
  17. '4d3a0d92-0adc-4052-80f5-512a2603d0e8',// system irregular
  18. '8359757e-9575-455b-a772-cc6f036caea0',// system sandhi
  19. '61f23efb-b526-4a8e-999e-076965034e60',// pali myanmar grammar
  20. 'eae9fd6f-7bac-4940-b80d-ad6cd6f433bf',// Concise P-E Dict
  21. '2f93d0fe-3d68-46ee-a80b-11fa445a29c6',// unity
  22. 'beb45062-7c20-4047-bcd4-1f636ba443d1',// U Hau Sein
  23. '8833de18-0978-434c-b281-a2e7387f69be',// 巴汉增订
  24. '3acf0c0f-59a7-4d25-a3d9-bf394a266ebd',// 汉译パーリ语辞典-黃秉榮
  25. ];
  26. /**
  27. * Create a new command instance.
  28. *
  29. * @return void
  30. */
  31. private function initSysDict()
  32. {
  33. // system regular
  34. $this->dictList[] = DictApi::getSysDict('system_regular');
  35. $this->dictList[] = DictApi::getSysDict('robot_compound');
  36. $this->dictList[] = DictApi::getSysDict('community');
  37. $this->dictList[] = DictApi::getSysDict('community_extract');
  38. }
  39. /**
  40. * Display a listing of the resource.
  41. * @param \Illuminate\Http\Request $request
  42. *
  43. * @return \Illuminate\Http\Response
  44. */
  45. public function index(Request $request)
  46. {
  47. //
  48. $startAt = microtime(true)*1000;
  49. $this->initSysDict();
  50. $words = \explode(',',$request->get("word"));
  51. $bases = \explode(',',$request->get("base"));
  52. # 查询深度
  53. $deep = $request->get("deep",2);
  54. $result = $this->lookup($words,$bases,$deep);
  55. $endAt = microtime(true)*1000;
  56. return $this->ok(["rows"=>$result,
  57. "count"=>count($result),
  58. "time"=>(int)($endAt-$startAt)]);
  59. }
  60. public function lookup($words,$bases,$deep){
  61. $wordPool = array();
  62. $output = array();
  63. foreach ($words as $word) {
  64. $wordPool[$word] = ['base' => false,'done' => false,'apply' => false];
  65. }
  66. foreach ($bases as $base) {
  67. $wordPool[$base] = ['base' => true,'done' => false,'apply' => false];
  68. }
  69. /**
  70. * 先查询字典名称
  71. */
  72. $dict_info = DictInfo::whereIn('id',$this->dictList)->select('id','shortname')->get();
  73. $dict_name = [];
  74. foreach ($dict_info as $key => $value) {
  75. # code...
  76. $dict_name[$value->id] = $value->shortname;
  77. }
  78. $caseman = new CaseMan();
  79. for ($i=0; $i < $deep; $i++) {
  80. $newBase = array();
  81. $newWords = [];
  82. foreach ($wordPool as $word => $info) {
  83. # code...
  84. if($info['done'] === false){
  85. $newWords[] = $word;
  86. $wordPool[$word]['done'] = true;
  87. }
  88. }
  89. $data = UserDict::whereIn('word',$newWords)
  90. ->whereIn('dict_id',$this->dictList)
  91. ->leftJoin('dict_infos', 'user_dicts.dict_id', '=', 'dict_infos.id')
  92. ->orderBy('confidence','desc')
  93. ->get();
  94. foreach ($data as $row) {
  95. # code...
  96. array_push($output,$row);
  97. if(!empty($row->parent) && !isset($wordPool[$row->parent]) ){
  98. //将parent 插入待查询列表
  99. $wordPool[$row->parent] = ['base' => true,'done' => false,'apply' => false];
  100. }
  101. }
  102. //处理查询结果中的拆分信息
  103. $newWordPart = array();
  104. foreach ($wordPool as $word => $info) {
  105. if(!empty($info['factors'])){
  106. $factors = \explode('+',$info['factors']);
  107. foreach ($factors as $factor) {
  108. # 将没有的拆分放入单词查询列表
  109. if(!isset($wordPool[$factor])){
  110. $wordPool[$factor] = ['base' => true,'done' => false,'apply' => false];
  111. }
  112. }
  113. }
  114. }
  115. }
  116. return $output;
  117. }
  118. /**
  119. * 自动查词
  120. *
  121. * @param \Illuminate\Http\Request $request
  122. * @return \Illuminate\Http\Response
  123. */
  124. public function store(Request $request)
  125. {
  126. //
  127. $startAt = microtime(true)*1000;
  128. // system regular
  129. $this->initSysDict();
  130. $channel = Channel::find($request->get('channel_id'));
  131. $orgData = $request->get('data');
  132. //句子中的单词
  133. $words = [];
  134. foreach ($orgData as $word) {
  135. # code...
  136. if($word['type']['value'] !== '.ctl.' && !empty($word['real']['value'])){
  137. $words[] = $word['real']['value'];
  138. }
  139. }
  140. $result = $this->lookup($words,[],2);
  141. $indexed = $this->toIndexed($result);
  142. foreach ($orgData as $key => $word) {
  143. if($word['type']['value'] !== '.ctl.' && !empty($word['real']['value'])){
  144. $data = $word;
  145. if(isset($indexed[$word['real']['value']])){
  146. //parent
  147. $case = [];
  148. $parent = [];
  149. $factors = [];
  150. $factorMeaning = [];
  151. $meaning = [];
  152. $parent2 = [];
  153. $case2 = [];
  154. foreach ($indexed[$word['real']['value']] as $value) {
  155. //非base优先
  156. if(strstr($value->type,'base') === FALSE){
  157. $increment = 10;
  158. }else{
  159. $increment = 1;
  160. }
  161. //将全部结果加上得分放入数组
  162. $parent = $this->insertValue([$value->parent],$parent,$increment);
  163. if(!empty($value->type) && $value->type !== ".cp."){
  164. $case = $this->insertValue([$value->type."#".$value->grammar],$case,$increment);
  165. }
  166. $factors = $this->insertValue([$value->factors],$factors,$increment);
  167. $factorMeaning = $this->insertValue([$value->factormean],$factorMeaning,$increment);
  168. $meaning = $this->insertValue(explode('$',$value->mean),$meaning,$increment,false);
  169. }
  170. if(count($case)>0){
  171. arsort($case);
  172. $first = array_keys($case)[0];
  173. $data['case'] = ['value'=>$first==="_null"?"":$first,'status'=>3];
  174. }
  175. if(count($parent)>0){
  176. arsort($parent);
  177. $first = array_keys($parent)[0];
  178. $data['parent'] = ['value'=>$first==="_null"?"":$first,'status'=>3];
  179. }
  180. if(count($factors)>0){
  181. arsort($factors);
  182. $first = array_keys($factors)[0];
  183. $data['factors'] = ['value'=>$first==="_null"?"":$first,'status'=>3];
  184. }
  185. //拆分意思
  186. if(count($factorMeaning)>0){
  187. arsort($factorMeaning);
  188. $first = array_keys($factorMeaning)[0];
  189. $data['factorMeaning'] = ['value'=>$first==="_null"?"":$first,'status'=>3];
  190. }
  191. $wbwFactorMeaning = [];
  192. if(!empty($data['factors']['value'])){
  193. foreach (explode("+",$data['factors']['value']) as $factor) {
  194. # code...
  195. $wbwAnalyses = WbwAnalysis::where('wbw_word',$factor)
  196. ->where('type',7)
  197. ->selectRaw('data,count(*)')
  198. ->groupBy("data")
  199. ->orderBy("count", "desc")
  200. ->first();
  201. if($wbwAnalyses){
  202. $wbwFactorMeaning[]=$wbwAnalyses->data;
  203. }else{
  204. $wbwFactorMeaning[]="";
  205. }
  206. }
  207. }
  208. $data['factorMeaning'] = ['value'=>implode('+',$wbwFactorMeaning),'status'=>3];
  209. if(!empty($data['parent'])){
  210. if(isset($indexed[$data['parent']['value']])){
  211. foreach ($indexed[$data['parent']['value']] as $value) {
  212. //根据base 查找词意
  213. //非base优先
  214. $increment = 10;
  215. $meaning = $this->insertValue(explode('$',$value->mean),$meaning,$increment,false);
  216. //查找词源
  217. if(!empty($value->parent) && $value->parent !== $value->word && strstr($value->type,"base") !== FALSE ){
  218. $parent2 = $this->insertValue([$value->grammar."$".$value->parent],$parent2,1,false);
  219. }
  220. }
  221. }
  222. }
  223. if(count($meaning)>0){
  224. arsort($meaning);
  225. $first = array_keys($meaning)[0];
  226. $data['meaning'] = ['value'=>$first==="_null"?"":$first,'status'=>3];
  227. }
  228. if(count($parent2)>0){
  229. arsort($parent2);
  230. $first = explode("$",array_keys($parent2)[0]);
  231. $data['parent2'] = ['value'=>$first[1],'status'=>3];
  232. $data['grammar2'] = ['value'=>$first[0],'status'=>3];
  233. }
  234. }
  235. $orgData[$key] = $data;
  236. }
  237. }
  238. return $this->ok($orgData);
  239. }
  240. /**
  241. * 自动查词
  242. *
  243. * @param string $sentId
  244. * @return \Illuminate\Http\Response
  245. */
  246. public function show(Request $request,string $sentId)
  247. {
  248. $startAt = microtime(true)*1000;
  249. $channel = Channel::find($request->get('channel_id'));
  250. //查询句子中的单词
  251. $sent = \explode('-',$sentId);
  252. $wbw = WbwTemplate::where('book',$sent[0])
  253. ->where('paragraph',$sent[1])
  254. ->whereBetween('wid',[$sent[2],$sent[3]])
  255. ->orderBy('wid')
  256. ->get();
  257. $words = [];
  258. foreach ($wbw as $row) {
  259. if($row->type !== '.ctl.' && !empty($row->real)){
  260. $words[] = $row->real;
  261. }
  262. }
  263. $result = $this->lookup($words,[],2);
  264. $indexed = $this->toIndexed($result);
  265. //生成自动填充结果
  266. $wbwContent = [];
  267. foreach ($wbw as $row) {
  268. $type = $row->type=='?'? '':$row->type;
  269. $grammar = $row->gramma=='?'? '':$row->gramma;
  270. $part = $row->part=='?'? '':$row->part;
  271. if(!empty($type) || !empty($grammar)){
  272. $case = "{$type}#$grammar";
  273. }else{
  274. $case = "";
  275. }
  276. $data = [
  277. 'sn'=>[$row->wid],
  278. 'word'=>['value'=>$row->word,'status'=>3],
  279. 'real'=> ['value'=>$row->real,'status'=>3],
  280. 'meaning'=> ['value'=>[],'status'=>3],
  281. 'type'=> ['value'=>$type,'status'=>3],
  282. 'grammar'=> ['value'=>$grammar,'status'=>3],
  283. 'case'=> ['value'=>$case,'status'=>3],
  284. 'style'=> ['value'=>$row->style,'status'=>3],
  285. 'factors'=> ['value'=>$part,'status'=>3],
  286. 'factorMeaning'=> ['value'=>'','status'=>3],
  287. 'confidence'=> 0.5
  288. ];
  289. if($row->type !== '.ctl.' && !empty($row->real)){
  290. if(isset($indexed[$row->real])){
  291. //parent
  292. $case = [];
  293. $parent = [];
  294. $factors = [];
  295. $factorMeaning = [];
  296. $meaning = [];
  297. $parent2 = [];
  298. $case2 = [];
  299. foreach ($indexed[$row->real] as $value) {
  300. //非base优先
  301. if(strstr($value->type,'base') === FALSE){
  302. $increment = 10;
  303. }else{
  304. $increment = 1;
  305. }
  306. //将全部结果加上得分放入数组
  307. $parent = $this->insertValue([$value->parent],$parent,$increment);
  308. $case = $this->insertValue([$value->type."#".$value->grammar],$case,$increment);
  309. $factors = $this->insertValue([$value->factors],$factors,$increment);
  310. $factorMeaning = $this->insertValue([$value->factormean],$factorMeaning,$increment);
  311. $meaning = $this->insertValue(explode('$',$value->mean),$meaning,$increment,false);
  312. }
  313. if(count($case)>0){
  314. arsort($case);
  315. $first = array_keys($case)[0];
  316. $data['case'] = ['value'=>$first==="_null"?"":$first,'status'=>3];
  317. }
  318. if(count($parent)>0){
  319. arsort($parent);
  320. $first = array_keys($parent)[0];
  321. $data['parent'] = ['value'=>$first==="_null"?"":$first,'status'=>3];
  322. }
  323. if(count($factors)>0){
  324. arsort($factors);
  325. $first = array_keys($factors)[0];
  326. $data['factors'] = ['value'=>$first==="_null"?"":$first,'status'=>3];
  327. }
  328. if(count($factorMeaning)>0){
  329. arsort($factorMeaning);
  330. $first = array_keys($factorMeaning)[0];
  331. $data['factorMeaning'] = ['value'=>$first==="_null"?"":$first,'status'=>3];
  332. }
  333. //根据base 查找词意
  334. if(!empty($data['parent'])){
  335. if(isset($indexed[$data['parent']['value']])){
  336. Log::info($data['parent']['value']."=".count($indexed[$data['parent']['value']]));
  337. foreach ($indexed[$data['parent']['value']] as $value) {
  338. //非base优先
  339. $increment = 10;
  340. $meaning = $this->insertValue(explode('$',$value->mean),$meaning,$increment,false);
  341. }
  342. }else{
  343. Log::error("no set parent".$data['parent']['value']);
  344. }
  345. }
  346. if(count($meaning)>0){
  347. arsort($meaning);
  348. Log::info('meanings=');
  349. Log::info(array_keys($meaning));
  350. $first = array_keys($meaning)[0];
  351. $data['meaning'] = ['value'=>$first==="_null"?"":$first,'status'=>3];
  352. }
  353. }
  354. }
  355. $wbwContent[] = $data;
  356. }
  357. $endAt = microtime(true)*1000;
  358. return $this->ok(["rows"=>$wbwContent,
  359. "count"=>count($wbwContent),
  360. "time"=>(int)($endAt-$startAt)]);
  361. }
  362. private function toIndexed($words){
  363. //转成索引数组
  364. $indexed = [];
  365. foreach ($words as $key => $value) {
  366. # code...
  367. $indexed[$value->word][] = $value;
  368. }
  369. return $indexed;
  370. }
  371. private function insertValue($value,$container,$increment,$empty=true){
  372. foreach ($value as $one) {
  373. if($empty === false){
  374. if(empty($one)){
  375. break;
  376. }
  377. }
  378. $one=trim($one);
  379. $key = $one;
  380. if(empty($key)){
  381. $key = '_null';
  382. }
  383. if(isset($container[$key])){
  384. $container[$key] += $increment;
  385. }else{
  386. $container[$key] = $increment;
  387. }
  388. }
  389. return $container;
  390. }
  391. /**
  392. * Update the specified resource in storage.
  393. *
  394. * @param \Illuminate\Http\Request $request
  395. * @param \App\Models\UserDict $userDict
  396. * @return \Illuminate\Http\Response
  397. */
  398. public function update(Request $request, UserDict $userDict)
  399. {
  400. //
  401. }
  402. /**
  403. * Remove the specified resource from storage.
  404. *
  405. * @param \App\Models\UserDict $userDict
  406. * @return \Illuminate\Http\Response
  407. */
  408. public function destroy(UserDict $userDict)
  409. {
  410. //
  411. }
  412. }