# You have grabbed so many red envelopes, do you know how it works?

Posted May 25, 2020 • 5 min read

With the popularity of electronic payments, grabbing red envelopes is currently very popular in social software such as WeChat Dingding.

The amount of red envelopes generally does not need to be large, in order to achieve a way to enhance everyone's enthusiasm. Grabbing red envelopes is actually more of a pastime, the joy of gaining nothing, and the joy is beyond imagination.

Red envelopes have been handed down as our traditional culture to this day, so how do you implement them with programs?

I probably realized it once 5 years ago, and the source code has been gone for too long. I will reorganize it today and hope to inspire you.

# lucky-money

lucky-money is my name for this red envelope gadget. A good name is half the battle.

During the period, I also saw several translations, which were directly translated by pinyin, HongBao, or red-packet of literal translation.

But I still think that lucky-money is more in line with my expectations, because the word lucky means luck, to be a good luck.

Those of us who have snatched red envelopes know that luck is very important in random red envelopes.

Lucky is the soul of this red envelope program.

# At a glance

## demand

Your product manager was "very simple" and came to your work station before you left work, giving you a simple requirement.

Similar to WeChat red envelopes, issued to multiple people, each person grabs a different amount. By the way, the day after tomorrow, this is very simple.

You were thinking about the joy of going home from work was instantly diluted by half, and began to consider how to meet the needs of this red envelope.

## All-takenism

If you are pursuing high efficiency, you immediately think of github, and you can find a pretty good tool lucky-money .

Introduce

com.github.houbb lucky-money 0.0.2 Random

Randomly divide 1000 points(10 yuan) to 5 people.

`List <Long> resultList = LuckyMoneyHelper.luckyMoney(1000, 5);`

The output is as follows:

`[253, 246, 272, 195, 34]`

It's easy to get it done. The rest encapsulates the interface and organizes the documents.

When the time comes to communicate with the front-end ui, there will be no problems with the coming online.

# Specified range

The "very simple" product went back and thought about it. When grabbing the red envelope, I hope that the rain and dew can be evenly covered. For example, 10 yuan is distributed to 5 people, and each person can not be less than 1 yuan.

And it took 5min to throw this requirement to you, and added a little change, the online time remains unchanged.

## Flexible configuration

You read the following document lucky-money has provided this feature, so three times, five and two are done:

```
List <Long> resultList = LuckyMoneyBs.newInstance()
.range(100, 300)
.luckyMoney(1000, 5);
```

Specify a random amount between \ [100, 300 ].

Output result

[175, 371, 163, 122, 169]

So the project went live smoothly, and you did not spend too much energy on it.

# Know why

## Changeable product design

The product manager was "very simple" and felt quite satisfied soon after it went online, so he began to think of new patterns for red envelopes.

And to give you some new needs, you shook your head helplessly, hoping to get off work a little bit lighter.

I want to have time to simply look at the implementation principle of lucky-money , and then we can deal with this changeable product design.

## LuckyMoneyHelper tool class

The tool class serves as the entrance to the core method, so you start from here.

The amount is cents, because the smallest unit of various domestic mobile payment is cents.

The total number is an int type, in fact, in general, many people will not be given red envelopes. You think about it too, sometimes there are hundreds of people in a group, and you can't grab anything by sending a red envelope.

/**

* Distribution

* 1. The number of people uses an integer, 21E is enough

* @param totalAmountFen total amount

* @param totalPerson

* @return result

* @since 0.0.1

* /

public static List

final int totalPerson) {

return LuckyMoneyBs.newInstance(). luckyMoney(totalAmountFen, totalPerson);

}

## LuckyMoneyBs boot class

This class is used as a guide class to facilitate flexible designation of various configurations.

You have read that you know that there is a default value when the amount range is not specified.

Of course, the calculation of this maximum value `calcDynamicMax()`

can be adjusted later according to your actual needs.

/**

* Random distribution

* 1. totalPerson GET 1

* 2. totalAmount GET totalPerson

* 3. maxAmount LTE totalAmount

* @param totalAmount

* @param totalPerson

* @return result

* @since 0.0.1

* /

public List

final int totalPerson) {

ArgUtil.gte("totalPerson", totalPerson, 1);

ArgUtil.gte("totalAmount", totalAmount, totalPerson);

//1. Build context

LuckyMoneyContext context = LuckyMoneyContext.newInstance()

.totalAmount(totalAmount)

.totalPerson(totalPerson);

//2. Automatic calculation

//2.1 The minimum default is 1

if(this.minAmount <= 0) {

this.minAmount = 1;

}

//2.2 The maximum default is all

if(this.maxAmount <= 0) {

this.maxAmount = this.calcDynamicMax(totalAmount);

} else {

//2.3 Custom parameter verification

ArgUtil.lte("maxAmount", maxAmount, totalAmount);

}

context.minAmount(minAmount) .maxAmount(maxAmount);

//3. Results

return this.luckyMoney.luckyMoney(context);

}

## ILuckyMoney core implementation

### Interface definition

Here is an interface. If the product wants an ordinary evenly distributed red envelope, you can expand it yourself.

```
public interface ILuckyMoney {
/**
* Results list
* @param context
* @return result
* @since 0.0.1
* /
List <Long> luckyMoney(final ILuckyMoneyContext context);
}
```

### Built-in implementation

- Basic judgment

You looked at the built-in implementation and found it to be very simple.

And there are notes, it is not difficult to write one yourself.

```
//1. Basic
final int totalPerson = context.totalPerson();
final long totalAmount = context.totalAmount();
long minAmount = context.minAmount();
long maxAmount = context.maxAmount();
List <Long> resultList = Guavas.newArrayList(totalPerson);
//2. Total amount
if(totalAmount <totalPerson) {
throw new LuckyMoneyException("Total amount must be great than" + totalPerson);
}
//3. Dibao(min * total)
long totalMinAmount = minAmount * totalPerson;
if(totalAmount <totalMinAmount) {
throw new LuckyMoneyException("Total amount must be great than" + totalMinAmount);
}
```

Here, in order to prevent those who grab the red envelopes from grabbing 0 yuan, everyone enjoys the "minimum security".

The minimum is 1 cent, can also be specified according to demand

- European Emperor

If a person is very European, it may be that everyone else eats the minimum security, he robbed the rest of the money directly ~

```
long totalRemains = totalAmount-totalMinAmount;
if(maxAmount> totalRemains) {
//No more, all for you
maxAmount = totalRemains;
}
```

- Open grab

Fight for more and less, depending on luck.

Only the first few people are counted here, and the last person is the remaining amount.

```
for(int i = 0; i <totalPerson-1; i ++) {
//5.1 Dibao
long result = minAmount;
//5.2 random
long random = random(totalRemains, maxAmount);
//5.3 Calculation update
totalRemains-= random;
result + = random;
resultList.add(result);
}
long lastRemains = totalRemains + minAmount;
resultList.add(lastRemains);
```

- random()

The source code of the random method is as follows:

/**

* Random amount

* @param totalRemains total remaining

* @param maxAmount maximum amount

* @return result

* @since 0.0.1

* /

private long random(final long totalRemains,

final long maxAmount) {

if(totalRemains <= 0) {

return 0;

}

ThreadLocalRandom random = ThreadLocalRandom.current();

long randomAmount = random.nextLong(maxAmount);

if(randomAmount> totalRemains) {

//all the rest

randomAmount = totalRemains;

}

return randomAmount;

}

## reward

After reading this, you find that you still like the feeling of knowing and knowing why.

Thanks to this author for helping you get off work early, so you gave lucky-money a Star and recommended it to other friends who need it ~~