В создаваемой мной гибридной игре для Android и Cordova я позволяю пользователям указывать идентификатор в виде Emoji + буквенно-цифровое имя - то есть 0..9, A..Z, a..z - имя. Например,
taStackoverflow
Идентификаторы пользователя на стороне сервера хранятся с частями Emoji и Name, разделенными только частью Name, которая должна быть уникальной. Время от времени игра отображает «таблицу лиг», чтобы пользователь мог видеть, насколько хорошо они выступают по сравнению с другими игроками. Для этого сервер отправляет обратно последовательность из десяти значений «высокого балла», состоящих из эмодзи, имени и счета.
Затем он представляется пользователю в виде таблицы с тремя столбцами - по одному для Emoji, Name и Score. И здесь я столкнулся с небольшой проблемой. Первоначально я наивно полагал, что смогу понять эмодзи, просто взглянув на handle.codePointAt(0)
. Когда до меня дошло, что Emoji на самом деле может быть последовательностью из одного или нескольких 16-битных значений Unicode, я изменил свой код следующим образом
Часть 1 : разделение предоставленного пользователем «дескриптора»
var i,username,
codepoints = [],
handle = "?️StackOverflow",
len = handle,length;
while ((i < len) && (255 < handle.codePointAt(i)))
{codepoints.push(handle.codePointAt(i));i += 2;}
username = handle.substring(codepoints.length + 1);
На данный момент у меня есть ручка "dissected" с
codepoints = [128587, 8205, 65039];
username = 'Stackoverflow;
Примечание объяснения для i += 2
и использования handle.length
выше. Эта статья предполагает, что
- handle.codePointAt (n) вернет кодовую точку для полной суррогатной пары, если вы нажмете ведущую суррогатную матрицу. В моем случае, поскольку эмодзи должно быть первым персонажем, главные суррогаты для последовательности 16-битных юникодов для эмодзи находятся на
0,2,4...
. - Из той же статьи я узнал, что
String.length
в Javascript вернет число 16-битных кодовых единиц .
Часть II - Reгенерация Emojis для «таблицы лиги»
Предположим, что данные таблицы лиги, которые мои серверы возвращают в приложение, содержат запись {emoji: [128583, 8205, 65039],username:"Stackexchange",points:100}
для символа смайликов ?️. Теперь вот надоедливая вещь. Если я делаю
var origCP = [],
i = 0,
origEmoji = '?️',
origLen = origEmoji.length;
while ((i < origLen) && (255 < origEmoji.codePointAt(i))
{origCP.push(origEmoji.codePointAt(i);i += 2;}
, я получаю
origLen = 5, origCP = [128583, 8205, 65039]
Однако, если я восстанавливаю эмодзи из предоставленных данных
var reEmoji = String.fromCodePoint.apply(String,[128583, 8205, 65039]),
reEmojiLen = reEmoji.length;
, я получаю
reEmoji = '?️'
reEmojiLen = 4;
Таким образом, в то время как reEmoji имеет правильные эмодзи, его сообщаемая длина загадочным образом сократилась до 4 кодовых единиц вместо оригинальных 5.
Если я затем извлеку кодовые точки из восстановленных смайликов
var reCP = [],
i = 0;
while ((i < reEmojiLen) && (255 < reEmoji.codePointAt(i))
{reCP.push(reEmoji.codePointAt(i);i += 2;}
, что дает мне
reCP = [128583, 8205];
Даже любопытный, origEmoji.codePointAt(3)
дает значение задней суррогатной пары 9794
, в то время как reEmoji.codePointAt(3)
дает значение следующей полной суррогатной пары 65039
.
В этот момент я мог бы просто сказать
Меня это действительно волнует?
В конце концов, я просто хочу показать смайлики таблицы лиги в отдельномКолонка так что пока я получаю нужные смайлики, тонкости происходящего под капотом не имеют значения. Тем не менее, это может быть запасом проблем на будущее.
Может ли кто-нибудь здесь пролить свет на происходящее?