Пример #1
0
  /** @param args */
  public static void main(final String[] args) {
    LogUtils.initializeLogging();

    if (args.length != 1) {
      LOGGER.fatal("You must specify the output directory");
      return;
    }

    final String dbname = "generate_schema";
    Connection connection = null;
    try {
      // generate example database
      final DataSource datasource = Utilities.createMemoryDataSource(dbname);
      connection = datasource.getConnection();

      final String baseDir = "fll/resources/challenge-descriptors/";
      final String challengeName = "example-database.xml";
      final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
      final URL challengeUrl = classLoader.getResource(baseDir + challengeName);

      final InputStream stream = challengeUrl.openStream();
      final Reader reader = new InputStreamReader(stream, Utilities.DEFAULT_CHARSET);
      final Document document = ChallengeParser.parse(reader);

      GenerateDB.generateDB(document, connection);

      SchemaAnalyzer analyzer = new SchemaAnalyzer();
      final Config config = new HsqlMemConfig();
      config.setAdsEnabled(false);
      config.setDb(dbname);
      config.setHighQuality(true);
      config.setSchema("PUBLIC");
      config.setUser("SA");
      config.setOutputDir(args[0]);
      analyzer.analyze(config);

    } catch (final SQLException e) {
      LOGGER.fatal("Error talking to the database", e);
    } catch (final Exception e) {
      LOGGER.fatal("Error creating the diagram", e);
    } finally {
      // clean up database
      SQLFunctions.close(connection);
    }
  }
Пример #2
0
/** Populate page context for selectTournament.jsp. */
public class SelectTournament {

  private static final Logger LOGGER = LogUtils.getLogger();

  public static void populateContext(final HttpSession session, final PageContext page) {

    final DataSource importDataSource =
        SessionAttributes.getNonNullAttribute(session, "dbimport", DataSource.class);

    Connection connection = null;
    try {
      connection = importDataSource.getConnection();

      final List<Tournament> tournaments = Tournament.getTournaments(connection);
      page.setAttribute("tournaments", tournaments);

    } catch (final SQLException e) {
      LOGGER.error("There was an error talking to the database", e);
      throw new RuntimeException("There was an error talking to the database", e);
    } finally {
      SQLFunctions.close(connection);
    }
  }
}
Пример #3
0
@WebServlet("/scoreboard/Top10")
public class Top10 extends BaseFLLServlet {

  private static final Logger LOGGER = LogUtils.getLogger();

  /** Max number of characters in a team name to display. */
  public static final int MAX_TEAM_NAME = 12;

  /** Max number of characters in an organization to display. */
  public static final int MAX_ORG_NAME = 20;

  @SuppressFBWarnings(
      value = {"SQL_PREPARED_STATEMENT_GENERATED_FROM_NONCONSTANT_STRING"},
      justification = "Determine sort order based upon winner criteria")
  protected void processRequest(
      final HttpServletRequest request,
      final HttpServletResponse response,
      final ServletContext application,
      final HttpSession session)
      throws IOException, ServletException {
    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("Entering doPost");
    }

    final DataSource datasource = ApplicationAttributes.getDataSource(application);
    final Formatter formatter = new Formatter(response.getWriter());
    final String showOrgStr = request.getParameter("showOrganization");
    final boolean showOrg = null == showOrgStr ? true : Boolean.parseBoolean(showOrgStr);

