// Path: CutletLib/src/main/java/com/cutlet/lib/model/PanelInstance.java
// @ToString(exclude = "sheet")
// public class PanelInstance implements Serializable {
// 
//     private final String title;
//     private final StockSheet sheet;
//     private final Dimension dimension;
//     private final boolean canRotate;
//     private final int instanceId;
// 
//     public String getTitle() {
//         return title;
//     }
// 
//     public PanelInstance(@NonNull final StockSheet sheet,
//             @NonNull final Dimension dimension,
//             @NonNull final String title,
//             final int instanceId,
//             final boolean canRotate) {
// 
//         this.sheet = sheet;
//         this.title = title;
//         this.dimension = dimension;
//         this.canRotate = canRotate;
//         this.instanceId = instanceId;
// 
//         if (dimension.getWidth() > sheet.getDimension().getWidth() || dimension.getLength() > sheet.getDimension().getLength()) {
//             throw new RuntimeException("panel too large for sheet");
//         }
//     }
// 
//     public StockSheet getSheet() {
//         return sheet;
//     }
// 
//     public Dimension getDimension() {
//         return dimension;
//     }
// 
//     public int getInstanceId() {
//         return instanceId;
//     }
// }
// 
// Path: CutletLib/src/main/java/com/cutlet/lib/model/Project.java
// public class Project implements Serializable {
// 
//     private List<Panel> panels = new ArrayList<>();
//     private double bladeWidth = 3;
//     private Optional<OptimizationResult> optimizationResult;
// 
//     public List<Panel> getPanels() {
//         return panels;
//     }
// 
//     public void setPanels(@NonNull final List<Panel> inputs) {
//         this.panels = inputs;
//     }
// 
//     public double getBladeWidth() {
//         return bladeWidth;
//     }
// 
//     public void setBladeWidth(final double bladeWidth) {
//         checkArgument(bladeWidth >= 0, "bladeWidth can't be negative");
//         this.bladeWidth = bladeWidth;
//     }
// 
//     public Optional<OptimizationResult> getOptimizationResult() {
//         return optimizationResult;
//     }
// 
//     public void setOptimizationResult(@NonNull final Optional<OptimizationResult> optimizationResult) {
//         this.optimizationResult = optimizationResult;
//     }
// 
//     public void setOptimizationResult(java.util.Optional<OptimizationResult> newValue) {
//         if (newValue.isPresent()) {
//             this.optimizationResult = Optional.of(newValue.get());
// 
//         } else {
//             this.optimizationResult = Optional.absent();
// 
//         }
//     }
// 
//     public List<PanelInstance> getPanelInstances() {
//         List<PanelInstance> pis = new ArrayList<>();
//         for (Panel p : panels) {
//             for (int i = 0; i < p.getCount(); i++) {
//                 pis.add(new PanelInstance(p.getSheet(), p.getDimension(), p.getTitle(), i, p.canRotate()));
//             }
//         }
//         return pis;
//     }
// }
// 
// Path: CutletLib/src/main/java/com/cutlet/lib/data/cuttree/FreeNode.java
// public class FreeNode extends AbstractCutTreeNode {
// 
//     public FreeNode(@NonNull CutTreeNode parent, @NonNull Position position, @NonNull Dimension dimension) {
//         super(parent, position, dimension);
//     }
// 
//     @Override
//     public void replaceChild(@NonNull CutTreeNode from, @NonNull CutTreeNode to) {
//         throw new UnsupportedOperationException("Not supported: Freepanel.replace.");
//     }
// 
//     public CutNode cut(double bladeWidth, double cutPosition, @NonNull CutNode.Direction direction) {
//         final CutTreeNode parent = this.getParent();
//         final CutNode cut = new CutNode(parent,
//                 bladeWidth, cutPosition, direction,
//                 getPosition(),
//                 getDimension());
// 
//         parent.replaceChild(this, cut);
// 
//         return cut;
//     }
// 
//     public PanelNode setPanel(@NonNull PanelInstance panel) {
//         final CutTreeNode parent = this.getParent();
//         final PanelNode pn = new PanelNode(parent, panel, getPosition(), getDimension());
//         parent.replaceChild(this, pn);
//         return pn;
//     }
// }


import com.cutlet.lib.model.PanelInstance;
import com.cutlet.lib.model.Project;
import com.cutlet.lib.data.cuttree.FreeNode;
import java.util.List;
import java.util.logging.Logger;
import lombok.NonNull;
import org.jenetics.EnumGene;
import org.jenetics.Optimize;
import org.jenetics.engine.Codec;
import org.jenetics.engine.Engine;
import org.jenetics.engine.EvolutionResult;
import org.jenetics.engine.codecs;
import org.jenetics.util.ISeq;

/*
 * Copyright (C) 2017 rudolf.muehlbauer@gmail.com
 */
package com.cutlet.lib.optimizer;


/**
 *
 * @author rmuehlba
 */
public class GAOptimizationStrategy extends AbstractOptimizationStrategy {

    private static final Logger log = Logger.getLogger(GAOptimizationStrategy.class.getName());
    public static java.util.Random random = new java.util.Random();

    @Override

// Path: CutletLib/src/main/java/com/cutlet/lib/model/PanelInstance.java
// @ToString(exclude = "sheet")
// public class PanelInstance implements Serializable {
// 
//     private final String title;
//     private final StockSheet sheet;
//     private final Dimension dimension;
//     private final boolean canRotate;
//     private final int instanceId;
// 
//     public String getTitle() {
//         return title;
//     }
// 
//     public PanelInstance(@NonNull final StockSheet sheet,
//             @NonNull final Dimension dimension,
//             @NonNull final String title,
//             final int instanceId,
//             final boolean canRotate) {
// 
//         this.sheet = sheet;
//         this.title = title;
//         this.dimension = dimension;
//         this.canRotate = canRotate;
//         this.instanceId = instanceId;
// 
//         if (dimension.getWidth() > sheet.getDimension().getWidth() || dimension.getLength() > sheet.getDimension().getLength()) {
//             throw new RuntimeException("panel too large for sheet");
//         }
//     }
// 
//     public StockSheet getSheet() {
//         return sheet;
//     }
// 
//     public Dimension getDimension() {
//         return dimension;
//     }
// 
//     public int getInstanceId() {
//         return instanceId;
//     }
// }
// 
// Path: CutletLib/src/main/java/com/cutlet/lib/model/Project.java
// public class Project implements Serializable {
// 
//     private List<Panel> panels = new ArrayList<>();
//     private double bladeWidth = 3;
//     private Optional<OptimizationResult> optimizationResult;
// 
//     public List<Panel> getPanels() {
//         return panels;
//     }
// 
//     public void setPanels(@NonNull final List<Panel> inputs) {
//         this.panels = inputs;
//     }
// 
//     public double getBladeWidth() {
//         return bladeWidth;
//     }
// 
//     public void setBladeWidth(final double bladeWidth) {
//         checkArgument(bladeWidth >= 0, "bladeWidth can't be negative");
//         this.bladeWidth = bladeWidth;
//     }
// 
//     public Optional<OptimizationResult> getOptimizationResult() {
//         return optimizationResult;
//     }
// 
//     public void setOptimizationResult(@NonNull final Optional<OptimizationResult> optimizationResult) {
//         this.optimizationResult = optimizationResult;
//     }
// 
//     public void setOptimizationResult(java.util.Optional<OptimizationResult> newValue) {
//         if (newValue.isPresent()) {
//             this.optimizationResult = Optional.of(newValue.get());
// 
//         } else {
//             this.optimizationResult = Optional.absent();
// 
//         }
//     }
// 
//     public List<PanelInstance> getPanelInstances() {
//         List<PanelInstance> pis = new ArrayList<>();
//         for (Panel p : panels) {
//             for (int i = 0; i < p.getCount(); i++) {
//                 pis.add(new PanelInstance(p.getSheet(), p.getDimension(), p.getTitle(), i, p.canRotate()));
//             }
//         }
//         return pis;
//     }
// }
// 
// Path: CutletLib/src/main/java/com/cutlet/lib/data/cuttree/FreeNode.java
// public class FreeNode extends AbstractCutTreeNode {
// 
//     public FreeNode(@NonNull CutTreeNode parent, @NonNull Position position, @NonNull Dimension dimension) {
//         super(parent, position, dimension);
//     }
// 
//     @Override
//     public void replaceChild(@NonNull CutTreeNode from, @NonNull CutTreeNode to) {
//         throw new UnsupportedOperationException("Not supported: Freepanel.replace.");
//     }
// 
//     public CutNode cut(double bladeWidth, double cutPosition, @NonNull CutNode.Direction direction) {
//         final CutTreeNode parent = this.getParent();
//         final CutNode cut = new CutNode(parent,
//                 bladeWidth, cutPosition, direction,
//                 getPosition(),
//                 getDimension());
// 
//         parent.replaceChild(this, cut);
// 
//         return cut;
//     }
// 
//     public PanelNode setPanel(@NonNull PanelInstance panel) {
//         final CutTreeNode parent = this.getParent();
//         final PanelNode pn = new PanelNode(parent, panel, getPosition(), getDimension());
//         parent.replaceChild(this, pn);
//         return pn;
//     }
// }


// Path: CutletLib/src/main/java/com/cutlet/lib/optimizer/GAOptimizationStrategy.java
import com.cutlet.lib.model.PanelInstance;
import com.cutlet.lib.model.Project;
import com.cutlet.lib.data.cuttree.FreeNode;
import java.util.List;
import java.util.logging.Logger;
import lombok.NonNull;
import org.jenetics.EnumGene;
import org.jenetics.Optimize;
import org.jenetics.engine.Codec;
import org.jenetics.engine.Engine;
import org.jenetics.engine.EvolutionResult;
import org.jenetics.engine.codecs;
import org.jenetics.util.ISeq;

/*
 * Copyright (C) 2017 rudolf.muehlbauer@gmail.com
 */
package com.cutlet.lib.optimizer;


/**
 *
 * @author rmuehlba
 */
public class GAOptimizationStrategy extends AbstractOptimizationStrategy {

    private static final Logger log = Logger.getLogger(GAOptimizationStrategy.class.getName());
    public static java.util.Random random = new java.util.Random();

    @Override

    public OptimizationResult optimize(@NonNull final Project project, 
