Jump to content
Korean Random
Kapany3uk

[Lobby/Widgets] Виджет "Статистика игрока" в ангаре

Recommended Posts

Вывод статистики игрока непосредственно в ангаре, с помощью widgets.xc и макросов вида {{mystat.*}} 

 

post-24956-0-79243800-1502400896.jpg

 

скрипт в папку xvm/py_macro/

hangar_stat.zip   (необходим для расчета количества победных боев до желаемого процента побед)

'код'

 

import traceback
from xvm_main.python.logger import *

from gui.Scaleform.daapi.view.lobby.hangar.Hangar import Hangar
from helpers import dependency
from skeletons.gui.game_control import IBootcampController
from skeletons.gui.shared import IItemsCache

@xvm.export('winrate_next')
def winrate_next(diff):
    if dependency.instance(IBootcampController).isInBootcamp():
        return
    itemsCache = dependency.instance(IItemsCache)
    wins = itemsCache.items.getAccountDossier().getRandomStats().getWinsCount()
    battles = itemsCache.items.getAccountDossier().getRandomStats().getBattlesCount()
    winrate = itemsCache.items.getAccountDossier().getRandomStats().getWinsEfficiency() * 100
    if wins is None or battles is None or winrate is None:
        return '#'
    f = winrate - int(winrate)
    if f < diff:
        next = int(winrate) + diff
    elif f + diff < 1:
        next = round(winrate,2) + diff
    else:
        next = int(winrate) + diff + 1
    value = int((100 * wins - next * battles) / (next - 100)) + 1
    if next == int(next):
        next = int(next)
    return '<font color="#F8F400">{}</font>{}<font color="#F8F400">{}%</font>'.format(value, '{{l10n:toWithSpaces}}', next)

 

файлы в папку с конфигом

widgetsTemplates.xc   (виджет часов дефолтный)

 

'варианты размещение в ангаре'

 
post-24956-0-86960000-1502400897_thumb.jpg  - в центре (см. файлы выше)

 

post-24956-0-23278500-1502400896_thumb.jpg  - слева, под экипажем / над каруселью (см. код ниже)

'код для экрана 1366х768 и кастомной карусели'

 


"stat_hangar": {
    "enabled": true,
    "layer": "normal",
    "type": "extrafield",
    "formats": [
      { // фоновая картинка
        "x": 320,       // координата "х" равна 'width' картинки
        "y": 482,
        "scaleX": -1,   // зеркальное отражение по горизонтали
        "format": "<img src='xvm://res/icons/clock/clockBg.png' width='320' height='80'>"
      },
      {
        "updateEvent": "ON_MY_STAT_LOADED",
        "x": 7,
        "y": 485,
        "width": 320,   // ширина текстового поля равна ширине фоновой картинки
        "height": 150,
        // "screenHAlign": "center",
        "shadow": { "alpha": 80, "blur": 4, "strength": 2 },
        "textFormat": { "color": "0x959688", "size": 15 },
        "format": "<font size='13'>{{l10n:General stats}} (<font color='#F9F1BC'>{{py:xvm.formatDate('%Y-%m-%d')}}</font>)</font>\n{{l10n:WN8}}: <font color='{{mystat.c_wn8}}'>{{mystat.xwn8}} ({{mystat.wn8}})</font> {{l10n:EFF}}: <font color='{{mystat.c_eff}}'>{{mystat.xeff}} ({{mystat.eff}})</font>\n{{l10n:Avg level}}: <font color='{{mystat.c_avglvl}}'>{{mystat.avglvl%.2f}}</font>\n<font size='13'>{{l10n:Wins}}: <font color='{{mystat.c_winrate}}'>{{mystat.winrate%.2f~%}}</font>  ({{py:winrate_next(0.5)}} / {{py:winrate_next(1)}})</font>"
      }
    ]
  },

 

пример возможных вариантов для вывода "осталось побед до"