    PreparedStatement prep = null;
    ResultSet rs = null;
    Connection connection = null;
    try {
      connection = datasource.getConnection();

      final int currentTournament = Queries.getCurrentTournament(connection);
      final int maxScoreboardRound =
          TournamentParameters.getMaxScoreboardPerformanceRound(connection, currentTournament);

      final Integer divisionIndexObj =
          SessionAttributes.getAttribute(session, "divisionIndex", Integer.class);
      int divisionIndex;
      if (null == divisionIndexObj) {
        divisionIndex = 0;
      } else {
        divisionIndex = divisionIndexObj.intValue();
      }
      ++divisionIndex;
      final List<String> divisions = Queries.getAwardGroups(connection);
      if (divisionIndex >= divisions.size()) {
        divisionIndex = 0;
      }
      session.setAttribute("divisionIndex", Integer.valueOf(divisionIndex));

      formatter.format(
          "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">%n");
      formatter.format("<html>%n");
      formatter.format("<head>%n");
      formatter.format("<link rel='stylesheet' type='text/css' href='../style/fll-sw.css' />%n");
      formatter.format("<link rel='stylesheet' type='text/css' href='score_style.css' />%n");
      formatter.format(
          "<meta http-equiv='refresh' content='%d' />%n",
          GlobalParameters.getIntGlobalParameter(connection, GlobalParameters.DIVISION_FLIP_RATE));
      formatter.format("</head>%n");

      formatter.format("<body class='scoreboard'>%n");
      formatter.format("<table border='1' cellpadding='2' cellspacing='0' width='98%%'>%n");

      formatter.format("<colgroup>%n");
      formatter.format("<col width='30px' />%n");
      formatter.format("<col width='75px' />%n");
      formatter.format("<col />%n");
      if (showOrg) {
        formatter.format("<col />%n");
      }
      formatter.format("<col width='70px' />%n");
      formatter.format("</colgroup>%n");

      if (!divisions.isEmpty()) {
        formatter.format("<tr>%n");
        int numColumns = 5;
        if (!showOrg) {
          --numColumns;
        }
        formatter.format(
            "<th colspan='%d' bgcolor='%s'>Top Performance Scores: %s</th>",
            numColumns, Queries.getColorForIndex(divisionIndex), divisions.get(divisionIndex));
        formatter.format("</tr>%n");

        final ChallengeDescription challengeDescription =
            ApplicationAttributes.getChallengeDescription(application);
        final WinnerType winnerCriteria = challengeDescription.getWinner();

        prep =
            connection.prepareStatement(
                "SELECT Teams.TeamName, Teams.Organization, Teams.TeamNumber, T2.MaxOfComputedScore" //
                    + " FROM (SELECT TeamNumber, " //
                    + winnerCriteria.getMinMaxString()
                    + "(ComputedTotal) AS MaxOfComputedScore" //
                    + "  FROM verified_performance WHERE Tournament = ? "
                    + "   AND NoShow = False" //
                    + "   AND Bye = False" //
                    + "   AND RunNumber <= ?" //
                    + "  GROUP BY TeamNumber) AS T2"
                    + " JOIN Teams ON Teams.TeamNumber = T2.TeamNumber, current_tournament_teams"
                    + " WHERE Teams.TeamNumber = current_tournament_teams.TeamNumber" //
                    + " AND current_tournament_teams.event_division = ?"
                    + " ORDER BY T2.MaxOfComputedScore "
                    + winnerCriteria.getSortString());
        prep.setInt(1, currentTournament);
        prep.setInt(2, maxScoreboardRound);
        prep.setString(3, divisions.get(divisionIndex));
        rs = prep.executeQuery();

        double prevScore = -1;
        int i = 1;
        int rank = 0;
        while (rs.next()) {
          final double score = rs.getDouble("MaxOfComputedScore");
          if (!FP.equals(score, prevScore, 1E-6)) {
            rank = i;
          }

          formatter.format("<tr>%n");
          formatter.format("<td class='center'>%d</td>%n", rank);
          formatter.format("<td class='right'>%d</td>%n", rs.getInt("TeamNumber"));
          String teamName = rs.getString("TeamName");
          if (null == teamName) {
            teamName = "&nbsp;";
          }
          formatter.format("<td class='left truncate'>%s</td>%n", teamName);
          if (showOrg) {
            String organization = rs.getString("Organization");
            if (null == organization) {
              organization = "&nbsp;";
            }
            formatter.format("<td class='left truncate'>%s</td>%n", organization);
          }
          formatter.format(
              "<td class='right'>%s</td>%n", Utilities.NUMBER_FORMAT_INSTANCE.format(score));

          formatter.format("</tr>");

          prevScore = score;
          ++i;
        } // end while next
      } // end divisions not empty
      formatter.format("</table>%n");
      formatter.format("</body>%n");
      formatter.format("</html>%n");
    } catch (final SQLException e) {
      throw new RuntimeException("Error talking to the database", e);
    } finally {
      SQLFunctions.close(rs);
      SQLFunctions.close(prep);
      SQLFunctions.close(connection);
    }

    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("Exiting doPost");
    }
  }
}
Пример #4
0
/** Create a new playoff division. */
@WebServlet("/playoff/CreatePlayoffDivision")
public class CreatePlayoffDivision extends BaseFLLServlet {

