您的位置:首页 > 其它

在营销活动中的抽奖算法放送

2017-08-17 11:23 417 查看
做秒杀的深有体会

做抽奖的深有体会

体会什么?

奖品不一会儿就被抽光了??纳尼(一脸懵逼)

说好的这些奖品要维持一天呢!!

去数据库查查去~

这货怎么能有两个订单??不是说好的一个用户只能抽奖一次么!!(沮丧脸)

这货又是谁?他们的名字怎么那么相似??(挖日)

/// <summary>
/// 奖项
/// </summary>
public interface IAward
{
/// <summary>
/// 奖品编号
/// </summary>
int ID { get; set; }
/// <summary>
/// 奖品名称
/// </summary>
string  Name { get; set; }
/// <summary>
/// 奖品剩余数量
/// </summary>
int SurplusCount { get; set; }
/// <summary>
/// 产品总数
/// </summary>
int TotalCount { get; set; }
/// <summary>
/// 奖品位置
/// </summary>
int TurnLocation { get; set; }
/// <summary>
/// 商品价格
/// </summary>
decimal TurnPrice { get; set; }
/// <summary>
/// 最后一次被抽中时间
/// </summary>
DateTime LastWinningTime { get; set; }

}


View Code
  上边的代码是奖品项的接口,用于传递给算法和脱离实际的奖品实体。下边的才是硬菜



public class DrawPro
{
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
DateTime? LastUpdateTime;
public List<IAward> AwardsCollection { get; set; }

public DrawPro(List<IAward> awardsCollection, DateTime startTime, DateTime endTime ,DateTime lastTime)
{this.AwardsCollection = awardsCollection;   //奖项集合
this.StartTime = startTime;  //活动的开始时间
this.EndTime = endTime;   //活动的结束时间
this.LastUpdateTime = lastTime;
}

/// <summary>
/// 从奖项集合中抽取奖品
/// </summary>
/// <returns>奖品项</returns>
public IAward Draw(bool VaryAward=false)
{
if (this.AwardsCollection != null && this.AwardsCollection.Count > 0)
{
return GetWinningAwards(VaryAward);
}
//抽奖
return null;
}

/// <summary>
/// 从集合中抽取奖品项
/// </summary>
protected IAward GetWinningAwards(bool varyAward)
{

if (AwardsCollection == null)
{
return null; //没有传递奖品时候,直接返回null
}

//总是能够出奖,从所有的奖类中选出一个奖类,奖品余量越多的,越容易命中
IAward awards = RandomGetAwardBath(this.AwardsCollection); //

//奖品发放完毕
if (awards == null)
{
return null;
}

if (varyAward)
{
return awards;
}

TimeSpan lstspan = StartTime.Subtract(LastUpdateTime.Value);
int currentBalance = 0; // awards.SurplusCount; //剩余奖品数量
int currentAmount = 0; // awards.TotalCount;  //奖品总数

foreach (var item in this.AwardsCollection)
{
currentBalance += item.SurplusCount;
currentAmount += item.TotalCount;
}

TimeSpan tsanSs = EndTime.Subtract(StartTime);
long dataTime = Math.Abs((long)tsanSs.TotalMilliseconds / currentAmount);   //两个奖品出奖时间间隔(单位毫秒)

if (dataTime == 0)
{
dataTime = 100;//当时间无法分配的时候,设置默认出奖
}

//使用lastUpdateTime  作为随机因子保证下一个奖品的出奖时间对每个抽奖者一样
Random rand = new Random(lstspan.Milliseconds);

//计算下一个奖品的释放时间点
//已经出奖所用时间+  小于间隔的时间(<dataTime),就是下个奖品的出奖时间  ,
//用一个随机数%dataTime的到结果永远小于dataTime
long releaseTime = (currentAmount - currentBalance) * dataTime + rand.Next() % dataTime;

DateTime eqTime = this.StartTime.AddMilliseconds(releaseTime);
if (DateTime.Now < eqTime)
{
/*当前时间未达到下一个奖品的释放时间点*/
return null;
}

return awards;
}

/// <summary>
/// 随机获取一个奖品(总是出奖)
/// </summary>
/// <param name="awardBatchs"></param>
/// <returns></returns>
protected IAward RandomGetAwardBath(List<IAward> awardBatchs)
{
if (awardBatchs == null || awardBatchs.Count <= 0)
{
return null;
}

int weight = 0;
for (int i = 0; i < awardBatchs.Count; i++)
{
weight += awardBatchs[i].SurplusCount;
}

if (weight == 0)   //剩余奖品数量
{
return null;
}

/*这里:如果剩余的奖品数量不变,那么此处随机出的结果是不会变化的,即:当奖品数量不变时候,这里能指定下次出奖的奖品,任何情况下不会改变,除非
奖品数量发生了变化
*/
Random random = new Random(weight);
int num = random.Next(weight);
for (int i = 0; i < awardBatchs.Count; i++)
{
num -= awardBatchs[i].SurplusCount;   //确保num-每个奖品的数量,当小于0时候就可以出奖, 循环内确保总是能够出奖
if (num < 0)
{
return awardBatchs[i];
}
}

return null;
}

}


请大家看代码吧,懒得说了,看不明白私信我哦

欢迎拍砖
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: