1   /** 
2    * LOGBack: the reliable, fast and flexible logging library for Java.
3    *
4    * Copyright (C) 1999-2005, QOS.ch, LOGBack.com
5    *
6    * This library is free software, you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public License as
8    * published by the Free Software Foundation.
9    */
10  package ch.qos.logback.classic.control;
11  
12  import java.util.Random;
13  
14  import ch.qos.logback.classic.Level;
15  
16  public class ScenarioRandomUtil {
17    private final static long SEED = 74130;
18  
19    private final static Random random = new Random(SEED);
20    private final static int AVERAGE_ID_LEN = 32;
21    private final static int AVERAGE_ID_DEV = 16;
22  
23    private final static int AVERAGE_CHILDREN_COUNT = 30;
24    private final static int CHILDREN_COUNT_VAR = 10;
25  
26    public static boolean oneInFreq(int freq) {
27      return (random.nextInt(freq) % freq) == 0;
28    }
29  
30    public static Level randomLevel() {
31      int rl = random.nextInt(6);
32      switch (rl) {
33      case 0:
34        return null;
35      case 1:
36        return Level.TRACE;
37      case 2:
38        return Level.DEBUG;
39      case 3:
40        return Level.INFO;
41      case 4:
42        return Level.WARN;
43      case 5:
44        return Level.ERROR;
45      default:
46        throw new IllegalStateException(
47            "rl should have been a value between 0 to 5, but it is " + rl);
48      }
49    }
50  
51    public static String randomLoggerName(int average, int stdDeviation) {
52      int depth = gaussianAsPositiveInt(average, stdDeviation);
53      StringBuffer buf = new StringBuffer();
54      for (int i = 0; i < depth; i++) {
55        if (i != 0) {
56          buf.append('.');
57        }
58        buf.append(randomId());
59      }
60      return buf.toString();
61    }
62  
63    public static String randomId() {
64  
65      int len = gaussianAsPositiveInt(AVERAGE_ID_LEN, AVERAGE_ID_DEV);
66      StringBuffer buf = new StringBuffer();
67      for (int i = 0; i < len; i++) {
68        int offset = random.nextInt(26);
69        char c = (char) ('a' + offset);
70        buf.append(c);
71      }
72      return buf.toString();
73    }
74  
75    /**
76     * Approximate a gaussian distrib with only only positive integer values
77     * 
78     * @param average
79     * @param stdDeviation
80     * @return
81     */
82    public static int gaussianAsPositiveInt(int average, int stdDeviation) {
83      if (average < 1) {
84        throw new IllegalArgumentException(
85            "The average must not be smaller than 1.");
86      }
87  
88      if (stdDeviation < 1) {
89        throw new IllegalArgumentException(
90            "The stdDeviation must not be smaller than 1.");
91      }
92  
93      double d = random.nextGaussian() * stdDeviation + average;
94      int result = 1;
95      if (d > 1.0) {
96        result = (int) Math.round(d);
97      }
98      return result;
99    }
100 
101   /**
102    * Returns 3 for root, 3 for children of root, 9 for offspring of generation 2
103    * and 3, and for generations 4 and later, return 0 with probability 0.5 and a
104    * gaussian (average=AVERAGE_CHILDREN_COUNT) with probability 0.5.
105    * 
106    * @param name
107    * @return
108    */
109   public static int randomChildrenCount(String name) {
110     int dots = dotCount(name);
111     if (dots <= 1) {
112       return 3;
113     } else if (dots == 2 || dots == 3) {
114       return 9;
115     } else {
116       if (shouldHaveChildrenWithProbabilitz(0.5)) {
117         return gaussianAsPositiveInt(AVERAGE_CHILDREN_COUNT, CHILDREN_COUNT_VAR);
118       } else {
119         return 0;
120       }
121     }
122 
123   }
124 
125   /**
126    * Returns true with probability p.
127    * 
128    * @param p
129    * @return
130    */
131   static boolean shouldHaveChildrenWithProbabilitz(double p) {
132     if (p < 0 || p > 1.0) {
133       throw new IllegalArgumentException(
134           "p must be a value between 0 and 1.0, it was " + p + " instead.");
135     }
136     double r = random.nextDouble();
137     if (r < p) {
138       return true;
139     } else {
140       return false;
141     }
142   }
143 
144   static int dotCount(String s) {
145     int count = 0;
146     int len = s.length();
147     for (int i = 0; i < len; i++) {
148       char c = s.charAt(i);
149       if (c == '.') {
150         count++;
151       }
152     }
153     return count;
154   }
155 }