StockModeController.php 14 KB

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