size = rand.nextInt(rubbos.getCommentMaximumLength());
size = rand.nextInt(rubbos.getCommentMaxLength());
  public URL computeURLFromState(int state)  {    if (lastHTMLReply != null)    {      if (lastHTMLReply.indexOf("Sorry") != -1) // Nothing matched the request, we have to go back        state = transition.backToPreviousState();    }    if ((state < 17) || (state > 19)) // Reset lastSearch if we don't stay in a search state      lastSearch = 0;    switch (state)    {    case -1: // An error occured, reset to home page      transition.resetToInitialState();    case 0: // Home Page == Stories of the Day      return urlGen.homePage();    case 1: // Register User Page      return urlGen.register();    case 2: // Register the user in the database      { // Choose a random nb over already known attributed ids        int i = rubbos.getNbOfUsers()+rand.nextInt(1000000)+1;         String firstname = "Great"+i;        String lastname = "User"+i;        String nickname = "user"+i;        String email = firstname+"."+lastname+"@rubbos.com";        String password = "password"+i;                return urlGen.registerUser(firstname, lastname, nickname, email, password);      }    case 3: // Browse Page      return urlGen.browse();    case 4: // Browse Categories      return urlGen.browseCategories();    case 5: // Browse stories in a category      { // We randomly pickup a category from the generated HTML page        Vector c = extractCategoryFromHTML();        int    categoryId;        String categoryName;        if (c == null)        {          categoryId = lastCategoryId;          categoryName = lastCategoryName;        }        else        {          categoryId = ((Integer)c.get(0)).intValue();          categoryName = (String)c.get(1);          lastCategoryId = categoryId;          lastCategoryName = categoryName;                  }        return urlGen.browseStoriesByCategory(categoryId, categoryName, extractPageFromHTML(), rubbos.getNbOfStoriesPerPage());      }    case 6: // Older stories      {        // We have to make hit on past days more successful than hits on 10 years old stories        int day;        int month;        int year;        int when = rand.nextInt(100);        if (when > 95)        { // Pickup any date          day = rand.nextInt(31) + 1;          month = rand.nextInt(12) + 1;          year = rubbos.getOldestStoryYear()+rand.nextInt(3);        }        else        { // Some date in the past week          GregorianCalendar y = new GregorianCalendar();          when = when / 10;          if (when == 0)            when = 1;          if (when > 7)            when = 7;          for (int i = 0 ; i < when ; i++)            y.roll(GregorianCalendar.DAY_OF_MONTH, false);          day = y.get(GregorianCalendar.DAY_OF_MONTH);          month = y.get(GregorianCalendar.MONTH)+1; // Month start at 0          year = y.get(GregorianCalendar.YEAR);        }        if (year > thisYear)          year = thisYear;        if (year == rubbos.getOldestStoryYear())        {          if (month <= rubbos.getOldestStoryMonth())            month = rubbos.getOldestStoryMonth();        }        return urlGen.OlderStories(day, month, year, extractPageFromHTML(), rubbos.getNbOfStoriesPerPage());      }    case 7: // View a story      { // We randomly pickup a story from the generated HTML page        int storyId = extractStoryIdFromHTML();        if (storyId == -1)          return computeURLFromState(transition.backToPreviousState()); // Nothing then go back        else          return urlGen.viewStory(storyId);      }    case 8: // Post Comment      {        Vector p = extractPostCommentFromHTML(urlGen.PostCommentScript());        if (p == null)        {          if (debugLevel > 0)            System.out.println("Thread "+this.getName()+": Unable to extract PostComment parameters from last HTML reply.<br>");          return null;        }        String  comment_table = (String)p.get(0);        Integer storyId = (Integer)p.get(1);        Integer parent  = (Integer)p.get(2);        if ((comment_table == null) || (storyId == null) || (parent == null))          return computeURLFromState(transition.backToPreviousState()); // Nothing then go back        else          return urlGen.postComment(storyId.intValue(), parent.intValue(), comment_table);      }    case 9: // Store comment      {        String subject = "";        String body = "";        int size = rand.nextInt(100); // Subject size must be smaller than 100 characters        do          subject += randomWordFromDictionary(true);        while ((subject != null) && (subject.length() < size));                size = rand.nextInt(rubbos.getCommentMaximumLength());        do          body += randomWordFromDictionary(true);        while ((body != null) && (body.length() < size));        int[] pos = randomComputeLastIndex("name=comment_table value=", false);        if (pos == null)          return null;        String comment_table = lastHTMLReply.substring(pos[0], pos[1]);        return urlGen.storeComment(username, password, extractIntFromHTML("name=storyId value="), extractIntFromHTML("name=parent value="),                                   subject, body, comment_table);      }    case 10: // View comment      {        Vector p = extractViewCommentFromHTML(urlGen.ViewCommentScript());        if (p == null)        {          state = transition.backToPreviousState();          return computeURLFromState(state);        }        String  comment_table = (String)p.get(0);        Integer storyId   = (Integer)p.get(1);        Integer commentId = (Integer)p.get(2);        Integer filter    = (Integer)p.get(3);        Integer display   = (Integer)p.get(4);        if ((comment_table == null) || (storyId == null) || (commentId == null) || (filter == null) || (display == null))          return computeURLFromState(transition.backToPreviousState()); // Nothing then go back        else          return urlGen.viewComment(commentId.intValue(), filter.intValue(), display.intValue(), storyId.intValue(), comment_table);      }    case 11: // Moderate comment      {        Vector c = extractModerateCommentIdFromHTML(urlGen.ModerateCommentScript());        if (c == null)        {          state = transition.backToPreviousState();          return computeURLFromState(state);        }        String  comment_table = (String)c.get(0);        Integer commentId = (Integer)c.get(1);        if ((comment_table == null) || (commentId == null))          return computeURLFromState(transition.backToPreviousState()); // Nothing then go back        else          return urlGen.moderateComment(commentId.intValue(), comment_table);      }    case 12: // Moderate log      {        int rating = rand.nextInt(2)-1; // random value between -1 and 1        int[] pos = randomComputeLastIndex("name=comment_table value=", false);        if (pos == null)          return null;        String comment_table = lastHTMLReply.substring(pos[0], pos[1]);        return urlGen.storeModerateLog(username, password, extractIntFromHTML("name=commentId value="), rating, comment_table);      }    case 13: // Submit story      return urlGen.submitStory();    case 14: // Store story      {        String title = "";        String body = "";        int size = rand.nextInt(100); // title size must be smaller than 100 characters        do          title += randomWordFromDictionary(true);        while ((title != null) && (title.length() < size));                size = rand.nextInt(rubbos.getStoryMaximumLength());        do          body += randomWordFromDictionary(true);        while ((body != null) && (body.length() < size));        int[] pos = randomComputeLastIndex("OPTION value=\"", false);        if (pos == null)          return null;        Integer categoryId = new Integer(lastHTMLReply.substring(pos[0], pos[1]));        return urlGen.storeStory(username, password, title, body, categoryId.intValue());      }    case 15: // Search      return urlGen.search(null, null, 0, 0);    case 16: // Search stories      {        if (lastSearch != 17)          lastRandomWord = randomWordFromDictionary(false); // Generate randomly a word to look for        lastSearch = 17;        return urlGen.search(lastRandomWord, "0", extractPageFromHTML(), rubbos.getNbOfStoriesPerPage());      }    case 17: // Search comments      {        if (lastSearch != 18)          lastRandomWord = randomWordFromDictionary(false);        lastSearch = 18;        return urlGen.search(lastRandomWord, "1", extractPageFromHTML(), rubbos.getNbOfStoriesPerPage());      }    case 18: // Search users      {        if (lastSearch != 19) // Generate randomly a user to look for          lastRandomWord = "user"+(rand.nextInt(rubbos.getNbOfUsers())+1);        lastSearch = 19;        return urlGen.search(lastRandomWord, "2", extractPageFromHTML(), rubbos.getNbOfStoriesPerPage());      }    case 19: // Author login      return urlGen.authorLogin();    case 20: // Author tasks      return urlGen.authorTasks(username, password);    case 21: // Review stories      return urlGen.reviewStories();    case 22: // Accept story      {        Integer storyId = extractAcceptRejectStoryIdFromHTML(urlGen.AcceptStoryScript());        if (storyId == null)        { // No more stories to process go back to home page          transition.resetToInitialState();          return urlGen.homePage();        }        else          return urlGen.acceptStory(storyId.intValue());      }    case 23: // Reject story      {        Integer storyId = extractAcceptRejectStoryIdFromHTML(urlGen.RejectStoryScript());        if (storyId == null)        { // No more stories to process go back to home page          transition.resetToInitialState();          return urlGen.homePage();        }        else          return urlGen.rejectStory(storyId.intValue());      }    default:      if (debugLevel > 0)        System.err.println("Thread "+this.getName()+": This state is not supported ("+state+")<br>");      return null;    }  }