post-24956-0-94308400-1502400896.jpg

строка выводится через макрос {{py:winrate_next(...)}}, где задается интервал (минимум одна сотая (0.01)) до желаемого процента побед;

допускаются отрицательные числа, в результате макрос выведет отрицательное число [не] побед (-поражений), которые приведут к снижению процента побед на заданный интервал, 

 

'текущий список доступных макросов для виджета (см. macros-hangar_ru.txt)'

 

│ {{mystat.player_id}}       │ . │ . │ ID текущего игрока
│ {{mystat.name}}            │ . │ . │ ник текущего игрока
│ {{mystat.flag}}            │ . │ . │ флаг, выбранный в личном кабинете на сайте www.modxvm.com
│ {{mystat.clan}}            │ . │ . │ название клана
│ {{mystat.clan_id}}         │ . │ . │ ID клана
│ {{mystat.winrate}}         │ . │ . │ общий процент побед (Global Win Ratio)
│ {{mystat.eff}}             │ . │ . │ рейтинг эффективности (РЭ) по wot-news.com: http://www.koreanrandom.com/forum/topic/13386-
│ {{mystat.wgr}}             │ . │ . │ рейтинг WG (ЛРИ): http://www.koreanrandom.com/forum/topic/13433-
│ {{mystat.wn6}}             │ . │ . │ рейтинг WN6: http://www.koreanrandom.com/forum/topic/13388-
│ {{mystat.wn8}}             │ . │ . │ рейтинг WN8: http://www.koreanrandom.com/forum/topic/13434-
│ {{mystat.xeff}}            │ . │ . │ шкала XVM для РЭ  (значения 00-99, XX для топовых показателей)
│ {{mystat.xwgr}}            │ . │ . │ шкала XVM для WN8 (значения 00-99, XX для топовых показателей)
│ {{mystat.xwn6}}            │ . │ . │ шкала XVM для WN6 (значения 00-99, XX для топовых показателей)
│ {{mystat.xwn8}}            │ . │ . │ шкала XVM для WG  (значения 00-99, XX для топовых показателей)
│ {{mystat.avglvl}}          │ . │ . │ средний уровень техники игрока
│ {{mystat.battles}}         │ . │ . │ общее количество боев
│ {{mystat.wins}}            │ . │ . │ общее количество побед
│ {{mystat.def}}             │ . │ . │ общее количество очков защиты базы
│ {{mystat.frg}}             │ . │ . │ общее количество фрагов
│ {{mystat.dmg}}             │ . │ . │ общее количество очков нанесенного урона
│ {{mystat.cap}}             │ . │ . │ общее количество очков захвата базы
│ {{mystat.hip}}             │ . │ . │ общий средний процент попаданий
│ {{mystat.spo}}             │ . │ . │ общее количество засвеченных танков
│ {{mystat.ts}}              │ . │ . │ время последнего обновления статистики (timestamp)
│ {{mystat.c_winrate}}       │ . │ . │ динамический цвет по общему проценту побед
│ {{mystat.c_eff}}           │ . │ . │ динамический цвет по рейтингу эффективности (РЭ)
│ {{mystat.c_wgr}}           │ . │ . │ динамический цвет по WG
│ {{mystat.c_wn6}}           │ . │ . │ динамический цвет по WN6
│ {{mystat.c_wn8}}           │ . │ . │ динамический цвет по WN8
│ {{mystat.c_xeff}}          │ . │ . │ динамический цвет по шкале XVM для РЭ
│ {{mystat.c_xwgr}}          │ . │ . │ динамический цвет по шкале XVM для WG 
│ {{mystat.c_xwn6}}          │ . │ . │ динамический цвет по шкале XVM для WN6
│ {{mystat.c_xwn8}}          │ . │ . │ динамический цвет по шкале XVM для WN8
│ {{mystat.c_avglvl}}        │ . │ . │ динамический цвет по среднему уровню техники
│ {{mystat.c_battles}}       │ . │ . │ динамический цвет по количеству боев

 

