/
msrt-ccf-dice-tool.js
123 lines (119 loc) · 4 KB
/
msrt-ccf-dice-tool.js
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
120
121
122
123
const dicer = window['msrt-ccf-dicer'] = {
init() {
this.inputId = 'downshift-0-input'
this.messageSelector = '.MuiListItem-root.MuiListItem-gutters p'
this.diceResultSelector = 'span.MuiTypography-colorTextSecondary, span'
this.helpText = `
example:
2D6+3 2D6+1 2D6-3 1D6+2
alice bob chard denis
staff before last line will be ignored
...
#sort
and click \`msrt\` button
`
this.addButton()
},
getText() {
const text = document.getElementById(this.inputId).value
return text
},
checkFormat(s) {
const line = s.split(/\n/)
return (line.length >= 3) && line.some(l => /^#sort/.test(l))
},
dispatch(node, name) {
const event = new Event(name, {bubbles: true})
event.isTrust = true
node.dispatchEvent(event)
},
setNativeValue(element, value) {
const valueSetter = Object.getOwnPropertyDescriptor(element, 'value').set;
const prototype = Object.getPrototypeOf(element);
const prototypeValueSetter = Object.getOwnPropertyDescriptor(prototype, 'value').set;
if (valueSetter && valueSetter !== prototypeValueSetter) {
prototypeValueSetter.call(element, value);
}
else {
valueSetter.call(element, value);
}
},
putText(s) {
const node = document.getElementById(this.inputId)
this.setNativeValue(node, s)
this.dispatch(node, 'change')
},
send() {
document.querySelector('button[type=submit]').click()
},
sleep(second) {
return new Promise(wake => setTimeout(wake, second*1000))
},
getLastMessage() {
const list = document.querySelectorAll(this.messageSelector)
const last = list[list.length - 1]
return last
},
async waitRoll() {
const lastOrigin = this.getLastMessage()
while (true) {
await this.sleep(1)
const last = this.getLastMessage()
if (last != lastOrigin && this.checkFormat(last.textContent)) {
return last
}
}
},
parseDiceBracket(node) {
const text = node.querySelector(this.diceResultSelector).textContent
const scan = text.match(/\([\d,+\[\]\-]+\)/g)
if (scan) {
return scan.map(s => s.replace(/\[.*\]/, ''))
.map(s => eval(s))
}
else return null
},
normalizeLine(text) {
const line = text.split('\n').map(s => s.trim())
let hide = ''
if (line[line.length - 1].match('#hide')) hide = 'S'
if (line[0].match(' ')) {
const diceCode = line[0].split(/\s+/).map(d => `(${d})`).join('+')
line.unshift(hide + diceCode)
}
return line
},
handleError() {
alert('format wrong\n' + this.helpText)
},
async run() {
const text = this.getText().trim()
if (!text) throw new Error('empty input')
if (!this.checkFormat(text)) throw new Error('format wrong')
const line = this.normalizeLine(text)
const unitList = line[2].split(/\s+/).map(u => [u])
this.putText(line.join('\n') + '\n')
this.send()
const roll = await this.waitRoll()
const diceResult = this.parseDiceBracket(roll)
unitList.forEach((a, i) => a.push(diceResult[i]))
unitList.sort((x, y) => y[1] - x[1])
this.putText(
unitList.map(([n, v]) => `${n}(${n.match('#S') ? '#' : v})`)
.join(' > ') +
'\n' + line.slice(3, -1).join('\n')
)
},
addButton() {
const b = document.createElement('button')
b.type = 'button'
b.textContent = 'msrt'
b.className = 'MuiButtonBase-root MuiButton-root MuiButton-text MuiButton-textSizeSmall MuiButton-sizeSmall'
b.onclick = () => this.run().catch(error => {
alert(String(error))
this.handleError()
})
document.querySelector('button[type=submit]').parentNode.appendChild(b)
}
}
dicer.init()