суббота, 27 сентября 2014 г.

Реклама в WP8

Если честно, запускать игру только с микроплатежами я немного побаивался, а платной, как мне кажется, делать её совсем малоэффективно, поэтому решил посмотреть в сторону рекламы. Прошел уже год как я смотрел на рекламных провайдеров, многое изменилось, да и статистика была только по России - это не совсем то. Поэтому перед выпуском игры «Trucking Mania» я решил написать небольшую игру «Tapsquare» для тестирования рекламы.

В прошлый раз я смотрел на: AdMob, Microsoft Ads, Adduplex, Plus1, Begun.
В этот раз я решил взять их побольше и узнать где какой пользуется спросом, у меня вышло что-то такое:
Begun
Russia and CIS
Plus1
Russia and CIS
AdMob
Global
Adduplex
Global
Mobfox
Global
Inmobi
Global
Vserv
India
Smaato
Global
Leadbolt
Global
Mmedia
USA

В качестве ротора рекламы я решил использовать AdRotatorV2, но полностью переписал логику вывода рекламного баннера. Через некоторое время я планирую его опубликовать и сделать публичным, но пока никак не доходят руки. А если честно, можно обходиться и без ротатора, я нашел пару провайдеров, которые агрегируют внутри себя большое количество других рекламных площадок, в подробности я не вникал, но решил остановиться всё-таки на ротаторе, тк уже его написал и было интересно его испытать :)
К сожалению, приложение прожило не долго, из-за непредвиденных обстоятельств, а разбираться с ним было уже не охота.

Немного статистики в период с 26.08-26.09.2014, куда же без нее.
Пользователи
Сеансы
Средняя длительность
15122
95074
00:03:05


Страна или регион
Сеансы
Сеансы, %
1.
Russia
33 869
35,62 %
2.
Argentina
20 839
21,92 %
3.
China
4 173
4,39 %
4.
Ukraine
3 906
4,11 %
5.
Belarus
2 708
2,85 %
6.
Brazil
2 516
2,65 %
7.
Mexico
2 395
2,52 %
8.
Italy
1 949
2,05 %
9.
Chile
1 799
1,89 %
10.
United States
1 280
1,35 %

20% WP71 остальное WP80+
Ротатор работает по принципу: есть список доступных провайдеров, он формируется из конфигурационного файла для данного региона, если какой-то провайдер после запроса не смог подгрузить рекламу, он удаляется из этого списка, если список пуст, он возвращается к начальному состоянию.

Результат:

Рекламный провайдер
Fill rate, %
Показы
Клики
CTR, %
Доход
Begun
11,76
-
27
-
10,53руб
Plus1
16,87
10141
77
0,76
42,15руб
AdMob
98,67
635377
447
0,07
6,77$
Adduplex
97,47
200836
1157
0,74
0
Mobfox
77,07
-
-
-
-
Inmobi
68,48
-
-
-
-
Vserv
-
124
1
0.99
0
Smaato
54,32
94519
52
0,06
7,31$
Leadbolt
-
41
0
0
0,21$
Mmedia
-
-
-
-
-

Тут нужно понимать, что не у всех провайдеров SDK сообщает, что загрузилось.
Несколько слов о провайдерах:
  • Mmedia – сайт постоянно лежит, хотя вроде отзывы о нем не плохие, но у меня оно не завелось.
  • Leadbolt – работает плохо, так и не понял за что заработал 0,21$.
  • Inmobi – обновили панель управления да так, что старые перестали отображаться – не смог получить данные.
  • Mobfox – неведомая штука, заставить работать как рекламный провайдер так и не смог, походу он только агрегатор.
  • AdMob – имеет специфичный баннер, чтобы перейти по нему, нужно именно захотеть, поэтому такой низкий CTR.
  • Plus1 и Begun – в играх и приложениях показывает разную наполненность.

В целом результат понятен, и он меня разочаровал, а последняя новость от Plus1 и Begun вообще добила. Но есть и хорошая, AdMob для WP80+ показывает хороший FillRate что довольно хорошо и это подспорье Adduplex. Adduplex теперь позволяет у себя размещать платные рекламные компании, пока не пробовал.

Знающие люди посоветовали посмотреть в сторону полноэкранных игровых баннеров специально для игр, но руки попробовать не дошли.
Плохой результат — это тоже результат и в релизе «Trucking Mania» я решил ограничиться только микроплатежами!

среда, 17 сентября 2014 г.

Записки программиста #14. Релиз.

Статьи выходят с задержкой от реального развития событий. Прыгнем немного вперед по времени и можете меня поздравлять, мой долгострой пришел к концу - настал долгожданный релиз!


Игра доступна для WP8+ устройств, к сожалению, поддержка WP71 потребует очень больших усилий, начиная с полной перегенерации всего игрового контента из-за просчета в использованной памяти, в 90мб с графикой для 1280*768 я не влезу… заканчивая оптимизацией, тк много устройств под WP71 слабее самых бюджетных WP80…
Подведу итоги по данному проекту. В целом я реализовал весь функционал который изначально хотел, за исключением социальной авторизации и единого сетевого профиля. Получилось довольно неплохо, я доволен получившимся результатом.
Большое спасибо всем кто помогал с игрой и с тестированием!
Сразу после запуска возникала проблема с отображением для других языков на некоторых экранах, приложение тупо зависало, спасибо Тимуру, что помог оперативно её найти.
Спустя пару дней, нашелся человек которому игра очень понравилась Id 132 – он лидирует в топе с большим отрывом, за два дня купил все карты и осталось 2 машины не купленные, неожиданно если честно.
Игра собирает положительные отзывы и постепенно растет в топе, надеюсь взлетит высоко! К сожалению, с реализацией монетизации я немного прогадал, относительное понимание как следует (возможно) делать, появилось только со временем, есть уже планы на дальнейшее развитие игры, да и новых идей много.

