Util.lua 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. local Config = require("Config")
  2. local pi = math.acos(-1)
  3. local sqrt2 = math.sqrt(2)
  4. local os = _G.os
  5. local math = _G.math
  6. local floor = math.floor
  7. local cos = math.cos
  8. local sin = math.sin
  9. local atan2 = math.atan2
  10. function getTableCount(s)
  11. local count = 0
  12. if s == nil then return count end
  13. for _ in pairs(s) do
  14. count = count + 1
  15. end
  16. return count
  17. end
  18. function copyTableSimple(s, t, noNewTB)
  19. for k, v in pairs(s) do
  20. if type(v) == "table" then
  21. if not noNewTB then
  22. t[k] = {}
  23. end
  24. copyTableSimple(v, t[k])
  25. else
  26. t[k] = v
  27. end
  28. end
  29. end
  30. function copyTable(s)
  31. if not s then return end
  32. local t = {}
  33. copyTableSimple(s,t)
  34. return t
  35. end
  36. function initTable(tb)
  37. if not tb then return end
  38. for k in pairs(tb) do
  39. tb[k]= nil
  40. end
  41. end
  42. function cleanTable(s)
  43. for k,v in pairs(s) do
  44. s[k] = nil
  45. end
  46. end
  47. function getBit(n, index)
  48. local div = 2 ^ index
  49. return (n - n % div) / div % 2
  50. end
  51. function setBit(n, index)
  52. local bit = getBit(n, index)
  53. if bit ~= 0 then
  54. assert()
  55. end
  56. return n + 2 ^ index
  57. end
  58. function hypot(a, b)
  59. return math.sqrt(a * a + b * b)
  60. end
  61. local out = {}
  62. local out_len = 0
  63. function printTable(tb, step)
  64. if not step then
  65. step = 0
  66. out_len = 0
  67. end
  68. for k, v in pairs(tb) do
  69. for i = 1, step do
  70. out_len = out_len + 1
  71. out[out_len] = " "
  72. end
  73. if type(k) == "number" then
  74. out_len = out_len + 1
  75. out[out_len] = "["
  76. end
  77. out_len = out_len + 1
  78. out[out_len] = k
  79. if type(k) == "number" then
  80. out_len = out_len + 1
  81. out[out_len] = "]"
  82. end
  83. out_len = out_len + 1
  84. out[out_len] = "="
  85. if type(v) == "string" then
  86. out_len = out_len + 1
  87. out[out_len] = "\""
  88. end
  89. out_len = out_len + 1
  90. out[out_len] = type(v) == "table" and "" or v
  91. if type(v) == "boolean" then
  92. out[out_len] = tostring(v)
  93. end
  94. if type(v) == "string" then
  95. out_len = out_len + 1
  96. out[out_len] = "\""
  97. end
  98. out_len = out_len + 1
  99. out[out_len] = "\n"
  100. if type(v) == "table" then
  101. printTable(v, step + 1)
  102. end
  103. end
  104. if step == 0 then
  105. local str = table.concat(out, nil, 1, out_len)
  106. print(str)
  107. return str
  108. end
  109. end
  110. function serialize(val, name, skipmap, depth, buf)
  111. skipmap = skipmap or {} -- 用来检测循环引用
  112. depth = depth or 0
  113. buf = buf or {}
  114. local indent = string.rep(" ", depth)
  115. local t = type(val)
  116. if t == "string" then
  117. table.insert(buf, string.format("%q", val))
  118. elseif t == "number" or t == "boolean" or t == "nil" then
  119. table.insert(buf, tostring(val))
  120. elseif t == "table" then
  121. -- 循环引用检测
  122. if skipmap[val] then
  123. table.insert(buf, skipmap[val])
  124. return buf
  125. end
  126. skipmap[val] = string.format("<%s>", name or "table")
  127. table.insert(buf, "{\n")
  128. local idx = 1
  129. for k, v in pairs(val) do
  130. -- 拼 key
  131. if type(k) == "string" and k:match("^[%a_][%w_]*$") then
  132. table.insert(buf, indent .. " " .. k .. " = ")
  133. else
  134. table.insert(buf, indent .. " [" )
  135. serialize(k, nil, skipmap, 0, buf)
  136. table.insert(buf, "] = ")
  137. end
  138. -- 拼 value
  139. serialize(v, nil, skipmap, depth + 1, buf)
  140. table.insert(buf, ",\n")
  141. end
  142. table.insert(buf, indent .. "}")
  143. elseif t == "function" then
  144. table.insert(buf, string.format("<function:%s>", tostring(val)))
  145. elseif t == "userdata" then
  146. table.insert(buf, string.format("<userdata:%s>", tostring(val)))
  147. elseif t == "thread" then
  148. table.insert(buf, string.format("<thread:%s>", tostring(val)))
  149. else
  150. table.insert(buf, "<??>")
  151. end
  152. return buf
  153. end
  154. -- 判断是否同一天
  155. function isSameDay(time1)
  156. if not time1 then
  157. return
  158. end
  159. local now = os.time()
  160. local tToday = os.date("%Y%m%d", now)
  161. local t1 = os.date("%Y%m%d", time1)
  162. if tToday ~= t1 then
  163. return
  164. end
  165. return now
  166. end
  167. -- 判断传入的两个时间是否同一天
  168. function isSameDayByTimes(time1,time2)
  169. if not time1 or not time2 then
  170. return
  171. end
  172. local t1 = os.date("%Y%m%d", time1)
  173. local t2 = os.date("%Y%m%d", time2)
  174. if t1 ~= t2 then
  175. return
  176. end
  177. return true
  178. end
  179. -- 是否同一个月
  180. function isSameMonth(time)
  181. local now = os.date("*t")
  182. local d = os.date("*t",time)
  183. return now.year==d.year and now.month==d.month
  184. end
  185. -- 判断传入时间点与当前时间相差多少天
  186. local tb = {}
  187. function diffDay(time)
  188. local d = os.date("*t",time)
  189. tb.year = d.year
  190. tb.month = d.month
  191. tb.day = d.day
  192. time = os.time(tb)
  193. local nowDay = os.date("*t")
  194. tb.year = nowDay.year
  195. tb.month = nowDay.month
  196. tb.day = nowDay.day
  197. local nowTime = os.time(tb)
  198. return math.ceil(math.abs(nowTime-time)/86400)
  199. end
  200. -- 判断传入时间点与当前时间相差多少小时
  201. function diffHour(time)
  202. local d = os.date("*t",time)
  203. tb.year = d.year
  204. tb.month = d.month
  205. tb.day = d.day
  206. time = os.time(tb)
  207. local nowDay = os.date("*t")
  208. tb.year = nowDay.year
  209. tb.month = nowDay.month
  210. tb.day = nowDay.day
  211. local nowTime = os.time(tb)
  212. return math.ceil(math.abs(nowTime-time)/3600)
  213. end
  214. function diffDayByTimes(time1,time2)
  215. local t1 = os.date("*t",time1)
  216. tb.year = t1.year
  217. tb.month = t1.month
  218. tb.day = t1.day
  219. time1 = os.time(tb)
  220. local t2 = os.date("*t",time2)
  221. tb.year = t2.year
  222. tb.month = t2.month
  223. tb.day = t2.day
  224. time2 = os.time(tb)
  225. return math.ceil(math.abs(time1-time2)/86400)
  226. end
  227. -- 获取本月有多少天
  228. function getMonthDayNum()
  229. local currMonthDate = os.date("*t")
  230. tb.year = currMonthDate.year
  231. tb.month = currMonthDate.month
  232. tb.day = currMonthDate.day
  233. currMonthDate.hour = nil
  234. currMonthDate.min = nil
  235. currMonthDate.sec = nil
  236. currMonthDate.day = 1
  237. tb.day = 1
  238. if tb.month<12 then
  239. tb.month = tb.month + 1
  240. else
  241. tb.year = tb.year+1
  242. tb.month = 1
  243. end
  244. local nextMonthFirstDayTime = os.time(tb)
  245. local currMonthTime = os.time(currMonthDate)
  246. return math.floor(math.abs(nextMonthFirstDayTime-currMonthTime)/86400)
  247. end
  248. -- 取时间间隔 s
  249. function getInterval(time)
  250. if not time then
  251. return math.huge
  252. end
  253. local now = os.time()
  254. return now - time
  255. end
  256. --参数结构:year=****,month=****,day=****
  257. function isTime( startDate, endDate)
  258. local date_min = os.time(startDate) - 12 * 60 * 60
  259. local date_max = os.time(endDate) + 12 * 60 * 60
  260. local tmp_time = os.time()
  261. if not (date_min <= tmp_time and tmp_time < date_max) then
  262. return false
  263. end
  264. return true, date_max - tmp_time
  265. end
  266. -- check time
  267. function checkTime(startTimeConf,endTimeConf)
  268. local nowDate = os.date("*t")
  269. local nowMin = nowDate.hour * 60 + nowDate.min
  270. local startMin = startTimeConf.hour * 60 + startTimeConf.min
  271. local endMin = endTimeConf.hour * 60 + endTimeConf.min
  272. if nowMin >= startMin and nowMin < endMin then
  273. return true
  274. end
  275. end
  276. -- 检查传入时间,是否经过resetTime时间点;
  277. function isTimeOver(time,resetTime)
  278. if not time or not resetTime then
  279. return
  280. end
  281. local nowTime = os.time()
  282. local nowDay = os.date("%d", nowTime) + 0
  283. local nowHour = os.date("%H", nowTime) + 0
  284. local getDay = os.date("%d", time) + 0
  285. local getHour = os.date("%H", time) + 0
  286. local dirty = false
  287. if nowDay == getDay then
  288. if getHour < resetTime and nowHour >= resetTime then
  289. dirty = true
  290. end
  291. elseif nowDay == getDay + 1 then
  292. if nowHour >= resetTime then
  293. dirty = true
  294. end
  295. else
  296. dirty = true
  297. end
  298. return dirty
  299. end
  300. tmpDate = tmpDate or {}
  301. -- 取本月开始时间
  302. function getMonthStartTime(time)
  303. local d = os.date("*t",time)
  304. tmpDate.year = d.year
  305. tmpDate.month = d.month
  306. tmpDate.day = 1
  307. tmpDate.hour = 0
  308. tmpDate.min = 0
  309. tmpDate.sec = 0
  310. return os.time(tmpDate)
  311. end
  312. -- 取本周开始时间 周一凌晨
  313. function getWeekStartTime(time)
  314. local d = os.date("*t",time)
  315. tmpDate.year = d.year
  316. tmpDate.month = d.month
  317. tmpDate.hour = 0
  318. tmpDate.min = 0
  319. tmpDate.sec = 0
  320. local day = nil
  321. if d.wday == 1 then
  322. day = 6
  323. else
  324. day = d.wday - 2
  325. end
  326. tmpDate.day = d.day - day
  327. return os.time(tmpDate)
  328. end
  329. -- 取本日开始时间
  330. function getDayStartTime(time)
  331. local d = os.date("*t",time)
  332. tmpDate.year = d.year
  333. tmpDate.month = d.month
  334. tmpDate.day = d.day
  335. tmpDate.hour = 0
  336. tmpDate.min = 0
  337. tmpDate.sec = 0
  338. return os.time(tmpDate)
  339. end
  340. -- 取相差几天时间
  341. function getNextDayTime(time, day)
  342. local d = os.date("*t",time)
  343. tmpDate.year = d.year
  344. tmpDate.month = d.month
  345. tmpDate.day = d.day
  346. tmpDate.hour = 0
  347. tmpDate.min = 0
  348. tmpDate.sec = 0
  349. local ts = os.time(tmpDate)
  350. local dayTs = day * 86400
  351. return ts + dayTs
  352. end
  353. -- 获取前几天数据
  354. function getLastDayTime(time, day)
  355. local d = os.date("*t",time)
  356. tmpDate.year = d.year
  357. tmpDate.month = d.month
  358. tmpDate.day = d.day
  359. tmpDate.hour = 0
  360. tmpDate.min = 0
  361. tmpDate.sec = 0
  362. local ts = os.time(tmpDate)
  363. local dayTs = day * 86400
  364. return ts - dayTs
  365. end
  366. -- 取本日特定小时时间戳
  367. function getDayHourTime(time, hour)
  368. local d = os.date("*t",time)
  369. tmpDate.year = d.year
  370. tmpDate.month = d.month
  371. tmpDate.day = d.day
  372. tmpDate.hour = hour
  373. tmpDate.min = 0
  374. tmpDate.sec = 0
  375. return os.time(tmpDate)
  376. end
  377. -- 判断传入时间点,是否同周
  378. function isSameWeek(time1,time2)
  379. if not time1 or not time2 then
  380. return
  381. end
  382. return getWeekStartTime(time1) == getWeekStartTime(time2)
  383. end
  384. -- 星期中第几天的数字表示 1(表示星期天)到 7(表示星期六)
  385. function getWeekDay( time )
  386. local time = time or os.time()
  387. local d = os.date("*t",time)
  388. return d.wday
  389. end
  390. -- 处于第几分钟
  391. function getMin(time)
  392. time = time or os.time()
  393. local d = os.date("*t",time)
  394. return d.min
  395. end
  396. function split(str, split_char,isNumber)
  397. local t = {}
  398. while string.len(str)>0 do
  399. local pos = string.find(str, split_char);
  400. if (not pos) then
  401. if isNumber then
  402. t[#t + 1] = tonumber(str) or 0
  403. else
  404. t[#t + 1] = str
  405. end
  406. break
  407. end
  408. local sub_str = string.sub(str, 1, pos - 1)
  409. if isNumber then
  410. t[#t + 1] = tonumber(sub_str) or 0
  411. else
  412. t[#t + 1] = sub_str
  413. end
  414. str = string.sub(str, pos + 1, #str)
  415. end
  416. return t
  417. end
  418. TONUMBER_KEY = "key"
  419. TONUMBER_VALUE = "value"
  420. TONUMBER_ALL = "all"
  421. --- 灵活解析键值字符串
  422. -- @param str 源字符串,如 "1001-10|1002-11"
  423. -- @param segSep 段分隔符,如 "|"(默认 "|")
  424. -- @param kvSep 键值分隔符,如 "-"(默认 "-")
  425. -- @param tonumberMode 可选:"key"只转键,"value"只转值,"all"都转,nil不转
  426. -- @return table 解析后的字典表
  427. function parseKVString(str, segSep, kvSep, tonumberMode)
  428. -- 防护:nil 或空字符串直接返回空表
  429. if not str or str == "" then
  430. return {}
  431. end
  432. -- 去掉首尾空白(可选,视需求而定)
  433. str = string.match(str, "^%s*(.-)%s*$") or ""
  434. if str == "" then
  435. return {}
  436. end
  437. segSep = segSep or "|"
  438. kvSep = kvSep or "-"
  439. -- 转义模式中的特殊字符
  440. local function escapePattern(s)
  441. return (string.gsub(s, "([%-%.%+%*%?%[%]%^%$%(%)%%])", "%%%1"))
  442. end
  443. local segPattern = escapePattern(segSep)
  444. local result = {}
  445. for segment in string.gmatch(str, "([^" .. segPattern .. "]+)") do
  446. local pos = string.find(segment, kvSep, 1, true)
  447. if pos then
  448. local key = string.sub(segment, 1, pos - 1)
  449. local value = string.sub(segment, pos + string.len(kvSep))
  450. if tonumberMode == "key" or tonumberMode == "all" then
  451. key = tonumber(key) or key
  452. end
  453. if tonumberMode == "value" or tonumberMode == "all" then
  454. value = tonumber(value) or value
  455. end
  456. result[key] = value
  457. end
  458. end
  459. return result
  460. end
  461. -- 根据KEY从小到大排序
  462. function pairsByKeys(t)
  463. local a = {}
  464. for n in pairs(t) do
  465. a[#a+1] = n
  466. end
  467. table.sort(a)
  468. local i = 0
  469. return function()
  470. i = i + 1
  471. return a[i], t[a[i]]
  472. end
  473. end
  474. function cmptb(a, b)
  475. for k, v in pairs(a) do
  476. if type(v) == "table" then
  477. if type(b[k]) ~= "table" then
  478. return
  479. end
  480. if not cmptb(v, b[k]) then
  481. return
  482. end
  483. else
  484. if b[k] ~= v and k ~= "now" and k ~= "uid" then
  485. return
  486. end
  487. end
  488. end
  489. for k, v in pairs(b) do
  490. if type(v) == "table" then
  491. if type(a[k]) ~= "table" then
  492. return
  493. end
  494. if not cmptb(v, a[k]) then
  495. return
  496. end
  497. else
  498. if a[k] ~= v and k ~= "now" and k ~= "uid" then
  499. return
  500. end
  501. end
  502. end
  503. return true
  504. end
  505. function getWay(dx, dy)
  506. return ((floor(( atan2(dy, dx) + 11.388) / 1.57)) % 4) * 2;
  507. end
  508. function tableIsEmpty(tb)
  509. return _G.next(tb) == nil
  510. end
  511. -- 服务器是否符合
  512. function checkSvrIndex(svrIndexs, svrIndex)
  513. if #svrIndexs < 1 then return true end
  514. if not svrIndex then
  515. svrIndex = Config.SVR_INDEX
  516. end
  517. for i = 1, #svrIndexs do
  518. if svrIndexs[i][1] <= svrIndex and
  519. svrIndex <= svrIndexs[i][2] then
  520. return true
  521. end
  522. end
  523. end
  524. -- 含中文文本长度
  525. function utf8len(content)
  526. local len = string.len(content)
  527. local left = len
  528. local cnt = 0
  529. local arr = {0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}
  530. while left ~= 0 do
  531. local tmp = string.byte(content, -left)
  532. local i = #arr
  533. while arr[i] do
  534. if tmp >= arr[i] then
  535. left = left - i
  536. break
  537. end
  538. i = i - 1
  539. end
  540. cnt = cnt + 1
  541. end
  542. return cnt
  543. end
  544. function checkRandom(cmpValue)
  545. local r = math.random(0,10000)
  546. if r < cmpValue then
  547. return true
  548. end
  549. end
  550. SEPARATOR = "||"
  551. function format(...)
  552. local str = ""
  553. local t = {}
  554. for k,v in ipairs({...}) do
  555. if k == 1 then
  556. str = str .. v
  557. else
  558. t = split(v, SEPARATOR)
  559. if #t > 1 then
  560. t[1] = string.gsub(t[1],"({(.-)})",function(p1,p2)
  561. p2 = tonumber(p2)
  562. if p2 and t[p2+1] then
  563. return string.sub(t[p2+1], 2)
  564. else
  565. return p1
  566. end
  567. end)
  568. end
  569. if t[1] then
  570. str = str .. SEPARATOR .. t[1]
  571. end
  572. end
  573. end
  574. return str
  575. end
  576. --------------------------------------------------------
  577. --- 新增table.find函数
  578. ---@param1 array 数组
  579. ---@param2 elem 目标元素
  580. --------------------------------------------------------
  581. table.find = function(array,elem)
  582. for idx,e in ipairs(array) do
  583. if e == elem then
  584. return idx
  585. end
  586. end
  587. end
  588. --------------------------------------------------------
  589. --- 新增table.shuffle函数
  590. --- @param1 array 数组
  591. --------------------------------------------------------
  592. table.shuffle = function(array)
  593. for i = 1,#array do
  594. local r = math.random(1,#array)
  595. array[i],array[r] = array[r],array[i]
  596. end
  597. return array
  598. end
  599. --------------------------------------------------------
  600. --- 新增table.copy函数
  601. --- @param1 array 数组
  602. --------------------------------------------------------
  603. function table.copy(object)
  604. -- 已经复制过的table,key为复制源table,value为复制后的table
  605. -- 为了防止table中的某个属性为自身时出现死循环
  606. -- 避免本该是同一个table的属性,在复制时变成2个不同的table(内容同,但是地址关系和原来的不一样了)
  607. local lookup_table = {}
  608. local function _copy(object)
  609. if type(object) ~= 'table' then -- 非table类型都直接返回
  610. return object
  611. elseif lookup_table[object] then
  612. return lookup_table[object]
  613. end
  614. local new_table = {}
  615. lookup_table[object] = new_table
  616. for k,v in pairs(object) do
  617. new_table[_copy(k)] = _copy(v)
  618. end
  619. -- 这里直接拿mt来用是因为一般对table操作不会很粗暴的修改mt的相关内容
  620. return setmetatable(new_table, getmetatable(object))
  621. end
  622. return _copy(object)
  623. end
  624. --------------------------------------------------------
  625. --- 新增table.print_lua_table函数
  626. --- @param1 array 数组
  627. --------------------------------------------------------
  628. local function print_lua_table(lua_table, indent)
  629. indent = indent or 0
  630. for k, v in pairs(lua_table) do
  631. if type(k) == "string" then
  632. k = string.format("%q", k)
  633. end
  634. local szSuffix = ""
  635. if type(v) == "table" then
  636. szSuffix = "{"
  637. end
  638. local szPrefix = string.rep(" ", indent)
  639. formatting = szPrefix.."["..k.."]".." = "..szSuffix
  640. if type(v) == "table" then
  641. print(formatting)
  642. print_lua_table(v, indent + 1)
  643. print(szPrefix.."},")
  644. else
  645. local szValue = ""
  646. if type(v) == "string" then
  647. szValue = string.format("%q", v)
  648. else
  649. szValue = tostring(v)
  650. end
  651. print(formatting..szValue..",")
  652. end
  653. end
  654. end
  655. table.print_lua_table = print_lua_table
  656. -- 打印当前堆栈
  657. function PrintNowStackTrace()
  658. local stackTrace = debug.traceback("", 2)
  659. print("[PrintNowStackTrace] 堆栈信息 "..stackTrace)
  660. end