diff --git a/cmd/main/main b/cmd/main/main index 438c50b..dbba86d 100755 Binary files a/cmd/main/main and b/cmd/main/main differ diff --git a/pkg/controllers/gacha-controller.go b/pkg/controllers/gacha-controller.go index 99b0a3b..6e82b49 100644 --- a/pkg/controllers/gacha-controller.go +++ b/pkg/controllers/gacha-controller.go @@ -1,11 +1,13 @@ package controllers import ( + "crypto/rand" "encoding/json" + "errors" "fmt" "io/ioutil" + "math/big" "net/http" - "sync" "github.com/iamananya/ginco-task/pkg/models" "github.com/iamananya/ginco-task/pkg/utils" @@ -146,54 +148,19 @@ func HandleGachaDraw(w http.ResponseWriter, r *http.Request) { Results: make([]models.CharacterResponse, reqBody.Times), } - // A buffered channel to receive the drawn characters - drawnCharacters := make(chan models.CharacterResponse, reqBody.Times) - - // WaitGroup to synchronize goroutines - var wg sync.WaitGroup - - // Worker pool with a fixed number of goroutines - numWorkers := 10 - tasks := make(chan int, reqBody.Times) - - // Start goroutines to process tasks concurrently - for i := 0; i < numWorkers; i++ { - wg.Add(1) - go func() { - defer wg.Done() - for range tasks { - character, err := models.DrawCharacter(characters, characterPool) // Simulate drawing a character - if err != nil { - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - return - } - characterResponse := models.CharacterResponse{ - CharacterID: fmt.Sprintf("Character-%d", character.ID), - Name: character.Name, - Rarity: character.Rarity, - } - drawnCharacters <- characterResponse - } - }() - } - - // Enqueue tasks for i := 0; i < reqBody.Times; i++ { - tasks <- i - } - - // Close the tasks channel and wait for all goroutines to finish - go func() { - close(tasks) - wg.Wait() - close(drawnCharacters) - }() + character, err := drawCharacter(characterPool) + if err != nil { + http.Error(w, "Internal Server Error", http.StatusInternalServerError) + return + } - // Collect the drawn characters from the channel and populate the response - i := 0 - for characterResponse := range drawnCharacters { + characterResponse := models.CharacterResponse{ + CharacterID: fmt.Sprintf("Character-%d", character.ID), + Name: character.Name, + Rarity: character.Rarity, + } response.Results[i] = characterResponse - i++ } respBody, err := json.Marshal(response) @@ -208,13 +175,13 @@ func HandleGachaDraw(w http.ResponseWriter, r *http.Request) { } func generateCharacterPool(characters []models.Character) []models.Character { - var characterPool []models.Character + characterPool := make([]models.Character, 0) + probabilityMap := make(map[uint]int) for _, character := range characters { rarity := character.Rarity - - // Assign the probability based on rarity var probability int + switch rarity { case "SSR": probability = 5 @@ -224,12 +191,44 @@ func generateCharacterPool(characters []models.Character) []models.Character { probability = 80 } - // Add the character to the pool multiple times based on its probability - poolSize := probability - for i := 0; i < poolSize; i++ { + probabilityMap[character.ID] = probability + } + + for characterID, probability := range probabilityMap { + character := findCharacterByID(characters, characterID) + for i := 0; i < probability; i++ { characterPool = append(characterPool, character) } } return characterPool } + +func findCharacterByID(characters []models.Character, characterID uint) models.Character { + for _, character := range characters { + if character.ID == characterID { + return character + } + } + return models.Character{} +} + +func drawCharacter(characterPool []models.Character) (models.Character, error) { + poolSize := len(characterPool) + if poolSize == 0 { + return models.Character{}, errors.New("empty character pool") + } + + // Randomly select a character from the pool + randIndex, err := rand.Int(rand.Reader, big.NewInt(int64(poolSize))) + if err != nil { + return models.Character{}, errors.New("failed to generate random number") + } + index := int(randIndex.Int64()) + character := characterPool[index] + + // Remove the selected character from the pool + characterPool = append(characterPool[:index], characterPool[index+1:]...) + + return character, nil +} diff --git a/pkg/models/gacha.go b/pkg/models/gacha.go index 61d3b06..0960004 100644 --- a/pkg/models/gacha.go +++ b/pkg/models/gacha.go @@ -2,7 +2,6 @@ package models import ( "crypto/rand" - "errors" "math/big" "github.com/iamananya/ginco-task/pkg/config" @@ -141,29 +140,6 @@ func (uc *UserCharacter) CreateUserCharacter() *UserCharacter { return uc } -func DrawCharacter(characters []Character, characterPool []Character) (*Character, error) { - - if len(characterPool) == 0 { - return nil, errors.New("empty character pool") - } - randIndex, err := rand.Int(rand.Reader, big.NewInt(int64(len(characterPool)))) - if err != nil { - return nil, err - } - index := int(randIndex.Int64()) - selectedCharacter := &characterPool[index] - - // Save the gacha result in the database - gachaResult := GachaResult{ - CharacterID: selectedCharacter.ID, - CharacterName: selectedCharacter.Name, - } - if err := gachaResult.SaveGachaResult(); err != nil { - return nil, err - } - - return selectedCharacter, nil -} func (gr *GachaResult) SaveGachaResult() error { db := config.GetDB() err := db.Create(gr).Error