Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions internal/context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ type NFContext struct {

Messages []Message
DragonBallData map[string]int32

Fortunes []string
FortuneMutex sync.RWMutex
}

type Message struct {
Expand Down Expand Up @@ -97,6 +100,16 @@ func InitNfContext() {
"Krillin": 2,
"Yamcha": 1,
}

nfContext.Fortunes = []string{
"大吉: All your endeavors will be successful.",
"中吉: You will have good luck, but be cautious.",
"小吉: A small amount of luck is coming your way.",
"吉: Good fortune is with you.",
"末吉: Your luck is gradually improving.",
"凶: Be careful, misfortune may be ahead.",
"大凶: A great misfortune is coming. Be prepared.",
}
}

func GetSelf() *NFContext {
Expand Down
60 changes: 0 additions & 60 deletions internal/sbi/api_foodpicker.go

This file was deleted.

121 changes: 0 additions & 121 deletions internal/sbi/api_foodpicker_test.go

This file was deleted.

58 changes: 58 additions & 0 deletions internal/sbi/api_fortune.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package sbi

import (
"net/http"

"github.com/Alonza0314/nf-example/internal/logger"
"github.com/Alonza0314/nf-example/internal/sbi/processor"
"github.com/gin-gonic/gin"
)

func (s *Server) getFortuneRoute() []Route {
return []Route{
{
Name: "Get Today's Fortune",
Method: http.MethodGet,
Pattern: "/",
APIFunc: s.HTTPGetFortune,
// Use
// curl -X GET http://127.0.0.163:8000/fortune/ -w "\n"
},
{
Name: "Add a new Fortune",
Method: http.MethodPost,
Pattern: "/",
APIFunc: s.HTTPPostFortune,
// Use
// curl -X POST http://127.0.0.163:8000/fortune/ \
// -H "Content-Type: application/json" \
// -d '{"fortune":"New fortune text"}' -w "\n"
},
}
}

func (s *Server) HTTPGetFortune(c *gin.Context) {
logger.SBILog.Infof("In HTTPGetFortune")

s.Processor().GetFortune(c)
}

func (s *Server) HTTPPostFortune(c *gin.Context) {
logger.SBILog.Infof("In HTTPPostFortune")

var req processor.PostFortuneRequest
if err := c.ShouldBindJSON(&req); err != nil {
logger.SBILog.Errorf("Invalid request body: %+v", err)
c.JSON(http.StatusBadRequest, gin.H{
"message": "Invalid request body",
"error": err.Error(),
})
return
}

s.Processor().PostFortune(c, req)
}

func (s *Server) GetFortuneRoute() []Route {
return s.getFortuneRoute()
}
65 changes: 65 additions & 0 deletions internal/sbi/api_fortune_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package sbi_test

import (
"net/http"
"testing"

"github.com/Alonza0314/nf-example/internal/sbi"
"github.com/Alonza0314/nf-example/pkg/factory"
"go.uber.org/mock/gomock"
)

func Test_GetFortuneRoute(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

nfApp := sbi.NewMocknfApp(mockCtrl)
nfApp.EXPECT().Config().Return(&factory.Config{
Configuration: &factory.Configuration{
Sbi: &factory.Sbi{
Port: 8000,
},
},
}).AnyTimes()

server := sbi.NewServer(nfApp, "")

routes := server.GetFortuneRoute()
if routes == nil {
t.Fatalf("Expected routes slice, got nil")
}

if len(routes) != 2 {
t.Fatalf("Expected 2 routes, got %d", len(routes))
}

// Validate first route (GET)
r0 := routes[0]
if r0.Name != "Get Today's Fortune" {
t.Errorf("Route 0 Name: expected %q, got %q", "Get Today's Fortune", r0.Name)
}
if r0.Method != http.MethodGet {
t.Errorf("Route 0 Method: expected %q, got %q", http.MethodGet, r0.Method)
}
if r0.Pattern != "/" {
t.Errorf("Route 0 Pattern: expected %q, got %q", "/", r0.Pattern)
}
if r0.APIFunc == nil {
t.Errorf("Route 0 APIFunc should not be nil")
}

// Validate second route (POST)
r1 := routes[1]
if r1.Name != "Add a new Fortune" {
t.Errorf("Route 1 Name: expected %q, got %q", "Add a new Fortune", r1.Name)
}
if r1.Method != http.MethodPost {
t.Errorf("Route 1 Method: expected %q, got %q", http.MethodPost, r1.Method)
}
if r1.Pattern != "/" {
t.Errorf("Route 1 Pattern: expected %q, got %q", "/", r1.Pattern)
}
if r1.APIFunc == nil {
t.Errorf("Route 1 APIFunc should not be nil")
}
}
51 changes: 51 additions & 0 deletions internal/sbi/processor/fortune.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package processor

import (
"math/rand"
"net/http"
"time"

"github.com/gin-gonic/gin"
)

type PostFortuneRequest struct {
Fortune string `json:"fortune" binding:"required"`
}

func (p *Processor) GetFortune(c *gin.Context) {
ctx := p.Context()

ctx.FortuneMutex.RLock()
defer ctx.FortuneMutex.RUnlock()

if len(ctx.Fortunes) == 0 {
c.JSON(http.StatusInternalServerError, gin.H{
"message": "No fortunes available.",
})
return
}

// Seed the random number generator
rand.New(rand.NewSource(time.Now().UnixNano()))
// Get a random fortune
fortune := ctx.Fortunes[rand.Intn(len(ctx.Fortunes))]

c.JSON(http.StatusOK, gin.H{
"message": "Here is your fortune for today!",
"fortune": fortune,
})
}

func (p *Processor) PostFortune(c *gin.Context, req PostFortuneRequest) {
ctx := p.Context()

ctx.FortuneMutex.Lock()
defer ctx.FortuneMutex.Unlock()

ctx.Fortunes = append(ctx.Fortunes, req.Fortune)

c.JSON(http.StatusCreated, gin.H{
"message": "Fortune added successfully",
"fortune": req.Fortune,
})
}
Loading
Loading