bot.go 8.7 KB

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