dictList[] = DictApi::getSysDict('system_regular'); $this->dictList[] = DictApi::getSysDict('robot_compound'); $this->dictList[] = DictApi::getSysDict('community'); $this->dictList[] = DictApi::getSysDict('community_extract'); } /** * Display a listing of the resource. * @param \Illuminate\Http\Request $request * * @return \Illuminate\Http\Response */ public function index(Request $request) { // $startAt = microtime(true) * 1000; $this->initSysDict(); $words = \explode(',', $request->get("word")); $bases = \explode(',', $request->get("base")); # 查询深度 $deep = $request->get("deep", 2); $result = $this->lookup($words, $bases, $deep); $endAt = microtime(true) * 1000; return $this->ok([ "rows" => $result, "count" => count($result), "time" => (int)($endAt - $startAt) ]); } //查用户字典获取全部结果 public function lookup($words, $bases, $deep) { $wordPool = array(); $output = array(); foreach ($words as $word) { $wordPool[$word] = ['base' => false, 'done' => false, 'apply' => false]; } foreach ($bases as $base) { $wordPool[$base] = ['base' => true, 'done' => false, 'apply' => false]; } /** * 先查询字典名称 */ $dict_info = DictInfo::whereIn('id', $this->dictList)->select('id', 'shortname')->get(); $dict_name = []; foreach ($dict_info as $key => $value) { # code... $dict_name[$value->id] = $value->shortname; } $caseman = new CaseMan(); for ($i = 0; $i < $deep; $i++) { $newBase = array(); $newWords = []; foreach ($wordPool as $word => $info) { # code... if ($info['done'] === false) { $newWords[] = $word; $wordPool[$word]['done'] = true; } } $data = UserDict::whereIn('word', $newWords) ->whereIn('dict_id', $this->dictList) ->leftJoin('dict_infos', 'user_dicts.dict_id', '=', 'dict_infos.id') ->orderBy('confidence', 'desc') ->get(); foreach ($data as $row) { # code... array_push($output, $row); if (!empty($row->parent) && !isset($wordPool[$row->parent])) { //将parent 插入待查询列表 $wordPool[$row->parent] = ['base' => true, 'done' => false, 'apply' => false]; } } //处理查询结果中的拆分信息 $newWordPart = array(); foreach ($wordPool as $word => $info) { if (!empty($info['factors'])) { $factors = \explode('+', $info['factors']); foreach ($factors as $factor) { # 将没有的拆分放入单词查询列表 if (!isset($wordPool[$factor])) { $wordPool[$factor] = ['base' => true, 'done' => false, 'apply' => false]; } } } } } return $output; } /** * */ private function langCheck($query, $lang) { if ($query === []) { return true; } else { if (in_array(strtolower($lang), $query)) { return true; } else { $langFamily = explode('-', $lang)[0]; foreach ($query as $value) { if (strpos($value, $langFamily) !== false) { return true; } } } } return false; } private function wbwPreference($word, $field, $userId) { $prefix = 'wbw-preference'; $fieldMap = [ 'type' => 1, 'grammar' => 2, 'meaning' => 3, 'factors' => 4, 'factorMeaning' => 5, 'parent' => 6, 'part' => 7, 'case' => 8, ]; $fieldId = $fieldMap[$field]; $myPreference = Cache::get("{$prefix}/{$word}/{$fieldId}/{$userId}"); if (!empty($myPreference)) { Log::debug($word . '命中我的wbw-' . $field, ['data' => $myPreference]); return ['value' => $myPreference, 'status' => 5]; } else { $myPreference = Cache::get("{$prefix}/{$word}/3/0"); if (!empty($myPreference)) { Log::debug($word . '命中社区wbw-' . $field, ['data' => $myPreference]); return ['value' => $myPreference, 'status' => 5]; } } return false; } /** * 自动查词 * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { // $user = AuthApi::current($request); if (!$user) { //未登录用户 return $this->error(__('auth.failed'), 401, 401); } $startAt = microtime(true) * 1000; // system regular $this->initSysDict(); $channel = Channel::find($request->get('channel_id')); $orgData = $request->get('data'); $lang = []; foreach ($request->get('lang', []) as $value) { $lang[] = strtolower($value); } //句子中的单词 $words = []; foreach ($orgData as $word) { # code... if (isset($word['type']) && $word['type']['value'] === '.ctl.') { continue; } if (!empty($word['real']['value'])) { $words[] = $word['real']['value']; } } $result = $this->lookup($words, [], 2); $indexed = $this->toIndexed($result); foreach ($orgData as $key => $word) { if (isset($word['type']) && $word['type']['value'] === '.ctl.') { continue; } if (empty($word['real']['value'])) { continue; } $data = $word; $preference = $this->wbwPreference($word['real']['value'], 'meaning', $user['user_id']); if ($preference !== false) { $data['meaning'] = $preference; } $preference = $this->wbwPreference($word['real']['value'], 'factors', $user['user_id']); if ($preference !== false) { $data['factors'] = $preference; } $preference = $this->wbwPreference($word['real']['value'], 'factorMeaning', $user['user_id']); if ($preference !== false) { $data['factorMeaning'] = $preference; } $preference = $this->wbwPreference($word['real']['value'], 'case', $user['user_id']); if ($preference !== false) { $data['case'] = $preference; } $preference = $this->wbwPreference($word['real']['value'], 'parent', $user['user_id']); if ($preference !== false) { $data['parent'] = $preference; } if (isset($indexed[$word['real']['value']])) { //parent $case = []; $parent = []; $factors = []; $factorMeaning = []; $meaning = []; $parent2 = []; $case2 = []; foreach ($indexed[$word['real']['value']] as $value) { //非base优先 if (strstr($value->type, 'base') === FALSE) { $increment = 10; } else { $increment = 1; } //将全部结果加上得分放入数组 if ($value->type !== '.cp.') { $parent = $this->insertValue([$value->parent], $parent, $increment); } if (isset($data['case']) && $data['case']['status'] < 5) { if (!empty($value->type) && $value->type !== ".cp.") { $case = $this->insertValue([$value->type . "#" . $value->grammar], $case, $increment); } } if ($data['factors']['status'] < 50) { $factors = $this->insertValue([$value->factors], $factors, $increment); } if (isset($data['factorMeaning']) && $data['factorMeaning']['status'] < 50) { $factorMeaning = $this->insertValue([$value->factormean], $factorMeaning, $increment, false); } if ($data['meaning']['status'] < 50) { if ($this->langCheck($lang, $value->language)) { $meaning = $this->insertValue(explode('$', $value->mean), $meaning, $increment, false); } } } if (count($case) > 0) { arsort($case); $first = array_keys($case)[0]; $data['case'] = ['value' => $first === "_null" ? "" : $first, 'status' => 3]; } if (count($parent) > 0) { arsort($parent); $first = array_keys($parent)[0]; $data['parent'] = ['value' => $first === "_null" ? "" : $first, 'status' => 3]; } else { $data['parent'] = ['value' => "", 'status' => 3]; } if (count($factors) > 0 && empty($data['factors']['value'])) { arsort($factors); $first = array_keys($factors)[0]; $data['factors'] = ['value' => $first === "_null" ? "" : $first, 'status' => 3]; } if (count($factorMeaning) > 0) { arsort($factorMeaning); $first = array_keys($factorMeaning)[0]; $data['factorMeaning'] = ['value' => $first === "_null" ? "" : $first, 'status' => 5]; } if (isset($data['factorMeaning']) && $data['factorMeaning']['status'] < 5) { $wbwFactorMeaning = []; if (!empty($data['factors']['value'])) { foreach (explode("+", $data['factors']['value']) as $factor) { $preference = $this->wbwPreference($factor, 'meaning', $user['user_id']); if ($preference !== false) { $wbwFactorMeaning[] = $preference['value']; } else { $wbwFactorMeaning[] = $factor; } } } $data['factorMeaning'] = ['value' => implode('+', $wbwFactorMeaning), 'status' => 3]; } if (empty($data['meaning']['value']) && !empty($data['parent']['value'])) { if (isset($indexed[$data['parent']['value']])) { foreach ($indexed[$data['parent']['value']] as $value) { //根据base 查找词意 //非base优先 $increment = 10; if ($this->langCheck($lang, $value->language)) { $meaning = $this->insertValue(explode('$', $value->mean), $meaning, $increment, false); } //查找词源 if (!empty($value->parent) && $value->parent !== $value->word && strstr($value->type, "base") !== FALSE) { $parent2 = $this->insertValue([$value->grammar . "$" . $value->parent], $parent2, 1, false); } } } } if (count($meaning) > 0) { arsort($meaning); $first = array_keys($meaning)[0]; $data['meaning'] = ['value' => $first === "_null" ? "" : $first, 'status' => 3]; } if (count($parent2) > 0) { arsort($parent2); $first = explode("$", array_keys($parent2)[0]); $data['parent2'] = ['value' => $first[1], 'status' => 3]; $data['grammar2'] = ['value' => $first[0], 'status' => 3]; } } if ( !isset($data['factorMeaning']['value']) || $this->fmEmpty($data['factorMeaning']['value']) ) { $factorMeaning = []; //生成自动的拆分意思 $autoMeaning = ''; $currFactors = explode('+', $data['factors']['value']); $autoFM = []; foreach ($currFactors as $factor) { $subFactors = explode('-', $factor); $autoSubFM = []; foreach ($subFactors as $subFactor) { $preference = $this->wbwPreference($subFactor, 'factorMeaning', $user['user_id']); if ($preference !== false) { $autoSubFM[] = $preference['value']; } else { $preference = $this->wbwPreference($subFactor, 'meaning', $user['user_id']); if ($preference !== false) { $autoSubFM[] = $preference['value']; } else { $autoSubFM[] = ''; } } } $autoFM[] = implode('-', $autoSubFM); $autoMeaning .= implode('', $autoSubFM); } $autoMeaning .= implode('', $autoFM); if (count($autoFM) > 0) { $data['factorMeaning'] = ['value' => implode('+', $autoFM), 'status' => 3]; if (empty($data['meaning']['value']) && !empty($autoMeaning)) { $data['meaning'] = ['value' => $autoMeaning, 'status' => 3]; } } } $orgData[$key] = $data; } return $this->ok($orgData); } private function fmEmpty($value) { if (str_replace(['+', '-', ' '], '', $value) === '') { return true; } else { return false; } } /** * 自动查词 * * @param string $sentId * @return \Illuminate\Http\Response */ public function show(Request $request, string $sentId) { $startAt = microtime(true) * 1000; $channel = Channel::find($request->get('channel_id')); //查询句子中的单词 $sent = \explode('-', $sentId); $wbw = WbwTemplate::where('book', $sent[0]) ->where('paragraph', $sent[1]) ->whereBetween('wid', [$sent[2], $sent[3]]) ->orderBy('wid') ->get(); $words = []; foreach ($wbw as $row) { if ($row->type !== '.ctl.' && !empty($row->real)) { $words[] = $row->real; } } $result = $this->lookup($words, [], 2); $indexed = $this->toIndexed($result); //生成自动填充结果 $wbwContent = []; foreach ($wbw as $row) { $type = $row->type == '?' ? '' : $row->type; $grammar = $row->gramma == '?' ? '' : $row->gramma; $part = $row->part == '?' ? '' : $row->part; if (!empty($type) || !empty($grammar)) { $case = "{$type}#$grammar"; } else { $case = ""; } $data = [ 'sn' => [$row->wid], 'word' => ['value' => $row->word, 'status' => 3], 'real' => ['value' => $row->real, 'status' => 3], 'meaning' => ['value' => [], 'status' => 3], 'type' => ['value' => $type, 'status' => 3], 'grammar' => ['value' => $grammar, 'status' => 3], 'case' => ['value' => $case, 'status' => 3], 'style' => ['value' => $row->style, 'status' => 3], 'factors' => ['value' => $part, 'status' => 3], 'factorMeaning' => ['value' => '', 'status' => 3], 'confidence' => 0.5 ]; if ($row->type !== '.ctl.' && !empty($row->real)) { if (isset($indexed[$row->real])) { //parent $case = []; $parent = []; $factors = []; $factorMeaning = []; $meaning = []; $parent2 = []; $case2 = []; foreach ($indexed[$row->real] as $value) { //非base优先 if (strstr($value->type, 'base') === FALSE) { $increment = 10; } else { $increment = 1; } //将全部结果加上得分放入数组 $parent = $this->insertValue([$value->parent], $parent, $increment); $case = $this->insertValue([$value->type . "#" . $value->grammar], $case, $increment); $factors = $this->insertValue([$value->factors], $factors, $increment); $factorMeaning = $this->insertValue([$value->factormean], $factorMeaning, $increment); $meaning = $this->insertValue(explode('$', $value->mean), $meaning, $increment, false); } if (count($case) > 0) { arsort($case); $first = array_keys($case)[0]; $data['case'] = ['value' => $first === "_null" ? "" : $first, 'status' => 3]; } if (count($parent) > 0) { arsort($parent); $first = array_keys($parent)[0]; $data['parent'] = ['value' => $first === "_null" ? "" : $first, 'status' => 3]; } if (count($factors) > 0) { arsort($factors); $first = array_keys($factors)[0]; $data['factors'] = ['value' => $first === "_null" ? "" : $first, 'status' => 3]; } if (count($factorMeaning) > 0) { arsort($factorMeaning); $first = array_keys($factorMeaning)[0]; $data['factorMeaning'] = ['value' => $first === "_null" ? "" : $first, 'status' => 3]; } //根据base 查找词意 if (!empty($data['parent'])) { if (isset($indexed[$data['parent']['value']])) { foreach ($indexed[$data['parent']['value']] as $value) { //非base优先 $increment = 10; $meaning = $this->insertValue(explode('$', $value->mean), $meaning, $increment, false); } } else { //Log::error("no set parent".$data['parent']['value']); } } if (count($meaning) > 0) { arsort($meaning); $first = array_keys($meaning)[0]; $data['meaning'] = ['value' => $first === "_null" ? "" : $first, 'status' => 3]; } } } $wbwContent[] = $data; } $endAt = microtime(true) * 1000; return $this->ok([ "rows" => $wbwContent, "count" => count($wbwContent), "time" => (int)($endAt - $startAt) ]); } private function toIndexed($words) { //转成索引数组 $indexed = []; foreach ($words as $key => $value) { # code... $indexed[$value->word][] = $value; } return $indexed; } /** * $empty:是否允许空值 */ private function insertValue($value, $container, $increment, $empty = true) { foreach ($value as $one) { if ($empty === false) { if ($this->fmEmpty($one)) { break; } } $one = trim($one); $key = $one; if (empty($key)) { $key = '_null'; } if (isset($container[$key])) { $container[$key] += $increment; } else { $container[$key] = $increment; } } return $container; } /** * Update the specified resource in storage. * * @param \Illuminate\Http\Request $request * @param \App\Models\UserDict $userDict * @return \Illuminate\Http\Response */ public function update(Request $request, UserDict $userDict) { // } /** * Remove the specified resource from storage. * * @param \App\Models\UserDict $userDict * @return \Illuminate\Http\Response */ public function destroy(UserDict $userDict) { // } }