  private static final Logger LOGGER = LogUtils.getLogger();

  /**
   * Populate the context for create_playoff_division.jsp.
   *
   * @param application
   */
  public static void populateContext(
      final ServletContext application, final PageContext pageContext) {
    final DataSource datasource = ApplicationAttributes.getDataSource(application);
    Connection connection = null;
    try {
      connection = datasource.getConnection();

      final int currentTournamentID = Queries.getCurrentTournament(connection);

      final List<String> judgingStations =
          Queries.getJudgingStations(connection, currentTournamentID);
      pageContext.setAttribute("judgingStations", judgingStations);

      final List<String> awardGroups = Queries.getAwardGroups(connection, currentTournamentID);
      pageContext.setAttribute("awardGroups", awardGroups);

    } catch (final SQLException sqle) {
      LOGGER.error(sqle, sqle);
      throw new RuntimeException("Error talking to the database", sqle);
    } finally {
      SQLFunctions.close(connection);
    }
  }

  @Override
  protected void processRequest(
      final HttpServletRequest request,
      final HttpServletResponse response,
      final ServletContext application,
      final HttpSession session)
      throws IOException, ServletException {
    final StringBuilder message = new StringBuilder();
    final String existingMessage = SessionAttributes.getMessage(session);
    if (null != existingMessage) {
      message.append(existingMessage);
    }

    String redirect = "index.jsp";
    final DataSource datasource = ApplicationAttributes.getDataSource(application);
    Connection connection = null;
    try {
      connection = datasource.getConnection();

      final PlayoffSessionData data =
          SessionAttributes.getNonNullAttribute(
              session, PlayoffIndex.SESSION_DATA, PlayoffSessionData.class);

      final Tournament currentTournament = data.getCurrentTournament();
      final int currentTournamentID = currentTournament.getTournamentID();

      final List<String> playoffDivisions =
          Playoff.getPlayoffBrackets(connection, currentTournamentID);

      if (null != request.getParameter("selected_teams")) {
        final String bracketName = request.getParameter("bracket_name");
        if (null == bracketName || "".equals(bracketName)) {
          message.append("<p class='error'>You need to specify a name for the playoff bracket</p>");
          redirect = "create_playoff_division.jsp";
        } else if (playoffDivisions.contains(bracketName)) {
          message.append(
              "<p class='error'>The playoff bracket '"
                  + bracketName
                  + "' already exists, please pick a different name");
          redirect = "create_playoff_division.jsp";
        } else {
          final String[] selectedTeams = request.getParameterValues("selected_team");
          final List<Integer> teamNumbers = new LinkedList<Integer>();
          for (final String teamStr : selectedTeams) {
            final int num = Integer.parseInt(teamStr);
            teamNumbers.add(num);
          }

          if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("Selected team numbers: " + teamNumbers);
          }

          Playoff.createPlayoffBracket(connection, currentTournamentID, bracketName, teamNumbers);

          message.append("<p id='success'>Created playoff bracket" + bracketName + "</p>");

          redirect = "index.jsp";
        }
      } else {
        // create bracket based on award group or judging group

        boolean done = false;

        Enumeration<String> paramNames = request.getParameterNames();
        while (paramNames.hasMoreElements()) {
          final String paramName = paramNames.nextElement();
          if (paramName.startsWith("create_award_group_")) {
            final String idxStr = paramName.substring("create_award_group_".length());
            final int idx = Integer.parseInt(idxStr);
            final String awardGroup = request.getParameter("award_group_" + idx);

            // get list of teams in this award group
            final List<Integer> teamNumbers = new LinkedList<>();
            for (final Map.Entry<Integer, TournamentTeam> entry :
                data.getTournamentTeams().entrySet()) {
              if (awardGroup.equals(entry.getValue().getAwardGroup())) {
                teamNumbers.add(entry.getKey());
              }
            }

            Playoff.createPlayoffBracket(connection, currentTournamentID, awardGroup, teamNumbers);

            message.append("<p id='success'>Created playoff bracket '" + awardGroup + "'</p>");
            redirect = "index.jsp";
            done = true;
          } else if (paramName.startsWith("create_judging_group_")) {
            final String idxStr = paramName.substring("create_judging_group_".length());
            final int idx = Integer.parseInt(idxStr);
            final String judgingGroup = request.getParameter("judging_group_" + idx);

            // get list of teams in this judging group
            final List<Integer> teamNumbers = new LinkedList<>();
            for (final Map.Entry<Integer, TournamentTeam> entry :
                data.getTournamentTeams().entrySet()) {
              if (judgingGroup.equals(entry.getValue().getJudgingGroup())) {
                teamNumbers.add(entry.getKey());
              }
            }

            Playoff.createPlayoffBracket(
                connection, currentTournamentID, judgingGroup, teamNumbers);

            message.append("<p id='success'>Created playoff bracket '" + judgingGroup + "'</p>");
            redirect = "index.jsp";
            done = true;
          }
        }

        if (!done) {
          message.append("<p class='error'>No action specified</p>");
          redirect = "create_playoff_division.jsp";
        }
      }

    } catch (final SQLException sqle) {
      message.append(
          "<p class='error'>Error talking to the database: " + sqle.getMessage() + "</p>");
      LOGGER.error(sqle, sqle);
      throw new RuntimeException("Error talking to the database", sqle);
    } finally {
      SQLFunctions.close(connection);
    }