upd: Отключение:

для стандартного (многофайлового) конфига читаем тут

для однофайлового конфига - смотрим тут

Edited by Mixaill
  • Upvote 15

Share this post


Link to post

Short link
Share on other sites

 

 

Where can i find Python script for {{mystat. ...}}, those macros doesn't work for me.
for 9.19 see commit - the first and last simultaneously )) 

Share this post


Link to post

Short link
Share on other sites

Во втором варианте, скорее всего лутше будет сделать ориентацию относительно низа.

Для себя дела так:

  "stat_hangar": {
    "enabled": true,
    "layer": "normal",
    "type": "extrafield",
    "formats": [
      { // фоновая картинка
        "x": 320,       // координата "х" равна 'width' картинки
        "y": -238,
        "height": 80,
        "scaleX": -1,   // зеркальное отражение по горизонтали
        "screenVAlign": "bottom",
        "format": "<img src='xvm://res/icons/clock/clockBg.png' width='320' height='80'>"
      },
      {
        "updateEvent": "ON_MY_STAT_LOADED",
        "x": 7,
        "y": -234,
        "width": 320,   // ширина текстового поля равна ширине фоновой картинки
        "height": 80,
        "screenVAlign": "bottom",
        "shadow": { "alpha": 80, "blur": 4, "strength": 2 },
        "textFormat": { "color": "0x959688", "size": 15 },
        "format": "<font size='13'>{{l10n:General stats}} (<font color='#F9F1BC'>{{py:xvm.formatDate('%Y-%m-%d')}}</font>)</font>\n{{l10n:WN8}}: <font color='{{mystat.c_wn8}}'>{{mystat.xwn8}} ({{mystat.wn8}})</font> {{l10n:EFF}}: <font color='{{mystat.c_eff}}'>{{mystat.xeff}} ({{mystat.eff}})</font>\n{{l10n:Avg level}}: <font color='{{mystat.c_avglvl}}'>{{mystat.avglvl%.2f}}</font>\n<font size='13'>{{l10n:Wins}}: <font color='{{mystat.c_winrate}}'>{{mystat.winrate%.2f~%}}</font>  ({{py:winrate_next(0.5)}} / {{py:winrate_next(1)}})</font>"
      }
    ]
  }

PS. Пользую минималистичискую карусель в 4 ряда.

PPS. А в целом было бы неплохо реализовать макрос, с помощью котрого можно было бы получать координаты и размеры тех или иных элиментов. Бывают моменты когда возникает необходимость разместить что либо относительно определенного элемента.

Edited by xenus
  • Upvote 1

Share this post


Link to post

Short link
Share on other sites
if next == int(next):
    next = int(next)

вот уже минут эдак "много" сижу и не понимаю смысл этого if :)

 

round(winrate,2)

вот тут может быть проблема. ибо round(x,2) всё таки не математическое округление. я у себя благодаря твоему же замечанию исправил. так что странно видеть это у тебя в коде. :)

 

плюс логику можно бы подкорректировать. ибо как-то не системно получается:

winrate: 55.82    diff: 0.5   >>>    next: 56.5

winrate: 55.82    diff: 1      >>>    next: 56

winrate: 55.82    diff: -1     >>>    next: 54.82

ну и т.д.

вот и получается строка

Побед: 55.82% (871 до 56.5%/232 до 56%)

а должна была бы быть такой

Побед: 55.82% (232 до 56%/871 до 56.5%)

.

 

ну и может стоит учитывать то, что в достижениях отображается округлённый до сотых винрейт. другими словами сейчас {{py:winrate_next(х)}} показывает что нужно еще допустим 2 боя до 55% в то время как в достижениях уже светятся эти 55%

Edited by CrazyST

Share this post


Link to post

Short link
Share on other sites

 

 

вот и получается строка

...

а должна была бы быть такой

 

