Skip to content

Commit

Permalink
code has been improvised to generate fast response
Browse files Browse the repository at this point in the history
  • Loading branch information
iamananya committed Jun 1, 2023
1 parent 6306b4c commit ac0fe17
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 76 deletions.
Binary file modified cmd/main/main
Binary file not shown.
103 changes: 51 additions & 52 deletions pkg/controllers/gacha-controller.go
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -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
}
24 changes: 0 additions & 24 deletions pkg/models/gacha.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package models

import (
"crypto/rand"
"errors"
"math/big"

"github.com/iamananya/ginco-task/pkg/config"
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit ac0fe17

Please sign in to comment.