/** * Creates all the necessary sudokus. Returns <code>false</code> if interrupted. * * @return */ private boolean createSudokus() { int anzPuzzles = 0; for (int i = 0; i < numberTextFields.length; i++) { anzPuzzles += getNumberOfPuzzles(i); } if (anzPuzzles == 0) { // nothing to do return false; } sudokus = new Sudoku2[anzPuzzles]; candidates = new boolean[anzPuzzles]; int index = 0; for (int i = 0; i < numberTextFields.length; i++) { DifficultyLevel actDiffLevel = Options.getInstance().getDifficultyLevel(levelComboBoxes[i].getSelectedIndex() + 1); GameMode actGameMode = null; boolean withCandidates = candCheckBoxes[i].isSelected(); switch (modeComboBoxes[i].getSelectedIndex()) { case 0: actGameMode = GameMode.PLAYING; break; case 1: actGameMode = GameMode.LEARNING; break; case 2: actGameMode = GameMode.PRACTISING; break; } for (int j = 0; j < getNumberOfPuzzles(i); j++) { sudokus[index] = getSudoku(actDiffLevel, actGameMode); if (sudokus[index] == null || thread.isInterrupted()) { return false; } candidates[index] = withCandidates; // put puzzle in history Options.getInstance().addSudokuToHistory(sudokus[index]); index++; // update progress bar setPercentage((int) Math.round(index * 100.0 / anzPuzzles)); EventQueue.invokeLater( new Runnable() { @Override public void run() { setProgress(); } }); } } return true; }
/** * Retrieves a list of pages linking to the given page from Scalaris. * * @param connection the connection to Scalaris * @param contributor the user name or IP address of the user who created the revision * @return a result object with the page list on success */ public static final ValueResult<List<Contribution>> getContributions( Connection connection, String contributor) { final long timeAtStart = System.currentTimeMillis(); final String statName = "contributions of " + contributor; if (Options.getInstance().WIKI_STORE_CONTRIBUTIONS != STORE_CONTRIB_TYPE.NONE) { ValueResult<List<Contribution>> result = getPageList3( connection, ScalarisOpType.CONTRIBUTION, Arrays.asList(getContributionListKey(contributor)), false, timeAtStart, statName, new ErlangConverter<List<Contribution>>() { @Override public List<Contribution> convert(ErlangValue v) throws ClassCastException { return v.jsonListValue(Contribution.class); } }); if (result.success && result.value == null) { result.value = new ArrayList<Contribution>(0); } return result; } else { return new ValueResult<List<Contribution>>( new ArrayList<InvolvedKey>(0), new ArrayList<Contribution>(0)); } }
/** * Creates a new Sudoku with a given{@link DifficultyLevel} and a given {@link GameMode}. The * puzzles are taken from the cache if possible.<br> * If no puzzle could be generated (or the generation was aborted), <code>null</code> is returned. * * @param level * @param mode * @return */ private Sudoku2 getSudoku(DifficultyLevel level, GameMode mode) { if (mode == GameMode.LEARNING) { // in LEARNING ANY puzzle is accepted, that has at least one Training Step in it level = Options.getInstance().getDifficultyLevel(DifficultyType.EXTREME.ordinal()); } String preGenSudoku = BackgroundGeneratorThread.getInstance().getSudoku(level, mode); Sudoku2 tmpSudoku = null; SudokuSolver solver = SudokuSolverFactory.getDefaultSolverInstance(); if (preGenSudoku == null) { // no pregenerated puzzle available -> do it in GUI GenerateSudokuProgressDialog dlg = new GenerateSudokuProgressDialog(null, true, level, mode); dlg.setVisible(true); tmpSudoku = dlg.getSudoku(); } else { tmpSudoku = new Sudoku2(); tmpSudoku.setSudoku(preGenSudoku, true); Sudoku2 solvedSudoku = tmpSudoku.clone(); solver.solve( level, solvedSudoku, true, null, false, Options.getInstance().solverSteps, Options.getInstance().getGameMode()); tmpSudoku.setLevel(solvedSudoku.getLevel()); tmpSudoku.setScore(solvedSudoku.getScore()); } if (tmpSudoku == null) { // couldnt create anything or was aborted return null; } if (mode == GameMode.LEARNING) { // solve the sudoku up until the first trainingStep List<SolutionStep> steps = solver.getSteps(); for (SolutionStep step : steps) { if (step.getType().getStepConfig().isEnabledTraining()) { break; } else { // System.out.println("doStep(): " + step.getType().getStepName()); solver.doStep(tmpSudoku, step); } } } return tmpSudoku; }
/** * Retrieves a list of pages from Scalaris. * * @param <T> * @param connection the connection to Scalaris * @param opType operation type indicating what is being read * @param scalaris_keys the keys under which the page list is stored in Scalaris * @param failNotFound whether the operation should fail if the key is not found or not (the value * contains null if not failed!) * @param timeAtStart the start time of the method using this method * @param statName name for the time measurement statistics * @return a result object with the page list on success */ protected static final <T> ValueResult<List<T>> getPageList3( Connection connection, ScalarisOpType opType, Collection<String> scalaris_keys, boolean failNotFound, final long timeAtStart, String statName, ErlangConverter<List<T>> conv) { List<InvolvedKey> involvedKeys = new ArrayList<InvolvedKey>(); if (connection == null) { return new ValueResult<List<T>>( false, involvedKeys, "no connection to Scalaris", true, statName, System.currentTimeMillis() - timeAtStart); } final MyScalarisSingleOpExecutor executor = new MyScalarisSingleOpExecutor(new TransactionSingleOp(connection), involvedKeys); final ScalarisReadListOp1<T> readOp = new ScalarisReadListOp1<T>( scalaris_keys, Options.getInstance().OPTIMISATIONS.get(opType), conv, failNotFound); executor.addOp(readOp); try { executor.run(); } catch (Exception e) { return new ValueResult<List<T>>( false, involvedKeys, e.getClass().getCanonicalName() + " reading page list at \"" + involvedKeys.toString() + "\" from Scalaris: " + e.getMessage(), e instanceof ConnectionException, statName, System.currentTimeMillis() - timeAtStart); } return new ValueResult<List<T>>( involvedKeys, readOp.getValue(), statName, System.currentTimeMillis() - timeAtStart); }
/** * Retrieves a random page title from Scalaris. * * @param connection the connection to Scalaris * @param random the random number generator to use * @return a result object with the page list on success */ public static final ValueResult<NormalisedTitle> getRandomArticle( Connection connection, Random random) { final long timeAtStart = System.currentTimeMillis(); final String statName = "random article"; final Optimisation optimisation = Options.getInstance().OPTIMISATIONS.get(ScalarisOpType.PAGE_LIST); final ErlangConverter<List<ErlangValue>> conv = new ErlangConverter<List<ErlangValue>>() { @Override public List<ErlangValue> convert(ErlangValue v) throws ClassCastException { return v.listValue(); } }; final List<String> scalarisKeys = Arrays.asList(getPageListKey(0)); if (optimisation instanceof APPEND_INCREMENT_BUCKETS) { List<InvolvedKey> involvedKeys = new ArrayList<InvolvedKey>(); if (connection == null) { return new ValueResult<NormalisedTitle>( false, involvedKeys, "no connection to Scalaris", true, statName, System.currentTimeMillis() - timeAtStart); } final MyScalarisSingleOpExecutor executor = new MyScalarisSingleOpExecutor(new TransactionSingleOp(connection), involvedKeys); final ScalarisReadRandomListEntryOp1<ErlangValue> readOp = new ScalarisReadRandomListEntryOp1<ErlangValue>( scalarisKeys, optimisation, conv, true, random); executor.addOp(readOp); try { executor.run(); } catch (Exception e) { return new ValueResult<NormalisedTitle>( false, involvedKeys, e.getClass().getCanonicalName() + " reading page list at \"" + involvedKeys.toString() + "\" from Scalaris: " + e.getMessage(), e instanceof ConnectionException, statName, System.currentTimeMillis() - timeAtStart); } // return if successful, otherwise fall back and read the whole list // as with no optimisation if (readOp.getValue() != null) { return new ValueResult<NormalisedTitle>( involvedKeys, NormalisedTitle.fromNormalised(readOp.getValue().stringValue()), statName, System.currentTimeMillis() - timeAtStart); } } ValueResult<List<ErlangValue>> result = getPageList3( connection, ScalarisOpType.PAGE_LIST, scalarisKeys, true, timeAtStart, statName, conv); ValueResult<NormalisedTitle> vResult; if (result.success) { String randomTitle = result.value.get(random.nextInt(result.value.size())).stringValue(); vResult = new ValueResult<NormalisedTitle>( result.involvedKeys, NormalisedTitle.fromNormalised(randomTitle)); } else { vResult = new ValueResult<NormalisedTitle>( false, result.involvedKeys, result.message, result.connect_failed); } vResult.stats = result.stats; return vResult; }
/** * The actual printing is handled here. Note, that the method can be called more than once for * every page. * * @param graphics * @param pageFormat * @param pageIndex * @return * @throws PrinterException */ @Override public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException { if (pageIndex >= numberOfPages) { return Printable.NO_SUCH_PAGE; } if (printBooklet && manualDuplex && pageIndex >= (numberOfPages / 2)) { return Printable.NO_SUCH_PAGE; } setPercentage(-(pageIndex + 1)); EventQueue.invokeLater( new Runnable() { @Override public void run() { setProgress(); } }); // CAUTION: The Graphics2D object is created with the native printer // resolution, but scaled down to 72dpi using an AffineTransform. // To print in high resolution this downscaling has to be reverted. Graphics2D printG2 = (Graphics2D) graphics; double scale = SudokuUtil.adjustGraphicsForPrinting(printG2); printG2.translate( (int) (pageFormat.getImageableX() * scale), (int) (pageFormat.getImageableY() * scale)); printWidth = (int) (pageFormat.getImageableWidth() * scale); printHeight = (int) (pageFormat.getImageableHeight() * scale); // printG2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, // RenderingHints.VALUE_ANTIALIAS_ON); // printG2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, // RenderingHints.VALUE_TEXT_ANTIALIAS_ON); if (!initialized) { // create a few global attributes for that job // scale fonts up too fit the printer resolution Font tmpFont = Options.getInstance().getSmallFont(); smallFont = new Font(tmpFont.getName(), tmpFont.getStyle(), (int) (tmpFont.getSize() * scale)); printG2.setFont(smallFont); // gaps between puzzles, depend on layout footerHeight = 0; if (printRating) { FontMetrics metrics = printG2.getFontMetrics(); footerHeight = metrics.getHeight() * 2; } horizontalGap = 0; verticalGap = 0; borderWidth = printWidth; borderHeight = printHeight; if (!printBooklet) { // for layouts 1, 2 and 4 (no booklet) a vertical gap is needed if (layout == 1 || layout == 2 || layout == 4) { // 2 puzzles vertically verticalGap = (int) (borderHeight * GAP_FACTOR); borderHeight = (borderHeight - verticalGap) / 2; } // for layouts 2, 3 and 4 (no booklet) a horizontal gap is needed if (layout == 2 || layout == 3 || layout == 4) { // 2 puzzles horizontally horizontalGap = (int) (borderWidth * GAP_FACTOR); borderWidth = (borderWidth - horizontalGap) / 2; } } else { // if printing a booklet, layouts 3 and 4 need a horizontal gap, // 4 needs a vertical gap // in a booklet the gap in the middle is the sum of // insets (left inset - puzzle - right inset - left inset - puzzle - right inset) if (layout == 3 || layout == 4) { // should always be true... horizontalGap = (int) ((pageFormat.getWidth() - pageFormat.getImageableWidth()) * scale); borderWidth = (borderWidth - horizontalGap) / 2; } if (layout == 4) { verticalGap = (int) ((pageFormat.getHeight() - pageFormat.getImageableHeight()) * scale); borderHeight = (borderHeight - verticalGap) / 2; } } // ok: we know the space available for our sudoku; now determine the // actual imageSize imagePrintSize = (borderWidth < (borderHeight - footerHeight)) ? borderWidth : (borderHeight - footerHeight); // Construct Sudoku2 panel = new SudokuPanel(null); initialized = true; } // ok - draw the puzzles // first determine, which puzzles must be printed on the current page int leftStartIndex = 0; int rightStartIndex = 0; if (!printBooklet) { // int dummy = layout > 2 ? layout - 2 : layout; leftStartIndex = (int) Math.round(pageIndex * PPP[layout]); rightStartIndex = leftStartIndex + 1; if (PPP[layout] == 4) { rightStartIndex = leftStartIndex + 2; } } else { // number of puzzles per half page int dummy = layout - 2; // booklet contains numberOfPages * dummy * 2 puzzles; // the first puzzle on the right is in the middle int firstRightIndex = numberOfPages * dummy; int actPage = pageIndex; if (printBooklet && manualDuplex) { if (firstHalf) { actPage = (numberOfPages - pageIndex * 2 - 1); } else { actPage = (numberOfPages - (pageIndex + 1) * 2); } } leftStartIndex = firstRightIndex - (actPage + 1) * dummy; rightStartIndex = firstRightIndex + actPage * dummy; } // now print them // lets do every case on its own; bloats the code, but makes things easier switch (layout) { case 0: printSudoku(printG2, leftStartIndex, 0, scale); break; case 1: printSudoku(printG2, leftStartIndex, 0, scale); printSudoku(printG2, leftStartIndex + 1, 2, scale); break; case 2: printSudoku(printG2, leftStartIndex, 0, scale); printSudoku(printG2, leftStartIndex + 1, 1, scale); printSudoku(printG2, leftStartIndex + 2, 2, scale); printSudoku(printG2, leftStartIndex + 3, 3, scale); break; case 3: if (!printBooklet) { printSudoku(printG2, leftStartIndex, 0, scale); printSudoku(printG2, rightStartIndex, 1, scale); } else if ((manualDuplex && !firstHalf) || (!manualDuplex && (pageIndex % 2) == 1)) { printSudoku(printG2, leftStartIndex, 1, scale); printSudoku(printG2, rightStartIndex, 0, scale); } else { printSudoku(printG2, leftStartIndex, 0, scale); printSudoku(printG2, rightStartIndex, 1, scale); } break; case 4: if (!printBooklet) { printSudoku(printG2, leftStartIndex, 0, scale); printSudoku(printG2, leftStartIndex + 1, 2, scale); printSudoku(printG2, rightStartIndex, 1, scale); printSudoku(printG2, rightStartIndex + 1, 3, scale); } else if ((manualDuplex && !firstHalf) || (!manualDuplex && (pageIndex % 2) == 1)) { printSudoku(printG2, leftStartIndex, 1, scale); printSudoku(printG2, leftStartIndex + 1, 3, scale); printSudoku(printG2, rightStartIndex, 0, scale); printSudoku(printG2, rightStartIndex + 1, 2, scale); } else { printSudoku(printG2, leftStartIndex, 0, scale); printSudoku(printG2, leftStartIndex + 1, 2, scale); printSudoku(printG2, rightStartIndex, 1, scale); printSudoku(printG2, rightStartIndex + 1, 3, scale); } break; } return Printable.PAGE_EXISTS; }