    session.setAttribute(SessionAttributes.MESSAGE, message.toString());
    response.sendRedirect(response.encodeRedirectURL(redirect));
  }
}
Пример #5
0
/** XML utilities for FLL. */
@SuppressFBWarnings(
    value = {"NM_SAME_SIMPLE_NAME_AS_SUPERCLASS"},
    justification = "Intentionally shadowing parent class")
public final class XMLUtils extends net.mtu.eggplant.xml.XMLUtils {

  private static final Logger LOGGER = LogUtils.getLogger();

  private XMLUtils() {}

  /**
   * Find a subjective category by name.
   *
   * @param challengeDocument the document to look in
   * @param name the name to look for
   * @return the element or null if one is not found
   */
  public static Element getSubjectiveCategoryByName(
      final Document challengeDocument, final String name) {
    for (final Element categoryElement :
        new NodelistElementCollectionAdapter(
            challengeDocument.getDocumentElement().getElementsByTagName("subjectiveCategory"))) {
      final String categoryName = categoryElement.getAttribute("name");
      if (categoryName.equals(name)) {
        return categoryElement;
      }
    }
    return null;
  }

  /**
   * Check if an element describes an enumerated goal or not.
   *
   * @param element the goal element
   * @return if the element represents an enumerated goal
   */
  public static boolean isEnumeratedGoal(final Element element) {
    if (!"goal".equals(element.getNodeName())) {
      // not a goal element
      return false;
    }

    final Iterator<Element> values =
        new NodelistElementCollectionAdapter(element.getElementsByTagName("value")).iterator();
    return values.hasNext();
  }

  /**
   * Check if an element describes a computed goal or not.
   *
   * @param element the goal element
   * @return if the element represents a computed goal
   */
  public static boolean isComputedGoal(final Element element) {
    return "computedGoal".equals(element.getNodeName());
  }

