@Before public final void setUp() throws Exception { engine = new DefaultKnittingEngine(knittingFactory); List<Needle> needles = new ArrayList<Needle>(); needles.add(initialNeedle); engine.useNeedles(needles); engine.castOn(40, true); assertOriginalState(); save(); }
@Test public void checkNeedleReturned() throws Exception { Needle newNeedle = knittingFactory.createNeedle("new-needle", NeedleStyle.CIRCULAR); List<Needle> needles = new ArrayList<Needle>(); needles.add(newNeedle); engine.useNeedles(needles); engine.castOn(5); restore(); // note that needles which were not in the engine // are not affected by the restore assertEquals(5, newNeedle.getTotalStitches()); }
/** * A repeat is necessary only when its until condition has not yet been met. * * @param repeat * @param engine * @return */ protected boolean isRepeatNecessary(Repeat repeat, KnittingEngine engine) { Until until = repeat.getUntil(); Integer value = repeat.getValue(); switch (until) { case TIMES: // repeat if we have to repeat more than 0 times return value > 0; case BEFORE_END: return engine.getStitchesRemainingInRow() > value; case END: return engine.getStitchesRemainingInRow() > 0; case BEFORE_GAP: return engine.getStitchesToGap() > value; case BEFORE_MARKER: return engine.getStitchesToNextMarker() > value; case MARKER: return engine.getStitchesToNextMarker() > 0; default: throw new RuntimeException("The until value [" + until + "] has not been properly coded"); } }
@Test(expected = NoGapFoundException.class) public void checkGapsRemoved() throws Exception { engine.startNewRow(); engine.knit(10); engine.turn(); engine.knit(10); engine.turn(); assertEquals(10, engine.getStitchesToGap()); // restore restore(); engine.startNewRow(); engine.getStitchesToGap(); }
@Test public void checkRowPositionReset() throws Exception { engine.startNewRow(); engine.knit(40); engine.endRow(); // now right-side facing engine.startNewRow(); engine.knit(10); engine.designateEndOfRow(); engine.endRow(); }
private void assertOriginalState() { // capture state right after the cast-on row before startNewRow() is // called assertEquals(1, engine.getTotalRowsCompleted()); assertEquals(1, engine.getCurrentRowNumber()); assertEquals(40, engine.getTotalNumberOfStitchesInRow()); assertEquals(0, engine.getStitchesRemainingInRow()); assertEquals(Direction.FORWARDS, engine.getDirection()); assertEquals(KnittingShape.FLAT, engine.getKnittingShape()); }
protected InlineOperation handle(Repeat oldRepeat) { // initialize variables for this method KnittingEngine engine = renderingContext.getEngine(); Until until = oldRepeat.getUntil(); Integer value = oldRepeat.getValue(); // ensure that we can continue to analyze this instruction for charting if (dynamicFirstRowCastOn && until != Until.TIMES) { log.info( "Cannot chart this instruction because it is both defined in the header (i.e. without a knitting context) " + "and the first row has a repeat section that requires a knitting context." + "This can be fixed either by declaring the 'until' attribute of the repeat in the first row to be of type 'times', " + "or by including the repeats in the directions " + "section of the pattern instead of in the header."); return null; } if (currentlyRepeating) { log.info("Cannot currently chart nested repeats. This feature may be expanded in the future"); return null; } // see if we need to repeat at all. If not, just return "0 repeats" if (!isRepeatNecessary(oldRepeat, engine)) { return new Repeat(Until.TIMES, 0); } // at this point, we have to do the repeat (1 or more times) currentlyRepeating = true; // start gathering up information for the new repeat. Our goal is to // convert all repeats // into an until value that represents TIMES. This is so we won't need // the engine to chart. List<DiscreteInlineOperation> newOperations = new ArrayList<DiscreteInlineOperation>(); // gather current (pre-repeat) state Object engineState = engine.save(); int originalChartWidth = this.currentRowInfo.getRowWidth(); // walk through all the instructions of this repeat ONCE to calculate // the advance and increase count. If we find a work-even, remove // the repeat all together and completely expand the row boolean contextualOperationFound = false; for (InlineOperation operation : oldRepeat.getOperations()) { if (!contextualOperationFound && operation instanceof WorkEven) { contextualOperationFound = true; // if we find out there are contextual operations, clear out // newOperations // and wait for the actual repeat. We'll gather that info then. newOperations.clear(); break; } InlineOperation newOperation = handle(operation); // if a non-discrete inline operation or null is returned, we cannot // chart, so return null up the chain if (!(newOperation instanceof DiscreteInlineOperation)) { return null; } newOperations.add((DiscreteInlineOperation) newOperation); } // reset the engine to the state before we repeated once engine.restore(engineState); this.currentRowInfo.setRowWidth(originalChartWidth); int counter = 0; switch (until) { case TIMES: for (int i = 0; i < value; i++) { // advanceAndIncrease(advanceCount, increaseCount); for (InlineOperation operation : oldRepeat.getOperations()) { DiscreteInlineOperation newOperation = (DiscreteInlineOperation) handle(operation); if (contextualOperationFound) { newOperations.add(newOperation); } } } counter = value; break; case BEFORE_END: while (engine.getStitchesRemainingInRow() > value) { // advanceAndIncrease(advanceCount, increaseCount); for (InlineOperation operation : oldRepeat.getOperations()) { DiscreteInlineOperation newOperation = (DiscreteInlineOperation) handle(operation); if (contextualOperationFound) { newOperations.add(newOperation); } } counter++; } break; case END: while (engine.getStitchesRemainingInRow() > 0) { // advanceAndIncrease(advanceCount, increaseCount); for (InlineOperation operation : oldRepeat.getOperations()) { DiscreteInlineOperation newOperation = (DiscreteInlineOperation) handle(operation); if (contextualOperationFound) { newOperations.add(newOperation); } } counter++; } break; case BEFORE_GAP: while (engine.getStitchesToGap() > value) { // advanceAndIncrease(advanceCount, increaseCount); for (InlineOperation operation : oldRepeat.getOperations()) { DiscreteInlineOperation newOperation = (DiscreteInlineOperation) handle(operation); if (contextualOperationFound) { newOperations.add(newOperation); } } counter++; } break; case BEFORE_MARKER: while (engine.getStitchesToNextMarker() > value) { // advanceAndIncrease(advanceCount, increaseCount); for (InlineOperation operation : oldRepeat.getOperations()) { DiscreteInlineOperation newOperation = (DiscreteInlineOperation) handle(operation); if (contextualOperationFound) { newOperations.add(newOperation); } } counter++; } break; case MARKER: while (engine.getStitchesToNextMarker() > 0) { // advanceAndIncrease(advanceCount, increaseCount); for (InlineOperation operation : oldRepeat.getOperations()) { DiscreteInlineOperation newOperation = (DiscreteInlineOperation) handle(operation); if (contextualOperationFound) { newOperations.add(newOperation); } } counter++; } break; default: throw new RuntimeException("The until value [" + until + "] has not been properly coded"); } currentlyRepeating = false; if (contextualOperationFound) { // make a stitch group out of all of the gathered operations if // we are dealing with work even operations return new OperationGroup(newOperations); } else { Repeat newRepeat = new Repeat(); newRepeat.setOperations(newOperations); newRepeat.setUntil(Until.TIMES); newRepeat.setValue(counter); return newRepeat; } }
protected Row analyzeRow(Row originalRow) { KnittingEngine engine = renderingContext.getEngine(); // can't handle short rows if (originalRow.isShortRow()) { return null; } // can't handle colors (right now) if (originalRow.getYarnIdRef() != null) { return null; } List<InlineOperation> newOperations = new ArrayList<InlineOperation>(); Row newRow = new Row(originalRow, newOperations); this.currentRowInfo = new RowInfo(); // Begin the row for the engine if (dynamicFirstRowCastOn) { // if this is an instruction definition, infer the intended shape // from what is specified by the first row's shape. // If nothing is specified, flat knitting is assumed. if (originalRow.getType() != null) { this.shape = originalRow.getType(); } // cast on one stitch so that we can start a new row below engine.castOn(1, false); } engine.startNewRow(); if (this.startingSide == null) { this.startingSide = Side.RIGHT; if (dynamicFirstRowCastOn && originalRow.getSide() == Side.WRONG) { this.startingSide = Side.WRONG; engine.knit(); engine.endRow(); engine.startNewRow(); } else if (engine.getDirection() == Direction.BACKWARDS) { this.startingSide = Side.WRONG; } } // Walk through all of the row's operations and see how it affects the // counts for (InlineOperation operation : originalRow.getOperations()) { InlineOperation newOperation = handle(operation); // if null is returned, we cannot chart, so return null up the chain if (newOperation == null) { return null; } newOperations.add(newOperation); } // End the row for the engine if (dynamicFirstRowCastOn) { // remove the "extra" stitch we created in order to start the row. engine.reverseSlip(1); // don't swallow the real stitch's nature StitchNature stitchNature = engine.peekAtNextStitch().getCurrentNature(); if (stitchNature == StitchNature.PURL) { engine.purlTwoTogether(); } else { engine.knitTwoTogether(); } // now pretend like all is normal dynamicFirstRowCastOn = false; } engine.endRow(); // if this row pushed the bounds of the previously recorded maximum // width, record the new max width if (currentRowInfo.getRowWidth() > maxWidth) { maxWidth = currentRowInfo.getRowWidth(); } // if (!repeatInCurrentRow) { // resetGlobalRepeatTracker(); // } this.rowInfos.add(currentRowInfo); return newRow; }
@Test(expected = NoMarkerFoundException.class) public void checkMarkersRemoved() throws Exception { engine.startNewRow(); engine.knit(10); engine.placeMarker(); engine.knit(15); engine.placeMarker(); engine.knit(15); engine.endRow(); engine.startNewRow(); assertEquals(15, engine.getStitchesToNextMarker()); // restore restore(); engine.startNewRow(); engine.getStitchesToNextMarker(); }
@Test public void checkStitchCountsAndKnittingShapeRestored() throws Exception { engine.startNewRow(); assertEquals(Direction.BACKWARDS, engine.getDirection()); engine.knit(10); for (int i = 0; i < 10; i++) { engine.knitTwoTogether(); } engine.knit(10); assertEquals(2, engine.getCurrentRowNumber()); assertEquals(30, engine.getTotalNumberOfStitchesInRow()); engine.endRow(); assertEquals(2, engine.getTotalRowsCompleted()); engine.declareRoundKnitting(); assertEquals(KnittingShape.ROUND, engine.getKnittingShape()); engine.startNewRow(); engine.knit(5); }
private void restore() throws Exception { engine.restore(memento); }
private void save() throws Exception { memento = engine.save(); }