You robbed so many red envelopes. Do you know how it works?

With the popularity of electronic payment, red envelopes are very popular in social software such as wechat nails.

Generally, the amount of red envelopes does not need to be very large, which can achieve the way to improve everyone's enthusiasm. In fact, robbing red envelopes is more of a pastime. It's a joy that can't be imagined.

As our traditional culture, red envelopes have been passed down to the present, so how can we realize them with programs?

It was probably implemented once five years ago. The source code has been gone for too long. I'd like to reorganize it today, hoping to inspire you.

lucky-money

lucky-money It's my name for this red bag gadget. A good name is half the success.

During this period, I also saw several kinds of translations, namely, the direct pinyin translation, Hong Bao, or the direct translation of red packet.

But I still think lucky money is more in line with my expectation, because the word lucky means luck and winning the lottery.

We all know that luck is very important in random red envelopes.

lucky, is the soul of this red packet program.

See it

demand

Your product manager "very simple" comes to your work station before you leave work, and gives you a simple need.

It's similar to wechat red packets, which are sent to multiple people, and the amount of money each person grabs is different. By the way, it's going online the day after tomorrow. It's very simple.

You thought that the happiness of coming home from work was diluted in half, and you began to think about how to realize the demand of red envelopes.

mechanical borrowing without thought of appropriateness

For those who pursue high efficiency, you immediately think about github, and you can easily find a good tool lucky-money.

  • introduce
<dependency>
    <group>com.github.houbb</group>
    <artifact>lucky-money</artifact>
    <version>0.0.2</version>
</dependency>
  • random

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

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

The output is as follows:

[253, 246, 272, 195, 34]

Easy to handle, the rest of the package under the interface, organize the next document.

At that time, I will communicate with the front-end ui. The day after tomorrow, the online problem is not big.

Specify range

"Very simple" products go back and think about it. When robbing red envelopes, I hope they can keep the rain and dew evenly. For example, 10 yuan is given to 5 people, and each person can't be less than 1 yuan.

And spend 5min to change this demand to throw you, make up a change is not big, online time does not change Oh.

Flexible configuration

You read the next document lucky-money This feature has been provided, so it can be divided into three parts, five parts and two parts:

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

Specify a random amount between [100, 300].

  • Output results
[175, 371, 163, 122, 169]

So the project went online smoothly, and you didn't spend too much energy on it.

Know why

Changeable product design

Product manager "very simple" felt quite satisfied soon after the launch, so he began to think of all kinds of new patterns of red envelopes.

And also gave you some new needs, you reluctantly shook your head, looking forward to the mood of the end of work and a few minutes.

I think it's better to look at it simply when I have time lucky-money After that, we can deal with the changeable product design.

LuckyMoneyHelper tool class

The tool class is the entry to the core method, so you can start from here.

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

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

/**
 * distribute
 * 1. The number of people is in integer. 21E is enough
 * @param totalAmountFen Total amount
 * @param totalPerson Total number of people
 * @return result
 * @since 0.0.1
 */
public static List<Long> luckyMoney(final long totalAmountFen,
                                    final int totalPerson) {
    return LuckyMoneyBs.newInstance().luckyMoney(totalAmountFen, totalPerson);
}

LuckyMoneyBs boot class

As a guide class, this class is convenient for flexible specification of various configurations.

You can see 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 according to your actual needs in the later stage.

/**
 * Random distribution
 * 1. totalPerson GET 1
 * 2. totalAmount GET totalPerson
 * 3. maxAmount LTE totalAmount
 * @param totalAmount Total amount
 * @param totalPerson Total number of people
 * @return result
 * @since 0.0.1
 */
public List<Long> luckyMoney(final long totalAmount,
                             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 user defined 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 a common evenly distributed red packet, you can expand it by yourself.

public interface ILuckyMoney {

    /**
     * Results list
     * @param context context
     * @return result
     * @since 0.0.1
     */
    List<Long> luckyMoney(final ILuckyMoneyContext context);

}

Built in implementation

  • Basic judgment

You look at the built-in implementation and find it very simple.

It's not hard to write one by 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. Minimum living insurance (min * total)
long totalMinAmount = minAmount * totalPerson;
if(totalAmount < totalMinAmount) {
    throw new LuckyMoneyException("Total amount must be great than " + totalMinAmount);
}

Here, in order to make the person who robbed the red envelope not get 0 yuan, everyone enjoys the "minimum living insurance".

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

  • The emperor of Europe

If a person is very European, it may be that other people all eat the minimum living insurance, and he just robbed the rest of the money directly~~

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

Take more and take less, each by luck.

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

for(int i = 0; i < totalPerson-1; i++) {
    //5.1 minimum insurance
    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 random method source code is as follows:

/**
 * Random amount
 * @param totalRemains Total surplus
 * @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 that's left
        randomAmount = totalRemains;
    }
    return randomAmount;
}

harvest

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

Thanks to the author for helping me get off work early, so you lucky-money I ordered a Star and recommended it to other partners~~

Tags: Unix github REST less Mobile

Posted on Mon, 25 May 2020 23:16:21 -0400 by wee_eric