  /** Get the winner criteria for a particular element. */
  public static WinnerType getWinnerCriteria(final Element element) {
    if (element.hasAttribute("winner")) {
      final String str = element.getAttribute("winner");
      final String sortStr;
      if (!str.isEmpty()) {
        sortStr = str.toUpperCase();
      } else {
        sortStr = "HIGH";
      }
      return Enum.valueOf(WinnerType.class, sortStr);
    } else {
      return WinnerType.HIGH;
    }
  }

  /** Get the score type for a particular element. */
  public static ScoreType getScoreType(final Element element) {
    if (element.hasAttribute("scoreType")) {
      final String str = element.getAttribute("scoreType");
      final String sortStr;
      if (!str.isEmpty()) {
        sortStr = str.toUpperCase();
      } else {
        sortStr = "INTEGER";
      }
      return Enum.valueOf(ScoreType.class, sortStr);
    } else {
      return ScoreType.INTEGER;
    }
  }

  /** @see #getDoubleAttributeValue(Element, String) */
  public static String getStringAttributeValue(final Element element, final String attributeName) {
    if (null == element) {
      return null;
    }
    final String str = element.getAttribute(attributeName);
    return str;
  }

  /** @see #getDoubleAttributeValue(Element, String) */
  @SuppressFBWarnings(
      value = {"NP_BOOLEAN_RETURN_NULL"},
      justification = "Need to return Null so that we can determine when there is no score")
  public static Boolean getBooleanAttributeValue(
      final Element element, final String attributeName) {
    if (null == element) {
      return null;
    }
    final String str = element.getAttribute(attributeName);
    if (str.isEmpty()) {
      return null;
    } else {
      return Boolean.valueOf(str);
    }
  }

  /**
   * Get a double value from an attribute.
   *
   * @param element the element to get the attribute from, may be null
   * @param attributeName the attribute name to get
   * @return the value, null if element is null or the attribute value is null or empty
   */
  public static Double getDoubleAttributeValue(final Element element, final String attributeName) {
    if (null == element) {
      return null;
    }
    final String str = element.getAttribute(attributeName);
    if (str.isEmpty()) {
      return null;
    } else {
      return Double.valueOf(str);
    }
  }

  /**
   * Compare two documents and check if they are the same or not.
   *
   * @param controlDoc
   * @param testDoc
   * @return true if the documents have the same elements and attributes, reguardless of order
   */
  public static boolean compareDocuments(final Document controlDoc, final Document testDoc) {
    final Diff xmldiff = new Diff(controlDoc, testDoc);
    return xmldiff.similar();
  }

  public static List<String> getSubjectiveCategoryNames(final Document challengeDocument) {
    final List<String> subjectiveCategories = new LinkedList<String>();
    for (final Element categoryElement :
        new NodelistElementCollectionAdapter(
            challengeDocument.getDocumentElement().getElementsByTagName("subjectiveCategory"))) {
      final String categoryName = categoryElement.getAttribute("name");
      subjectiveCategories.add(categoryName);
    }
    return subjectiveCategories;
  }

  public static boolean isValidCategoryName(final Document challengeDocument, final String name) {
    return getSubjectiveCategoryNames(challengeDocument).contains(name);
  }

