StockModeController.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. <?php
  2. namespace App\Http\Controllers\Admin;
  3. use App\Http\Controllers\Controller;
  4. use App\Http\helper\NumConfig;
  5. use Illuminate\Http\Request;
  6. use Illuminate\Support\Facades\DB;
  7. class StockModeController extends Controller
  8. {
  9. /**
  10. * 显示库存模式配置页面
  11. */
  12. public function index()
  13. {
  14. // 获取 SystemStatusInfo 中的配置
  15. $systemConfig = DB::connection('write')
  16. ->table('QPAccountsDB.dbo.SystemStatusInfo')
  17. ->whereIn('StatusName', ['StockMode2BetLevels', 'StockMode2RevenueRatio', 'StockMode2SwitchRecharge'])
  18. ->get()
  19. ->keyBy('StatusName');
  20. // 解析 StockMode2BetLevels
  21. $betLevelsString = $systemConfig['StockMode2BetLevels']->StatusString ?? '0|2|10|10000,0|0|100|1000';
  22. $betLevelsParts = explode(',', $betLevelsString);
  23. $betMaxLimits = explode('|', $betLevelsParts[0] ?? '0|2|10|10000');
  24. $rechargeMinLimits = explode('|', $betLevelsParts[1] ?? '0|0|100|1000');
  25. // 获取 RoomStockStatic2 数据
  26. $roomStocks = DB::connection('write')
  27. ->table('QPPlatformDB.dbo.RoomStockStatic2')
  28. ->where('GameID', 0)
  29. ->orderBy('SortID')
  30. ->get();
  31. // 今日税收 rtp 中间率
  32. $todayID = date('Ymd');
  33. $gameRoom = DB::connection('read')
  34. ->table('QPPlatformDB.dbo.GameRoomInfo')
  35. ->select('RevenueRatio')
  36. ->first();
  37. // 将千分比转换为百分比显示(例如:50 -> 5%)
  38. $revenueRatio = $gameRoom ? ($gameRoom->RevenueRatio / 10) : 0;
  39. $rst2 = DB::Table('QPPlatformDB.dbo.RoomStockDay2')
  40. ->lock('with(nolock)')
  41. ->selectRaw('SortID, SUM(Winlost) as SumWinlost, SUM(Turnover) as SumTurnover')
  42. ->groupBy('SortID')
  43. ->where('DateID', $todayID)
  44. ->get();
  45. foreach ($rst2 as $k => $v) {
  46. $rst2[$k]->todayRevenue = $v->SumTurnover / NumConfig::NUM_VALUE * ($revenueRatio / 100);
  47. $rst2[$k]->todayRtp = round($v->SumWinlost / $v->SumTurnover, 4);
  48. $rst2[$k]->todayWinRatio = 0; // today 获取中奖率并赋值
  49. }
  50. $rst2 = $rst2->keyBy('SortID');
  51. return view('admin.stock_mode.index', compact(
  52. 'systemConfig',
  53. 'betMaxLimits',
  54. 'rechargeMinLimits',
  55. 'roomStocks',
  56. 'rst2'
  57. ));
  58. }
  59. /**
  60. * 更新系统配置参数
  61. */
  62. public function updateSystemConfig(Request $request)
  63. {
  64. try {
  65. $betMaxLimits = $request->input('bet_max_limits', []);
  66. $rechargeMinLimits = $request->input('recharge_min_limits', []);
  67. $revenueRatio = $request->input('revenue_ratio', 50);
  68. $switchRecharge = $request->input('switch_recharge', 100);
  69. // 构建 StockMode2BetLevels 的 StatusString
  70. $betMaxString = implode('|', $betMaxLimits);
  71. $rechargeMinString = implode('|', $rechargeMinLimits);
  72. $betLevelsString = $betMaxString . ',' . $rechargeMinString;
  73. // 更新 StockMode2BetLevels
  74. DB::connection('write')
  75. ->table('QPAccountsDB.dbo.SystemStatusInfo')
  76. ->where('StatusName', 'StockMode2BetLevels')
  77. ->update([
  78. 'StatusString' => $betLevelsString,
  79. 'StatusValue' => 0
  80. ]);
  81. // 更新 StockMode2RevenueRatio
  82. DB::connection('write')
  83. ->table('QPAccountsDB.dbo.SystemStatusInfo')
  84. ->where('StatusName', 'StockMode2RevenueRatio')
  85. ->update([
  86. 'StatusValue' => $revenueRatio
  87. ]);
  88. // 更新 StockMode2SwitchRecharge
  89. DB::connection('write')
  90. ->table('QPAccountsDB.dbo.SystemStatusInfo')
  91. ->where('StatusName', 'StockMode2SwitchRecharge')
  92. ->update([
  93. 'StatusValue' => $switchRecharge
  94. ]);
  95. \Log::info('库存模式系统配置更新成功', [
  96. 'bet_levels' => $betLevelsString,
  97. 'revenue_ratio' => $revenueRatio,
  98. 'switch_recharge' => $switchRecharge
  99. ]);
  100. return response()->json(['status' => 'success', 'message' => '系统配置更新成功']);
  101. } catch (\Exception $e) {
  102. \Log::error('库存模式系统配置更新失败', ['error' => $e->getMessage()]);
  103. return response()->json(['status' => 'error', 'message' => '更新失败: ' . $e->getMessage()]);
  104. }
  105. }
  106. /**
  107. * 更新房间库存配置
  108. */
  109. public function updateRoomStock(Request $request)
  110. {
  111. try {
  112. $sortId = $request->input('sort_id');
  113. $levelBase = $request->input('level_base');
  114. if (!$sortId || !is_numeric($levelBase)) {
  115. return response()->json(['status' => 'error', 'message' => '参数错误']);
  116. }
  117. // 更新 RoomStockStatic2
  118. $affected = DB::connection('write')
  119. ->table('QPPlatformDB.dbo.RoomStockStatic2')
  120. ->where('GameID', 0)
  121. ->where('SortID', $sortId)
  122. ->update([
  123. 'LevelBase' => $levelBase
  124. ]);
  125. if ($affected === 0) {
  126. // 如果没有记录,则插入新记录
  127. DB::connection('write')
  128. ->table('QPPlatformDB.dbo.RoomStockStatic2')
  129. ->insert([
  130. 'GameID' => 0,
  131. 'SortID' => $sortId,
  132. 'Stock' => 0,
  133. 'LevelBase' => $levelBase,
  134. 'Revenue' => 0,
  135. 'RevenueD' => 0
  136. ]);
  137. }
  138. \Log::info('房间库存配置更新成功', [
  139. 'sort_id' => $sortId,
  140. 'level_base' => $levelBase
  141. ]);
  142. return response()->json(['status' => 'success', 'message' => '房间库存配置更新成功']);
  143. } catch (\Exception $e) {
  144. \Log::error('房间库存配置更新失败', ['error' => $e->getMessage()]);
  145. return response()->json(['status' => 'error', 'message' => '更新失败: ' . $e->getMessage()]);
  146. }
  147. }
  148. /**
  149. * 更新库存(增减)
  150. */
  151. public function updateStock(Request $request)
  152. {
  153. try {
  154. $sortId = $request->input('sort_id');
  155. $adjustValue = $request->input('adjust_value'); // 已经是数据库值(前端已乘以100)
  156. if (!$sortId || !is_numeric($adjustValue)) {
  157. return response()->json(['status' => 'error', 'message' => '参数错误']);
  158. }
  159. // 使用 increment/decrement 方法更新库存
  160. $query = DB::connection('write')
  161. ->table('QPPlatformDB.dbo.RoomStockStatic2')
  162. ->where('GameID', 0)
  163. ->where('SortID', $sortId);
  164. if ($adjustValue > 0) {
  165. $query->increment('Stock', $adjustValue);
  166. } elseif ($adjustValue < 0) {
  167. $query->decrement('Stock', abs($adjustValue));
  168. }
  169. // 获取更新后的库存值
  170. $roomStock = DB::connection('write')
  171. ->table('QPPlatformDB.dbo.RoomStockStatic2')
  172. ->where('GameID', 0)
  173. ->where('SortID', $sortId)
  174. ->first();
  175. if (!$roomStock) {
  176. return response()->json(['status' => 'error', 'message' => '房间数据不存在']);
  177. }
  178. \Log::info('库存更新成功', [
  179. 'sort_id' => $sortId,
  180. 'adjust_value' => $adjustValue,
  181. 'new_stock' => $roomStock->Stock
  182. ]);
  183. return response()->json([
  184. 'status' => 'success',
  185. 'message' => '库存更新成功',
  186. 'new_stock' => $roomStock->Stock
  187. ]);
  188. } catch (\Exception $e) {
  189. \Log::error('库存更新失败', ['error' => $e->getMessage()]);
  190. return response()->json(['status' => 'error', 'message' => '更新失败: ' . $e->getMessage()]);
  191. }
  192. }
  193. /**
  194. * 获取房间库存统计信息
  195. */
  196. public function getRoomStockStats()
  197. {
  198. try {
  199. $roomStocks = DB::connection('write')
  200. ->table('QPPlatformDB.dbo.RoomStockStatic2')
  201. ->where('GameID', 0)
  202. ->orderBy('SortID')
  203. ->get();
  204. return response()->json(['status' => 'success', 'data' => $roomStocks]);
  205. } catch (\Exception $e) {
  206. \Log::error('获取房间库存统计失败', ['error' => $e->getMessage()]);
  207. return response()->json(['status' => 'error', 'message' => '获取失败: ' . $e->getMessage()]);
  208. }
  209. }
  210. /**
  211. * 获取库存快照历史数据
  212. */
  213. public function getSnapshotHistory(Request $request)
  214. {
  215. try {
  216. $sortId = $request->input('sort_id', 1);
  217. $minutes = $request->input('minutes', 60); // 默认1小时
  218. // 计算开始时间
  219. $startTime = date('Y-m-d H:i:s', strtotime("-{$minutes} minutes"));
  220. // 查询起始时间之前的最后一条数据(用于填充前置空白)
  221. $previousSnapshot = DB::connection('write')
  222. ->table('QPPlatformDB.dbo.RoomStockSnapshot2')
  223. ->where('GameID', 0)
  224. ->where('SortID', $sortId)
  225. ->where('CreateTime', '<', $startTime)
  226. ->orderBy('CreateTime', 'desc')
  227. ->first();
  228. // 查询时间范围内的快照数据
  229. $snapshots = DB::connection('write')
  230. ->table('QPPlatformDB.dbo.RoomStockSnapshot2')
  231. ->where('GameID', 0)
  232. ->where('SortID', $sortId)
  233. ->where('CreateTime', '>=', $startTime)
  234. ->orderBy('CreateTime', 'asc')
  235. ->get();
  236. // 处理数据
  237. $data = [];
  238. // 添加前置数据(如果存在)
  239. if ($previousSnapshot) {
  240. $stock = $previousSnapshot->Stock;
  241. $levelBase = $previousSnapshot->LevelBase;
  242. $stockRatio = $levelBase > 0 ? round($stock / $levelBase, 2) : 0;
  243. $zValue = $this->calculateZValue($stock, $levelBase);
  244. $data[] = [
  245. 'id' => $previousSnapshot->ID,
  246. 'stock' => round($stock / 100, 2),
  247. 'levelBase' => round($levelBase / 100, 2),
  248. 'revenue' => round($previousSnapshot->Revenue / 100, 2),
  249. 'revenueD' => round($previousSnapshot->RevenueD / 100, 2),
  250. 'stockChange' => round($previousSnapshot->StockChange / 100, 2),
  251. 'revenueChange' => round($previousSnapshot->RevenueChange / 100, 2),
  252. 'stockRatio' => $stockRatio,
  253. 'zValue' => $zValue,
  254. 'createTime' => $previousSnapshot->CreateTime,
  255. 'timestamp' => strtotime($previousSnapshot->CreateTime) * 1000,
  256. 'isPrevious' => true // 标记为前置数据
  257. ];
  258. }
  259. // 添加时间范围内的数据
  260. foreach ($snapshots as $snapshot) {
  261. $stock = $snapshot->Stock;
  262. $levelBase = $snapshot->LevelBase;
  263. $stockRatio = $levelBase > 0 ? round($stock / $levelBase, 2) : 0;
  264. $zValue = $this->calculateZValue($stock, $levelBase);
  265. $data[] = [
  266. 'id' => $snapshot->ID,
  267. 'stock' => round($stock / 100, 2),
  268. 'levelBase' => round($levelBase / 100, 2),
  269. 'revenue' => round($snapshot->Revenue / 100, 2),
  270. 'revenueD' => round($snapshot->RevenueD / 100, 2),
  271. 'stockChange' => round($snapshot->StockChange / 100, 2),
  272. 'revenueChange' => round($snapshot->RevenueChange / 100, 2),
  273. 'stockRatio' => $stockRatio,
  274. 'zValue' => $zValue,
  275. 'createTime' => $snapshot->CreateTime,
  276. 'timestamp' => strtotime($snapshot->CreateTime) * 1000,
  277. 'isPrevious' => false
  278. ];
  279. }
  280. return response()->json(['status' => 'success', 'data' => $data]);
  281. } catch (\Exception $e) {
  282. \Log::error('获取快照历史失败', ['error' => $e->getMessage()]);
  283. return response()->json(['status' => 'error', 'message' => '获取失败: ' . $e->getMessage()]);
  284. }
  285. }
  286. /**
  287. * 计算 Z 值(个控)
  288. */
  289. private function calculateZValue($stock, $levelBase)
  290. {
  291. if ($levelBase == 0) {
  292. return 0;
  293. }
  294. if ($stock < $levelBase * 2) {
  295. return 0;
  296. } elseif ($stock >= $levelBase * 2 && $stock < $levelBase * 4) {
  297. // 2x ~ 4x 区间:Z = FLOOR((stock - 2*base) / (2*base / 5)) + 1
  298. $stockDiff = $stock - ($levelBase * 2);
  299. $baseStep = $levelBase * 2 / 5;
  300. $zValue = floor($stockDiff / $baseStep) + 1;
  301. return min(max($zValue, 1), 5);
  302. } elseif ($stock >= $levelBase * 4 && $stock < $levelBase * 6) {
  303. // 4x ~ 6x 区间
  304. $stockDiff = $stock - ($levelBase * 4);
  305. $baseStep = $levelBase * 2 / 5;
  306. $zValue = floor($stockDiff / $baseStep) + 6;
  307. return min(max($zValue, 6), 10);
  308. } elseif ($stock >= $levelBase * 6 && $stock < $levelBase * 8) {
  309. // 6x ~ 8x 区间
  310. $stockDiff = $stock - ($levelBase * 6);
  311. $baseStep = $levelBase * 2 / 5;
  312. $zValue = floor($stockDiff / $baseStep) + 11;
  313. return min(max($zValue, 11), 15);
  314. } else {
  315. // 8x+ 区间
  316. $stockDiff = $stock - ($levelBase * 8);
  317. $baseStep = $levelBase * 4 / 5;
  318. $zValue = floor($stockDiff / $baseStep) + 16;
  319. return min(max($zValue, 16), 20);
  320. }
  321. }
  322. }