Compare commits

...

21 Commits

Author SHA1 Message Date
Dustin Pianalto
3169953f3f Test github.ref to get branch name
Some checks failed
CI / build (push) Has been cancelled
2020-08-30 17:07:37 -08:00
Dustin Pianalto
d119425236 revert to previous method of getting branch name
Some checks failed
CI / build (push) Has been cancelled
2020-08-30 16:51:00 -08:00
Dustin Pianalto
ce1bbbc445 Check branch name 2020-08-30 16:46:05 -08:00
Dustin Pianalto
f4ec8a7a49 Fix globs
Some checks failed
CI / build (push) Has been cancelled
2020-08-30 16:19:35 -08:00
Dustin Pianalto
bec52ad5a5 Fix globs 2020-08-30 16:03:44 -08:00
Dustin Pianalto
5411730a96 Fix globs 2020-08-30 16:03:01 -08:00
Dustin Pianalto
187f9816ca Fix globs 2020-08-30 16:00:59 -08:00
Dustin Pianalto
feab8e661c Fix globs 2020-08-30 15:45:28 -08:00
Dustin Pianalto
96b63a4e83 Add action to build and push to ECR 2020-08-30 15:43:45 -08:00
Dustin Pianalto
fcddca2226 Delete old organization 2020-08-30 00:10:11 -08:00
Dustin Pianalto
28d78bdb8c Reorganize and update Dockerfile 2020-08-30 00:08:40 -08:00
Dusty.P
23c0434ed3
Merge branch 'master' into development 2020-08-29 18:27:47 -08:00
Dustin Pianalto
e9adc05536 Bump rpnparse version 2020-08-25 22:27:15 -08:00
Dustin Pianalto
b8ee6a1505 Move rpn logic to separate package 2020-08-25 22:22:39 -08:00
Dustin Pianalto
ac46753546 Add infix alias 2020-08-25 21:12:08 -08:00
Dustin Pianalto
d16521e5e3 Add prpn alias 2020-08-25 21:10:32 -08:00
Dustin Pianalto
4955f4bf88 Fix bug due to wrong quotes 2020-08-25 21:07:36 -08:00
Dustin Pianalto
c3d2073b2b Fix bug due to redefining Stack 2020-08-25 21:06:33 -08:00
Dustin Pianalto
1ddc4d4c36 Add rpn parser and infix solver 2020-08-25 21:03:50 -08:00
Dustin Pianalto
d66a25a525 Add rpn command 2020-08-25 17:23:28 -08:00
Dustin Pianalto
6c05518146 Add rpn command 2020-08-25 16:53:51 -08:00
25 changed files with 393 additions and 25 deletions

43
.github/workflows/main.yml vendored Normal file
View File

