warbot.go 9.2 KB

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