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