bot.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. // package bot -- бот для игры в wartank
  2. package bot
  3. import (
  4. "context"
  5. "fmt"
  6. "log"
  7. "strings"
  8. "time"
  9. . "gitp78su.ipnodns.ru/svi/kern"
  10. . "gitp78su.ipnodns.ru/svi/kern/kc/helpers"
  11. . "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
  12. . "wartank/app/lev0/alias"
  13. . "wartank/app/lev0/types"
  14. "wartank/app/lev2/arena/arena_angar"
  15. "wartank/app/lev3/bot/bot_config"
  16. "wartank/app/lev3/bot/bot_net"
  17. "wartank/app/lev3/bot/bot_stat/tank_stat"
  18. )
  19. // ВарБот -- бот для игры в вартанк
  20. type Бот struct {
  21. прилож ИПриложение
  22. хран IKernelStoreKv
  23. стата ИТанкСтат
  24. errFinal error // Финальная ошибка работы, если была
  25. ангар ИАренаАнгар
  26. сеть ИБотСеть
  27. еслиРаботает ISafeBool
  28. еслиАвтозапуск ISafeBoolReact
  29. конфиг *bot_config.БотКонфиг // Конфиг бота для хранения в базе
  30. кнт context.Context // Контекст бота
  31. фтОтмена func() // Функция отменя контекста бота
  32. лог ILogBuf
  33. конт ИБотКонтекст
  34. }
  35. // ЗагрузитьВарБот -- загружает бота из базы
  36. func ЗагрузитьВарБот(конт IKernelCtx, номер АБотНомер) *Бот {
  37. лог := NewLogBuf()
  38. лог.Info("ЗагрузитьВарБот()\n")
  39. Hassert(номер != 0, "ЗагрузитьВарБот(): номер пустой")
  40. стрНомер := fmt.Sprint(номер)
  41. лог.Info("ЗагрузитьВарБот(): номер=%q\n", стрНомер)
  42. хран := конт.Get("kernStore").Val().(IKernelStoreKv)
  43. binData, err := хран.Get("/bots/" + стрНомер)
  44. if err != nil {
  45. if !strings.Contains(err.Error(), "not found") {
  46. Hassert(false, "ЗагрузитьВарБот(): in load bot '%v' from store, err=\n\t%v\n", номер, err)
  47. }
  48. Hassert(err == nil, "ЗагрузитьВарБот(): in load bot '%v' from store, err=\n\t%v\n", номер, err)
  49. }
  50. конфиг := &bot_config.БотКонфиг{}
  51. конфиг.Unmarshal(binData)
  52. сам := создатьЯдроВарБот(конт, конфиг)
  53. go сам.рестарт()
  54. _ = ИБот(сам)
  55. return сам
  56. }
  57. // Каждые два часа перезапускает себя
  58. func (сам *Бот) рестарт() {
  59. time.Sleep(time.Hour * 2)
  60. сам.прилож.Cancel()
  61. сам.лог.Info("рестарт(): бот %q перезагружен\n", сам.конфиг.Логин_)
  62. }
  63. // НовВарБот -- возвращает новый WarBot
  64. func НовВарБот(конт IKernelCtx, номер АБотНомер, логин, пароль string, еслиАвто bool) *Бот {
  65. лог := NewLogBuf()
  66. лог.Info("НовВарБот()\n")
  67. Hassert(логин != "", "НовВарБот(): логин пустой")
  68. Hassert(пароль != "", "НовВарБот(): пароль пустой")
  69. лог.Info("НовВарБот(): name=%q\n", логин)
  70. config := &bot_config.БотКонфиг{
  71. ЕслиАвтозапуск_: еслиАвто,
  72. Логин_: логин,
  73. Пароль_: пароль,
  74. Номер_: номер,
  75. }
  76. сам := создатьЯдроВарБот(конт, config)
  77. сам.сохрКонфиг()
  78. _ = ИБот(сам)
  79. return сам
  80. }
  81. // Создаёт ядро бота
  82. func создатьЯдроВарБот(конт IKernelCtx, конфиг *bot_config.БотКонфиг) *Бот {
  83. лог := NewLogBuf()
  84. лог.Info("создатьЯдроВарБот()\n")
  85. Hassert(конфиг != nil, "создатьЯдроВарБот(): ВарБотКонфиг==nil")
  86. ctx, fnCancel := context.WithCancel(конт.Ctx())
  87. приложение := конт.Get("приложение").Val().(ИПриложение)
  88. контБот := NewLocalCtx(конт.Ctx())
  89. сам := &Бот{
  90. конт: контБот,
  91. прилож: приложение,
  92. хран: конт.Get("kernStore").Val().(IKernelStoreKv),
  93. стата: tank_stat.НовТанкСтат(конт),
  94. еслиРаботает: NewSafeBool(),
  95. конфиг: конфиг,
  96. кнт: ctx,
  97. фтОтмена: fnCancel,
  98. лог: лог,
  99. }
  100. сам.еслиАвтозапуск = NewSafeBoolReact()
  101. сам.еслиАвтозапуск.Add(сам.Имя(), сам.автозапускИзм)
  102. сам.конт.Set("бот", сам, "создание ядра")
  103. сам.конт.Set("приложение", приложение, "Приложение WarBot")
  104. сам.сеть = bot_net.НовБотСеть(сам.конт)
  105. сам.ангар = arena_angar.НовАнгар(сам.конт)
  106. if сам.конфиг.ЕслиАвтозапуск_ {
  107. сам.еслиАвтозапуск.Set()
  108. сам.Пуск()
  109. }
  110. return сам
  111. }
  112. // ЕслиРабота -- возвращает признак, что бот подключен
  113. func (сам *Бот) ЕслиРабота() bool {
  114. return сам.еслиРаботает.Get()
  115. }
  116. // Номер -- возвращает номер бота
  117. func (сам *Бот) Номер() АБотНомер {
  118. return сам.конфиг.Номер()
  119. }
  120. // Имя -- возвращает имя бота
  121. func (сам *Бот) Имя() string {
  122. return сам.конфиг.Логин()
  123. }
  124. // Пароль -- возвращает пароль бота
  125. func (сам *Бот) Пароль() string {
  126. return сам.конфиг.Пароль_
  127. }
  128. // Пуск -- запускает бот в работу
  129. func (сам *Бот) Пуск() {
  130. if сам.еслиРаботает.Get() {
  131. return
  132. }
  133. сам.ангар.Пуск()
  134. сам.еслиРаботает.Set()
  135. }
  136. // Error -- возвращает финальную ошибку работы, если была
  137. func (сам *Бот) Error() error {
  138. return сам.errFinal
  139. }
  140. // Ангар -- возвращает ангар игры
  141. func (сам *Бот) Ангар() ИАренаАнгар {
  142. return сам.ангар
  143. }
  144. // Стата -- возвращает статистику танка
  145. func (сам *Бот) Стата() ИТанкСтат {
  146. return сам.стата
  147. }
  148. // Сеть -- возвращает ссылку на свой сетевой клиент
  149. func (сам *Бот) Сеть() ИБотСеть {
  150. return сам.сеть
  151. }
  152. // Автозапуск -- возвращает признак автоматического запуска бота
  153. func (сам *Бот) Автозапуск() ISafeBoolReact {
  154. return сам.еслиАвтозапуск
  155. }
  156. // Обратный вызов автоматического запуска бота
  157. func (сам *Бот) автозапускИзм(знач bool) {
  158. сам.лог.Debug("Бот.автозапускИзм()")
  159. // сам.еслиАвтозапуск.Уст()
  160. сам.конфиг.ЕслиАвтозапуск_ = знач
  161. сам.сохрКонфиг()
  162. }
  163. // Сохраняет конфиг бота
  164. func (сам *Бот) сохрКонфиг() {
  165. log.Printf("ВарБот.сохрКонфиг()")
  166. strConf := сам.конфиг.Marshall()
  167. стрНомер := fmt.Sprint(сам.Номер())
  168. err := сам.хран.Set("/bots/"+стрНомер, strConf)
  169. Hassert(err == nil, "ВарБот.сохрКонфиг(): err=\n\t%v\n", err)
  170. }
  171. // Контекст -- возвращает контекст бота
  172. func (сам *Бот) Контекст() context.Context {
  173. return сам.кнт
  174. }
  175. // Закончить -- отменяет контекст бота
  176. func (сам *Бот) Закончить() {
  177. сам.фтОтмена()
  178. }
  179. // КонтБот -- возвращает контекст бота
  180. func (сам *Бот) КонтБот() ILocalCtx {
  181. return сам.конт
  182. }