четверг, 11 сентября 2014 г.

Записки программиста #13. Разработка back-end’а.

Разработка завершена и тестирование идет полным ходом. Немного хочу рассказать о подходах которые использовал и проблемы на которые наткнулся...

MongoDB
Интересное решение которое работает из коробки и работает очень неплохо, C# драйвер порадовал своей простотой, пока только одни положительные моменты.
В качестве ID в документах (аналог таблицы) принято использовать ObjectId или GuId. Но я в своем решении хотел бы видеть int, так как использую Player_{id}. Покопавшись в документации я понял:
1) стандартными средствами нельзя использовать для генерации int.
2) что можно использовать свой генератор.
Собственно, я его и написал, выглядит это примерно так, может кому и пригодиться:

[BsonId(IdGenerator = typeof(EmptyIdGenerator<RegistrationEntity>))]
public int ClientId { get; set; }

        public static class EmptyIdGenerator
       {
               public static int EmptyId { get; set; }
        }

        public class EmptyIdGenerator<T> : IIdGenerator where T : class    {
       
        public object GenerateId(object container, object document)
        {
            if (EmptyIdGenerator.EmptyId <= 0)
            {
                var col = (MongoCollection<T>)container;
                var sortBy = SortBy.Descending("_id");
                var last = col.FindAll().SetSortOrder(sortBy).FirstOrDefault();
                EmptyIdGenerator.EmptyId = (last == null) ? 1 : (int)last.ToBsonDocument()["_id"] + 1;
            }
            else
            {
                EmptyIdGenerator.EmptyId++;
            }
            return EmptyIdGenerator.EmptyId;
        }

        public bool IsEmpty(object id)
        {
            return ((id is int) && (id as int? == 0));
        }
    }

Пока по использованию mongodb нечего сказать больше к сожалению, не могу, но проблем вроде не возникает.

Логирование
Что за сервер который не ведет логов?! Куда складировать логи, в файл или в БД? Писать свой велосипед или использовать готовые решения? Вопросов больше чем ответов…
Тк велосипеды свои уже надоели решил посмотреть в сторону готовых решений, их много:
NLog, Log4Net, Enterprise Library, SmartInspect. Сравнений в интернете нашел уйму и выбор мой пал на NLog. Пока выбор мой был полностью оправдан и не разочаровался...

Тестирование
Тестирование в плане сервера вещь довольна необходимая, тк ручками там особо не натыкаешь.
Архитектура и логика сервера постоянно меняется, поэтому покрывать всю логику тестами будет не совсем правильно, но спать спокойно хочется, поэтому основной функционал и тот, который не будет меняться - будет обкладываться тестами.
Юнит тесты - я их немного недолюбливаю, поэтому в текущей версии она тестируют протокол на уровне пакетов и корректность их формирования, удобно вскрываются мелкие опечатки в данных вещах.
Интеграционный тесты - тестируют основной функционал, сервера, работу всех позитивных сценариев. Эти тесты я использую для проверки после внесённых изменений на работоспособность сервера.
Также на базе этих интеграционных тестов был написан клиент, который эмулирует работу клиента, но более интенсивную, на его основе я тестировал производительность сервера.

Миграция в облако
В качестве облачного провайдера была выбрана azure, в силу некоторых причин которые останутся за кадром. Вот тут меня ожидали кучи подводных камней! Скажу сразу я полный профан в администрировании, поэтому я наступал на все грабли которые были.
Для тестирования была создана Большая ВМ (4 ЦП по 1,6 ГГц, 7 ГБ ОЗУ)
В панели управления в разделе конечные точки были прописаны порты для сервера, внутри сервера на файервол настроил необходимые правила. Залил сервер и запустил - проблема номер раз, пакеты тупо не приходят. Скачал wireshark, поглядел, пакеты действительно уходят, но не приходят. Длительный поиск в гугле результатов не дал. Решил поиграть с настройками, из самых не понятных мне были настройки порта в панели управления, там нужно было указать общий и частный порт. Изначально я поставил их разные, на сервере биндился на публичный, это не правильно, их следует выставлять либо одинаковые, либо вещаться на приватный, а я то думал это для локальной сети настройки… Повторный запуск, пакет уходит, приходит на сервер, отправляется обратно и тишина. Да здравствует NAT!
Я изначально сделал общение примерно таким: создавал два сокета, один отправляет, другой принимает, в первом пакете говорим какой порт мы будем слушать, все хорошо, но только в локальной сети. Собственно, решения не меньше двух, аналоги как сделано в SIPe и использовать один порт, я выбрал наименее затратное - слушать и отправлять с одного порта. Звучит конечно все просто и логично, но выходные я убил на то, чтобы это все заработало в облаке.

Итог
Сервер уже удачно работает без сбоев неделю.
Результат максимальной нормальной работы 50 пакетов в тик, те 1500 пакетов в секунду, много это или мало, пока тяжело сказать. Для эмуляции максимальной нагрузки мне потребовалось около 2 000 клиентов с повышенной интенсивность, это больше чем 10 000 реальных клиентов единовременно, обмен пактов у меня не особо интенсивный :-)