UpgradeProgressChapter.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. <?php
  2. namespace App\Console\Commands;
  3. use Illuminate\Support\Facades\Log;
  4. use Carbon\Carbon;
  5. use Illuminate\Support\Facades\Validator;
  6. use Illuminate\Console\Command;
  7. use App\Models\Sentence;
  8. use App\Models\PaliSentence;
  9. use App\Models\Progress;
  10. use App\Models\ProgressChapter;
  11. use App\Models\PaliText;
  12. use App\Models\Tag;
  13. use App\Models\TagMap;
  14. use App\Models\Channel;
  15. use App\Http\Api\MdRender;
  16. use App\Services\PaliTextService;
  17. class UpgradeProgressChapter extends Command
  18. {
  19. /**
  20. * The name and signature of the console command.
  21. * php artisan upgrade:progress.chapter --book=168 --para=915 --channel=19f53a65-81db-4b7d-8144-ac33f1217d34
  22. * @var string
  23. */
  24. protected $signature = 'upgrade:progress.chapter {--book=} {--para=} {--channel=} {--driver=str} {--resume}';
  25. /**
  26. * The console command description.
  27. *
  28. * @var string
  29. */
  30. protected $description = '更新章节完成度,以channel为单位';
  31. const COMPLETION_RATE = 0.9;
  32. /**
  33. * Create a new command instance.
  34. *
  35. * @return void
  36. */
  37. public function __construct()
  38. {
  39. parent::__construct();
  40. }
  41. /**
  42. * Execute the console command.
  43. *
  44. * @return int
  45. */
  46. public function handle()
  47. {
  48. if (\App\Tools\Tools::isStop()) {
  49. return 0;
  50. }
  51. $paliTextService = app(PaliTextService::class);
  52. $this->info("upgrade:progresschapter start.");
  53. $startTime = time();
  54. $book = $this->option('book');
  55. $para = $this->option('para');
  56. $channelId = $this->option('channel');
  57. \App\Tools\Markdown::driver($this->option('driver'));
  58. $tagCount = 0;
  59. #第一步 查询有多少书有译文
  60. if ($book) {
  61. if ($this->option('resume')) {
  62. $table = Sentence::whereBetween('book_id', [$book, 217]);
  63. } else {
  64. $table = Sentence::where('book_id', $book);
  65. }
  66. $books = $table->groupby('book_id')
  67. ->select('book_id')
  68. ->get();
  69. } else {
  70. $books = Sentence::where('strlen', '>', 0)
  71. ->where('book_id', '<', 1000)
  72. ->whereNotNull('channel_uid')
  73. ->groupby('book_id')
  74. ->select('book_id')
  75. ->get();
  76. }
  77. $totalBook = count($books);
  78. foreach ($books as $book) {
  79. $this->info("{$book->book_id} start total {$totalBook}");
  80. if ($para) {
  81. $table = PaliText::where('book', $book->book_id)
  82. ->where('paragraph', '<=', $para);
  83. } else {
  84. $table = PaliText::where('book', $book->book_id);
  85. }
  86. $chapters = $table->where('level', '>', 0)
  87. ->where('level', '<', 8)
  88. ->select('paragraph', 'chapter_strlen', 'chapter_len')
  89. ->get();
  90. foreach ($chapters as $key => $chapter) {
  91. # code...
  92. $chapter_strlen = PaliSentence::where('book', $book->book_id)
  93. ->whereBetween('paragraph', [$chapter->paragraph, $chapter->paragraph + $chapter->chapter_len - 1])
  94. ->sum('length');
  95. if ($chapter_strlen == 0) {
  96. $this->error('chapter_strlen is 0 book:' . $book->book_id . ' paragraph:' . $chapter->paragraph . '-' . ($chapter->paragraph + $chapter->chapter_len - 1));
  97. continue;
  98. }
  99. $table = Progress::where('book', $book->book_id)
  100. ->whereBetween('para', [$chapter->paragraph, $chapter->paragraph + $chapter->chapter_len - 1]);
  101. if ($channelId) {
  102. $table->where('channel_id', $channelId);
  103. }
  104. $strlen = $table->groupby('channel_id')
  105. ->selectRaw('channel_id, sum(all_strlen) as cp_len')
  106. ->get();
  107. foreach ($strlen as $final) {
  108. # code...
  109. # 计算此段落完成时间
  110. $finalAt = Progress::where('book', $book->book_id)
  111. ->whereBetween('para', [$chapter->paragraph, $chapter->paragraph + $chapter->chapter_len - 1])
  112. ->where('channel_id', $final->channel_id)
  113. ->max('created_at');
  114. $updateAt = Progress::where('book', $book->book_id)
  115. ->whereBetween('para', [$chapter->paragraph, $chapter->paragraph + $chapter->chapter_len - 1])
  116. ->where('channel_id', $final->channel_id)
  117. ->max('updated_at');
  118. $transTexts = Sentence::where('book_id', $book->book_id)
  119. ->whereBetween('paragraph', [$chapter->paragraph + 1, $chapter->paragraph + $chapter->chapter_len - 1])
  120. ->where('channel_uid', $final->channel_id)
  121. ->select('content')
  122. ->orderBy('paragraph')
  123. ->orderBy('word_start')
  124. ->get();
  125. $mdRender = new MdRender(['format' => 'simple']);
  126. #查询标题
  127. $title = Sentence::where('book_id', $book->book_id)
  128. ->where('paragraph', $chapter->paragraph)
  129. ->where('channel_uid', $final->channel_id)
  130. ->value('content');
  131. $title = $mdRender->convert($title, [$final->channel_id]);
  132. $summaryText = "";
  133. foreach ($transTexts as $text) {
  134. # code...
  135. $textContent = $mdRender->convert($text->content, [$final->channel_id]);
  136. $summaryText .= str_replace("\n", "", $textContent);
  137. if (mb_strlen($summaryText, "UTF-8") > 255) {
  138. break;
  139. }
  140. }
  141. //查询语言
  142. $channelLang = Channel::where('uid', $final->channel_id)->value('lang');
  143. $lang = explode('-', $channelLang)[0];
  144. $attributes = [
  145. 'book' => $book->book_id,
  146. 'para' => $chapter->paragraph,
  147. 'channel_id' => $final->channel_id
  148. ];
  149. $rules = array(
  150. 'book' => 'integer',
  151. 'para' => 'integer',
  152. 'channel_id' => 'uuid'
  153. );
  154. $validator = Validator::make($attributes, $rules);
  155. if ($validator->fails()) {
  156. $this->error("Validator is fails");
  157. return 0;
  158. }
  159. if (ProgressChapter::where($attributes)->exists()) {
  160. $chapterData = ProgressChapter::where($attributes)->first();
  161. } else {
  162. $chapterData = new ProgressChapter;
  163. $chapterData->book = $attributes["book"];
  164. $chapterData->para = $attributes["para"];
  165. $chapterData->channel_id = $attributes["channel_id"];
  166. }
  167. $progress = $final->cp_len / $chapter_strlen;
  168. $addChapter = false;
  169. if ($progress >= self::COMPLETION_RATE) {
  170. if (empty($chapterData->completed_at)) {
  171. // 添加新的章节了
  172. $chapterData->completed_at = $finalAt;
  173. $addChapter = true;
  174. }
  175. }
  176. $chapterData->lang = $lang;
  177. $chapterData->all_trans = $progress;
  178. $chapterData->public = $progress;
  179. $chapterData->progress = $progress;
  180. $chapterData->title = $title ? mb_substr($title, 0, 255, "UTF-8") : "";
  181. $chapterData->summary = $summaryText ? mb_substr($summaryText, 0, 255, "UTF-8") : "";
  182. $chapterData->created_at = $finalAt;
  183. $chapterData->updated_at = $updateAt;
  184. $chapterData->save();
  185. if ($addChapter) {
  186. // 添加新的章节了
  187. //修改父目录
  188. $loop = 0;
  189. $currBook = $attributes["book"];
  190. $currPara = $attributes["para"];
  191. while ($parent = $paliTextService->getParent($currBook, $currPara)) {
  192. $parentChapter = ProgressChapter::where('book', $currBook)
  193. ->where('para', $parent->paragraph)
  194. ->where('channel_id', $attributes["channel_id"])
  195. ->first();
  196. if ($parentChapter) {
  197. $currPara = $parent->paragraph;
  198. if (
  199. is_null($parentChapter->last_chapter_completed_at) ||
  200. Carbon::parse($finalAt)->gt(Carbon::parse($parentChapter->last_chapter_completed_at))
  201. ) {
  202. $parentChapter->last_chapter_completed_at = $finalAt;
  203. // 计算字章节有多少已经完成
  204. $chapterEnd = $parent->paragraph + $parent->chapter_len - 1;
  205. $totalCompleted = ProgressChapter::where('book', $currBook)
  206. ->whereBetween('para', [$parent->paragraph, $chapterEnd])
  207. ->where('channel_id', $attributes["channel_id"])
  208. ->whereNotNull('completed_at')
  209. ->count();
  210. $parentChapter->completed_chapters = $totalCompleted;
  211. $parentChapter->save();
  212. /*
  213. Log::info('update last_chapter_completed_at', [
  214. 'para' => $parent->paragraph,
  215. 'completed' => $totalCompleted
  216. ]);
  217. */
  218. }
  219. } else {
  220. break;
  221. }
  222. $loop++;
  223. }
  224. //Log::info('update parent completed loop ' . $loop);
  225. }
  226. $wasCreated = $chapterData->wasRecentlyCreated;
  227. $wasChanged = $chapterData->wasChanged();
  228. #查询路径
  229. $path = json_decode(
  230. PaliText::where('book', $book->book_id)
  231. ->where('paragraph', $chapter->paragraph)
  232. ->value('path')
  233. );
  234. if ($path) {
  235. //查询标签
  236. $tags = [];
  237. foreach ($path as $key => $value) {
  238. # code...
  239. if ($value->level > 0) {
  240. $paliTextUuid = PaliText::where('book', $value->book)
  241. ->where('paragraph', $value->paragraph)
  242. ->value('uid');
  243. $tagUuids = TagMap::where('table_name', 'pali_texts')
  244. ->where('anchor_id', $paliTextUuid)
  245. ->select(['tag_id'])
  246. ->get();
  247. foreach ($tagUuids as $key => $taguuid) {
  248. # code...
  249. $tags[$taguuid['tag_id']] = 1;
  250. }
  251. }
  252. }
  253. //更新标签映射表
  254. //删除旧的标签映射表
  255. TagMap::where('table_name', 'progress_chapters')
  256. ->where('anchor_id', $chapterData->uid)
  257. ->delete();
  258. foreach ($tags as $key => $tag) {
  259. # code...
  260. $tagmap = TagMap::create([
  261. 'table_name' => 'progress_chapters',
  262. 'anchor_id' => $chapterData->uid,
  263. 'tag_id' => $key
  264. ]);
  265. if ($tagmap) {
  266. $tagCount++;
  267. }
  268. }
  269. }
  270. }
  271. }
  272. }
  273. $time = time() - $startTime;
  274. $this->info("upgrade:progresschapter finished in {$time}s tag count:{$tagCount}");
  275. return 0;
  276. }
  277. }