All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.hasor.cobble.ref.RandomRatio Maven / Gradle / Ivy

/*
 * Copyright 2015-2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.hasor.cobble.ref;
import net.hasor.cobble.RandomUtils;

import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;

/**
 * 控制操作生成比率
 * @version : 2022-07-25
 * @author 赵永春 ([email protected])
 */
public class RandomRatio {
    private final    List> opsBoundary = new CopyOnWriteArrayList<>();
    private volatile long              maxBoundary = 0;

    private long maxBoundary(List> opsBoundary) {
        Boundary boundary = opsBoundary.stream().max(Comparator.comparingLong(Boundary::getMaximum)).orElse(null);
        return (boundary != null) ? boundary.getMaximum() : 0L;
    }

    public synchronized void clearRatio() {
        this.opsBoundary.clear();
        this.maxBoundary = 0;
    }

    public synchronized void addRatio(int ratio, T value) {
        this.opsBoundary.add(new Boundary<>(value, this.maxBoundary, this.maxBoundary + ratio));
        this.maxBoundary = maxBoundary(this.opsBoundary);
    }

    private long getMaxBoundary() {
        return this.maxBoundary;
    }

    public T getByBoundary(long boundaryNumber) {
        for (Boundary entry : this.opsBoundary) {
            if (entry.getMinimum() <= boundaryNumber && boundaryNumber <= entry.getMaximum()) {
                return entry.getValue();
            }
        }
        return null;
    }

    public T getByIndex(int index) {
        return this.opsBoundary.get(index).getValue();
    }

    public T getLast() {
        if (this.opsBoundary.isEmpty()) {
            return null;
        } else {
            return this.opsBoundary.get(this.opsBoundary.size() - 1).getValue();
        }
    }

    public T getFirst() {
        if (this.opsBoundary.isEmpty()) {
            return null;
        } else {
            return this.opsBoundary.get(0).getValue();
        }
    }

    public T getByRandom() {
        return getByBoundary(RandomUtils.nextLong(0, this.maxBoundary));
    }

    public boolean isEmpty() {
        return this.opsBoundary.isEmpty();
    }

    public int getBoundaryCount() {
        return this.opsBoundary.size();
    }

    public void forEach(Consumer action) {
        Objects.requireNonNull(action);
        for (Boundary t : this.opsBoundary) {
            action.accept(t.value);
        }
    }

    /** 拥有上下界的一个范围 */
    protected static class Boundary extends Range {
        private final V value;

        public Boundary(V value, long lower, long upper) {
            super(lower, upper, Long::compare);
            this.value = value;
        }

        public V getValue() {
            return value;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o)
                return true;
            if (o == null || getClass() != o.getClass())
                return false;
            Boundary boundary = (Boundary) o;
            return boundary.value == this.value && super.equals(boundary);
        }

        @Override
        public int hashCode() {
            return Objects.hash(this.value, getMinimum(), getMaximum());
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy