/*
* Copyright 2013-2016 consulo.io
*
* 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 com.intellij.internal.statistic;
import com.intellij.internal.statistic.beans.UsageDescriptor;
import com.intellij.util.containers.ContainerUtil;
import java.util.Arrays;
import java.util.List;
/**
* @author VISTALL
* @since 10-Sep-16
* <p>
* port com/intellij/internal/statistic/StatisticsUtil.kt
*/
public class StatisticsUtilKt {
/**
* Constructs a proper UsageDescriptor for a boolean value,
* by adding "enabled" or "disabled" suffix to the given key, depending on the value.
*/
public static UsageDescriptor getBooleanUsage(String key, boolean value) {
key += value ? ".enabled" : ".disabled";
return new UsageDescriptor(key, 1);
}
/**
* Constructs a proper UsageDescriptor for a counting value.
* If one needs to know a number of some items in the project, there is no direct way to report usages per-project.
* Therefore this workaround: create several keys representing interesting ranges, and report that key which correspond to the range
* which the given value belongs to.
* <p>
* For example, to report a number of commits in Git repository, you can call this method like that:
* ```
* val usageDescriptor = getCountingUsage("git.commit.count", listOf(0, 1, 100, 10000, 100000), realCommitCount)
* ```
* and if there are e.g. 50000 commits in the repository, one usage of the following key will be reported: `git.commit.count.10K+`.
* <p>
* NB:
* (1) the list of steps must be sorted ascendingly; If it is not, the result is undefined.
* (2) the value should lay somewhere inside steps ranges. If it is below the first step, the following usage will be reported:
* `git.commit.count.<1`.
*
* @key The key prefix which will be appended with "." and range code.
* @steps Limits of the ranges. Each value represents the start of the next range. The list must be sorted ascendingly.
* @value Value to be checked among the given ranges.
*/
public static UsageDescriptor getCountingUsage(String key, int value, List<Integer> steps) {
if (steps.isEmpty()) return new UsageDescriptor(key + "." + value, 1);
if (value < steps.get(0)) {
return new UsageDescriptor(key + ".<" + steps.get(0), 1);
}
int index = Arrays.binarySearch(steps.toArray(), value);
int stepIndex;
if (index == steps.size()) {
stepIndex = ContainerUtil.getLastItem(steps);
}
else if (index >= 0) {
stepIndex = index;
}
else {
stepIndex = -index - 2;
}
int step = steps.get(stepIndex);
boolean addPlus = stepIndex == steps.size() - 1 || steps.get(stepIndex + 1) != step + 1;
String maybePlus = addPlus ? "+" : "";
return new UsageDescriptor(key + "." + humanize(step) + maybePlus, 1);
}
private static final int kilo = 1000;
private static final int mega = kilo * kilo;
private static String humanize(int number) {
if (number == 0) return "0";
int m = number / mega;
int k = (number % mega) / kilo;
int r = (number % kilo);
String ms = m > 0 ? (m + "M") : "";
String ks = k > 0 ? (k + "K") : "";
String rs = r > 0 ? String.valueOf(r) : "";
return ms + ks + rs;
}
}