Compare commits
29 Commits
Author | SHA1 | Date | |
---|---|---|---|
ef074b98e5 | |||
72ea3c83a4 | |||
d07031c242 | |||
c6d1e79360 | |||
af9aca41b4 | |||
5b079a5872 | |||
20f24be349 | |||
36e6a0f986 | |||
6f0d84aa87 | |||
a4d4cee6cd | |||
f7be57f9dd | |||
57491651d2 | |||
5ee7a22486 | |||
cfd1bb66bd | |||
6e368518c5 | |||
3e4851555d | |||
5f73c5ab5a | |||
e730068834 | |||
7a43213aa4 | |||
d9db1b406a | |||
2d295bb384 | |||
20b6d055bb | |||
545366564f | |||
aee5d92d8d | |||
756272d064 | |||
dfa0f2daff | |||
124ee61e1d | |||
55f710cbbb | |||
9fe660aa71 |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
.idea/
|
19
README.md
19
README.md
@ -1,6 +1,25 @@
|
||||
# telegram
|
||||
|
||||
`go2v` — утилита для транслирования кода на Go в V. В текущий момент доступна только старая версия утилиты.
|
||||
|
||||
Для установки `go2v`, нужно клонировать репозиторий в данный момент с ветки `old_implementation` и запустить команду `v run .` для компиляции файлов:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/vlang/go2v.git -b old_implementation
|
||||
cd go2v
|
||||
v run .
|
||||
```
|
||||
|
||||
После установки утилиты, можно использовать go2v для трансляции Go-файлов в V:
|
||||
|
||||
```sh
|
||||
v run . path/to/file.go
|
||||
```
|
||||
|
||||
Транслированный файл будет создан в том же каталоге с именем v.
|
||||
Может потребоваться проверка синтаксиса, так как транслирование может содержать ошибки.
|
||||
|
||||
Дополнительную информацию и документацию можно найти в репозитории [go2v на GitHub](https://github.com/vlang/go2v/tree/old_implementation).
|
||||
|
||||
## Getting started
|
||||
|
||||
|
18
client/client.go
Normal file
18
client/client.go
Normal file
@ -0,0 +1,18 @@
|
||||
package client
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Client struct {
|
||||
Messages []string
|
||||
}
|
||||
|
||||
func NewClient() *Client {
|
||||
return &Client{
|
||||
Messages: []string{},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) SendMessage(msg string) {
|
||||
c.Messages = append(c.Messages, msg)
|
||||
fmt.Println("saved message: ", msg)
|
||||
}
|
11
client/client.v
Normal file
11
client/client.v
Normal file
@ -0,0 +1,11 @@
|
||||
module client
|
||||
|
||||
pub struct Client {
|
||||
pub mut:
|
||||
messages []string
|
||||
}
|
||||
|
||||
pub fn (mut c Client) send_message(msg string) {
|
||||
c.messages << msg
|
||||
//println('saved message: ${msg}')
|
||||
}
|
3
go.mod
Normal file
3
go.mod
Normal file
@ -0,0 +1,3 @@
|
||||
module penahub.gitlab.yandexcloud.net/backend/quiz/telegram
|
||||
|
||||
go 1.22.5
|
71
main.go
Normal file
71
main.go
Normal file
@ -0,0 +1,71 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"math/rand"
|
||||
"os"
|
||||
"penahub.gitlab.yandexcloud.net/backend/quiz/telegram/client"
|
||||
"penahub.gitlab.yandexcloud.net/backend/quiz/telegram/models"
|
||||
"penahub.gitlab.yandexcloud.net/backend/quiz/telegram/respondent"
|
||||
stateManager "penahub.gitlab.yandexcloud.net/backend/quiz/telegram/state_manager"
|
||||
"time"
|
||||
)
|
||||
|
||||
var dataSetMap map[string]models.Question
|
||||
|
||||
func init() {
|
||||
f, err := os.Open("treedata.json")
|
||||
if err != nil {
|
||||
log.Fatalf("err open json file: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
values, err := io.ReadAll(f)
|
||||
if err != nil {
|
||||
log.Fatalf("err read json file: %v", err)
|
||||
}
|
||||
|
||||
var dataSet []models.Question
|
||||
err = json.Unmarshal(values, &dataSet)
|
||||
if err != nil {
|
||||
log.Fatalf("err unmarshall json: %v", err)
|
||||
}
|
||||
|
||||
dataSetMap = make(map[string]models.Question)
|
||||
for _, data := range dataSet {
|
||||
dataSetMap[data.Title] = data
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
mockClient := client.NewClient()
|
||||
mockStateManager := stateManager.NewStateManager(stateManager.Deps{
|
||||
Questions: dataSetMap,
|
||||
State: "q00",
|
||||
Client: mockClient,
|
||||
})
|
||||
|
||||
mockRespondent := respondent.NewRespondent(mockStateManager)
|
||||
mockStateManager.SendQuestion()
|
||||
|
||||
for {
|
||||
if _, ok := dataSetMap[mockStateManager.State]; !ok {
|
||||
fmt.Println("state not found")
|
||||
break
|
||||
}
|
||||
mockRespondent.Respond("q00")
|
||||
fmt.Println("respond")
|
||||
}
|
||||
|
||||
for number, msg := range mockClient.Messages {
|
||||
fmt.Println(fmt.Sprintf("message %d: %s", number, msg))
|
||||
}
|
||||
//}
|
||||
|
||||
fmt.Println("Complete")
|
||||
}
|
78
main.v
Normal file
78
main.v
Normal file
@ -0,0 +1,78 @@
|
||||
module main
|
||||
import json
|
||||
import log
|
||||
import os
|
||||
import client
|
||||
import models
|
||||
import respondent
|
||||
import state_manager
|
||||
import our_benchmark
|
||||
import tg_handle
|
||||
import time
|
||||
|
||||
//v -enable-globals run main.v
|
||||
__global (
|
||||
data_set_map map[string]models.Question
|
||||
)
|
||||
|
||||
fn init() {
|
||||
f := os.read_file('treedata.json') or {
|
||||
log.error('err read json file: $err')
|
||||
return
|
||||
}
|
||||
|
||||
data_set := json.decode([]models.Question, f) or {
|
||||
log.error('err unmarshall json: $err')
|
||||
return
|
||||
}
|
||||
|
||||
for data in data_set {
|
||||
data_set_map[data.title] = data
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
mut b := our_benchmark.new_custom_benchmark(test_main,0,0,false) or {
|
||||
eprintln('Error creating benchmark: $err')
|
||||
return
|
||||
}
|
||||
|
||||
b.run_benchmark()
|
||||
|
||||
// mut benchmarks := our_benchmark.InternalBenchmark{
|
||||
// name: 'test_main',
|
||||
// f: test_main,
|
||||
// }
|
||||
// our_benchmark.run_benchmarks(benchmarks)
|
||||
}
|
||||
|
||||
fn test_main()! {
|
||||
mut mock_client := &client.Client{messages: []string{}}
|
||||
mut mock_state_manager := &state_manager.StateManager{
|
||||
questions: data_set_map
|
||||
state: "q00"
|
||||
client: mock_client
|
||||
}
|
||||
|
||||
// tg_handle.new_tg_bot("6712573453:AAFqTOsgwe_j48ZQ1GzWKQDT5Nwr-SAWjz8")
|
||||
|
||||
mut mock_respondent := respondent.Respondent{manager: mock_state_manager}
|
||||
mock_state_manager.send_question()
|
||||
|
||||
for {
|
||||
if mock_state_manager.state !in data_set_map {
|
||||
//println('state not found')
|
||||
break
|
||||
}
|
||||
mock_respondent.respond("q00")
|
||||
//println('respond')
|
||||
}
|
||||
|
||||
// for number, msg in mock_client.messages {
|
||||
// println('message $number: $msg')
|
||||
// }
|
||||
|
||||
//println('Complete')
|
||||
|
||||
// time.sleep(10 * time.minute)
|
||||
}
|
41
main_test.go
Normal file
41
main_test.go
Normal file
@ -0,0 +1,41 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"penahub.gitlab.yandexcloud.net/backend/quiz/telegram/client"
|
||||
"penahub.gitlab.yandexcloud.net/backend/quiz/telegram/respondent"
|
||||
stateManager "penahub.gitlab.yandexcloud.net/backend/quiz/telegram/state_manager"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func BenchmarkMain(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
mockClient := client.NewClient()
|
||||
mockStateManager := stateManager.NewStateManager(stateManager.Deps{
|
||||
Questions: dataSetMap,
|
||||
State: "q00",
|
||||
Client: mockClient,
|
||||
})
|
||||
|
||||
mockRespondent := respondent.NewRespondent(mockStateManager)
|
||||
mockStateManager.SendQuestion()
|
||||
|
||||
for {
|
||||
if _, ok := dataSetMap[mockStateManager.State]; !ok {
|
||||
fmt.Println("state not found")
|
||||
break
|
||||
}
|
||||
mockRespondent.Respond("q00")
|
||||
fmt.Println("respond")
|
||||
}
|
||||
|
||||
for number, msg := range mockClient.Messages {
|
||||
fmt.Println(fmt.Sprintf("message %d: %s", number, msg))
|
||||
}
|
||||
|
||||
fmt.Println("Complete")
|
||||
}
|
||||
}
|
37
main_test.v
Normal file
37
main_test.v
Normal file
@ -0,0 +1,37 @@
|
||||
module main
|
||||
|
||||
import benchmark
|
||||
import models
|
||||
import respondent
|
||||
import state_manager
|
||||
import client
|
||||
|
||||
fn test_main(){
|
||||
mut bench := benchmark.new_benchmark()
|
||||
for i := 0; i < models.data_set.len; i++ {
|
||||
bench.step()
|
||||
mut mock_client := &client.Client{messages: []string{}}
|
||||
mut mock_state_manager := &state_manager.StateManager{
|
||||
questions: models.data_set[i]
|
||||
state: 'start'
|
||||
client: mock_client
|
||||
}
|
||||
mut mock_respondent := respondent.Respondent{manager: mock_state_manager}
|
||||
mock_state_manager.send_question()
|
||||
for mock_state_manager.state != 'end' {
|
||||
mock_respondent.respond()
|
||||
println('respond')
|
||||
}
|
||||
for number, msg_1 in mock_client.messages {
|
||||
println(' ${'out'} ${i} ${msg_1} ${number}')
|
||||
}
|
||||
bench.ok()
|
||||
}
|
||||
|
||||
bench.stop()
|
||||
|
||||
// выводит время
|
||||
bench.measure("test_main")
|
||||
|
||||
println(bench.total_message('remarks about the our_benchmark'))
|
||||
}
|
12
models/models.go
Normal file
12
models/models.go
Normal file
@ -0,0 +1,12 @@
|
||||
package models
|
||||
|
||||
type Question struct {
|
||||
Title string
|
||||
Description string
|
||||
Buttons []Button
|
||||
}
|
||||
|
||||
type Button struct {
|
||||
Text string
|
||||
State string
|
||||
}
|
16
models/models.v
Normal file
16
models/models.v
Normal file
@ -0,0 +1,16 @@
|
||||
module models
|
||||
// структуры объявляются в принципе как в гошке, заисключением того что видимо взято из С происходит деление на публичные и приватные
|
||||
// поэтому для того чтобы реализовать инкапсуляцию, если указать ключевое слово pub - будет все доступно
|
||||
|
||||
pub struct Button {
|
||||
pub mut:
|
||||
text string @[json: 'Text']
|
||||
state string @[json: 'State']
|
||||
}
|
||||
|
||||
pub struct Question {
|
||||
pub mut:
|
||||
title string @[json: 'Title']
|
||||
description string @[json: 'Description']
|
||||
buttons []Button @[json: 'Buttons']
|
||||
}
|
51
models/variants.go
Normal file
51
models/variants.go
Normal file
@ -0,0 +1,51 @@
|
||||
package models
|
||||
|
||||
var DataSet = []map[string]Question{
|
||||
{
|
||||
"start": {
|
||||
Title: "Start question",
|
||||
Description: "This first question, start",
|
||||
Buttons: []Button{
|
||||
{"start", "q1"},
|
||||
},
|
||||
},
|
||||
"q1": {
|
||||
Title: "Question 1",
|
||||
Description: "This question 1 after start question",
|
||||
Buttons: []Button{
|
||||
{"q2", "q2"},
|
||||
{"q3", "q3"},
|
||||
{"q4", "q4"},
|
||||
},
|
||||
},
|
||||
"q2": {
|
||||
Title: "Question 2",
|
||||
Description: "This question 2 after question 1",
|
||||
Buttons: []Button{
|
||||
{"Go end", "end"},
|
||||
{"Need end", "end"},
|
||||
},
|
||||
},
|
||||
"q3": {
|
||||
Title: "Question 3",
|
||||
Description: "This question 3 after question 1",
|
||||
Buttons: []Button{
|
||||
{"Want end", "end"},
|
||||
{"Go dota 2", "end"},
|
||||
},
|
||||
},
|
||||
"q4": {
|
||||
Title: "Question 4",
|
||||
Description: "This question 4 after question 1",
|
||||
Buttons: []Button{
|
||||
{"Run end", "end"},
|
||||
{"Swimming to end", "end"},
|
||||
},
|
||||
},
|
||||
"end": {
|
||||
Title: "Last question",
|
||||
Description: "This is last question",
|
||||
Buttons: []Button{},
|
||||
},
|
||||
},
|
||||
}
|
81
models/variants.v
Normal file
81
models/variants.v
Normal file
@ -0,0 +1,81 @@
|
||||
module models
|
||||
|
||||
pub const data_set = [
|
||||
{
|
||||
'end': Question{
|
||||
title: 'Last question'
|
||||
description: 'This is last question'
|
||||
buttons: []
|
||||
}
|
||||
'q1': Question{
|
||||
title: 'Question 1'
|
||||
description: 'This question 1 after start question'
|
||||
buttons: [
|
||||
Button{
|
||||
text: 'q2'
|
||||
state: 'q2'
|
||||
},
|
||||
Button{
|
||||
text: 'q3'
|
||||
state: 'q3'
|
||||
},
|
||||
Button{
|
||||
text: 'q4'
|
||||
state: 'q4'
|
||||
},
|
||||
]
|
||||
}
|
||||
'q2': Question{
|
||||
title: 'Question 2'
|
||||
description: 'This question 2 after question 1'
|
||||
buttons: [
|
||||
Button{
|
||||
text: 'Go end'
|
||||
state: 'end'
|
||||
},
|
||||
Button{
|
||||
text: 'Need end'
|
||||
state: 'end'
|
||||
},
|
||||
]
|
||||
}
|
||||
'q3': Question{
|
||||
title: 'Question 3'
|
||||
description: 'This question 3 after question 1'
|
||||
buttons: [
|
||||
Button{
|
||||
text: 'Want end'
|
||||
state: 'end'
|
||||
},
|
||||
Button{
|
||||
text: 'Go dota 2'
|
||||
state: 'end'
|
||||
},
|
||||
]
|
||||
}
|
||||
'q4': Question{
|
||||
title: 'Question 4'
|
||||
description: 'This question 4 after question 1'
|
||||
buttons: [
|
||||
Button{
|
||||
text: 'Run end'
|
||||
state: 'end'
|
||||
},
|
||||
Button{
|
||||
text: 'Swimming to end'
|
||||
state: 'end'
|
||||
},
|
||||
]
|
||||
}
|
||||
'start': Question{
|
||||
title: 'Start question'
|
||||
description: 'This first question, start'
|
||||
buttons: [
|
||||
Button{
|
||||
text: 'start'
|
||||
state: 'q1'
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
]
|
175
our_benchmark/benchmark.v
Normal file
175
our_benchmark/benchmark.v
Normal file
@ -0,0 +1,175 @@
|
||||
module our_benchmark
|
||||
|
||||
import time
|
||||
import math
|
||||
|
||||
@[noinit]
|
||||
pub struct CustomBenchmark {
|
||||
pub mut:
|
||||
n i64 // Количество итераций
|
||||
bench_func ?fn()! // функция которая тестируется, не может быть пустой
|
||||
bench_time time.Duration // время выполнения бенчмарка дефолтно 1 секунда, проверка на то что не может быть меньше секунды?
|
||||
is_parallel bool // флаг паралельного запуска, дефолтно 0
|
||||
benchmark_result BenchmarkResult // сюда складываются результаты бенчмарка
|
||||
timer_on bool
|
||||
start_time time.Time
|
||||
duration time.Duration
|
||||
failed bool
|
||||
start_memory usize
|
||||
start_allocs usize
|
||||
}
|
||||
|
||||
struct BenchmarkResult {
|
||||
pub mut:
|
||||
n i64 // Количество итераций
|
||||
t time.Duration // Общее затраченное время
|
||||
mem usize // память
|
||||
allocs usize // аллокации
|
||||
}
|
||||
|
||||
pub fn new_custom_benchmark (bench_func fn()!,n i64,duration time.Duration,is_parallel bool) !CustomBenchmark{
|
||||
if bench_func == voidptr(0) {
|
||||
return error('Benchmark function cannot be empty')
|
||||
}
|
||||
|
||||
mut check_duration := duration
|
||||
if duration == 0 { check_duration = time.second }
|
||||
|
||||
return CustomBenchmark{
|
||||
n:n
|
||||
bench_func: bench_func
|
||||
bench_time: check_duration
|
||||
is_parallel: is_parallel
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut b CustomBenchmark) run_benchmark(){
|
||||
mut n := b.n // нужно для того чтобы если нам передали n о после прогрева его оставить
|
||||
b.run_n(1)
|
||||
// тут проверяем если n != 0 это проверка на то что не передали, по дефолту будет всегда 1 n
|
||||
if n != 0{
|
||||
b.n =n
|
||||
b.run_n(n)
|
||||
}else {
|
||||
for !b.failed && b.duration < b.bench_time && n < 1000000000 {
|
||||
// предсказываем количество итераций, исходя из предыдущих результатов
|
||||
n = b.predict_n()
|
||||
// выполняем бенчмарк n раз
|
||||
b.run_n(n)
|
||||
}
|
||||
}
|
||||
|
||||
b.benchmark_result.n = b.n
|
||||
b.benchmark_result.t = b.duration
|
||||
|
||||
b.benchmark_result.show()
|
||||
}
|
||||
|
||||
// функция run_n выполняет бенчмарк указанное количество раз (n итераций)
|
||||
// обеспечивает синхронизацию, управляет временем выполнения и обрабатывает ошибки
|
||||
fn (mut b CustomBenchmark) run_n(n i64) {
|
||||
// очищаем память для минимизации влияния сборщика мусора на результаты бенчмарка
|
||||
gc_collect()
|
||||
// устанавливаем количество итераций
|
||||
b.n = n
|
||||
// сбрасываем и запускаем таймер для измерения времени выполнения
|
||||
b.reset_timer()
|
||||
b.start_timer()
|
||||
|
||||
// извлекаем функцию бенчмарка
|
||||
mut f := b.bench_func or {
|
||||
return
|
||||
}
|
||||
// выполняем бенчмарк n раз в цикле
|
||||
for i := i64(0); i < n; i++ {
|
||||
f() or {
|
||||
// если во время выполнения произошла ошибка, устанавливаем флаг ошибки и выводим сообщение
|
||||
b.failed = true
|
||||
eprintln('Error: $err')
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// останавливаем таймер после выполнения всех итераций
|
||||
b.stop_timer()
|
||||
}
|
||||
|
||||
// predict_n предсказывает количество итераций для следующего запуска бенчмарка,
|
||||
// основываясь на предыдущих результатах выполнения
|
||||
fn (mut b CustomBenchmark) predict_n() i64 {
|
||||
mut goal_ns := b.bench_time.nanoseconds() // Не меняем, поэтому берем из ресивера
|
||||
prev_iters := b.n // Берем последний n который был из b.n так как в run_n мы его записываем
|
||||
mut prev_ns := b.duration.nanoseconds()
|
||||
|
||||
if prev_ns <= 0 {
|
||||
prev_ns = 1
|
||||
}
|
||||
|
||||
mut n := goal_ns *prev_iters
|
||||
n = n / prev_ns
|
||||
n += n / 5
|
||||
|
||||
n = math.min(n, 100 * b.n)
|
||||
n = math.max(n, b.n + 1)
|
||||
n = math.min(n, 1000000000)
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
fn (mut b CustomBenchmark) reset_timer() {
|
||||
if b.timer_on {
|
||||
b.start_time = time.now()
|
||||
b.start_memory = gc_memory_use()
|
||||
b.start_allocs = gc_heap_usage().bytes_since_gc
|
||||
}
|
||||
b.duration = 0
|
||||
b.benchmark_result.mem = 0
|
||||
b.benchmark_result.allocs = 0
|
||||
}
|
||||
|
||||
fn (mut b CustomBenchmark) start_timer() {
|
||||
if !b.timer_on{
|
||||
b.start_time = time.now()
|
||||
b.start_memory = gc_memory_use()
|
||||
b.start_allocs = gc_heap_usage().bytes_since_gc
|
||||
b.timer_on = true
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut b CustomBenchmark) stop_timer() {
|
||||
if b.timer_on{
|
||||
b.duration += time.since(b.start_time)
|
||||
b.benchmark_result.mem +=gc_memory_use() - b.start_memory
|
||||
b.benchmark_result.allocs += gc_heap_usage().bytes_since_gc - b.start_allocs
|
||||
b.timer_on = false
|
||||
}
|
||||
}
|
||||
|
||||
fn (r BenchmarkResult) ns_per_op() i64 {
|
||||
if r.n <= 0 {
|
||||
return 0
|
||||
}
|
||||
return r.t.nanoseconds() / i64(r.n)
|
||||
}
|
||||
|
||||
fn (r BenchmarkResult) allocs_per_op() i64 {
|
||||
if r.n <= 0 {
|
||||
return 0
|
||||
}
|
||||
return i64(r.allocs) / i64(r.n)
|
||||
}
|
||||
|
||||
fn (r BenchmarkResult) alloced_bytes_per_op() i64 {
|
||||
if r.n <= 0 {
|
||||
return 0
|
||||
}
|
||||
return i64(r.mem) / i64(r.n)
|
||||
}
|
||||
|
||||
fn (r BenchmarkResult) show() {
|
||||
println('Iterations: ${r.n}')
|
||||
println('Total Duration: ${r.t}')
|
||||
println('ns/op: ${r.ns_per_op()}')
|
||||
println('B/op: ${r.alloced_bytes_per_op()}')
|
||||
println('allocs/op: ${r.allocs_per_op()}')
|
||||
}
|
179
our_benchmark/benchmark_test.v
Normal file
179
our_benchmark/benchmark_test.v
Normal file
@ -0,0 +1,179 @@
|
||||
module our_benchmark
|
||||
|
||||
import time
|
||||
|
||||
// if n == 0, n predict == 1
|
||||
fn test_predict_n_zero() {
|
||||
mut b := CustomBenchmark{
|
||||
n: 0,
|
||||
duration: 0,
|
||||
bench_time: time.second,
|
||||
}
|
||||
expected := 1
|
||||
println(b.predict_n())
|
||||
assert b.predict_n() == expected
|
||||
}
|
||||
|
||||
// n can't be more 1000000000
|
||||
fn test_predict_n_limit() {
|
||||
mut b := CustomBenchmark{
|
||||
n: 10000000000,
|
||||
duration: 0,
|
||||
bench_time: time.second,
|
||||
}
|
||||
expected := 1000000000
|
||||
assert b.predict_n() == expected
|
||||
}
|
||||
|
||||
// если произошла ошибка в бенч функции то флаг failed должен быть помечен в тру, n = 1
|
||||
fn test_fn_with_error() {
|
||||
f := fn() ! {
|
||||
return error('error')
|
||||
}
|
||||
mut bench := our_benchmark.new_custom_benchmark(f, 0, 0, false)or {
|
||||
eprintln('Error creating benchmark: $err')
|
||||
return
|
||||
}
|
||||
|
||||
bench.run_benchmark()
|
||||
|
||||
assert bench.failed == true
|
||||
assert bench.benchmark_result.n == 1
|
||||
}
|
||||
|
||||
fn test_n_must_be_over_1(){
|
||||
f := fn() ! {
|
||||
mut i := 0
|
||||
i++
|
||||
}
|
||||
mut bench := our_benchmark.new_custom_benchmark(f, 0, 0, false)or {
|
||||
eprintln('Error creating benchmark: $err')
|
||||
return
|
||||
}
|
||||
|
||||
bench.run_benchmark()
|
||||
|
||||
assert bench.benchmark_result.n > 1
|
||||
}
|
||||
|
||||
fn test_n(){
|
||||
f := fn() ! {
|
||||
mut i := 0
|
||||
i++
|
||||
}
|
||||
mut bench := our_benchmark.new_custom_benchmark(f, 1000, 0, false)or {
|
||||
eprintln('Error creating benchmark: $err')
|
||||
return
|
||||
}
|
||||
|
||||
bench.run_benchmark()
|
||||
|
||||
assert bench.benchmark_result.n == 1000
|
||||
}
|
||||
|
||||
// n == 2 так как прогрев = 1 итерация + 1 итерация == 2
|
||||
fn test_max_bench_time(){
|
||||
f := fn() ! {
|
||||
time.sleep(500* time.millisecond)
|
||||
}
|
||||
mut bench := our_benchmark.new_custom_benchmark(f, 0, 0, false)or {
|
||||
eprintln('Error creating benchmark: $err')
|
||||
return
|
||||
}
|
||||
|
||||
bench.run_benchmark()
|
||||
|
||||
assert bench.benchmark_result.n == 2
|
||||
assert bench.benchmark_result.t >= time.second
|
||||
}
|
||||
|
||||
// проверка на то что n обновляется корректно после run_n
|
||||
fn test_n_updated_correct() {
|
||||
mut b := CustomBenchmark{
|
||||
n: 1,
|
||||
bench_time: time.second,
|
||||
bench_func: fn () ! {
|
||||
mut i := 0
|
||||
i++
|
||||
},
|
||||
}
|
||||
|
||||
b.run_n(100)
|
||||
assert b.n == 100
|
||||
|
||||
b.run_n(1)
|
||||
assert b.n == 1
|
||||
}
|
||||
|
||||
// проверка на то как вообще работает
|
||||
fn test_performance() {
|
||||
scheduler := [func_1,func_2,func_3]
|
||||
expected := [false,false,false]
|
||||
mut actual := []bool{}
|
||||
|
||||
for i in scheduler{
|
||||
mut bench := our_benchmark.new_custom_benchmark(i, 0, 0, false)or {
|
||||
eprintln('Error creating benchmark: $err')
|
||||
return
|
||||
}
|
||||
|
||||
bench.run_benchmark()
|
||||
actual << bench.failed
|
||||
}
|
||||
|
||||
assert expected.len == actual.len
|
||||
for i:=0;i<expected.len;i++{
|
||||
assert expected[i] == actual[i]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn func_1() !{
|
||||
mut arr := []int{}
|
||||
appender(mut arr)
|
||||
assert arr.len == 10
|
||||
}
|
||||
|
||||
fn appender(mut arr []int){
|
||||
if arr.len==10{
|
||||
return
|
||||
}
|
||||
arr << 1
|
||||
appender(mut arr)
|
||||
}
|
||||
|
||||
fn func_2() !{
|
||||
target := 2
|
||||
arr := [1,2,3,4,5,6,7,8,9,10]
|
||||
|
||||
mut left := 0
|
||||
mut right := arr.len-1
|
||||
|
||||
for left<=right{
|
||||
mid :=left+(right-left)/2
|
||||
if arr[mid] == target{
|
||||
return
|
||||
}
|
||||
if arr[mid]<target{
|
||||
left = mid + 1
|
||||
}
|
||||
if arr[mid]>target{
|
||||
right = mid - 1
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
fn func_3() !{
|
||||
mut arr := [10,2,13,4,5,16,7,1,9,20]
|
||||
|
||||
for i :=0; i<arr.len-1;i++{
|
||||
for j:=0;j<arr.len-i-1;j++{
|
||||
if arr[j] > arr[j+1]{
|
||||
arr[j],arr[j+1]=arr[j+1],arr[j]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
33
respondent/respondent.go
Normal file
33
respondent/respondent.go
Normal file
@ -0,0 +1,33 @@
|
||||
package respondent
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"penahub.gitlab.yandexcloud.net/backend/quiz/telegram/models"
|
||||
"penahub.gitlab.yandexcloud.net/backend/quiz/telegram/state_manager"
|
||||
)
|
||||
|
||||
type Respondent struct {
|
||||
Manager *stateManager.StateManager
|
||||
}
|
||||
|
||||
func NewRespondent(m *stateManager.StateManager) *Respondent {
|
||||
return &Respondent{
|
||||
Manager: m,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Respondent) Respond(startState string) {
|
||||
question := r.Manager.Questions[r.Manager.State]
|
||||
if len(question.Buttons) > 0 {
|
||||
var choice models.Button
|
||||
for {
|
||||
choice = question.Buttons[rand.Intn(len(question.Buttons))]
|
||||
fmt.Println("choice it:", choice.Text)
|
||||
if choice.State != startState {
|
||||
break
|
||||
}
|
||||
}
|
||||
r.Manager.Listener(choice.State)
|
||||
}
|
||||
}
|
27
respondent/respondent.v
Normal file
27
respondent/respondent.v
Normal file
@ -0,0 +1,27 @@
|
||||
module respondent
|
||||
|
||||
import rand
|
||||
import state_manager
|
||||
|
||||
pub struct Respondent {
|
||||
pub mut:
|
||||
manager &state_manager.StateManager
|
||||
}
|
||||
|
||||
pub fn (mut r Respondent) respond(start_state string) {
|
||||
mut question := r.manager.questions[r.manager.state]
|
||||
if question.buttons.len > 0 {
|
||||
mut choice := question.buttons[0]
|
||||
for {
|
||||
choice = question.buttons[rand.intn(question.buttons.len) or {
|
||||
eprintln('Failed rand.intn: ${err}')
|
||||
return
|
||||
}]
|
||||
//println('choice it: ${choice}')
|
||||
if choice.state != start_state {
|
||||
break
|
||||
}
|
||||
}
|
||||
r.manager.listener(choice.state)
|
||||
}
|
||||
}
|
41
state_manager/stateManager.go
Normal file
41
state_manager/stateManager.go
Normal file
@ -0,0 +1,41 @@
|
||||
package stateManager
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"penahub.gitlab.yandexcloud.net/backend/quiz/telegram/client"
|
||||
"penahub.gitlab.yandexcloud.net/backend/quiz/telegram/models"
|
||||
)
|
||||
|
||||
type StateManager struct {
|
||||
Questions map[string]models.Question
|
||||
State string
|
||||
client *client.Client
|
||||
}
|
||||
|
||||
type Deps struct {
|
||||
Questions map[string]models.Question
|
||||
State string
|
||||
Client *client.Client
|
||||
}
|
||||
|
||||
func NewStateManager(deps Deps) *StateManager {
|
||||
return &StateManager{
|
||||
Questions: deps.Questions,
|
||||
State: deps.State,
|
||||
client: deps.Client,
|
||||
}
|
||||
}
|
||||
|
||||
func (sm *StateManager) Listener(state string) {
|
||||
sm.State = state
|
||||
sm.SendQuestion()
|
||||
}
|
||||
|
||||
func (sm *StateManager) SendQuestion() {
|
||||
question := sm.Questions[sm.State]
|
||||
message := fmt.Sprintf("%s\n%s", question.Title, question.Description)
|
||||
for _, button := range question.Buttons {
|
||||
message += fmt.Sprintf("\n%s", button.Text)
|
||||
}
|
||||
sm.client.SendMessage(message)
|
||||
}
|
26
state_manager/stateManager.v
Normal file
26
state_manager/stateManager.v
Normal file
@ -0,0 +1,26 @@
|
||||
module state_manager
|
||||
|
||||
import strconv
|
||||
import models
|
||||
import client
|
||||
|
||||
pub struct StateManager {
|
||||
pub mut:
|
||||
questions map[string]models.Question
|
||||
state string
|
||||
client &client.Client
|
||||
}
|
||||
|
||||
pub fn (mut sm StateManager) listener(state string) {
|
||||
sm.state = state
|
||||
sm.send_question()
|
||||
}
|
||||
|
||||
pub fn (mut sm StateManager) send_question() {
|
||||
mut question := sm.questions[sm.state]
|
||||
mut message := unsafe { strconv.v_sprintf('%s\n%s', question.title, question.description)}
|
||||
for _, button in question.buttons {
|
||||
message += unsafe { strconv.v_sprintf('\n%s', button.text)}
|
||||
}
|
||||
sm.client.send_message(message)
|
||||
}
|
55
tg_handle/tg.v
Normal file
55
tg_handle/tg.v
Normal file
@ -0,0 +1,55 @@
|
||||
module tg_handle
|
||||
|
||||
import dariotarantini.vgram
|
||||
|
||||
pub struct TgBot {
|
||||
pub:
|
||||
bot vgram.Bot
|
||||
}
|
||||
|
||||
pub fn new_tg_bot(token string){
|
||||
bot := vgram.new_bot(token)
|
||||
b := TgBot{
|
||||
bot: bot
|
||||
}
|
||||
spawn b.start()
|
||||
}
|
||||
|
||||
fn (b TgBot) start() ! {
|
||||
mut new := true
|
||||
mut last_offset := 0
|
||||
for {
|
||||
mut updates := b.bot.get_updates(offset: last_offset, limit: 100)
|
||||
for update in updates {
|
||||
if last_offset < update.update_id {
|
||||
last_offset = update.update_id
|
||||
if new{
|
||||
new = false
|
||||
break
|
||||
}
|
||||
if update.message.text == "/start" {
|
||||
b.start_handler(update)!
|
||||
}
|
||||
else {
|
||||
b.message_handler(update)!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (b TgBot) start_handler(update vgram.Update) ! {
|
||||
b.bot.send_message(
|
||||
chat_id: update.message.from.id.str(),
|
||||
text: 'Привет!'
|
||||
)
|
||||
}
|
||||
|
||||
fn (b TgBot) message_handler(update vgram.Update) ! {
|
||||
if !update.message.text.starts_with('/') {
|
||||
b.bot.send_message(
|
||||
chat_id: update.message.from.id.str(),
|
||||
text: 'Кнопка: $update.message.text'
|
||||
)
|
||||
}
|
||||
}
|
7184
treedata.json
Normal file
7184
treedata.json
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user