Kami keluar di top10. Bot telegram

Kami keluar di top10. Bot telegram


Latar belakang


Semuanya dimulai dengan fakta bahwa mereka mengirimi saya tautan ke bot di Telegram dengan tawaran untuk bermain.
Itu terlihat seperti ini.



Setelah pertandingan pertama saya, saya mendapat 28 poin, bukan hasil yang sangat mengesankan. Jadi Anda tidak memerlukan apa pun - program yang menemukan kata-kata dari huruf-huruf kata asli dan basis data kata benda Rusia.


Ayo pergi


Saya memutuskan untuk menggunakan sqlite3 untuk database, ini mobile dan untuk tugas ini yang paling.


Struktur dasar terlihat seperti ini.


CREATE TABLE IF NOT EXISTS words ( word VARCHAR(225) UNIQUE NOT NULL, length INTEGER NOT NULL ); 

  • kata - dari namanya jelas bahwa ini adalah makna kata yang tersimpan secara harfiah.
  • panjang - panjang karakter.

Ada struktur, untuk mengisinya, saya menggunakan daftar kata benda dari kata-kata Rusia .


Mengisi database dan mencari kata-kata, diputuskan untuk mengimplementasikan dalam satu kode, pemrosesan dibagi dengan bendera.


Pembuatan file dasar dan pembuatan tabel juga diterapkan di init ()


 func init() { var err error connection, err = sql.Open("sqlite3", "./words.db") if err != nil { log.Fatalf("Failed connection: %v", err) } _, err = connection.Exec(`CREATE TABLE IF NOT EXISTS words (word VARCHAR(225) UNIQUE NOT NULL, length INTEGER NOT NULL);`) if err != nil { log.Fatalf("Failed create database table words: %v", err) } } 

Sisipkan fungsi ()


Saat menambahkan kata, Anda harus ingat bahwa kami menggunakan alfabet Cyrillic, itulah sebabnya fungsi len() biasa tidak cocok dengan kami, kami akan menggunakan utf8.RuneCountInString() untuk menghitung panjang kata dengan benar.


Tambahkan pengecekan kesalahan if err.Error() != "UNIQUE constraint failed: words.word" - diperlukan untuk kemungkinan memperkenalkan kamus baru yang berisi salinan kata-kata dari database.


 func insert(word string) error { _, err := connection.Exec("INSERT INTO words (word,length) VALUES(?,?)", word, utf8.RuneCountInString(word)) if err != nil && err.Error() != "UNIQUE constraint failed: words.word" { return err } return nil } 

Untuk mencari kata-kata yang membentuk sumber, perlu untuk menguraikannya menjadi huruf-huruf. Sebuah kata dapat berisi beberapa huruf yang identik, untuk menghitung jumlah yang kita gunakan map[rune]int mana int adalah jumlah huruf yang ditemukan dalam kata tersebut.


 func decay(word string) map[rune]int { var m = make(map[rune]int) for _, char := range word { m[char]++ } return m } 

Pencarian itu sendiri dilakukan dalam mode multithreaded, jumlah gorutine = panjang kata aslinya, dikurangi satu gorutine karena Kita mulai dengan mencari kata-kata yang terdiri dari dua huruf atau lebih.


Dengan pendekatan ini, program bekerja terlalu cepat dan mengirim sejumlah jawaban = gorutine ke chat ke bot, walaupun ada waktu. time.Sleap(1 * time.Second) di setiap gorutine - ini menyebabkan pemblokiran Telegram saya dari semua perangkat selama 10 menit. Saya memperhitungkan hal ini dan dalam versi saat ini saya menetapkan penundaan pengiriman, dan menempatkan fungsi pengiriman itu sendiri dalam gorutine terpisah, yang berkomunikasi dengan yang lain melalui saluran umum. Pencarian dilakukan seperti sebelumnya.

Kami menggunakan waitGroup{} sebagai mekanisme untuk mengakhiri pencarian semua kata dari database, dan kemudian menutup saluran.


 func findSubWords(word string) { list := decay(word) for length := 2; length <= utf8.RuneCountInString(word); length++ { wg.Add(1) go func(out chan<- string, length int) { search(out, list, length) wg.Done() fmt.Println("Done: ", length) }(out, length) } wg.Wait() fmt.Println("search done") close(out) } 