от "перемены мест слагаемых сумма не меняется", другими словами, при совместном использовании интервала 0.5 и 1 (что и предполагается в дефолтном исполнении) отображение привычно и знакомо, в противном случае придется писать две формулы и два макроса на отработку именно 0.5 и 1 интервалов. 

Пришлось в угоду универсальности макроса пренебречь этой "перестановкой"...

 

про округление:

повторюсь, пытался ограничить скрипт одним макросом "на все случаи", поэтому погрешностью в расчетах для кастомных интервалов (отличных от 0.5 и 1) пришлось пожертвовать ))

 

и по 

 

вот уже минут эдак "много" сижу и не понимаю смысл этого if :)
без этого вывод "до 53%" будет выглядеть как "до 53.0%" - вот от этого незначащего нуля после точки и избавлялся...

Есть вариант лучше - давай, мне тоже не нравится "топорность" такого "метода" ))

Share this post


Link to post

Short link
Share on other sites

с динамическими цветами понятно, но это в лог сыплет тоже потому, что я не на 20CT ? - 

2017-08-16 17:47:14: [ERROR] Traceback (most recent call last):
  File "./res_mods/mods/packages\xvm_main\python\python_macro.py", line 157, in process_python_macro
    return (func(), deterministic)
  File "./res_mods/mods/packages\xvm_main\python\python_macro.py", line 150, in <lambda>
    return (lambda: func(*args), deterministic)
  File "res_mods/configs/xvm/py_macro\hangar_stat.py", line 20, in winrate_next
    winrate = itemsCache.items.getAccountDossier().getRandomStats().getWinsEfficiency() * 100
TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'
arg='winrate_next(1)'
2017-08-16 17:47:14: [ERROR] Traceback (most recent call last):
  File "./res_mods/mods/packages\xvm_main\python\python_macro.py", line 157, in process_python_macro
    return (func(), deterministic)
  File "./res_mods/mods/packages\xvm_main\python\python_macro.py", line 150, in <lambda>
    return (lambda: func(*args), deterministic)
  File "res_mods/configs/xvm/py_macro\hangar_stat.py", line 20, in winrate_next
    winrate = itemsCache.items.getAccountDossier().getRandomStats().getWinsEfficiency() * 100
TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'
arg='winrate_next(0.5)'

Share this post


Link to post

Short link
Share on other sites

 

 

с динамическими цветами понятно, но это в лог сыплет тоже потому, что я не на 20CT ? - 
 

Нет,это что-то не так с обновленным  xvm-6.8.2,там еще и с полосой захвата проблемы.

Share this post


Link to post

Short link
Share on other sites

В последней релизной версии ошибки из лога пропали и рейтинги отображаются корректно.

Динамические цвета будут в 9.20? В теме не нашел отсылок.

Edited by ADv

Share this post


Link to post

Short link
Share on other sites

на всякий случай сообщу, что ошибки выше - как раз на последней релизной версии (она же 7826).

Edited by arom

Share this post


Link to post

Short link
Share on other sites

на всякий случай сообщу, что ошибки выше - как раз на последней релизной версии (она же 7826).

ошибки в логе из-за вероятной проблемы на стороне ВГ:  API периодически не корректно отдает данные...

 

для текущего патча 0.9.19.1.2 все выложенное вполне работоспособно, только в widgetsTemplates.xc надо заменить пару макросов: 

вместо {{mystat.eff}} вписать {{mystat.e}} (первоначальная версия наименования)

вместо {{mystat.avglvl%.2f}} вписать {{mystat.lvl%.2f}} (также первая версия макроса)

 

для ленивых: срипт берем из первого сообщения, файлы конфига ниже:

widgets.xc

widgetsTemplates.xc

'скрин'

post-24956-0-46221300-1502919378_thumb.jpg  - динамический цвет будет работать только в патче 9.20
  • Upvote 2

Share this post


Link to post

Short link
Share on other sites

