bot.go 8.9 KB

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