Fungsi pencarian memilih dari basis data semua kata dengan panjang yang diinginkan dan melalui perulangan memeriksa apakah kata itu cocok. Verifikasi dilakukan dalam beberapa tahap. Karena penggunaan map kami membuat salinan baru setiap kali kami menyelesaikan siklus loop. Kami membutuhkan salinan map untuk memeriksa jumlah huruf dalam sebuah kata, setiap kali sebuah huruf cocok, kami menurunkan nilainya dengan satu kunci per satu hingga berkurang menjadi nol, setelah itu jika huruf tersebut memiliki nilai = 0, kami menetapkan variabel ontain=false variabel dan saat siklus berakhir, kata tidak akan ditambahkan ke saluran.


 func search(out chan<- string, wordRuneList map[rune]int, length int) { wordList, err := selects(length) if err != nil { log.Printf("fail length %v, error: %v", length, err) } for _, word := range wordList { var ( wordCopyList = make(map[rune]int) contain = true ) for k, v := range wordRuneList { wordCopyList[k] = v } for _, r := range word { if _, ok := wordCopyList[r]; ok && wordCopyList[r] > 0 { wordCopyList[r]-- } else { contain = false break } } if contain { out <- word } } } 

Tetap kecil, sehingga program itu sendiri mengirimkan jawaban untuk obrolan. Karena bot tidak dapat berkomunikasi dengan bot lain, saya harus menggunakan akun pribadi saya. Saya memutuskan untuk menggunakan klien open source .


Menjalankannya di port: 9090. Kami mengirim pesan ke obrolan ke bot.


 func send(in <-chan string) { conn, _ := net.Dial("tcp", "localhost:9090") // conncect to client telegram for word := range in { fmt.Fprintf(conn, "msg WordsGame-bot %v\n", word) time.Sleep(5 * time.Second) } } 

Perintah untuk segera meluncurkan telegram-cli pada debian.


Instal pustaka yang diperlukan.


 sudo apt install libreadline-dev libconfig-dev libssl-dev lua5.2 liblua5.2-dev libevent-dev libjansson-dev libpython-dev libgcrypt20 libz-dev make git 

Mengkloning repositori.


 git clone --recursive https://github.com/vysheng/tg.git && cd tg 

Melakukan konfigurasi.


 ./configure make 

Peluncuran klien pada port 9090


 bin/telegram-cli -P 9090 

Agar klien dapat menemukan bot, perlu untuk menjalankan perintah search WordsGame-bot sudah ada di klien, kemudian periksa hasilnya dengan perintah msg WordsGame-bot test , jika setelah tindakan Anda tidak menulis tes teks ke obrolan obrolan, coba mainkan game itu secara pribadi.
Agar klien mulai bekerja, jangan lupa untuk masuk, dia akan menyarankan ketika Anda masuk untuk pertama kalinya.

Segalanya tampak siap. Program ini dapat mengisi basis serta memainkan game dengan bot, tetapi hanya jika Anda sendiri meminta kata-kata dari bot.


Tetapi semua ini lambat, tetapi kami ingin segera mengambil baris pertama, dan untuk ini kita perlu mengajarkan program untuk meminta kata-kata dari bot. Kami akan membuat koneksi dan mengirimkan perintah msg WordsGame-bot /play , msg WordsGame-bot /play memiliki penundaan, jadi kami menunggu 5 detik. Setelah itu kami meminta pesan terakhir dari cerita dengan history WordsGame-bot 1 Ini akan menjadi jawaban, atau lebih tepatnya kata yang harus kita gunakan sebagai sumber. Untuk membaca dari conn buat variabel reply = make([]byte, 512) . Setelah kami mendapat seluruh jawaban dengan onn itu terlihat seperti ini.


  history @manymanywords_bot 1 ANSWER 58 [16:10] WordsGame-bot ยปยปยป  

Buat regexp.MustCompile("([-]{1,100})") untuk mencari kata-kata dari alfabet Cyrillic. Setelah itu, kita memilih kata kita.


 else if *god { go send(out) for { var ( conn, _ = net.Dial("tcp", "localhost:9090") // conncect to client telegram reply = make([]byte, 512) r = regexp.MustCompile("([-]{1,100})") ) fmt.Fprintln(conn, "msg WordsGame-bot /play") time.Sleep(5 * time.Second) fmt.Fprintln(conn, "history WordsGame-bot 1") time.Sleep(2 * time.Second) _, err := conn.Read(reply) if err != nil { log.Fatalf("failed read connection %v", err) } word := r.FindAllString(string(reply), 1) if len(word) <= 0 { log.Fatalf("somthing wrong %s", reply) } findSubWords(word[0]) time.Sleep(5 * time.Minute) } 

Tetapi ada masalah, karena kami menutup saluran setelah kami menemukan semua kata. Untuk memperbaikinya, kita memerlukan variabel GODMOD global. Tambahkan syarat untuk findSubWords . Sekarang ketika kita menggunakan sakelar -g, variabel GODMOD disetel ke true dan saluran tidak menutup, dan setelah menyelesaikan loop, kami meminta kata baru.


  if !GODMOD { close(out) } 

Sekarang Anda bisa melihat hasilnya.



Tautan yang bermanfaat


Source: https://habr.com/ru/post/id432278/


All Articles