@Kapany3uk, спасибо за исходники и примеры.

сделал так

'1366x768 & 1920x1080'

post-15661-0-99189400-1502970224_thumb.jpgpost-15661-0-24940200-1502970226_thumb.jpg
отображение с разными аргументами макроса (размер шага и кол-во шагов):

post-15661-0-48020000-1502970226.jpgpost-15661-0-61789300-1502970226.jpg

post-15661-0-73011200-1502970226.jpgpost-15661-0-86710900-1502970226.jpg

def NbattlesToWR(step=0.01,stepscount=0):
    itemsCache = dependency.instance(IItemsCache)
    winsCount = itemsCache.items.getAccountDossier().getRandomStats().getWinsCount()
    battlesCount = itemsCache.items.getAccountDossier().getRandomStats().getBattlesCount()
    winsEfficiency = itemsCache.items.getAccountDossier().getRandomStats().getWinsEfficiency() * 100
    if step < 0.01 :
        step = 0.01
    else :
        step = round(step*100)/100
    stepscount = round(stepscount)
    if stepscount == 0 :
        wrn = round(winsEfficiency/step)*step
    elif stepscount > 0 :
        wrn = math.floor(winsEfficiency/step)*step + step * stepscount
    else :
        wrn = math.ceil(winsEfficiency/step)*step + step * stepscount
    if wrn == winsEfficiency :
        return 'Ровно <font color="#FFCC66">{}%</font>'.format(wrn)
    f = wrn > winsEfficiency
    if f :
        b = math.ceil((100 * winsCount - wrn * battlesCount) / (wrn - 100))
    else :
        b = -math.ceil(winsCount*100 / wrn - battlesCount)
    if round(wrn*100)/100 == int(wrn) :
        wrn = int(wrn)
    if b > 0 :
        return '<font color="#60FF00">{}</font>{}<font color="#FFCC66">{}%</font>'.format(int(b),'{{l10n:toWithSpaces}}',wrn)
    elif b < 0 :
        b = abs(b)
        return '<font color="#FE7903">{}</font>{}<font color="#FFCC66">{}%</font>'.format(int(b),'{{l10n:toWithSpaces}}',wrn)
    else :
        return '<font color="#FFCC66">{}</font>{}<font color="#FFCC66">{}%</font>'.format(int(b),'{{l10n:toWithSpaces}}',wrn)

"зеленым" - число побед до %, "красным" - число сливов до %

step - размер шага кратный 0,01 и stepscount - кол-во шагов (целое) задают критерий расчета целевого процента побед. если stepscount == 0 или не указан, то расчет боёв будет вестись до процента побед ближайшего к текущему (или большего или меньшего) и кратного шагу. если stepscount == 1, то ближайшего в сторону увеличения и кратного шагу, stepscount == -1 значит ближайшего в сторону уменьшения и кратного шагу. ну и т.д.

'примеры'

допустим текущий ПП = 55,82.

тогда:

step=0,05  stepscount=0   >>> расчетный ПП = 55,80

step=1      stepscount=0   >>> расчетный ПП = 56,00

step=0,1    stepscount=-1  >>> расчетный ПП = 55,80

step=0,1    stepscount=1   >>> расчетный ПП = 55,90

step=0,5    stepscount=1   >>> расчетный ПП = 56,00

step=0,5    stepscount=2   >>> расчетный ПП = 56,50

стандартные результаты для статистики получаются из (step=0,5 stepscount=1) и (step=0,5 stepscount=2) соответственно.

макросы динамических цветов ясное дело пока не работают.

с датой только так и не смог нормально перевести timestamp из {{mystat.ts}} в нормальный вид. а текущая дата тут не очень в тему.

UPD: теперь отображается дата и время обновления статистики на сервере XVM, а не текущие

post-15661-0-02323000-1503053241.pngpost-15661-0-15045100-1503053241.jpg

