514 lines
16 KiB
Go
514 lines
16 KiB
Go
package gamemanagement
|
||
|
||
import (
|
||
"strings"
|
||
"unicode"
|
||
)
|
||
|
||
const (
|
||
robotNicknameLanguageArabic = "arabic"
|
||
robotNicknameLanguageEnglish = "english"
|
||
)
|
||
|
||
var defaultRobotAvatarSources = []string{
|
||
"https://randomuser.me/api/portraits/men/0.jpg",
|
||
"https://randomuser.me/api/portraits/men/1.jpg",
|
||
"https://randomuser.me/api/portraits/men/2.jpg",
|
||
"https://randomuser.me/api/portraits/men/3.jpg",
|
||
"https://randomuser.me/api/portraits/men/4.jpg",
|
||
"https://randomuser.me/api/portraits/men/5.jpg",
|
||
"https://randomuser.me/api/portraits/men/6.jpg",
|
||
"https://randomuser.me/api/portraits/men/7.jpg",
|
||
"https://randomuser.me/api/portraits/men/8.jpg",
|
||
"https://randomuser.me/api/portraits/men/9.jpg",
|
||
"https://randomuser.me/api/portraits/men/10.jpg",
|
||
"https://randomuser.me/api/portraits/men/11.jpg",
|
||
"https://randomuser.me/api/portraits/men/12.jpg",
|
||
"https://randomuser.me/api/portraits/men/13.jpg",
|
||
"https://randomuser.me/api/portraits/men/14.jpg",
|
||
"https://randomuser.me/api/portraits/men/15.jpg",
|
||
"https://randomuser.me/api/portraits/men/16.jpg",
|
||
"https://randomuser.me/api/portraits/men/17.jpg",
|
||
"https://randomuser.me/api/portraits/men/18.jpg",
|
||
"https://randomuser.me/api/portraits/men/19.jpg",
|
||
"https://randomuser.me/api/portraits/men/20.jpg",
|
||
"https://randomuser.me/api/portraits/men/21.jpg",
|
||
"https://randomuser.me/api/portraits/men/22.jpg",
|
||
"https://randomuser.me/api/portraits/men/23.jpg",
|
||
"https://randomuser.me/api/portraits/men/24.jpg",
|
||
"https://randomuser.me/api/portraits/men/25.jpg",
|
||
"https://randomuser.me/api/portraits/men/26.jpg",
|
||
"https://randomuser.me/api/portraits/men/27.jpg",
|
||
"https://randomuser.me/api/portraits/men/28.jpg",
|
||
"https://randomuser.me/api/portraits/men/29.jpg",
|
||
"https://randomuser.me/api/portraits/men/30.jpg",
|
||
"https://randomuser.me/api/portraits/men/31.jpg",
|
||
"https://randomuser.me/api/portraits/men/32.jpg",
|
||
"https://randomuser.me/api/portraits/men/33.jpg",
|
||
"https://randomuser.me/api/portraits/men/34.jpg",
|
||
"https://randomuser.me/api/portraits/men/35.jpg",
|
||
"https://randomuser.me/api/portraits/men/36.jpg",
|
||
"https://randomuser.me/api/portraits/men/37.jpg",
|
||
"https://randomuser.me/api/portraits/men/38.jpg",
|
||
"https://randomuser.me/api/portraits/men/39.jpg",
|
||
"https://randomuser.me/api/portraits/men/40.jpg",
|
||
"https://randomuser.me/api/portraits/men/41.jpg",
|
||
"https://randomuser.me/api/portraits/men/42.jpg",
|
||
"https://randomuser.me/api/portraits/men/43.jpg",
|
||
"https://randomuser.me/api/portraits/men/44.jpg",
|
||
"https://randomuser.me/api/portraits/men/45.jpg",
|
||
"https://randomuser.me/api/portraits/men/46.jpg",
|
||
"https://randomuser.me/api/portraits/men/47.jpg",
|
||
"https://randomuser.me/api/portraits/men/48.jpg",
|
||
"https://randomuser.me/api/portraits/men/49.jpg",
|
||
"https://randomuser.me/api/portraits/men/50.jpg",
|
||
"https://randomuser.me/api/portraits/men/51.jpg",
|
||
"https://randomuser.me/api/portraits/men/52.jpg",
|
||
"https://randomuser.me/api/portraits/men/53.jpg",
|
||
"https://randomuser.me/api/portraits/men/54.jpg",
|
||
"https://randomuser.me/api/portraits/men/55.jpg",
|
||
"https://randomuser.me/api/portraits/men/56.jpg",
|
||
"https://randomuser.me/api/portraits/men/57.jpg",
|
||
"https://randomuser.me/api/portraits/men/58.jpg",
|
||
"https://randomuser.me/api/portraits/men/59.jpg",
|
||
"https://randomuser.me/api/portraits/men/60.jpg",
|
||
"https://randomuser.me/api/portraits/men/61.jpg",
|
||
"https://randomuser.me/api/portraits/men/62.jpg",
|
||
"https://randomuser.me/api/portraits/men/63.jpg",
|
||
"https://randomuser.me/api/portraits/men/64.jpg",
|
||
"https://randomuser.me/api/portraits/men/65.jpg",
|
||
"https://randomuser.me/api/portraits/men/66.jpg",
|
||
"https://randomuser.me/api/portraits/men/67.jpg",
|
||
"https://randomuser.me/api/portraits/men/68.jpg",
|
||
"https://randomuser.me/api/portraits/men/69.jpg",
|
||
"https://randomuser.me/api/portraits/men/70.jpg",
|
||
"https://randomuser.me/api/portraits/men/71.jpg",
|
||
"https://randomuser.me/api/portraits/men/72.jpg",
|
||
"https://randomuser.me/api/portraits/men/73.jpg",
|
||
"https://randomuser.me/api/portraits/men/74.jpg",
|
||
"https://randomuser.me/api/portraits/men/75.jpg",
|
||
"https://randomuser.me/api/portraits/men/76.jpg",
|
||
"https://randomuser.me/api/portraits/men/77.jpg",
|
||
"https://randomuser.me/api/portraits/men/78.jpg",
|
||
"https://randomuser.me/api/portraits/men/79.jpg",
|
||
"https://randomuser.me/api/portraits/men/80.jpg",
|
||
"https://randomuser.me/api/portraits/men/81.jpg",
|
||
"https://randomuser.me/api/portraits/men/82.jpg",
|
||
"https://randomuser.me/api/portraits/men/83.jpg",
|
||
"https://randomuser.me/api/portraits/men/84.jpg",
|
||
"https://randomuser.me/api/portraits/men/85.jpg",
|
||
"https://randomuser.me/api/portraits/men/86.jpg",
|
||
"https://randomuser.me/api/portraits/men/87.jpg",
|
||
"https://randomuser.me/api/portraits/men/88.jpg",
|
||
"https://randomuser.me/api/portraits/men/89.jpg",
|
||
"https://randomuser.me/api/portraits/men/90.jpg",
|
||
"https://randomuser.me/api/portraits/men/91.jpg",
|
||
"https://randomuser.me/api/portraits/men/92.jpg",
|
||
"https://randomuser.me/api/portraits/men/93.jpg",
|
||
"https://randomuser.me/api/portraits/men/94.jpg",
|
||
"https://randomuser.me/api/portraits/men/95.jpg",
|
||
"https://randomuser.me/api/portraits/men/96.jpg",
|
||
"https://randomuser.me/api/portraits/men/97.jpg",
|
||
"https://randomuser.me/api/portraits/men/98.jpg",
|
||
"https://randomuser.me/api/portraits/men/99.jpg",
|
||
"https://randomuser.me/api/portraits/women/0.jpg",
|
||
"https://randomuser.me/api/portraits/women/1.jpg",
|
||
"https://randomuser.me/api/portraits/women/2.jpg",
|
||
"https://randomuser.me/api/portraits/women/3.jpg",
|
||
"https://randomuser.me/api/portraits/women/4.jpg",
|
||
"https://randomuser.me/api/portraits/women/5.jpg",
|
||
"https://randomuser.me/api/portraits/women/6.jpg",
|
||
"https://randomuser.me/api/portraits/women/7.jpg",
|
||
"https://randomuser.me/api/portraits/women/8.jpg",
|
||
"https://randomuser.me/api/portraits/women/9.jpg",
|
||
"https://randomuser.me/api/portraits/women/10.jpg",
|
||
"https://randomuser.me/api/portraits/women/11.jpg",
|
||
"https://randomuser.me/api/portraits/women/12.jpg",
|
||
"https://randomuser.me/api/portraits/women/13.jpg",
|
||
"https://randomuser.me/api/portraits/women/14.jpg",
|
||
"https://randomuser.me/api/portraits/women/15.jpg",
|
||
"https://randomuser.me/api/portraits/women/16.jpg",
|
||
"https://randomuser.me/api/portraits/women/17.jpg",
|
||
"https://randomuser.me/api/portraits/women/18.jpg",
|
||
"https://randomuser.me/api/portraits/women/19.jpg",
|
||
"https://randomuser.me/api/portraits/women/20.jpg",
|
||
"https://randomuser.me/api/portraits/women/21.jpg",
|
||
"https://randomuser.me/api/portraits/women/22.jpg",
|
||
"https://randomuser.me/api/portraits/women/23.jpg",
|
||
"https://randomuser.me/api/portraits/women/24.jpg",
|
||
"https://randomuser.me/api/portraits/women/25.jpg",
|
||
"https://randomuser.me/api/portraits/women/26.jpg",
|
||
"https://randomuser.me/api/portraits/women/27.jpg",
|
||
"https://randomuser.me/api/portraits/women/28.jpg",
|
||
"https://randomuser.me/api/portraits/women/29.jpg",
|
||
"https://randomuser.me/api/portraits/women/30.jpg",
|
||
"https://randomuser.me/api/portraits/women/31.jpg",
|
||
"https://randomuser.me/api/portraits/women/32.jpg",
|
||
"https://randomuser.me/api/portraits/women/33.jpg",
|
||
"https://randomuser.me/api/portraits/women/34.jpg",
|
||
"https://randomuser.me/api/portraits/women/35.jpg",
|
||
"https://randomuser.me/api/portraits/women/36.jpg",
|
||
"https://randomuser.me/api/portraits/women/37.jpg",
|
||
"https://randomuser.me/api/portraits/women/38.jpg",
|
||
"https://randomuser.me/api/portraits/women/39.jpg",
|
||
"https://randomuser.me/api/portraits/women/40.jpg",
|
||
"https://randomuser.me/api/portraits/women/41.jpg",
|
||
"https://randomuser.me/api/portraits/women/42.jpg",
|
||
"https://randomuser.me/api/portraits/women/43.jpg",
|
||
"https://randomuser.me/api/portraits/women/44.jpg",
|
||
"https://randomuser.me/api/portraits/women/45.jpg",
|
||
"https://randomuser.me/api/portraits/women/46.jpg",
|
||
"https://randomuser.me/api/portraits/women/47.jpg",
|
||
"https://randomuser.me/api/portraits/women/48.jpg",
|
||
"https://randomuser.me/api/portraits/women/49.jpg",
|
||
"https://randomuser.me/api/portraits/women/50.jpg",
|
||
"https://randomuser.me/api/portraits/women/51.jpg",
|
||
"https://randomuser.me/api/portraits/women/52.jpg",
|
||
"https://randomuser.me/api/portraits/women/53.jpg",
|
||
"https://randomuser.me/api/portraits/women/54.jpg",
|
||
"https://randomuser.me/api/portraits/women/55.jpg",
|
||
"https://randomuser.me/api/portraits/women/56.jpg",
|
||
"https://randomuser.me/api/portraits/women/57.jpg",
|
||
"https://randomuser.me/api/portraits/women/58.jpg",
|
||
"https://randomuser.me/api/portraits/women/59.jpg",
|
||
"https://randomuser.me/api/portraits/women/60.jpg",
|
||
"https://randomuser.me/api/portraits/women/61.jpg",
|
||
"https://randomuser.me/api/portraits/women/62.jpg",
|
||
"https://randomuser.me/api/portraits/women/63.jpg",
|
||
"https://randomuser.me/api/portraits/women/64.jpg",
|
||
"https://randomuser.me/api/portraits/women/65.jpg",
|
||
"https://randomuser.me/api/portraits/women/66.jpg",
|
||
"https://randomuser.me/api/portraits/women/67.jpg",
|
||
"https://randomuser.me/api/portraits/women/68.jpg",
|
||
"https://randomuser.me/api/portraits/women/69.jpg",
|
||
"https://randomuser.me/api/portraits/women/70.jpg",
|
||
"https://randomuser.me/api/portraits/women/71.jpg",
|
||
"https://randomuser.me/api/portraits/women/72.jpg",
|
||
"https://randomuser.me/api/portraits/women/73.jpg",
|
||
"https://randomuser.me/api/portraits/women/74.jpg",
|
||
"https://randomuser.me/api/portraits/women/75.jpg",
|
||
"https://randomuser.me/api/portraits/women/76.jpg",
|
||
"https://randomuser.me/api/portraits/women/77.jpg",
|
||
"https://randomuser.me/api/portraits/women/78.jpg",
|
||
"https://randomuser.me/api/portraits/women/79.jpg",
|
||
"https://randomuser.me/api/portraits/women/80.jpg",
|
||
"https://randomuser.me/api/portraits/women/81.jpg",
|
||
"https://randomuser.me/api/portraits/women/82.jpg",
|
||
"https://randomuser.me/api/portraits/women/83.jpg",
|
||
"https://randomuser.me/api/portraits/women/84.jpg",
|
||
"https://randomuser.me/api/portraits/women/85.jpg",
|
||
"https://randomuser.me/api/portraits/women/86.jpg",
|
||
"https://randomuser.me/api/portraits/women/87.jpg",
|
||
"https://randomuser.me/api/portraits/women/88.jpg",
|
||
"https://randomuser.me/api/portraits/women/89.jpg",
|
||
"https://randomuser.me/api/portraits/women/90.jpg",
|
||
"https://randomuser.me/api/portraits/women/91.jpg",
|
||
"https://randomuser.me/api/portraits/women/92.jpg",
|
||
"https://randomuser.me/api/portraits/women/93.jpg",
|
||
"https://randomuser.me/api/portraits/women/94.jpg",
|
||
"https://randomuser.me/api/portraits/women/95.jpg",
|
||
"https://randomuser.me/api/portraits/women/96.jpg",
|
||
"https://randomuser.me/api/portraits/women/97.jpg",
|
||
"https://randomuser.me/api/portraits/women/98.jpg",
|
||
"https://randomuser.me/api/portraits/women/99.jpg",
|
||
}
|
||
|
||
var defaultArabicRobotNicknames = []string{
|
||
"أمير",
|
||
"سيف",
|
||
"مالك",
|
||
"فارس",
|
||
"ليث",
|
||
"بدر",
|
||
"ماهر",
|
||
"رامي",
|
||
"كريم",
|
||
"سامي",
|
||
"عمر",
|
||
"يوسف",
|
||
"آدم",
|
||
"ريان",
|
||
"زيد",
|
||
"نور",
|
||
"ياسين",
|
||
"أنس",
|
||
"خالد",
|
||
"طارق",
|
||
"حازم",
|
||
"نادر",
|
||
"وسيم",
|
||
"جواد",
|
||
"مروان",
|
||
"إياد",
|
||
"نبيل",
|
||
"هلال",
|
||
"تميم",
|
||
"سلمان",
|
||
"راشد",
|
||
"جاسم",
|
||
"ماجد",
|
||
"سلطان",
|
||
"عادل",
|
||
"هاني",
|
||
"بلال",
|
||
"يزن",
|
||
"غيث",
|
||
"قصي",
|
||
"سليم",
|
||
"ريان_الليل",
|
||
"نجم",
|
||
"ملك_اللعبة",
|
||
"صقر",
|
||
"ذيب",
|
||
"أسد",
|
||
"الزعيم",
|
||
"القناص",
|
||
"الأسطورة",
|
||
"ظل",
|
||
"برق",
|
||
"رعد",
|
||
"موج",
|
||
"نمر",
|
||
"شهاب",
|
||
"فهد",
|
||
"نايف",
|
||
"نوف",
|
||
"ليان",
|
||
"ريم",
|
||
"سارة",
|
||
"مريم",
|
||
"لينا",
|
||
"هنا",
|
||
"جود",
|
||
"تالا",
|
||
"دانا",
|
||
"لارا",
|
||
"ياسمين",
|
||
"نوران",
|
||
"رؤى",
|
||
"سما",
|
||
"ملك",
|
||
"جنى",
|
||
"آية",
|
||
"ندى",
|
||
"فرح",
|
||
"أمل",
|
||
"هدى",
|
||
"سلمى",
|
||
"ليلى",
|
||
"رنا",
|
||
"نورا",
|
||
"ديما",
|
||
"مايا",
|
||
"ميس",
|
||
"رهف",
|
||
"شهد",
|
||
"غلا",
|
||
"لولو",
|
||
"وردة",
|
||
"قمر",
|
||
"نجمة",
|
||
"لؤلؤة",
|
||
"الملكة",
|
||
"أميرة",
|
||
"روح",
|
||
"حلم",
|
||
"بسمة",
|
||
}
|
||
|
||
var defaultEnglishRobotNicknames = []string{
|
||
"Alex",
|
||
"Jordan",
|
||
"Taylor",
|
||
"Morgan",
|
||
"Riley",
|
||
"Nova",
|
||
"Phoenix",
|
||
"Hunter",
|
||
"Luna",
|
||
"Mia",
|
||
"Noah",
|
||
"Liam",
|
||
"Ava",
|
||
"Emma",
|
||
"Oliver",
|
||
"Elijah",
|
||
"James",
|
||
"William",
|
||
"Benjamin",
|
||
"Lucas",
|
||
"Mason",
|
||
"Ethan",
|
||
"Logan",
|
||
"Jackson",
|
||
"Levi",
|
||
"Sebastian",
|
||
"Mateo",
|
||
"Jack",
|
||
"Owen",
|
||
"Theodore",
|
||
"Aiden",
|
||
"Samuel",
|
||
"Joseph",
|
||
"John",
|
||
"David",
|
||
"Wyatt",
|
||
"Matthew",
|
||
"Luke",
|
||
"Asher",
|
||
"Carter",
|
||
"Julian",
|
||
"Grayson",
|
||
"Leo",
|
||
"Jayden",
|
||
"Gabriel",
|
||
"Isaac",
|
||
"Lincoln",
|
||
"Anthony",
|
||
"Hudson",
|
||
"Dylan",
|
||
"Ezra",
|
||
"Thomas",
|
||
"Charles",
|
||
"Christopher",
|
||
"Jaxon",
|
||
"Maverick",
|
||
"Josiah",
|
||
"Isaiah",
|
||
"Andrew",
|
||
"Elias",
|
||
"Joshua",
|
||
"Nathan",
|
||
"Caleb",
|
||
"Ryan",
|
||
"Adrian",
|
||
"Miles",
|
||
"Eli",
|
||
"Nolan",
|
||
"Christian",
|
||
"Aaron",
|
||
"Cameron",
|
||
"Ezekiel",
|
||
"Colton",
|
||
"Luca",
|
||
"Landon",
|
||
"Hannah",
|
||
"Sofia",
|
||
"Isabella",
|
||
"Amelia",
|
||
"Olivia",
|
||
"Charlotte",
|
||
"Harper",
|
||
"Evelyn",
|
||
"Abigail",
|
||
"Ella",
|
||
"Scarlett",
|
||
"Grace",
|
||
"Chloe",
|
||
"Victoria",
|
||
"Aria",
|
||
"Penelope",
|
||
"Layla",
|
||
"Zoey",
|
||
"Nora",
|
||
"Lily",
|
||
"Ellie",
|
||
"Violet",
|
||
"Aurora",
|
||
"Stella",
|
||
"Hazel",
|
||
}
|
||
|
||
func normalizeRobotNicknameLanguage(value string) string {
|
||
// 后台只开放英语和阿拉伯语两类昵称池;未知值回退英语,避免历史请求继续落到英阿混合池。
|
||
switch strings.ToLower(strings.TrimSpace(value)) {
|
||
case "ar", "arabic", "arab":
|
||
return robotNicknameLanguageArabic
|
||
case "en", "english":
|
||
return robotNicknameLanguageEnglish
|
||
default:
|
||
return robotNicknameLanguageEnglish
|
||
}
|
||
}
|
||
|
||
func robotAccountLanguage(nicknameLanguage string) string {
|
||
// 用户资料里的 language 跟昵称池保持一致,后续客户端或运营筛选机器人时不用再反推昵称字符集。
|
||
if normalizeRobotNicknameLanguage(nicknameLanguage) == robotNicknameLanguageArabic {
|
||
return "ar"
|
||
}
|
||
return "en"
|
||
}
|
||
|
||
func robotNickname(index int, nicknameLanguage string) string {
|
||
// 机器人昵称只从单一语言池取值,不能再拼随机 hex,否则会出现数字、下划线和英阿混排。
|
||
language := normalizeRobotNicknameLanguage(nicknameLanguage)
|
||
if language == robotNicknameLanguageArabic {
|
||
return robotNicknameFromPool(index, defaultArabicRobotNicknames, "لاعب", language)
|
||
}
|
||
return robotNicknameFromPool(index, defaultEnglishRobotNicknames, "Player", language)
|
||
}
|
||
|
||
func robotNicknameFromPool(index int, pool []string, fallback string, language string) string {
|
||
// 前 100 个直接使用预设名;超过预设数量时用同语言两个预设名拼接,保证批量 200 个仍然不带数字后缀。
|
||
if index < 0 {
|
||
index = 0
|
||
}
|
||
if len(pool) == 0 {
|
||
return fallback
|
||
}
|
||
base := sanitizeRobotNickname(pool[index%len(pool)], language)
|
||
if base == "" {
|
||
base = fallback
|
||
}
|
||
if index < len(pool) {
|
||
return base
|
||
}
|
||
next := sanitizeRobotNickname(pool[(index%len(pool)+1)%len(pool)], language)
|
||
if next == "" || next == base {
|
||
next = sanitizeRobotNickname(pool[(index+index/len(pool)+2)%len(pool)], language)
|
||
}
|
||
if next == "" || next == base {
|
||
return base
|
||
}
|
||
return base + next
|
||
}
|
||
|
||
func sanitizeRobotNickname(value string, language string) string {
|
||
// 预设里可能有旧的分隔符或非目标语言字符;写库前统一剔除,保证“英语纯英语、阿拉伯语纯阿拉伯语”。
|
||
var builder strings.Builder
|
||
for _, item := range strings.TrimSpace(value) {
|
||
switch language {
|
||
case robotNicknameLanguageArabic:
|
||
if unicode.Is(unicode.Arabic, item) {
|
||
builder.WriteRune(item)
|
||
}
|
||
default:
|
||
if (item >= 'A' && item <= 'Z') || (item >= 'a' && item <= 'z') {
|
||
builder.WriteRune(item)
|
||
}
|
||
}
|
||
}
|
||
return builder.String()
|
||
}
|
||
|
||
func robotGender(index int, requested string) string {
|
||
requested = strings.TrimSpace(requested)
|
||
if requested != "" {
|
||
return requested
|
||
}
|
||
if index%2 == 0 {
|
||
return "male"
|
||
}
|
||
return "female"
|
||
}
|
||
|
||
func robotAvatarSource(index int, requested []string) string {
|
||
if source := pickString(requested, index); source != "" {
|
||
return source
|
||
}
|
||
if len(defaultRobotAvatarSources) == 0 {
|
||
return ""
|
||
}
|
||
return defaultRobotAvatarSources[index%len(defaultRobotAvatarSources)]
|
||
}
|