首页 > 其他分享 >年会抽奖实现

年会抽奖实现

时间:2022-11-26 16:01:26浏览次数:61  
标签:awarders 抽奖 return err gift 实现 http Awarder 年会

最近接手的项目中要新增一个抽奖功能,场景类似年会上的抽奖,触发抽奖的只有一个动作,不存在多线程操作导致所抽奖品已经被抽完的情况。简单来说,就是不存在需要锁的场景,也不存在数据同步的情况。

这种场景的抽奖是最容易实现的,我这里的实现思路就是首先获取参与抽奖的总数,然后根据奖品数量生成几个随机数来确定中奖者。

我这里的实现首先需要上传奖品,然后上传抽奖名单,最后再根据奖品类别和数据库中未中奖用户的数量来生成随机数:

// 奖品
type Gift struct {
	gorm.Model
	Name     string `json:"name" gorm:"type:varchar(32)"` // 奖品名称
	GiftType int    `json:"giftType"`                     // 奖品类别
	Number   int    `json:"number"`                       // 奖品数据
}

type Gifts struct {
	Gifts []*Gift `json:"gifts"`
}

func (p *Gift) TableName() string {
	return "gifts"
}

func (p *Gift) Create(ctx context.Context, db *gorm.DB) error {
	tx := db.Begin()
	if err := tx.Save(p).Error; err != nil {
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}

// 抽奖人员
type Awarder struct {
	Name  string `json:"name" gorm:"type:varchar(32)"`                // 抽奖人员名称
	ID    string `json:"id" gorm:"primarykey;type:varchar(32)"`       // 抽奖人员id
	Prize string `json:"prize" gorm:"type:varchar(32);default:prize"` // 奖品
}

func (a Awarder) Equal(o Awarder) bool {
	if a.Name != o.Name {
		return false
	}
	if a.ID != o.ID {
		return false
	}
	return true
}

type Awarders struct {
	Awarders []*Awarder `json:"awarders"`
}

func (p *Awarder) TableName() string {
	return "awarders"
}

func (p *Awarder) Create(ctx context.Context, db *gorm.DB) error {
	tx := db.Begin()
	if err := tx.Save(p).Error; err != nil {
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}

type Draw struct {
	GiftType int `json:"giftType" form:"giftType"`
}

func award(ctx *gin.Context) {
	draw := &Draw{}
	if err := ctx.Bind(draw); err != nil {
		log.Errorf("Call award function error: %s", err.Error())
		ctx.JSON(http.StatusBadRequest, gin.H{"code": http.StatusBadRequest, "msg": err.Error()})
		return
	}

	gift := &Gift{}
	if err := dbHandler.Model(&Gift{}).Where(&Gift{GiftType: draw.GiftType}).First(gift).Error; err != nil {
		log.Errorf("Get gifts from db error: %s", err.Error())
		ctx.JSON(http.StatusOK, gin.H{"code": http.StatusInternalServerError, "msg": err.Error()})
		return
	}
	if gift.Number == 0 {
		log.Infof("there is no gift with name: %s", gift.Name)
		ctx.JSON(http.StatusBadRequest, gin.H{"code": http.StatusBadRequest, "msg": fmt.Sprintf("there is no gift with name: %s", gift.Name)})
		return
	}

	var awarders []Awarder
	if err := dbHandler.Model(&Awarder{}).Where("prize = ?", "prize").Find(&awarders).Error; err != nil {
		log.Errorf("Get awarders from db error: %s", err.Error())
		ctx.JSON(http.StatusOK, gin.H{"code": http.StatusInternalServerError, "msg": err.Error()})
		return
	}
	if len(awarders) == 0 {
		log.Info("there is no body without prize")
		ctx.JSON(http.StatusBadRequest, gin.H{"code": http.StatusBadRequest, "msg": "there is no body without prize"})
		return
	}

	var winner []Awarder
	if gift.Number > len(awarders) {
		winner = make([]Awarder, len(awarders))
	} else {
		winner = make([]Awarder, gift.Number)
	}

	for i := 0; i < len(winner); i++ {
		if gift.Number == 0 {
			log.Info("no gift with name: %s", gift.Name)
			break
		}
		gift.Number -= 1
		index, err := rand.Int(rand.Reader, big.NewInt(int64(len(winner))))
		if err != nil {
			log.Errorf("Gen random number error: %s", err.Error())
			ctx.JSON(http.StatusOK, gin.H{"code": http.StatusInternalServerError, "msg": err.Error()})
			return
		}
		awarder := awarders[index.Int64()]
		awarder.Prize = gift.Name
		awarder.Create(context.TODO(), dbHandler)
		awarders = delAwarder(awarders, awarder)

		winner[i] = awarder
	}
	gift.Create(context.TODO(), dbHandler)
	ctx.JSON(http.StatusOK, gin.H{"code": http.StatusOK, "msg": "success", "data": winner})
}

func delAwarder(awarders []Awarder, awarder Awarder) []Awarder {
	i := 0
	for _, v := range awarders {
		if !v.Equal(awarder) {
			awarders[i] = v
			i++
		}
	}
	return awarders[:i]
}

声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin92
Github: mengbin92
cnblogs: 恋水无意


标签:awarders,抽奖,return,err,gift,实现,http,Awarder,年会
From: https://www.cnblogs.com/lianshuiwuyi/p/16927581.html

相关文章

  • wordpress代码实现相关文章的几种方法
    我们在制作wordpress主题的时候经常会为文章模板添加一些相关文章的功能丰富,他们有的时候出现在侧栏,有的时候出现在文章的底部相关文章这块,当然WordPress相关文章的插件也......
  • Dockerfile配合IDEA实现一键部署
    1.1Dokcker开启远程访问1.1.0修改docker服务的配置文件vim/lib/systemd/system/docker.service1在ExecStart那行,加上-Htcp://0.0.0.0:2375代表任何ip都可以访问重新加......
  • 使用MeshCmd实现AMT命令行远程开机
        MeshCmd(MeshCommander)是一个新的全功能命令行工具,适用于在Windows和Linux上运行的英特尔®AMT。新工具称为“MeshCmd”,也称为“MeshCommand”。它使使用......
  • 【图像分割】基于神经气体网络 (NGN)实现图像分割附matlab代码
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进。......
  • 好消息 突破:IM开源项目OpenIM采用wasm技术实现jssdk
    OpenIM客户端sdk用golang实现,同时采用sqlite存储本地聊天记录,通过gomobile生成sdk,供iOSAndroid调用,达到了了一套代码多端复用的效果。最近融合wasm技术,让浏览器具备存储......
  • python实现输出文件夹的目录树结构
    最近清理QQ文件夹的时候,发现群聊图片巨TM大,就想看看群友们都发了什么怪图片但是QQ群聊图片文件夹里面的文件夹是一个套一个,靠手工copy肯定是不太行的,就写了个简单......
  • 分位数回归损失函数代码实现解析
    目录1.绪论2.分位数回归3.分位数回归损失函数4.\((\gamma-1)\)的放入5.程序代码表达1.绪论对于分位数回归损失函数,最近看到了两种不同的实现。这种实现和Bing......
  • 5-6 显示html页面-使用post实现登录
    1.创建自己的应用(app)文件夹执行下面的命令,将自动生成对应的文件夹polls是应用名称,可以自己更改pythonmanage.pystartapppolls在主文件中settings中添加应用......
  • 【计算机视觉(CV)】基于全连接网络实现宝石分类
    【计算机视觉(CV)】基于全连接网络实现宝石分类作者简介:在校大学生一枚,华为云享专家,阿里云专家博主,腾云先锋(TDP)成员,云曦智划项目总负责人,全国高等学校计算机教学与产业实践资......
  • Flutter实现录音播放
    之前写过一一篇iOS的录音播放文档,现在在app改写的时候,需要用到Flutter改写,把遇到的问题记录下来用的flutter-sound这个库,实现了录音和播放等功能,录制时可以指定录音的格......