@ -0,0 +1,43 @@
name: CI
# Controls when the action will run. Triggers the workflow on push to master or development
# with a tag like v1.0.0 or v1.0.0-dev
on:
push:
tags:
- v[0-9]+.[0-9]+.[0-9]+
- v[0-9]+.[0-9]+.[0-9]+-[a-zA-Z]+
jobs:
build:
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/development'
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Get Version
id: get_version
uses: battila7/get-version-action@v2.0.0
- name: Build, tag, and push image to Amazon ECR
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: goff
IMAGE_TAG: ${{ steps.get_version.outputs.version-without-v }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG

View File

@ -1,13 +1,20 @@
FROM golang:1.14-alpine
FROM golang:1.14-alpine as dev
WORKDIR /go/src/Goff
COPY ./go.mod .
COPY ./go.sum .
RUN apk add --no-cache git
RUN go get -d -v ./...
RUN go mod download
COPY . .
RUN go install -v ./...
RUN go install github.com/dustinpianalto/goff
ENTRYPOINT /go/bin/goff
CMD [ "go", "run", "goff.go"]
from alpine
WORKDIR /bin
COPY --from=dev /go/bin/goff ./goff
CMD [ "goff" ]

View File

@ -1,12 +1,13 @@
package events
import (
"djpianalto.com/goff/djpianalto.com/goff/utils"
"fmt"
"github.com/bwmarrin/discordgo"
"log"
"strconv"
"time"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/goff/utils"
)
func OnGuildMemberAddLogging(s *discordgo.Session, member *discordgo.GuildMemberAdd) {

View File

@ -4,8 +4,8 @@ import (
"fmt"
"log"
"djpianalto.com/goff/djpianalto.com/goff/utils"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/goff/utils"
)
func OnMessageUpdate(session *discordgo.Session, m *discordgo.MessageUpdate) {

View File

@ -2,8 +2,11 @@ package exts
import (
"fmt"
"github.com/dustinpianalto/disgoman"
"strconv"
"strings"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/rpnparse"
)
func interleave(ctx disgoman.Context, args []string) {
@ -47,3 +50,35 @@ func deinterleave(ctx disgoman.Context, args []string) {
ctx.Send(fmt.Sprintf("(%v, %v)", x, y))
}
}
func generateRPNCommand(ctx disgoman.Context, args []string) {
rpn, err := rpnparse.GenerateRPN(args)
if err != nil {
ctx.Send(err.Error())
return
}
ctx.Send(rpn)
}
func parseRPNCommand(ctx disgoman.Context, args []string) {
res, err := rpnparse.ParseRPN(args)
if err != nil {
ctx.Send(err.Error())
return
}
ctx.Send(fmt.Sprintf("The result is: %v", res))
}
func solveCommand(ctx disgoman.Context, args []string) {
rpn, err := rpnparse.GenerateRPN(args)
if err != nil {
ctx.Send(err.Error())
return
}
res, err := rpnparse.ParseRPN(strings.Split(rpn, " "))
if err != nil {
ctx.Send(err.Error())
return
}
ctx.Send(fmt.Sprintf("The result is: %v", res))
}

View File

@ -4,8 +4,8 @@ import (
"fmt"
"strings"
"djpianalto.com/goff/djpianalto.com/goff/utils"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/utils"
)
// Guild management commands

View File

@ -204,4 +204,31 @@ func AddCommandHandlers(h *disgoman.CommandManager) {
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: getPuzzleChannel,
})
_ = h.AddCommand(&disgoman.Command{
Name: "RPN",
Aliases: []string{"rpn"},
Description: "Convert infix to rpn",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: generateRPNCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "ParseRPN",
Aliases: []string{"PRPN", "prpn"},
Description: "Parse RPN string and return the result",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: parseRPNCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "solve",
Aliases: []string{"math", "infix"},
Description: "Solve infix equation and return the result",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: solveCommand,
})
}

View File

@ -6,8 +6,8 @@ import (
"log"
"strings"
"djpianalto.com/goff/djpianalto.com/goff/utils"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/utils"
"github.com/kballard/go-shellquote"
)

View File

@ -1,15 +1,16 @@
package exts
import (
"djpianalto.com/goff/djpianalto.com/goff/utils"
"errors"
"fmt"
"strings"
"time"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/utils"
"github.com/olebedev/when"
"github.com/olebedev/when/rules/common"
"github.com/olebedev/when/rules/en"
"strings"
"time"
)
func addReminderCommand(ctx disgoman.Context, args []string) {

View File

@ -1,13 +1,14 @@
package exts
import (
"djpianalto.com/goff/djpianalto.com/goff/utils"
"errors"
"fmt"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/disgoman"
"strings"
"time"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/utils"
)
func kickUserCommand(ctx disgoman.Context, args []string) {

View File

@ -1,14 +1,15 @@
package exts
import (
"djpianalto.com/goff/djpianalto.com/goff/utils"
"fmt"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/disgoman"
"sort"
"strconv"
"strings"
"time"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/utils"
)
func pingCommand(ctx disgoman.Context, _ []string) {

3
go.mod
View File

@ -1,10 +1,11 @@
module djpianalto.com/goff
module github.com/dustinpianalto/goff
go 1.14
require (
github.com/bwmarrin/discordgo v0.20.3-0.20200525154655-ca64123b05de
github.com/dustinpianalto/disgoman v0.0.10
github.com/dustinpianalto/rpnparse v1.0.1
github.com/emersion/go-imap v1.0.5
github.com/emersion/go-message v0.12.0
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51

View File

@ -4,10 +4,10 @@ import (
"fmt"
"log"
"djpianalto.com/goff/djpianalto.com/goff/events"
"djpianalto.com/goff/djpianalto.com/goff/exts"
"djpianalto.com/goff/djpianalto.com/goff/utils"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/events"
"github.com/dustinpianalto/goff/exts"
"github.com/dustinpianalto/goff/utils"
//"github.com/MikeModder/anpan"
"os"

156
utils/rpn.go Normal file
View File

@ -0,0 +1,156 @@
package utils
import (
"fmt"
"strconv"
"strings"
)
type Operator struct {
Token string
Precedence int
Association string
}
func (o Operator) HasHigherPrecedence(t Operator) bool {
return o.Precedence < t.Precedence // lower number is higher precedence
}
func (o Operator) HasEqualPrecedence(t Operator) bool {
return o.Precedence == t.Precedence
}
func (o Operator) IsLeftAssociative() bool {
return o.Association == "left"
}
var operators = map[string]Operator{
"+": Operator{
Token: "+",
Precedence: 4,
Association: "left",
},
"-": Operator{
Token: "-",
Precedence: 4,
Association: "left",
},
"*": Operator{
Token: "*",
Precedence: 3,
Association: "left",
},
"/": Operator{
Token: "/",
Precedence: 3,
Association: "left",
},
"%": Operator{
Token: "%",
Precedence: 3,
Association: "left",
},
"(": Operator{
Token: "(",
Precedence: 1,
Association: "left",
},
")": Operator{
Token: ")",
Precedence: 1,
Association: "left",
},
}
type Stack []Operator
func (s *Stack) IsEmpty() bool {
return len(*s) == 0
}
func (s *Stack) Push(op Operator) {
*s = append(*s, op)
}
func (s *Stack) Pop() (Operator, bool) {
if s.IsEmpty() {
return Operator{}, false
}
index := len(*s) - 1
element := (*s)[index]
*s = (*s)[:index]
return element, true
}
func (s *Stack) Top() Operator {
if s.IsEmpty() {
return Operator{}
}
return (*s)[len(*s)-1]
}
func GenerateRPN(tokens []string) (string, error) {
output := ""
s := Stack{}
for _, token := range tokens {
err := processToken(token, &s, &output)
if err != nil {
return "", err
}
}
for !s.IsEmpty() {
ele, _ := s.Pop()
output += " " + ele.Token
}
return strings.TrimSpace(output), nil
}
func processToken(t string, s *Stack, o *string) error {
if _, err := strconv.Atoi(t); err == nil {
*o += " " + t
return nil
} else if op, ok := operators[t]; ok {
if op.Token == "(" {
s.Push(op)
} else if op.Token == ")" {
if s.IsEmpty() {
return fmt.Errorf("mismatched parentheses")
}
for s.Top().Token != "(" {
if ele, ok := s.Pop(); ok {
*o += " " + ele.Token
} else {
return fmt.Errorf("mismatched parentheses")
}
if s.IsEmpty() {
break
}
}
s.Pop() // Pop and discard the (
} else if !s.IsEmpty() {
for {
if (s.Top().HasHigherPrecedence(op) ||
(s.Top().HasEqualPrecedence(op) &&
op.IsLeftAssociative())) &&
s.Top().Token != "(" {
if ele, ok := s.Pop(); ok {
*o += " " + ele.Token
if s.IsEmpty() {
break
}
continue
} else {
break
}
}
break
}
s.Push(op)
} else {
s.Push(op)
}
return nil
}
return fmt.Errorf("invalid character %s", t)
}

95
utils/rpnParser.go Normal file
View File

@ -0,0 +1,95 @@
package utils
import (
"errors"
"fmt"
"math"
"strconv"
)
type FStack []float64
func (s *FStack) IsEmpty() bool {
return len(*s) == 0
}
func (s *FStack) Push(op float64) {
*s = append(*s, op)
}
func (s *FStack) Pop() (float64, bool) {
if s.IsEmpty() {
return 0, false
}
index := len(*s) - 1
element := (*s)[index]
*s = (*s)[:index]
return element, true
}
func (s *FStack) PopTwo() (float64, float64, bool) {
if s.IsEmpty() || len(*s) < 2 {
return 0, 0, false
}
index := len(*s) - 1
b := (*s)[index]
a := (*s)[index-1]
*s = (*s)[:index-1]
return a, b, true
}
func (s *FStack) Top() float64 {
if s.IsEmpty() {
return 0
}
return (*s)[len(*s)-1]
}
func ParseRPN(args []string) (float64, error) {
s := FStack{}
for _, token := range args {
switch token {
case "+":
if a, b, ok := s.PopTwo(); ok {
s.Push(a + b)
} else {
return 0, fmt.Errorf("not enough operands on stack for +: %v", s)
}
case "-":
if a, b, ok := s.PopTwo(); ok {
s.Push(a - b)
} else {
return 0, fmt.Errorf("not enough operands on stack for -: %v", s)
}
case "*":
if a, b, ok := s.PopTwo(); ok {
s.Push(a * b)
} else {
return 0, fmt.Errorf("not enough operands on stack for *: %v", s)
}
case "/":
if a, b, ok := s.PopTwo(); ok {
s.Push(a / b)
} else {
return 0, fmt.Errorf("not enough operands on stack for /: %v", s)
}
case "%":
if a, b, ok := s.PopTwo(); ok {
s.Push(math.Mod(a, b))
} else {
return 0, fmt.Errorf("not enough operands on stack for %: %v", s)
}
default:
f, err := strconv.ParseFloat(token, 64)
if err != nil {
return 0, err
}
s.Push(f)
}
}
if res, ok := s.Pop(); ok {
return res, nil
}
return 0, errors.New("no result")
}