PkService.php 9.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: gevnc
  5. * Date: 2018/5/16
  6. * Time: 17:49
  7. */
  8. namespace App\Services;
  9. use App\Models\PkRoom;
  10. use App\Traits\Singleton;
  11. use Illuminate\Support\Facades\Log;
  12. use Illuminate\Support\Facades\Redis;
  13. class PkService
  14. {
  15. use Singleton;
  16. const QUESTION_COLLECT = "bs_question_collect";
  17. const PK_ROOMS = "bs_pk_rooms";
  18. const PK_ROOM_ANSWERS = "bs_pk_room_answers";
  19. const PK_QUEUE = "bs_pk_queue";
  20. const PK_STATUS_QUEUE = "bs_pk_room_queue";
  21. const PK_ROOM_JOINS = "bs_pk_room_joins";
  22. const PK_RUN = "bs_pk_room_run";
  23. const NOT_COMPLETE_PKS = "bs_pk_room_not_completes";
  24. const QUESTION_COUNT = 5;
  25. const COUNT_DOWN = 13;
  26. const ROOM_OVER_TIME = 300;
  27. /**
  28. * 获取房间信息
  29. * @param $roomId
  30. * @return array
  31. */
  32. public function getRoomInfo($roomId)
  33. {
  34. return Redis::hGetAll(self::PK_ROOMS . ":" . $roomId);
  35. }
  36. /**
  37. * 获取PK对战的双方信息
  38. * @param $sponsorUserId
  39. * @param $challengerUserId
  40. * @return array
  41. */
  42. public function getPkUserInfo($sponsorUserId, $challengerUserId)
  43. {
  44. $data = [
  45. "sponsor_user_id" => $sponsorUserId,
  46. "sponsor_name" => "",
  47. "sponsor_short_name" => "",
  48. "sponsor_headpic_url" => "",
  49. "sponsor_department" => "",
  50. "challenger_user_id" => $challengerUserId,
  51. "challenger_name" => "",
  52. "challenger_short_name" => "",
  53. "challenger_headpic_url" => "",
  54. "challenger_department" => ""
  55. ];
  56. if ($sponsorUserId) {
  57. $sponsor = UserService::getInstance()->getUser($sponsorUserId);
  58. if ($sponsor) {
  59. $data["sponsor_name"] = $sponsor["name"];
  60. $data["sponsor_short_name"] = mb_substr($sponsor["name"], -2, 2, "utf-8");
  61. $data["sponsor_headpic_url"] = $sponsor["avatar"];
  62. $data["sponsor_department"] = DepartmentService::getInstance()->getDepartmentName($sponsor["department_id"]);
  63. }
  64. }
  65. if ($challengerUserId) {
  66. $challenger = UserService::getInstance()->getUser($challengerUserId);
  67. if ($challenger) {
  68. $data["challenger_name"] = $challenger["name"];
  69. $data["challenger_short_name"] = mb_substr($challenger["name"], -2, 2, "utf-8");
  70. $data["challenger_headpic_url"] = $challenger["avatar"];
  71. $data["challenger_department"] = DepartmentService::getInstance()->getDepartmentName($challenger["department_id"]);
  72. }
  73. }
  74. return $data;
  75. }
  76. /**
  77. * 开始PK
  78. * @param $activityId
  79. * @param $sponsorUserId
  80. * @param $challengerUserId
  81. * @return mixed
  82. */
  83. public function startPk($activityId,$sponsorUserId, $challengerUserId){
  84. try{
  85. //如果发起人已经在PK则,返回null
  86. if(UserService::getInstance()->getUserCurrentWork($sponsorUserId)){
  87. return null;
  88. }
  89. $brainstorming = BrainstormingService::getInstance()->get($activityId);
  90. $corpId = $brainstorming["corp_id"];
  91. $count = $brainstorming["pk_question_num"];
  92. $questionIds = Redis::sRandMember(self::QUESTION_COLLECT.":".$activityId.":pk", $count);
  93. $data = [
  94. "corp_id" => $corpId,
  95. "activity_id" => $activityId,
  96. "sponsor_user_id" => $sponsorUserId,
  97. "challenger_user_id" => $challengerUserId,
  98. "start_time" => time(),
  99. "knowledge_money" => 0,
  100. "question_ids" => implode(",", $questionIds),
  101. "win_user_id" => 0,
  102. "status" => 3,
  103. "is_success" => 0
  104. ];
  105. $pkRoomModel = PkRoom::create($data);
  106. if (!empty($pkRoomModel)) {
  107. $roomId = $pkRoomModel->room_id;
  108. $data["create_time"] = time();
  109. $data["room_id"] = $roomId;
  110. $data["fd"] = 0;
  111. $data["question_count"] = $count;
  112. $data["step"] = 0;
  113. $data["sponsor_score"] = 0;
  114. $data["challenger_score"] = 0;
  115. Redis::hMset(self::PK_ROOMS . ":" . $roomId, $data);
  116. Redis::expire(self::PK_ROOMS . ":" . $roomId,86400);
  117. Redis::sAdd(self::PK_RUN, $roomId);
  118. $questions = QuestionService::getInstance()->mget($questionIds);
  119. $step = 1;
  120. //生成答题
  121. foreach ($questions as $question) {
  122. $this->addAnswer($roomId, $question, $step, $count, $sponsorUserId);
  123. $this->addAnswer($roomId, $question, $step, $count, $challengerUserId);
  124. $step++;
  125. }
  126. //发送PK开始通知
  127. $pkUserInfo = $this->getPkUserInfo($sponsorUserId, $challengerUserId);
  128. $responseData = [
  129. "room_id" => $roomId,
  130. "knowledge_money" => 0,
  131. "status" => 3,
  132. "create_time" => time()
  133. ];
  134. $responseData = array_merge($responseData, $pkUserInfo);
  135. PushMessageService::getInstance()->pushByUserId("pk", "startNotify", $responseData, $sponsorUserId,0);
  136. PushMessageService::getInstance()->pushByUserId("pk", "startNotify", $responseData, $challengerUserId,0);
  137. //设置用户正在PK
  138. UserService::getInstance()->setUserCurrentWork($sponsorUserId,'pk',$roomId,20);
  139. UserService::getInstance()->setUserCurrentWork($challengerUserId,'pk',$roomId,20);
  140. //延时3秒发送开始答题
  141. Redis::hSet(self::PK_ROOMS . ":" . $roomId, "step", 1);
  142. //处理发起人
  143. Redis::hSet(self::PK_ROOM_ANSWERS . ":" . $roomId . ":" . $sponsorUserId . ":1" , "answer_start_time", time());
  144. $this->addAnswerQueue($roomId, 1, $sponsorUserId);
  145. //处理挑战人
  146. Redis::hSet(self::PK_ROOM_ANSWERS . ":" . $roomId . ":" . $challengerUserId . ":1", "answer_start_time", time());
  147. $this->addAnswerQueue($roomId, 1, $challengerUserId);
  148. $this->sendQuestion($roomId,1,$sponsorUserId,3);
  149. $this->sendQuestion($roomId,1,$challengerUserId,3);
  150. return $roomId;
  151. }
  152. }catch (\Exception $exception){
  153. Log::info($exception->getTraceAsString());
  154. return null;
  155. }
  156. }
  157. /**
  158. * 获取某闯关的第几到题目
  159. * @param $roomId
  160. * @param $step
  161. * @param $userId
  162. * @return mixed
  163. */
  164. public function getQuestion($roomId, $step, $userId)
  165. {
  166. $userAnswer = $this->getUserAnswer($roomId, $step, $userId);
  167. if ($userAnswer) {
  168. $question = QuestionService::getInstance()->get($userAnswer["question_id"]);
  169. return [
  170. "room_id" => $roomId,
  171. "count" => $userAnswer["count"],
  172. "step" => $step,
  173. "question_type" => $question["question_type"],
  174. "correct_answer" => $question["correct_answer"],
  175. "question_id" => $userAnswer["question_id"],
  176. "question_title" => $question["question_title"],
  177. "question_options" => $question["question_options"]
  178. ];
  179. }
  180. return null;
  181. }
  182. /**
  183. * 发送答题
  184. * @param $roomId
  185. * @param $step
  186. * @param $userId
  187. * @param $delay
  188. */
  189. public function sendQuestion($roomId, $step, $userId, $delay = 0)
  190. {
  191. $question = $this->getQuestion($roomId, $step, $userId);
  192. $question["count_down"] = self::COUNT_DOWN;
  193. //unset($question["correct_answer"]);
  194. PushMessageService::getInstance()->pushByUserId("pk", "question", $question, $userId,$delay);
  195. }
  196. /**
  197. * 获取用户答题
  198. * @param $roomId
  199. * @param $step
  200. * @param $userId
  201. * @return array
  202. */
  203. public function getUserAnswer($roomId, $step, $userId)
  204. {
  205. return Redis::hGetAll(self::PK_ROOM_ANSWERS . ":" . $roomId . ":" . $userId . ":" . $step);
  206. }
  207. /**
  208. * 添加答题
  209. * @param $roomId
  210. * @param $question
  211. * @param $step
  212. * @param $count
  213. * @param $userId
  214. * @return mixed
  215. */
  216. public function addAnswer($roomId, $question, $step, $count, $userId)
  217. {
  218. $data = [
  219. "room_id" => $roomId,
  220. "step" => $step,
  221. "question_id" => $question["question_id"],
  222. "count" => $count,
  223. "user_answer" => "",
  224. "user_id" => $userId,
  225. "correct_answer" => $question["correct_answer"],
  226. "answer_start_time" => 0,
  227. "answer_time" => 0,
  228. "score" => 0,
  229. "is_over_time" => 0,
  230. "is_correct" => 0
  231. ];
  232. $ret = Redis::hMset(self::PK_ROOM_ANSWERS . ":" . $roomId . ":" . $userId . ":" . $step, $data);
  233. Redis::expire(self::PK_ROOM_ANSWERS . ":" . $roomId . ":" . $userId . ":" . $step,86400);
  234. return $ret;
  235. }
  236. /**
  237. * 加入到答题倒计队列
  238. * @param $roomId
  239. * @param $step
  240. * @param $userId
  241. * @return mixed
  242. */
  243. public function addAnswerQueue($roomId, $step, $userId)
  244. {
  245. $countDown = self::COUNT_DOWN;
  246. if($step==1){
  247. $countDown+=3;
  248. }
  249. Redis::hSet(self::PK_QUEUE, $roomId . "_" . $step . "_" . $userId, $countDown);
  250. }
  251. }