local String_Utility = {} local private = {} local _stringIdDict={} local UNIT_DESC local HUNDRED_MILLION_UNIT_DESC local MailParamFormatType = { OfficialPositionTitle = "1", OfficialPositionGrade = "2", ThreeTeamFightLevel = "3", ThreeTeamFightReward = "4", TimeStamp2HourMinute = "5", --时间戳转【时:分】,解决时间的本地化 } local base_pb = require("Proto/base_pb") local showKB = "%dKB" local showMB = "%.2fMB" local BYTE_ZERO_NUM = string.byte(0) local BYTE_NINE_NUM = string.byte(9) local IDS_PREFIX = "IDS" local combineIdsParams = {} local IDS_COUNTRY_NAME = { [LuaConst.Kingdom.Wei] = "IDS_DrawCard_PageTitle_WEI", [LuaConst.Kingdom.Shu] = "IDS_DrawCard_PageTitle_SHU", [LuaConst.Kingdom.Wu] = "IDS_DrawCard_PageTitle_WU", [LuaConst.Kingdom.Qun] = "IDS_DrawCard_PageTitle_QUN", } local COLOR_COUNTRY_NAME = { [LuaConst.Kingdom.Wei] = "6f8ace", [LuaConst.Kingdom.Shu] = "5ec56f", [LuaConst.Kingdom.Wu] = "e05c59", [LuaConst.Kingdom.Qun] = "d5a35e", } function String_Utility.OnStartup() private.InitStringUtil() end --一个汉字算一位 function String_Utility.GetStrLen(input) local len = string.len(input) local left = len local cnt = 0 local arr = {0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc} while left ~= 0 do local tmp = string.byte(input, -left) local i = #arr while arr[i] do if tmp >= arr[i] then left = left - i break end i = i - 1 end cnt = cnt + 1 end return cnt end function String_Utility.CutStrByLength(str, length) local last = #str + 1 local prev = nil local sum = 0 local len = 0 for i in utf8.byte_indices(str) do if prev then local count = i - prev if count == 3 then --汉字 sum = sum + 2 else sum = sum + 1 end len = len + 1 end if length and sum >= length then return string.sub(str, 1, i-1) end prev = i end if prev then local count = last - prev if count == 3 then --汉字 sum = sum + 2 else sum = sum + 1 end len = len + 1 end if length and sum > length then return string.sub(str, 1, prev-1) end return str end --返回utf8字符串占的总字符数(汉字占2 其他占1) function String_Utility.GetStrCharCount(str,chineseLength) --chineseLength 一个汉字算几个字符 local last = #str + 1 local prev = nil local sum = 0 chineseLength = chineseLength or 2 for i in utf8.byte_indices(str) do if prev then local count = i - prev if count == 3 then --汉字 sum = sum + chineseLength else sum = sum + 1 end end prev = i end if prev then local count = last - prev if count == 3 then --汉字 sum = sum + chineseLength else sum = sum + 1 end end return sum end function String_Utility.GetTextCharLengthWithoutRichTag(text) if string.isNilOrEmpty(text) then return 0 end local rawLength = String_Utility.GetStrCharCount(text) for str in string.gmatch(text, "%b<>") do rawLength = rawLength - String_Utility.GetStrCharCount(str) end return rawLength end function String_Utility.IsChineseChar(str) local prev = nil for i in utf8.byte_indices(str) do if prev then local count = i - prev if count ~= 3 then --汉字 return false end end prev = i end return true end --返回协议消息字符串 function String_Utility.GetMessageStr(strParams) local str if strParams then for i, v in ipairs(strParams) do str = v break end end return str end --邮件参数解析 --1、文本(IDS) --2、非文本 formatType|param function String_Utility.GetMessageFormatStr(strFormat,strParams) --local str = UIUtils.GetLocalizedTxt(Const_IDS[strFormat]) if strParams then for i, v in ipairs(strParams) do if string.match(v,"^IDS") then strParams[i] = UIUtils.GetLocalizedTxt(Const_IDS[v]) else local formatType, param = string.match(v, "^(%d+)|(%w+)$", 1) if formatType and param then if formatType == MailParamFormatType.OfficialPositionTitle then strParams[i] = CTL.OfficialPosition.GetColorTitleFullTxt(tonumber(param)) end end end end return string.FormatByIdsId(Const_IDS[strFormat],unpack(strParams)) end return UIUtils.GetLocalizedTxt(Const_IDS[strFormat]) end --string 和 int 的映射,用于传递给C#使用,避免内存分配 function String_Utility.GetIdByString(str) if _stringIdDict[str] ~=nil then return _stringIdDict[str] end local newId= UIUtils.SaveStringToId(str) _stringIdDict[str]=newId return newId end function String_Utility.SetLabelContent(label,content) if type(content) == "number" then --IDS UIUtils.SetLabelText(label,content) else UIUtils.SetLabel(label,content) end end -- 字节大小转换 size默认为KB 根据大小转换MB或KB function String_Utility.TransferKiloBytesSize(size) if size == nil then return string.format(showKB, 0); end if size >= 1024 then return string.format(showMB, size / 1024) end return string.format(showKB, size); end function String_Utility.TransferBytesSize(size) if size == nil then return string.format(showKB, 0); end local kiloBytes = size / 1024 if kiloBytes >= 1024 then return String_Utility.TransferKiloBytesSize(kiloBytes) end return string.format(showKB, kiloBytes) end --判断该文本是否为ids function String_Utility.CheckIsIds(str) local value = rawget(Const_IDS, str) return value ~= nil end function String_Utility.GetCountStr(count) --超过一万展示 xx万 if UNIT_DESC == nil then UNIT_DESC = UIUtils.GetLocalizedTxt(Const_IDS.IDS_LocalNum_TenThousand) end if HUNDRED_MILLION_UNIT_DESC == nil then HUNDRED_MILLION_UNIT_DESC = UIUtils.GetLocalizedTxt(Const_IDS.IDS_LocalNum_HundredMillion) end local COUNT_UNIT = Localization.GetCountUnit() local HUNDRED_MILLION_COUNT_UNIT = Localization.GetHundredMillionCountUnit() if count < COUNT_UNIT then return count elseif count >= COUNT_UNIT and count < HUNDRED_MILLION_COUNT_UNIT then return private.GetCountUnitStr(count, COUNT_UNIT, UNIT_DESC) else return private.GetCountUnitStr(count, HUNDRED_MILLION_COUNT_UNIT, HUNDRED_MILLION_UNIT_DESC) end end function private.GetCountUnitStr(count, coutUnit, unitDesc) local reminder = count % coutUnit local intPart = (count - reminder) / coutUnit if reminder >= coutUnit / 10 then local decimalPart = reminder / (coutUnit / 10) --保留两位两位小数 local _, decimal = math.modf(decimalPart) if decimal > 0 then decimalPart = decimalPart * 10 end return intPart .. string.format(".%d", decimalPart) .. unitDesc elseif reminder >= coutUnit / 100 then local decimalPart = reminder / (coutUnit / 100) return intPart .. string.format(".0%d", decimalPart) .. unitDesc else return string.format("%d", count / coutUnit) .. unitDesc end end -- 邮件\提示 根据参数获得显示字符串 function String_Utility.GetShowStrByParamInfo(paramInfo) local resultStr = "" if not paramInfo then return resultStr end for _, v in ipairs (paramInfo.value) do if paramInfo.type == base_pb.ItemId then resultStr = resultStr .. UTL.Item.GetItemColorName(v.uint32Param) elseif paramInfo.type == base_pb.StrOrIds then if string.match(v.stringParam, "^IDS") and Const_IDS[v.stringParam] then resultStr = resultStr .. UIUtils.GetLocalizedTxt(Const_IDS[v.stringParam]) else local formatType, param = string.match(v.stringParam, "^(%d+)|(%w+)$", 1) if formatType and param then if formatType == MailParamFormatType.OfficialPositionTitle then resultStr = resultStr .. CTL.OfficialPosition.GetColorTitleFullTxt(tonumber(param)) elseif formatType == MailParamFormatType.OfficialPositionGrade then resultStr = resultStr .. CTL.OfficialPosition.GetGradeDescByGradeID(tonumber(param)) elseif formatType == MailParamFormatType.ThreeTeamFightLevel then resultStr = resultStr .. CTL.ThreeTeamFight.GetRankDesc(tonumber(param), false, true) elseif formatType == MailParamFormatType.TimeStamp2HourMinute then resultStr = resultStr .. os.date(UTL.Time.FormatDateEnum.HM, tonumber(param)) end else resultStr = resultStr .. v.stringParam end end end end return resultStr end function String_Utility.CutZHStrByLength(str, length) --把中文当一个长度 去裁剪 local last = #str + 1 local prev = nil local sum = 0 local len = 0 for i in utf8.byte_indices(str) do if prev then local count = i - prev if count == 3 then --汉字 sum = sum + 2 else sum = sum + 1 end len = len + 1 end if length and len >= length then return string.sub(str, 1, i-1) end prev = i end if prev then local count = last - prev if count == 3 then --汉字 sum = sum + 2 else sum = sum + 1 end len = len + 1 end if length and len > length then return string.sub(str, 1, prev-1) end return str end function String_Utility.GetErrorCodeMsg(errorCode) local tipErrorMsg if Const_IDS["IDS_ERROR_NETWORK_AUTH_" .. errorCode] then tipErrorMsg = UIUtils.GetLocalizedTxt(Const_IDS["IDS_ERROR_NETWORK_AUTH_" .. errorCode]); else tipErrorMsg = string.gsub(UIUtils.GetLocalizedTxt(Const_IDS["IDS_ERROR_NETWORK_AUTH"]), "{0}", errorCode); end return tipErrorMsg or "" end --默认拼接方式,无空格 local function ConcatByDefault(param1, param2, param3, param4, param5) if param2 == nil then return param1 elseif param3 == nil then return string.format("%s%s", param1, param2) elseif param4 == nil then return string.format("%s%s%s", param1, param2, param3) elseif param5 == nil then return string.format("%s%s%s%s", param1, param2, param3, param4) else return string.format("%s%s%s%s%s", param1, param2, param3, param4, param5) end end --参数之间加空格 local function ConcatWithSpace(param1, param2, param3, param4, param5) if param2 == nil then return param1 elseif param3 == nil then return string.format("%s %s", param1, param2) elseif param4 == nil then return string.format("%s %s %s", param1, param2, param3) elseif param5 == nil then return string.format("%s %s %s %s", param1, param2, param3, param4) else return string.format("%s %s %s %s %s", param1, param2, param3, param4, param5) end end --字符0到9对应48到57,只需判断这个范围即知道是否为数字 function String_Utility.IsByteNumber(byte) return byte >= BYTE_ZERO_NUM and byte <= BYTE_NINE_NUM end -- id:int -- IDSCombine表ID function String_Utility.FormatCombineTextByID(id) local data = DataSheetManager.IDSCombine:GetDataByID(id) if data == nil then logging.error(LTAG.ERROR, "IDSCombine表ID 不存在 :",id) return "" end -- 无参数,直接返回IDS if #data.replaceIDSs == 0 then return UIUtils.GetLocalizedTxt(Const_IDS[data.MainIDS]) end -- 参数中可能包含IDS table.clearArray(combineIdsParams) for _, v in ipairs(data.replaceIDSs) do if string.find(v, IDS_PREFIX, 1, true) then table.insert(combineIdsParams, UIUtils.GetLocalizedTxt(Const_IDS[v])) else table.insert(combineIdsParams, v) end end return string.FormatByIdsId(Const_IDS[data.MainIDS], table.unpack(combineIdsParams)) end --英文参数拼接加上空格,其他语言暂时不需要 function private.InitStringUtil() if Localization.IsEnglish() or Localization.IsIndonesian() or Localization.IsVietnamese() or Localization.IsThailand() then string.Concat = ConcatWithSpace else string.Concat = ConcatByDefault end end -- 折扣字符串 -- discountVal = 80, CN:8折, 其他:20%off local PercentStr = "%d%%" function String_Utility.GetDiscountStrByIdsId(discountVal, idsId) --默认的ids local idsId = idsId or Const_IDS.IDS_Store_SaleOff if discountVal == 0 then return UIUtils.GetLocalizedTxt(Const_IDS.IDS_Store_Free) end local num = String_Utility.GetDiscountNum(discountVal) if Localization.IsAllChinese() then return string.FormatByIdsId(idsId, num) else return string.FormatByIdsId(idsId, string.format(PercentStr, num)) end end -- 默认是中文折扣 -- discountVal = 80, CN:8折, 其他:20%off function String_Utility.GetDiscountNum(discountVal) if Localization.IsAllChinese() then return discountVal / 10 else return 100 - discountVal end end function String_Utility.GetDiscountedValue(discountVal, num) return num * discountVal / 100 end -- | Unicode符号范围 | UTF-8编码方式 n | (十六进制) | (二进制) ---+-----------------------+------------------------------------------------------ -- 1 | 0000 0000 - 0000 007F | 0xxxxxxx -- 2 | 0000 0080 - 0000 07FF | 110xxxxx 10xxxxxx -- 3 | 0000 0800 - 0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx -- 4 | 0001 0000 - 0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx -- 5 | 0020 0000 - 03FF FFFF | 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx -- 6 | 0400 0000 - 7FFF FFFF | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 表 1. UTF-8的编码规则 -- 以下, 还是以汉字"严"为例, 演示怎样实现UTF-8编码. -- 已知"严"的unicode是4E25(1001110 00100101), 依据上表, 能够发现4E25处在第三行的 -- 范围内(0000 0800 - 0000 FFFF), 因此"严"的UTF-8编码须要三个字节, 即格式是 -- "1110xxxx 10xxxxxx 10xxxxxx". 然后, 从"严"的最后一个二进制位開始, 依次从后向前 -- 填入格式中的x, 多出的位补0. 这样就得到了, "严"的UTF-8编码是 "11100100 10111000 -- Arabic (0600–06FF, 256 characters) -- Arabic 占两个字符长度 所以 0x0060 二进制 110 0000 0000 以上述2的方式补全 11011000 = 216 1000 0000 = 128 -- 06ff 二进制110 1111 1111 以上述2的方式补全 11011011 = 219 1011 1111 = 191 --综上所述 阿拉伯语第一个字符的int值在lua上的范围是 216 - 219 第二个是 129 - 191 function String_Utility.ArabicFix(str) if private.OpenCheckArabic() then local prev = 0 local isArabicStr = false for i=1,#str do local byteValue = string.byte(str, i) if (byteValue >=128 and byteValue <= 191) and (prev >= 216 and prev <= 219) then isArabicStr = true break end prev = byteValue end if isArabicStr then local fixStr = CSExt.CSFunc_ArabicFix(str) or str return true, fixStr end end return false, str end function private.OpenCheckArabic() --阿拉伯语言国家在非洲与亚洲的连接处 时区从0 - 4 if not UNITY_EDITOR then local localTimeZone = UTL.Time.GetLocalTimeZone() return localTimeZone >= 0 and localTimeZone <= 4 else return false end end function String_Utility.SetCountryName(label, country) UIUtils.SetLabelText(label, Const_IDS[IDS_COUNTRY_NAME[country]]) end function String_Utility.GetCountryName(country) return UIUtils.GetLocalizedTxt(Const_IDS[IDS_COUNTRY_NAME[country]]) end function String_Utility.GetColorCountryName(country) return UTL.Color.GetColorfulText(COLOR_COUNTRY_NAME[country], IDS_COUNTRY_NAME[country]) end --解析deeplink url,返回活动类型key和参数param function String_Utility.CheckDeeplink(url) if not url then return nil end local splits = string.split(url, "?") local key = splits[1] local param if #splits == 2 then param = tonumber(splits[2]) end return key, param end --x月x日 function String_Utility.FormatMonthDay(month, day) local monthStr = string.FormatByIdsId(Const_IDS["IDS_MonthCommon"], month) local dayStr = string.FormatByIdsId(Const_IDS["IDS_DayCommon"], day) if Localization.IsAllChinese() or Localization.IsJapanese() then return monthStr .. dayStr elseif GameAppInfo.IsVietnamPackage() then return day .. "/" .. month else return monthStr .. "/" .. dayStr end end local smallIconPathTable = {} function String_Utility.GetSmallIconPath(iconPath) local path = smallIconPathTable[iconPath] if path == nil then path = string.gsub(iconPath, "(.*)(/)", ConstAssetPathConfig.Path1) smallIconPathTable[iconPath] = path end return path end --判断该acid是否为机器人 function String_Utility.IsRobotByAcid(acid) if string.match(acid, ".(-Robot)$") then return true end return false end --float数字保留小数点后有效数字 --0 正常的四舍五入,1,向下取,2向上取 --validNum 保留几位 function String_Utility.GetPercentFormatFloat(floatNum, customType, validNum) local tempNum = 1 for i=1, validNum do tempNum = tempNum*10 end floatNum = floatNum*tempNum if customType == 0 then floatNum = math.floor(floatNum+0.5)/tempNum elseif customType == 1 then floatNum = math.floor(floatNum)/tempNum elseif customType == 2 then floatNum = math.ceil(floatNum)/tempNum end return string.format("%." .. validNum .. "f%%", floatNum) end return String_Utility