-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathtext-generator.go
119 lines (101 loc) · 2.29 KB
/
text-generator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package textgenerator
import (
"math/rand"
"time"
)
// GeneratorInterface Text generator interface for expanding functionality
type GeneratorInterface interface {
Generate(text string) string
Configure(startTag rune, endTag rune, separator rune) GeneratorInterface
}
// TextGenerator Generator of unique texts by mask
type TextGenerator struct {
startTag rune
endTag rune
separator rune
}
// New returns a new instance a text generator.
func New() *TextGenerator {
rand.Seed(time.Now().UnixNano())
return &TextGenerator{
startTag: '{',
endTag: '}',
separator: '|',
}
}
// Configure method configures the parser
func (t *TextGenerator) Configure(startTag rune, endTag rune, separator rune) GeneratorInterface {
t.startTag = startTag
t.endTag = endTag
t.separator = separator
return t
}
// Generate generates and returns a new text.
// Use the rules for generating a plurality of texts.
// Example mask: `Good {morning|day}!`
func (t *TextGenerator) Generate(text string) string {
return string(t.scanAndReplace([]rune(text)))
}
func (t *TextGenerator) getRandomPart(text []rune) []rune {
openLevel := 0
lastPos := 0
isIgnore := false
var parts []string
for i := 0; i < len(text); i++ {
if text[i] == t.startTag {
openLevel++
isIgnore = true
continue
}
if text[i] == t.endTag {
openLevel--
if openLevel == 0 {
isIgnore = false
}
continue
}
if isIgnore {
continue
}
if text[i] == t.separator {
parts = append(parts, string(text[lastPos:i]))
lastPos = i + 1
}
}
parts = append(parts, string(text[lastPos:]))
return []rune(parts[rand.Intn(len(parts))])
}
func (t *TextGenerator) scanAndReplace(text []rune) []rune {
startSafePos := 0
startPos := 0
endPos := 0
openLevel := 0
isFind := false
var result []rune
for i := 0; i < len(text); i++ {
if text[i] == t.startTag {
if openLevel == 0 {
startPos = i
//
result = append(result, text[startSafePos:startPos]...)
}
openLevel++
continue
}
if text[i] == t.endTag {
openLevel--
if openLevel == 0 {
isFind = true
endPos = i
//
startSafePos = i + 1
result = append(result, t.scanAndReplace(t.getRandomPart(text[startPos+1:endPos]))...)
continue
}
}
}
if !isFind {
return text
}
return append(result, text[endPos+1:]...)
}