package com.github.projectflink.generators;
import org.apache.commons.math3.random.RandomDataGenerator;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Utils {
private static String[] realWordsDict;
private static String[] userAgents;
static {
BufferedReader br;
// get real words
try {
URL rsrc = Logdata.class.getResource("/dictionary.txt");
System.err.println("rs="+rsrc);
br = new BufferedReader( new InputStreamReader(rsrc.openStream()));
String line;
List<String> el = new ArrayList<String>();
while ((line = br.readLine()) != null) {
el.add(line.trim());
}
br.close();
realWordsDict = el.toArray(new String[el.size()]);
} catch (IOException e) {
e.printStackTrace();
}
// get user agents
try {
URL rsrc = Logdata.class.getResource("/ua.txt");
System.err.println("rs="+rsrc);
br = new BufferedReader( new InputStreamReader(rsrc.openStream()));
String line;
List<String> el = new ArrayList<String>();
while ((line = br.readLine()) != null) {
el.add(line.trim());
}
br.close();
userAgents = el.toArray(new String[el.size()]);
} catch (IOException e) {
e.printStackTrace();
}
}
public static String[] getDictionary() {
return realWordsDict;
}
public static String[] getUAs() {
return userAgents;
}
public static String getRandomRealWord(Random rnd) {
return realWordsDict[rnd.nextInt(realWordsDict.length-1)];
}
private static RandomDataGenerator rndZipf = new RandomDataGenerator();
public static String getSlowZipfRandomWord() {
int idx = rndZipf.nextZipf(realWordsDict.length, 0.77);
return realWordsDict[idx];
}
private static ZipfDistribution fastZipf = new ZipfDistribution(1.5, realWordsDict.length);
public static String getFastZipfRandomWord() {
int idx = (int)fastZipf.next();
return realWordsDict[idx];
}
public static String getRandomUA(Random rnd) {
return userAgents[rnd.nextInt(userAgents.length-1)];
}
//
// Util classes
//
public static class XORShiftRandom extends Random {
private long seed = System.nanoTime();
public XORShiftRandom() {
}
protected int next(int nbits) {
// N.B. Not thread-safe!
long x = this.seed;
x ^= (x << 21);
x ^= (x >>> 35);
x ^= (x << 4);
this.seed = x;
x &= ((1L << nbits) -1);
return (int) x;
}
}
public static class ZipfDistribution {
private double skew;
private long maxVal;
private double[] sumProbCache;
private double normalizationConstant = 0.0;
private Random rand = new XORShiftRandom();
public ZipfDistribution(double skew, long maxVal) {
this.skew = skew;
this.maxVal = maxVal;
// Compute normalization constant on first call only
for (long i = 1; i <= this.maxVal; ++i) {
normalizationConstant = normalizationConstant +
(1.0 / Math.pow((double) i, skew));
}
normalizationConstant = 1.0f / normalizationConstant;
sumProbCache = new double[(int)this.maxVal];
for (int i = 0; i < this.maxVal; ++i) {
this.sumProbCache[i] = -1.0f;
}
}
public long next() {
double z; // Uniform random number (0 < z < 1)
double sumProb; // Sum of probabilities
int zipfValue = -1; // Computed exponential value to be returned
// Pull a uniform random number (0 < z < 1)
do {
z = rand.nextDouble();
} while (z == 0.0f);
// Map z to the value
sumProb = 0;
for (int i = 1; i <= this.maxVal; i++) {
if (sumProbCache[i - 1] < 0.0f) {
sumProb = sumProb + normalizationConstant / Math.pow((double) i, skew);
sumProbCache[i - 1] = sumProb;
} else {
sumProb = sumProbCache[i - 1];
}
if (sumProb >= z) {
zipfValue = i;
break;
}
}
return zipfValue - 1;
}
}
}