This commit is contained in:
commit
b72a1a32ce
8 changed files with 268 additions and 0 deletions
11
.drone.yml
Normal file
11
.drone.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
kind: pipeline
|
||||
name: default
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:alpine
|
||||
commands:
|
||||
- CGO_ENABLED=0 go test -v ./...
|
||||
volumes:
|
||||
- name: gopath
|
||||
path: /go
|
9
Dockerfile
Normal file
9
Dockerfile
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Would love to use scratch but we need those CA certs
|
||||
FROM golang:alpine
|
||||
|
||||
ENV GOPROXY https://modules.fromouter.space
|
||||
ENV GO111MODULE=on
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ENTRYPOINT go run .
|
1
README.md
Normal file
1
README.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Bot for scrabble sylladex
|
5
go.mod
Normal file
5
go.mod
Normal file
|
@ -0,0 +1,5 @@
|
|||
module git.fromouter.space/Hamcha/scrabblego
|
||||
|
||||
go 1.12
|
||||
|
||||
require github.com/bwmarrin/discordgo v0.19.0
|
6
go.sum
Normal file
6
go.sum
Normal file
|
@ -0,0 +1,6 @@
|
|||
github.com/bwmarrin/discordgo v0.19.0 h1:kMED/DB0NR1QhRcalb85w0Cu3Ep2OrGAqZH1R5awQiY=
|
||||
github.com/bwmarrin/discordgo v0.19.0/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q=
|
||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 h1:y6ce7gCWtnH+m3dCjzQ1PCuwl28DDIc3VNnvY29DlIA=
|
||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
100
index.html
Normal file
100
index.html
Normal file
|
@ -0,0 +1,100 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Scrabble calculator</title>
|
||||
<meta charset="UTF-8" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/spectre.css/dist/spectre.min.css"
|
||||
/>
|
||||
<style>
|
||||
body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
main {
|
||||
padding: 3em;
|
||||
}
|
||||
.number {
|
||||
width: 3em;
|
||||
}
|
||||
p {
|
||||
padding: 1em 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main id="app">
|
||||
<input type="text" placeholder="Oggetto" v-model="text" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Quanti slot hai"
|
||||
class="number"
|
||||
v-model="maxslot"
|
||||
/>
|
||||
<p>
|
||||
Risultato: <b>{{ score }}</b> % {{ maxslot }} => <b>{{ slot }}</b>
|
||||
</p>
|
||||
</main>
|
||||
<script type="module">
|
||||
import Vue from "https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.esm.browser.js";
|
||||
|
||||
let points = {
|
||||
A: 1,
|
||||
O: 1,
|
||||
I: 1,
|
||||
E: 1,
|
||||
C: 2,
|
||||
R: 2,
|
||||
S: 2,
|
||||
T: 2,
|
||||
L: 3,
|
||||
M: 3,
|
||||
N: 3,
|
||||
U: 3,
|
||||
W: 4,
|
||||
Y: 4,
|
||||
B: 5,
|
||||
D: 5,
|
||||
F: 5,
|
||||
P: 5,
|
||||
V: 5,
|
||||
K: 5,
|
||||
G: 8,
|
||||
H: 8,
|
||||
Z: 8,
|
||||
J: 8,
|
||||
X: 8,
|
||||
Q: 10
|
||||
};
|
||||
|
||||
const app = new Vue({
|
||||
el: "#app",
|
||||
data: {
|
||||
text: "",
|
||||
maxslot: 10
|
||||
},
|
||||
computed: {
|
||||
score: function() {
|
||||
const letters = this.text
|
||||
.toUpperCase()
|
||||
.trim()
|
||||
.split("");
|
||||
return letters.reduce((total, letter) => {
|
||||
if (letter in points) {
|
||||
total += points[letter];
|
||||
}
|
||||
return total;
|
||||
}, 0);
|
||||
},
|
||||
|
||||
slot: function() {
|
||||
return (this.score % this.maxslot) + 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
118
main.go
Normal file
118
main.go
Normal file
|
@ -0,0 +1,118 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
const TriggerWord = "!syl-"
|
||||
|
||||
var points = map[rune]int{
|
||||
'A': 1, 'O': 1, 'I': 1, 'E': 1,
|
||||
'C': 2, 'R': 2, 'S': 2, 'T': 2,
|
||||
'L': 3, 'M': 3, 'N': 3, 'U': 3,
|
||||
'W': 4, 'Y': 4,
|
||||
'B': 5, 'D': 5, 'F': 5, 'P': 5, 'V': 5, 'K': 5,
|
||||
'G': 8, 'H': 8, 'Z': 8, 'J': 8, 'X': 8,
|
||||
'Q': 10,
|
||||
}
|
||||
|
||||
func scrabbleScore(letters string) int {
|
||||
letters = strings.ToUpper(letters)
|
||||
totalScore := 0
|
||||
for _, glyph := range letters {
|
||||
letterScore, ok := points[glyph]
|
||||
if ok {
|
||||
totalScore += letterScore
|
||||
}
|
||||
}
|
||||
return totalScore
|
||||
}
|
||||
|
||||
func scrabbleToStr(letters string) string {
|
||||
letters = strings.ToUpper(letters)
|
||||
arr := []string{}
|
||||
for _, glyph := range letters {
|
||||
letterScore, ok := points[glyph]
|
||||
if ok {
|
||||
arr = append(arr, fmt.Sprintf("%s=%d", string(glyph), letterScore))
|
||||
}
|
||||
}
|
||||
return strings.Join(arr, " + ")
|
||||
}
|
||||
|
||||
func main() {
|
||||
token := os.Getenv("TOKEN")
|
||||
if token == "" {
|
||||
panic("TOKEN env var is missing")
|
||||
}
|
||||
|
||||
// Create a new Discordgo session
|
||||
dg, err := discordgo.New(token)
|
||||
checkErr(err)
|
||||
|
||||
dg.AddHandler(func(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||
// Ignore bot commands
|
||||
if m.Author.Bot {
|
||||
return
|
||||
}
|
||||
|
||||
if strings.HasPrefix(m.Content, TriggerWord) {
|
||||
msg := m.Content[len(TriggerWord):]
|
||||
parts := strings.SplitN(msg, " ", 2)
|
||||
if len(parts) < 2 {
|
||||
return
|
||||
}
|
||||
maxsize, err := strconv.Atoi(parts[0])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
score := scrabbleScore(parts[1])
|
||||
slot := score % maxsize
|
||||
_, err = s.ChannelMessageSendEmbed(m.ChannelID, &discordgo.MessageEmbed{
|
||||
Author: &discordgo.MessageEmbedAuthor{
|
||||
Name: "Scrabble Sylladex",
|
||||
},
|
||||
Title: fmt.Sprintf("Risultato: %d", slot+1),
|
||||
Description: fmt.Sprintf("\"%s\" va nello slot %d (di %d)", parts[1], slot+1, maxsize),
|
||||
Fields: []*discordgo.MessageEmbedField{
|
||||
{
|
||||
Name: "Valore parola",
|
||||
Value: fmt.Sprintf("%s = %d", scrabbleToStr(parts[1]), score),
|
||||
}, {
|
||||
Name: "Posizionamento",
|
||||
Value: fmt.Sprintf("%d mod %d = %d → %d", score, maxsize, slot, slot+1),
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Error: %s\n", err.Error())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
dg.AddHandler(func(s *discordgo.Session, m *discordgo.Ready) {
|
||||
log.Print("ready")
|
||||
})
|
||||
|
||||
checkErr(dg.Open())
|
||||
defer dg.Close()
|
||||
|
||||
sc := make(chan os.Signal, 1)
|
||||
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, syscall.SIGSEGV, syscall.SIGHUP)
|
||||
<-sc
|
||||
}
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
log.Fatalf("FATAL ERROR: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
18
main_test.go
Normal file
18
main_test.go
Normal file
|
@ -0,0 +1,18 @@
|
|||
package main
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestScrabbleScore(t *testing.T) {
|
||||
testscores := map[string]int{
|
||||
"spada del potere": 35,
|
||||
"puppami la fava": 39,
|
||||
"yogurt alla papaja": 49,
|
||||
"jack": 16,
|
||||
"mela": 8,
|
||||
}
|
||||
for testword, testscore := range testscores {
|
||||
if score := scrabbleScore(testword); score != testscore {
|
||||
t.Errorf("Expected word \"%s\" to have score %d but got %d", testword, testscore, score)
|
||||
}
|
||||
}
|
||||
}
|
Reference in a new issue