public Event next ( int minIp , int maxIp ) { final double p = rnd . nextDouble ( ) ; if ( p * 1000 >= states . size ( ) ) { // create a new state machine final int nextIP = rnd . nextInt ( maxIp - minIp ) + minIp ; if ( ! states . containsKey ( nextIP ) ) { EventTypeAndState eventAndState = State . Initial . randomTransition ( rnd ) ; states . put ( nextIP , eventAndState . state ) ; return new Event ( eventAndState . eventType , nextIP ) ; } else { // collision on IP address, try again return next ( minIp , maxIp ) ; } } else { // pick an existing state machine // skip over some elements in the linked map, then take the next // update it, and insert it at the end int numToSkip = Math . min ( 20 , rnd . nextInt ( states . size ( ) ) ) ; Iterator < Entry < Integer , State > > iter = states . entrySet ( ) . iterator ( ) ; for ( int i = numToSkip ; i > 0 ; -- i ) { iter . next ( ) ; } Entry < Integer , State > entry = iter . next ( ) ; State currentState = entry . getValue ( ) ; int address = entry . getKey ( ) ; iter . remove ( ) ; if ( p < errorProb ) { EventType event = currentState . randomInvalidTransition ( rnd ) ; return new Event ( event , address ) ; } else { EventTypeAndState eventAndState = currentState . randomTransition ( rnd ) ; if ( ! eventAndState . state . isTerminal ( ) ) { // reinsert states . put ( address , eventAndState . state ) ; } return new Event ( eventAndState . eventType , address ) ; } } }
Creates a new random event . This method randomly pick either one of its currently running state machines or start a new state machine for a random IP address .