  /** Get all challenge descriptors build into the software. */
  public static Collection<URL> getAllKnownChallengeDescriptorURLs() {
    final String baseDir = "fll/resources/challenge-descriptors/";

    final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    final URL directory = classLoader.getResource(baseDir);
    if (null == directory) {
      LOGGER.warn("base dir for challenge descriptors not found");
      return Collections.emptyList();
    }

    final Collection<URL> urls = new LinkedList<URL>();
    if ("file".equals(directory.getProtocol())) {
      try {
        final URI uri = directory.toURI();
        final File fileDir = new File(uri);
        final File[] files = fileDir.listFiles();
        if (null != files) {
          for (final File file : files) {
            if (file.getName().endsWith(".xml")) {
              try {
                final URL fileUrl = file.toURI().toURL();
                urls.add(fileUrl);
              } catch (final MalformedURLException e) {
                LOGGER.error("Unable to convert file to URL: " + file.getAbsolutePath(), e);
              }
            }
          }
        }
      } catch (final URISyntaxException e) {
        LOGGER.error("Unable to convert URL to URI: " + e.getMessage(), e);
      }
    } else if (directory.getProtocol().equals("jar")) {
      final CodeSource src = XMLUtils.class.getProtectionDomain().getCodeSource();
      if (null != src) {
        final URL jar = src.getLocation();

        JarInputStream zip = null;
        try {
          zip = new JarInputStream(jar.openStream());

          JarEntry ze = null;
          while ((ze = zip.getNextJarEntry()) != null) {
            final String entryName = ze.getName();
            if (entryName.startsWith(baseDir) && entryName.endsWith(".xml")) {
              // add 1 to baseDir to skip past the path separator
              final String challengeName = entryName.substring(baseDir.length());

              // check that the file really exists and turn it into a URL
              final URL challengeUrl = classLoader.getResource(baseDir + challengeName);
              if (null != challengeUrl) {
                urls.add(challengeUrl);
              } else {
                // TODO could write the resource out to a temporary file if
                // needed
                // then mark the file as delete on exit
                LOGGER.warn(
                    "URL doesn't exist for " + baseDir + challengeName + " entry: " + entryName);
              }
            }
          }

          zip.close();
        } catch (final IOException e) {
          LOGGER.error("Error reading jar file at: " + jar.toString(), e);
        } finally {
          IOUtils.closeQuietly(zip);
        }

      } else {
        LOGGER.warn("Null code source in protection domain, cannot get challenge descriptors");
      }
    } else {
      throw new UnsupportedOperationException("Cannot list files for URL " + directory);
    }

    return urls;
  }
}
Пример #6
0
/** Generate a schema diagram of our example database. */
public class GenerateDatabaseDiagram {

  private static final Logger LOGGER = LogUtils.getLogger();

  /** @param args */
  public static void main(final String[] args) {
    LogUtils.initializeLogging();

    if (args.length != 1) {
      LOGGER.fatal("You must specify the output directory");
      return;
    }

    final String dbname = "generate_schema";
    Connection connection = null;
    try {
      // generate example database
      final DataSource datasource = Utilities.createMemoryDataSource(dbname);
      connection = datasource.getConnection();

      final String baseDir = "fll/resources/challenge-descriptors/";
      final String challengeName = "example-database.xml";
      final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
      final URL challengeUrl = classLoader.getResource(baseDir + challengeName);

      final InputStream stream = challengeUrl.openStream();
      final Reader reader = new InputStreamReader(stream, Utilities.DEFAULT_CHARSET);
      final Document document = ChallengeParser.parse(reader);

      GenerateDB.generateDB(document, connection);

      SchemaAnalyzer analyzer = new SchemaAnalyzer();
      final Config config = new HsqlMemConfig();
      config.setAdsEnabled(false);
      config.setDb(dbname);
      config.setHighQuality(true);
      config.setSchema("PUBLIC");
      config.setUser("SA");
      config.setOutputDir(args[0]);
      analyzer.analyze(config);

    } catch (final SQLException e) {
      LOGGER.fatal("Error talking to the database", e);
    } catch (final Exception e) {
      LOGGER.fatal("Error creating the diagram", e);
    } finally {
      // clean up database
      SQLFunctions.close(connection);
    }
  }

  /** Special {@link Config} for handling hsqldb mem. Also turns off the SF logo. */
  private static final class HsqlMemConfig extends Config {
    @Override
    public String getDbType() {
      // make sure we are compatible with the existing configurations
      return "hsqldb";
    }

    @Override
    public String getHost() {
      // keeps DbSpecificConfig for hsql happy
      return "localhost";
    }

    @Override
    public Properties getDbProperties(final String type)
        throws IOException, InvalidConfigurationException {
      final Properties props = super.getDbProperties("hsqldb");
      props.setProperty("connectionSpec", "jdbc:hsqldb:mem:<db>");
      return props;
    }

    /** Always disable the logo. */
    @Override
    public boolean isLogoEnabled() {
      return false;
    }
  }
}