последняя строка с процентом побед и "боёв до %" содержит актуальную информацию на текущий момент, а WN8 РЭ и средний уровень по состоянию на дату и время из верхней строки.

теперь ждём обновы чтобы уже с макросами цвета отображалось )))

но это так, побаловаться. просто играть в танки уже не так интересно как раньше. а вот конфиг ковырять еще интересно )))

для себя делал и постоянно чекаю такой вот маленький виджет  post-15661-0-55361100-1502970232.jpg

def battlesToWins():
    itemsCache = dependency.instance(IItemsCache)
    winsCount = itemsCache.items.getAccountDossier().getRandomStats().getWinsCount()
    battlesCount = itemsCache.items.getAccountDossier().getRandomStats().getBattlesCount()
    winsEfficiency = itemsCache.items.getAccountDossier().getRandomStats().getWinsEfficiency() * 100
    wrn = (round(winsEfficiency*100) + 0.5) / 100
    wn = math.ceil((100 * winsCount - wrn * battlesCount) / (wrn - 100))
    wrp = wrn - 0.01
    bn = math.ceil(winsCount*100 / wrp - battlesCount)
    rwe = round(winsEfficiency*100)/100
    if rwe > winsEfficiency :
        return '( <font color="#FE7903">{}</font> )  {:0.2f}%  ( <font color="#60FF00">{}</font> )'.format(int(bn),rwe,int(wn))
    return '( <font color="#FE7903">{}</font> )  <b>{:0.2f}%</b>  ( <font color="#60FF00">{}</font> )'.format(int(bn),rwe,int(wn))

текущий % побед и сколько сливов/побед до его изменения с учётом того, что в достижениях отображается округлённое до сотых значение % побед. другими словами на виджете цифра 7 говорит о том, что нужно 7 побед чтобы % стал не менее чем 55,855 и округлился до 55,86. ну и 6 сливов до того что % станет менее 55,845 и округлится до 55,84

Edited by CrazyST
  • Upvote 3

Share this post


Link to post

Short link
Share on other sites

Дату через py_macro можно перевести, нужно макрос сделать.

Share this post


Link to post

Short link
Share on other sites

Дату через py_macro можно перевести, нужно макрос сделать.

это понятно. вот только я не смог подобрать функции :( пару часов пытался без толку... кто бы помог...  сделал. чего вчера тупил непонятно...

Edited by CrazyST

Share this post


Link to post

Short link
Share on other sites

Можно функцию закоммитить в общий репозиторий, другим тоже пригодится.

  • Upvote 1

Share this post


Link to post

Short link
Share on other sites
закоммитить

этого я не умею еще. может @Kapany3uk сделает pull request.

а функция оказалась простой. долго тупил из-за того что timestamp возвращаемый макросом {{mystat.ts}} имеет 3 лишних для функции разряда (на сколько я понимаю с миллисекундами)

ну и может имеет смысл сделать 2 функции. отдельно дату и отдельно время.

вот я реально туплю в последнее время...

from datetime import datetime
import locale

_defaultlocale = locale.getdefaultlocale()[1]

@xvm.export('unnormalman.DTfromTS')
def DTfromTS(ts=0,TSFormat='%d.%m.%Y %H:%M'):
    dt = datetime.fromtimestamp(int(ts/1000)).strftime(TSFormat).decode(_defaultlocale)
    return dt

вызов такой

{{py:unnormalman.DTfromTS({{mystat.ts}})}} //по умолчанию дата и время

или можно со своим форматом

{{py:unnormalman.DTfromTS({{mystat.ts}},'%d.%m.%Y')}} //только дата

формат можно построить используя эту таблицу

Edited by CrazyST

Share this post


Link to post

Short link
Share on other sites

deterministic убери, эта функция детерминированная.

И для локализации лучше использовать WGшные методы, так как локализация клиента может не совпадать с локализацией инюгры. Где-то в py_macro были примеры.

Share this post


Link to post

Short link
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...