From 4fab1ce6b3e7f0459351591bbbf33864730ef5a1 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Thu, 25 Jul 2024 10:50:02 -0700 Subject: [PATCH 01/16] Note that computeUtilizationComponentsPrimary is YUC1 --- .../ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java | 1 + 1 file changed, 1 insertion(+) diff --git a/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java b/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java index 24fd37ae9..71e202d3b 100644 --- a/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java +++ b/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java @@ -1113,6 +1113,7 @@ private float meanVolumeSmall(VdypSpecies spec, float quadMeanDiameterSpecSmall, ); } + // YUC1 public void computeUtilizationComponentsPrimary( BecDefinition bec, VdypLayer vdypLayer, VolumeComputeMode volumeComputeMode, CompatibilityVariableMode compatibilityVariableMode From f1c4ebbbf9528cd658097c993ad19b8a62c83255 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Thu, 25 Jul 2024 10:51:47 -0700 Subject: [PATCH 02/16] Rename compatibility variable mode enum NO_VOLUME to ALL_BUT_VOLUME --- .../ca/bc/gov/nrs/vdyp/model/CompatibilityVariableMode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/CompatibilityVariableMode.java b/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/CompatibilityVariableMode.java index f62f8b4dc..42d8749c8 100644 --- a/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/CompatibilityVariableMode.java +++ b/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/CompatibilityVariableMode.java @@ -8,7 +8,7 @@ public enum CompatibilityVariableMode { /** * Apply compatibility variables to all but volume */ - NO_VOLUME, // 1 + ALL_BUT_VOLUME, // 1 /** * Apply compatibility variables to all components */ From bd938613108c2757034d961b4349bea0193e08df Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Wed, 31 Jul 2024 15:42:27 -0700 Subject: [PATCH 03/16] Update model classes in Common to have Site be a child of Species --- .../application/VdypStartApplication.java | 12 +- .../nrs/vdyp/common/EstimationMethods.java | 3 +- .../common_calculators/Height2SiteIndex.java | 1 - .../common_calculators/SiteIndex2Height.java | 1 - .../bc/gov/nrs/vdyp/model/BaseVdypLayer.java | 66 +- .../gov/nrs/vdyp/model/BaseVdypPolygon.java | 6 +- .../gov/nrs/vdyp/model/BaseVdypSpecies.java | 97 ++- .../gov/nrs/vdyp/model/ModelClassBuilder.java | 8 + .../gov/nrs/vdyp/model/SingleSiteLayer.java | 24 +- .../ca/bc/gov/nrs/vdyp/model/VdypLayer.java | 22 +- .../ca/bc/gov/nrs/vdyp/model/VdypSpecies.java | 38 +- .../nrs/vdyp/model/VdypUtilizationHolder.java | 2 - .../application/VdypStartApplicationTest.java | 579 +++++++++--------- .../nrs/vdyp/application/test/TestLayer.java | 8 - .../vdyp/application/test/TestSpecies.java | 25 +- .../test/TestStartApplication.java | 2 +- .../vdyp/common/EstimationMethodsTest.java | 12 +- .../ca/bc/gov/nrs/vdyp/common/UtilsTest.java | 1 - .../io/write/VriAdjustInputWriterTest.java | 130 ++-- .../bc/gov/nrs/vdyp/model/VdypLayerTest.java | 157 ++--- .../gov/nrs/vdyp/model/VdypSpeciesTest.java | 14 +- .../ca/bc/gov/nrs/vdyp/test/TestUtils.java | 4 +- 22 files changed, 570 insertions(+), 642 deletions(-) diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java index e957a2ef8..e9372e8dd 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java @@ -69,7 +69,7 @@ import ca.bc.gov.nrs.vdyp.model.VdypUtilizationHolder; import ca.bc.gov.nrs.vdyp.model.VolumeComputeMode; -public abstract class VdypStartApplication

, S, I>, L extends BaseVdypLayer & InputLayer, S extends BaseVdypSpecies, I extends BaseVdypSite> +public abstract class VdypStartApplication

, S, I>, L extends BaseVdypLayer & InputLayer, S extends BaseVdypSpecies, I extends BaseVdypSite> extends VdypApplication implements Closeable { private static final Logger log = LoggerFactory.getLogger(VdypStartApplication.class); @@ -170,8 +170,8 @@ protected static void doMain(VdypStartApplication app, final String. public EstimationMethods estimationMethods; - static final Comparator PERCENT_GENUS_DESCENDING = Utils - .compareUsing(BaseVdypSpecies::getPercentGenus).reversed(); + static final Comparator> PERCENT_GENUS_DESCENDING = Utils + .compareUsing(BaseVdypSpecies::getPercentGenus).reversed(); /** * When finding primary species these genera should be combined @@ -263,7 +263,7 @@ public void close() throws IOException { closeVriWriter(); } - protected Coefficients getCoeForSpecies(BaseVdypSpecies species, ControlKey controlKey) { + protected Coefficients getCoeForSpecies(BaseVdypSpecies species, ControlKey controlKey) { var coeMap = Utils.>expectParsedControl(controlMap, controlKey, java.util.Map.class); return coeMap.get(species.getGenus()); } @@ -300,7 +300,7 @@ protected float getPercentTotal(L layer) throws StandProcessingException { return percentTotal; } - protected abstract S copySpecies(S toCopy, Consumer> config); + protected abstract S copySpecies(S toCopy, Consumer> config); /** * Returns the primary, and secondary if present species records as a one or two element list. @@ -633,7 +633,7 @@ protected float estimatePrimaryBaseArea( public S leadGenus(L fipLayer) { return fipLayer.getSpecies().values().stream() - .sorted(Utils.compareUsing(BaseVdypSpecies::getFractionGenus).reversed()).findFirst().orElseThrow(); + .sorted(Utils.compareUsing(BaseVdypSpecies::getFractionGenus).reversed()).findFirst().orElseThrow(); } protected L getPrimaryLayer(P poly) throws StandProcessingException { diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/common/EstimationMethods.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/common/EstimationMethods.java index d48910294..f6dc082ce 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/common/EstimationMethods.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/common/EstimationMethods.java @@ -171,7 +171,8 @@ public float primaryHeightFromLeadHeightInitial( * @throws ProcessingException */ public float estimateNonPrimaryLoreyHeight( - BaseVdypSpecies vspec, BaseVdypSpecies vspecPrime, BecDefinition bec, float leadHeight, float primaryHeight + BaseVdypSpecies vspec, BaseVdypSpecies vspecPrime, BecDefinition bec, float leadHeight, + float primaryHeight ) throws ProcessingException { return estimateNonPrimaryLoreyHeight(vspec.getGenus(), vspecPrime.getGenus(), bec, leadHeight, primaryHeight); } diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/common_calculators/Height2SiteIndex.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/common_calculators/Height2SiteIndex.java index 9e414432c..986ff0f51 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/common_calculators/Height2SiteIndex.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/common_calculators/Height2SiteIndex.java @@ -6,7 +6,6 @@ import static ca.bc.gov.nrs.vdyp.common_calculators.enumerations.SiteIndexAgeType.SI_AT_TOTAL; import static ca.bc.gov.nrs.vdyp.common_calculators.enumerations.SiteIndexEstimationType.*; -import java.util.function.DoubleBinaryOperator; import java.util.function.DoubleUnaryOperator; import ca.bc.gov.nrs.vdyp.common.Utils; diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/common_calculators/SiteIndex2Height.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/common_calculators/SiteIndex2Height.java index 972c6d0a9..2fc70f2ab 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/common_calculators/SiteIndex2Height.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/common_calculators/SiteIndex2Height.java @@ -7,7 +7,6 @@ import static ca.bc.gov.nrs.vdyp.common_calculators.enumerations.SiteIndexEstimationType.SI_EST_DIRECT; import java.util.function.DoubleBinaryOperator; -import java.util.function.DoubleUnaryOperator; import ca.bc.gov.nrs.vdyp.common.Utils; import ca.bc.gov.nrs.vdyp.common_calculators.custom_exceptions.CommonCalculatorException; diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypLayer.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypLayer.java index 755757a3c..e2cb67cbd 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypLayer.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypLayer.java @@ -11,12 +11,11 @@ import java.util.function.Consumer; import java.util.stream.Collectors; -public abstract class BaseVdypLayer { +public abstract class BaseVdypLayer, I extends BaseVdypSite> { private final PolygonIdentifier polygonIdentifier; private final LayerType layerType; private LinkedHashMap species = new LinkedHashMap<>(); - private LinkedHashMap sites = new LinkedHashMap<>(); private Optional inventoryTypeGroup = Optional.empty(); protected BaseVdypLayer( @@ -52,17 +51,9 @@ public void setSpecies(Collection species) { } public LinkedHashMap getSites() { - return sites; - } - - public void setSites(Map sites) { - this.sites.clear(); - this.sites.putAll(sites); - } - - public void setSites(Collection sites) { - this.sites.clear(); - sites.forEach(spec -> this.sites.put(spec.getSiteGenus(), spec)); + var result = new LinkedHashMap(species.size()); + species.forEach((key, spec) -> spec.getSite().ifPresent(site -> result.put(key, site))); + return result; } public Optional getInventoryTypeGroup() { @@ -73,7 +64,7 @@ public void setInventoryTypeGroup(Optional inventoryTypeGroup) { this.inventoryTypeGroup = inventoryTypeGroup; } - public abstract static class Builder, S extends BaseVdypSpecies, I extends BaseVdypSite, SB extends BaseVdypSpecies.Builder, IB extends BaseVdypSite.Builder> + public abstract static class Builder, S extends BaseVdypSpecies, I extends BaseVdypSite, SB extends BaseVdypSpecies.Builder, IB extends BaseVdypSite.Builder> extends ModelClassBuilder { protected Optional polygonIdentifier = Optional.empty(); protected Optional layerType = Optional.empty(); @@ -124,16 +115,6 @@ public Builder addSpecies(S species) { return this; } - public Builder addSite(Consumer config) { - siteBuilders.add(config); - return this; - } - - public Builder addSite(I site) { - this.sites.add(site); - return this; - } - public Builder inventoryTypeGroup(int inventoryTypeGroup) { return this.inventoryTypeGroup(Optional.of(inventoryTypeGroup)); } @@ -155,37 +136,7 @@ public Builder copy(T toCopy) { return this; } - public Builder - adaptSites(BaseVdypLayer toCopy, BiConsumer config) { - toCopy.getSites().values().forEach(siteToCopy -> { - this.adaptSite(siteToCopy, config); - }); - return this; - } - - public Builder adaptSite(I2 toCopy, BiConsumer config) { - this.addSite(builder -> { - builder.adapt(toCopy); - builder.polygonIdentifier = Optional.empty(); - builder.layerType = Optional.empty(); - config.accept(builder, toCopy); - }); - return this; - } - - public Builder copySites(T toCopy, BiConsumer config) { - toCopy.getSites().values().forEach(siteToCopy -> { - this.addSite(builder -> { - builder.copy(siteToCopy); - builder.polygonIdentifier = Optional.empty(); - builder.layerType = Optional.empty(); - config.accept(builder, siteToCopy); - }); - }); - return this; - } - - public Builder + public , I2 extends BaseVdypSite> Builder adaptSpecies(BaseVdypLayer toCopy, BiConsumer config) { toCopy.getSpecies().values().forEach(speciesToCopy -> { this.addSpecies(builder -> { @@ -232,16 +183,12 @@ protected void check(Collection errors) { protected abstract S buildSpecies(Consumer config); - protected abstract I buildSite(Consumer config); - /** * Build any builders for child objects and store the results. This will clear the stored child builders. */ public void buildChildren() { speciesBuilders.stream().map(this::buildSpecies).collect(Collectors.toCollection(() -> species)); speciesBuilders.clear(); - siteBuilders.stream().map(this::buildSite).collect(Collectors.toCollection(() -> sites)); - siteBuilders.clear(); } @Override @@ -249,7 +196,6 @@ protected void postProcess(T result) { super.postProcess(result); buildChildren(); result.setSpecies(species); - result.setSites(sites); } } diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypPolygon.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypPolygon.java index 465f1f750..fa1d3af5b 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypPolygon.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypPolygon.java @@ -12,7 +12,7 @@ import java.util.function.Function; import java.util.stream.Collectors; -public abstract class BaseVdypPolygon, PA, SP extends BaseVdypSpecies, SI extends BaseVdypSite> { +public abstract class BaseVdypPolygon, PA, SP extends BaseVdypSpecies, SI extends BaseVdypSite> { private PolygonIdentifier polygonIdentifier; // FIP_P/POLYDESC private PA percentAvailable; // FIP_P2/PCTFLAND @@ -107,10 +107,10 @@ protected abstract static class Builder< // T extends BaseVdypPolygon, // L extends BaseVdypLayer, // PA, // - SP extends BaseVdypSpecies, // + SP extends BaseVdypSpecies, // SI extends BaseVdypSite, // LB extends BaseVdypLayer.Builder, // - SPB extends BaseVdypSpecies.Builder, // + SPB extends BaseVdypSpecies.Builder, // SIB extends BaseVdypSite.Builder> // extends ModelClassBuilder { diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypSpecies.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypSpecies.java index 46ff8fca3..c5603fce9 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypSpecies.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypSpecies.java @@ -4,9 +4,12 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.Optional; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + import ca.bc.gov.nrs.vdyp.common.Computed; -public abstract class BaseVdypSpecies { +public abstract class BaseVdypSpecies { private final PolygonIdentifier polygonIdentifier; // FIP_P/POLYDESC private final LayerType layerType; // This is also represents the distinction between data stored in // FIPL_1(A) and FIP_V(A). Where VDYP7 stores both and looks at certain values @@ -23,24 +26,16 @@ public abstract class BaseVdypSpecies { private float fractionGenus; // FRBASP0/FR private Map speciesPercent; // Map from + private Optional site; protected BaseVdypSpecies( - PolygonIdentifier polygonIdentifier, LayerType layerType, String genus, float percentGenus + PolygonIdentifier polygonIdentifier, LayerType layerType, String genus, float percentGenus, Optional site ) { this.polygonIdentifier = polygonIdentifier; this.layerType = layerType; this.genus = genus; this.setPercentGenus(percentGenus); - } - - protected BaseVdypSpecies(BaseVdypSpecies toCopy) { - this( - toCopy.getPolygonIdentifier(), // - toCopy.getLayerType(), // - toCopy.getGenus(), // - toCopy.getPercentGenus() - ); - setSpeciesPercent(toCopy.getSpeciesPercent()); + this.site = site; } public PolygonIdentifier getPolygonIdentifier() { @@ -82,61 +77,85 @@ public String getGenus() { return genus; } - public abstract static class Builder extends ModelClassBuilder { + public Optional getSite() { + return site; + } + + public abstract static class Builder, I extends BaseVdypSite, IB extends BaseVdypSite.Builder> + extends ModelClassBuilder { protected Optional polygonIdentifier = Optional.empty(); protected Optional layerType = Optional.empty(); protected Optional genus = Optional.empty(); protected Optional percentGenus = Optional.empty(); protected Optional fractionGenus = Optional.empty(); protected Map speciesPercent = new LinkedHashMap<>(); + protected Optional> siteBuilder = Optional.empty(); + protected Optional site = Optional.empty(); - public Builder polygonIdentifier(PolygonIdentifier polygonIdentifier) { + public Builder polygonIdentifier(PolygonIdentifier polygonIdentifier) { this.polygonIdentifier = Optional.of(polygonIdentifier); return this; } - public Builder polygonIdentifier(String polygonIdentifier) { + public Builder polygonIdentifier(String polygonIdentifier) { this.polygonIdentifier = Optional.of(PolygonIdentifier.split(polygonIdentifier)); return this; } - public Builder polygonIdentifier(String base, int year) { + public Builder polygonIdentifier(String base, int year) { this.polygonIdentifier = Optional.of(new PolygonIdentifier(base, year)); return this; } - public Builder layerType(LayerType layer) { + public Builder layerType(LayerType layer) { this.layerType = Optional.of(layer); return this; } - public Builder genus(String genus) { + public Builder genus(String genus) { this.genus = Optional.of(genus); return this; } - public Builder percentGenus(float percentGenus) { + public Builder percentGenus(float percentGenus) { this.percentGenus = Optional.of(percentGenus); return this; } - protected Builder fractionGenus(float fractionGenus) { + protected Builder fractionGenus(float fractionGenus) { this.fractionGenus = Optional.of(fractionGenus); return this; } - public Builder addSpecies(String id, float percent) { + public Builder addSpecies(String id, float percent) { this.speciesPercent.put(id, percent); return this; } - public Builder addSpecies(Map toAdd) { + public Builder addSpecies(Map toAdd) { this.speciesPercent.putAll(toAdd); return this; } - public Builder copy(T toCopy) { - return adapt(toCopy); + public Builder copy(T toCopy) { + return this.adapt(toCopy); + } + + public Builder addSite(Consumer config) { + this.siteBuilder = Optional.of(config); + this.site = Optional.empty(); + return this; + } + + public Builder addSite(I site) { + addSite(Optional.of(site)); + return this; + } + + public Builder addSite(Optional site) { + this.site = site; + this.siteBuilder = Optional.empty(); + return this; } @Override @@ -154,7 +173,13 @@ protected void postProcess(T result) { this.fractionGenus.ifPresent(result::setFractionGenus); } - public Builder adapt(BaseVdypSpecies toCopy) { + @Override + protected void preProcess() { + super.preProcess(); + site = siteBuilder.map(this::buildSite).or(() -> site); + } + + public Builder adapt(BaseVdypSpecies toCopy) { polygonIdentifier(toCopy.getPolygonIdentifier()); layerType(toCopy.getLayerType()); genus(toCopy.getGenus()); @@ -169,6 +194,28 @@ public Builder adapt(BaseVdypSpecies toCopy) { return this; } + public Builder adaptSite(I2 toCopy, BiConsumer config) { + this.addSite(builder -> { + builder.adapt(toCopy); + builder.polygonIdentifier = Optional.empty(); + builder.layerType = Optional.empty(); + config.accept(builder, toCopy); + }); + return this; + } + + public Builder copySite(I toCopy, BiConsumer config) { + this.addSite(builder -> { + builder.copy(toCopy); + builder.siteGenus = Optional.empty(); + builder.polygonIdentifier = Optional.empty(); + builder.layerType = Optional.empty(); + config.accept(builder, toCopy); + }); + return this; + } + + protected abstract I buildSite(Consumer config); } } diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/ModelClassBuilder.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/ModelClassBuilder.java index c66e902ff..88291eb7f 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/ModelClassBuilder.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/ModelClassBuilder.java @@ -39,6 +39,7 @@ protected static void requirePresent(Optional holder, String name, Collection */ public T build() { Collection errors = new LinkedList<>(); + preProcess(); check(errors); if (!errors.isEmpty()) { throw new IllegalStateException(String.join(", ", errors)); @@ -48,6 +49,13 @@ public T build() { return result; } + /** + * Additional steps before building + */ + protected void preProcess() { + // Do Nothing + } + /** * Run the constructor, assuming all required properties are present */ diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/SingleSiteLayer.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/SingleSiteLayer.java index 58f0c6d6b..7e3ee91d2 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/SingleSiteLayer.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/SingleSiteLayer.java @@ -1,11 +1,9 @@ package ca.bc.gov.nrs.vdyp.model; -import java.util.Collection; import java.util.LinkedHashMap; -import java.util.Map; import java.util.Optional; -public class SingleSiteLayer extends BaseVdypLayer { +public class SingleSiteLayer, I extends BaseVdypSite> extends BaseVdypLayer { protected SingleSiteLayer( PolygonIdentifier polygonIdentifier, LayerType layer, Optional inventoryTypeGroup @@ -57,24 +55,4 @@ public LinkedHashMap getSites() { return result; } - @Override - public void setSites(Map sites) { - if (sites.size() > 1) { - throw new IllegalArgumentException( - "Layer type " + this.getClass().getSimpleName() + " can only have one site" - ); - } - super.setSites(sites); - } - - @Override - public void setSites(Collection sites) { - if (sites.size() > 1) { - throw new IllegalArgumentException( - "Layer type " + this.getClass().getSimpleName() + " can only have one site" - ); - } - super.setSites(sites); - } - } diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/VdypLayer.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/VdypLayer.java index 71cc00a0e..a5a2ce7e2 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/VdypLayer.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/VdypLayer.java @@ -28,8 +28,6 @@ public class VdypLayer extends SingleSiteLayer implements private UtilizationVector closeUtilizationVolumeNetOfDecayWasteAndBreakageByUtilization = // VdypUtilizationHolder.emptyUtilization(); // LVCOM/VOL_DWB species 0 - private Optional dominantSpecies; - private Optional empericalRelationshipParameterIndex = Optional.empty(); // INXL1/GRPBA1 public VdypLayer( @@ -241,6 +239,16 @@ public void quadMeanDiameter(float height) { this.quadMeanDiameter = Utils.utilizationVector(height); } + protected UtilizationVector wholeStemVolume = VdypUtilizationHolder.emptyUtilization(); + + public void wholeStemVolume(float small, float u1, float u2, float u3, float u4) { + this.wholeStemVolume = Utils.utilizationVector(small, u1, u2, u3, u4); + } + + public void wholeStemVolume(float volume) { + this.wholeStemVolume = Utils.utilizationVector(volume); + } + @Override protected void postProcess(VdypLayer layer) { super.postProcess(layer); @@ -248,6 +256,7 @@ protected void postProcess(VdypLayer layer) { layer.setBaseAreaByUtilization(baseArea); layer.setTreesPerHectareByUtilization(treesPerHectare); layer.setQuadraticMeanDiameterByUtilization(quadMeanDiameter); + layer.setWholeStemVolumeByUtilization(wholeStemVolume); } @Override @@ -269,15 +278,6 @@ protected VdypSpecies buildSpecies(Consumer config) { }); } - @Override - protected VdypSite buildSite(Consumer config) { - return VdypSite.build(builder -> { - config.accept(builder); - builder.polygonIdentifier(polygonIdentifier.get()); - builder.layerType(layerType.get()); - }); - } - public void baseAreaByUtilization(UtilizationVector utilizationVector) { // TODO Auto-generated method stub diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/VdypSpecies.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/VdypSpecies.java index e3de41be5..30243be48 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/VdypSpecies.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/VdypSpecies.java @@ -6,7 +6,7 @@ import ca.bc.gov.nrs.vdyp.common.Utils; -public class VdypSpecies extends BaseVdypSpecies implements VdypUtilizationHolder { +public class VdypSpecies extends BaseVdypSpecies implements VdypUtilizationHolder { private UtilizationVector baseAreaByUtilization = Utils.utilizationVector(); // LVCOM/BA private UtilizationVector loreyHeightByUtilization = Utils.heightVector(); // LVCOM/HL @@ -24,20 +24,16 @@ public class VdypSpecies extends BaseVdypSpecies implements VdypUtilizationHolde int breakageGroup; public VdypSpecies( - PolygonIdentifier polygonIdentifier, LayerType layer, String genus, float percentGenus, // - int volumeGroup, int decayGroup, int breakageGroup + PolygonIdentifier polygonIdentifier, LayerType layer, String genus, float percentGenus, + Optional site, int volumeGroup, int decayGroup, int breakageGroup ) { - super(polygonIdentifier, layer, genus, percentGenus); + super(polygonIdentifier, layer, genus, percentGenus, site); this.volumeGroup = volumeGroup; this.decayGroup = decayGroup; this.breakageGroup = breakageGroup; } - public VdypSpecies(BaseVdypSpecies toCopy) { - super(toCopy); - } - /** * Base area for utilization index -1 through 4 */ @@ -210,7 +206,7 @@ public static VdypSpecies build(VdypLayer layer, Consumer config) { return result; } - public static class Builder extends BaseVdypSpecies.Builder { + public static class Builder extends BaseVdypSpecies.Builder { protected Optional volumeGroup = Optional.empty(); protected Optional decayGroup = Optional.empty(); protected Optional breakageGroup = Optional.empty(); @@ -255,6 +251,16 @@ public void quadMeanDiameter(float height) { this.quadMeanDiameter = Utils.utilizationVector(height); } + protected UtilizationVector wholeStemVolume = VdypUtilizationHolder.emptyUtilization(); + + public void wholeStemVolume(float small, float u1, float u2, float u3, float u4) { + this.wholeStemVolume = Utils.utilizationVector(small, u1, u2, u3, u4); + } + + public void wholeStemVolume(float volume) { + this.wholeStemVolume = Utils.utilizationVector(volume); + } + @Override protected void check(Collection errors) { super.check(errors); @@ -279,21 +285,33 @@ protected void postProcess(VdypSpecies spec) { spec.setBaseAreaByUtilization(baseArea); spec.setTreesPerHectareByUtilization(treesPerHectare); spec.setQuadraticMeanDiameterByUtilization(quadMeanDiameter); + spec.setWholeStemVolumeByUtilization(wholeStemVolume); } @Override protected VdypSpecies doBuild() { + return new VdypSpecies( polygonIdentifier.get(), // layerType.get(), // genus.get(), // percentGenus.get(), // - volumeGroup.get(), // + site, volumeGroup.get(), // decayGroup.get(), // breakageGroup.get() // ); } + @Override + protected VdypSite buildSite(Consumer config) { + return VdypSite.build(builder -> { + config.accept(builder); + builder.polygonIdentifier(polygonIdentifier.get()); + builder.layerType(layerType.get()); + builder.siteGenus(genus); + }); + } + public Builder volumeGroup(int i) { this.volumeGroup = Optional.of(i); return this; diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/VdypUtilizationHolder.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/VdypUtilizationHolder.java index 4e3f21af1..91f892404 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/VdypUtilizationHolder.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/VdypUtilizationHolder.java @@ -1,7 +1,5 @@ package ca.bc.gov.nrs.vdyp.model; -import java.util.Arrays; - /** * Common accessors for utilization vecors shared by Layer and Species * diff --git a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplicationTest.java b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplicationTest.java index b2d6252d4..67b02fd1b 100644 --- a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplicationTest.java +++ b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplicationTest.java @@ -22,7 +22,6 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Optional; @@ -701,33 +700,29 @@ void testSimple() throws Exception { var bec = Utils.getBec("CWH", controlMap); - var layer = getTestPrimaryLayer(polygonId, l -> { - l.crownClosure(82.8000031f); - - }, s -> { - s.ageTotal(Optional.of(85f)); - s.height(Optional.of(38.2999992f)); - s.siteIndex(Optional.of(28.6000004f)); - s.yearsToBreastHeight(Optional.of(5.4000001f)); - s.siteCurveNumber(Optional.of(34)); - s.siteGenus(Optional.of("H")); - }); - - var spec1 = getTestSpecies(polygonId, LayerType.PRIMARY, "B", s -> { - s.setPercentGenus(33f); - s.setFractionGenus(0.330000013f); - }); - var spec2 = getTestSpecies(polygonId, LayerType.PRIMARY, "H", s -> { - s.setPercentGenus(67f); - s.setFractionGenus(0.670000017f); + var layer = TestLayer.build(lb -> { + lb.polygonIdentifier(polygonId); + lb.layerType(LayerType.PRIMARY); + lb.crownClosure(82.8000031f); + lb.addSpecies(sb -> { + sb.genus("B"); + sb.percentGenus(33f); + sb.addSpecies("B", 100f); + }); + lb.addSpecies(sb -> { + sb.genus("H"); + sb.percentGenus(67f); + sb.addSpecies("H", 100f); + sb.addSite(ib -> { + ib.ageTotal(85f); + ib.height(38.2999992f); + ib.siteIndex(28.6000004f); + ib.yearsToBreastHeight(5.4000001f); + ib.siteCurveNumber(34); + }); + }); }); - Map allSpecies = new LinkedHashMap<>(); - allSpecies.put(spec1.getGenus(), spec1); - allSpecies.put(spec2.getGenus(), spec2); - - layer.setSpecies(allSpecies); - var result = app.estimatePrimaryBaseArea(layer, bec, 1f, 79.5999985f, 3.13497972f); assertThat(result, closeTo(62.6653595f)); @@ -742,32 +737,29 @@ void testHeightCloseToA2() throws Exception { var bec = Utils.getBec("CWH", controlMap); - var layer = getTestPrimaryLayer(polygonId, l -> { - l.crownClosure(82.8000031f); - }, s -> { - s.ageTotal(Optional.of(85f)); - s.height(Optional.of(10.1667995f)); // Altered this in the debugger while running VDYP7 - s.siteIndex(Optional.of(28.6000004f)); - s.yearsToBreastHeight(Optional.of(5.4000001f)); - s.siteCurveNumber(Optional.of(34)); - s.siteGenus(Optional.of("H")); - }); - - var spec1 = getTestSpecies(polygonId, LayerType.PRIMARY, "B", s -> { - s.setPercentGenus(33f); - s.setFractionGenus(0.330000013f); - }); - var spec2 = getTestSpecies(polygonId, LayerType.PRIMARY, "H", s -> { - s.setPercentGenus(67f); - s.setFractionGenus(0.670000017f); + var layer = TestLayer.build(lb -> { + lb.polygonIdentifier(polygonId); + lb.layerType(LayerType.PRIMARY); + lb.crownClosure(82.8000031f); + lb.addSpecies(sb -> { + sb.genus("B"); + sb.percentGenus(33f); + sb.addSpecies("B", 100f); + }); + lb.addSpecies(sb -> { + sb.genus("H"); + sb.percentGenus(67f); + sb.addSpecies("H", 100f); + sb.addSite(ib -> { + ib.ageTotal(85f); + ib.height(10.1667995f); // Altered this in the debugger while running VDYP7 + ib.siteIndex(28.6000004f); + ib.yearsToBreastHeight(5.4000001f); + ib.siteCurveNumber(34); + }); + }); }); - Map allSpecies = new LinkedHashMap<>(); - allSpecies.put(spec1.getGenus(), spec1); - allSpecies.put(spec2.getGenus(), spec2); - - layer.setSpecies(allSpecies); - var result = app.estimatePrimaryBaseArea(layer, bec, 1f, 79.5999985f, 3.13497972f); assertThat(result, closeTo(23.1988659f)); @@ -782,32 +774,29 @@ void testLowCrownClosure() throws Exception { var bec = Utils.getBec("CWH", controlMap); - var layer = getTestPrimaryLayer(polygonId, l -> { - l.crownClosure(9f); // Altered this in the debugger while running VDYP7 - }, s -> { - s.ageTotal(Optional.of(85f)); - s.height(Optional.of(38.2999992f)); - s.siteIndex(Optional.of(28.6000004f)); - s.yearsToBreastHeight(Optional.of(5.4000001f)); - s.siteCurveNumber(Optional.of(34)); - s.siteGenus(Optional.of("H")); - }); - - var spec1 = getTestSpecies(polygonId, LayerType.PRIMARY, "B", s -> { - s.setPercentGenus(33f); - s.setFractionGenus(0.330000013f); - }); - var spec2 = getTestSpecies(polygonId, LayerType.PRIMARY, "H", s -> { - s.setPercentGenus(67f); - s.setFractionGenus(0.670000017f); + var layer = TestLayer.build(lb -> { + lb.polygonIdentifier(polygonId); + lb.layerType(LayerType.PRIMARY); + lb.crownClosure(9f);// Altered this in the debugger while running VDYP7 + lb.addSpecies(sb -> { + sb.genus("B"); + sb.percentGenus(33f); + sb.addSpecies("B", 100f); + }); + lb.addSpecies(sb -> { + sb.genus("H"); + sb.percentGenus(67f); + sb.addSpecies("H", 100f); + sb.addSite(ib -> { + ib.ageTotal(85f); + ib.height(38.2999992f); + ib.siteIndex(28.6000004f); + ib.yearsToBreastHeight(5.4000001f); + ib.siteCurveNumber(34); + }); + }); }); - Map allSpecies = new LinkedHashMap<>(); - allSpecies.put(spec1.getGenus(), spec1); - allSpecies.put(spec2.getGenus(), spec2); - - layer.setSpecies(allSpecies); - var result = app.estimatePrimaryBaseArea(layer, bec, 1f, 79.5999985f, 3.13497972f); assertThat(result, closeTo(37.6110077f)); @@ -822,32 +811,29 @@ void testLowResult() throws Exception { var bec = Utils.getBec("CWH", controlMap); - TestLayer layer = getTestPrimaryLayer(polygonId, l -> { - l.crownClosure(82.8000031f); - }, s -> { - s.ageTotal(85f); - s.height(7f); // Altered this in the debugger while running VDYP7 - s.siteIndex(28.6000004f); - s.yearsToBreastHeight(5.4000001f); - s.siteCurveNumber(34); - s.siteGenus("H"); - }); - - var spec1 = getTestSpecies(polygonId, LayerType.PRIMARY, "B", s -> { - s.setPercentGenus(33f); - s.setFractionGenus(0.330000013f); - }); - var spec2 = getTestSpecies(polygonId, LayerType.PRIMARY, "H", s -> { - s.setPercentGenus(67f); - s.setFractionGenus(0.670000017f); + var layer = TestLayer.build(lb -> { + lb.polygonIdentifier(polygonId); + lb.layerType(LayerType.PRIMARY); + lb.crownClosure(82.8000031f); + lb.addSpecies(sb -> { + sb.genus("B"); + sb.percentGenus(33f); + sb.addSpecies("B", 100f); + }); + lb.addSpecies(sb -> { + sb.genus("H"); + sb.percentGenus(67f); + sb.addSpecies("H", 100f); + sb.addSite(ib -> { + ib.ageTotal(85f); + ib.height(7f); // Altered this in the debugger while running VDYP7 + ib.siteIndex(28.6000004f); + ib.yearsToBreastHeight(5.4000001f); + ib.siteCurveNumber(34); + }); + }); }); - Map allSpecies = new LinkedHashMap<>(); - allSpecies.put(spec1.getGenus(), spec1); - allSpecies.put(spec2.getGenus(), spec2); - - layer.setSpecies(allSpecies); - var ex = assertThrows( LowValueException.class, () -> app.estimatePrimaryBaseArea(layer, bec, 1f, 79.5999985f, 3.13497972f) @@ -872,32 +858,29 @@ void testSimple() throws Exception { var becLookup = BecDefinitionParser.getBecs(controlMap); var bec = becLookup.get("CWH").get(); - var layer = getTestPrimaryLayer(polygonId, l -> { - l.crownClosure(82.8000031f); - }, s -> { - s.ageTotal(85f); - s.height(38.2999992f); - s.siteIndex(28.6000004f); - s.yearsToBreastHeight(5.4000001f); - s.siteCurveNumber(34); - s.siteGenus("H"); - }); - - var spec1 = getTestSpecies(polygonId, LayerType.PRIMARY, "B", s -> { - s.setPercentGenus(33f); - s.setFractionGenus(0.330000013f); - }); - var spec2 = getTestSpecies(polygonId, LayerType.PRIMARY, "H", s -> { - s.setPercentGenus(67f); - s.setFractionGenus(0.670000017f); + var layer = TestLayer.build(lb -> { + lb.polygonIdentifier(polygonId); + lb.layerType(LayerType.PRIMARY); + lb.crownClosure(82.8000031f); + lb.addSpecies(sb -> { + sb.genus("B"); + sb.percentGenus(33f); + sb.addSpecies("B", 100f); + }); + lb.addSpecies(sb -> { + sb.genus("H"); + sb.percentGenus(67f); + sb.addSpecies("H", 100f); + sb.addSite(ib -> { + ib.ageTotal(85f); + ib.height(38.2999992f); + ib.siteIndex(28.6000004f); + ib.yearsToBreastHeight(5.4000001f); + ib.siteCurveNumber(34); + }); + }); }); - Map allSpecies = new LinkedHashMap<>(); - allSpecies.put(spec1.getGenus(), spec1); - allSpecies.put(spec2.getGenus(), spec2); - - layer.setSpecies(allSpecies); - var result = app.estimatePrimaryQuadMeanDiameter(layer, bec, 79.5999985f, 3.13497972f); assertThat(result, closeTo(32.5390053f)); @@ -913,32 +896,29 @@ void testHeightLessThanA5() throws Exception { var becLookup = BecDefinitionParser.getBecs(controlMap); var bec = becLookup.get("CWH").get(); - var layer = getTestPrimaryLayer(polygonId, l -> { - l.crownClosure(82.8000031f); - }, s -> { - s.ageTotal(85f); - s.height(4.74730005f); - s.siteIndex(28.6000004f); - s.yearsToBreastHeight(5.4000001f); - s.siteCurveNumber(34); - s.siteGenus("H"); - }); - - var spec1 = getTestSpecies(polygonId, LayerType.PRIMARY, "B", s -> { - s.setPercentGenus(33f); - s.setFractionGenus(0.330000013f); - }); - var spec2 = getTestSpecies(polygonId, LayerType.PRIMARY, "H", s -> { - s.setPercentGenus(67f); - s.setFractionGenus(0.670000017f); + var layer = TestLayer.build(lb -> { + lb.polygonIdentifier(polygonId); + lb.layerType(LayerType.PRIMARY); + lb.crownClosure(82.8000031f); + lb.addSpecies(sb -> { + sb.genus("B"); + sb.percentGenus(33f); + sb.addSpecies("B", 100f); + }); + lb.addSpecies(sb -> { + sb.genus("H"); + sb.percentGenus(67f); + sb.addSpecies("H", 100f); + sb.addSite(ib -> { + ib.ageTotal(85f); + ib.height(4.74730005f); + ib.siteIndex(28.6000004f); + ib.yearsToBreastHeight(5.4000001f); + ib.siteCurveNumber(34); + }); + }); }); - Map allSpecies = new LinkedHashMap<>(); - allSpecies.put(spec1.getGenus(), spec1); - allSpecies.put(spec2.getGenus(), spec2); - - layer.setSpecies(allSpecies); - var result = app.estimatePrimaryQuadMeanDiameter(layer, bec, 79.5999985f, 3.13497972f); assertThat(result, closeTo(7.6f)); @@ -954,33 +934,29 @@ void testResultLargerThanUpperBound() throws Exception { var becLookup = BecDefinitionParser.getBecs(controlMap); var bec = becLookup.get("CWH").get(); - // Tweak the values to produce a very large DQ - var layer = getTestPrimaryLayer(polygonId, l -> { - l.crownClosure(82.8000031f); - }, s -> { - s.ageTotal(350f); - s.height(80f); - s.siteIndex(28.6000004f); - s.yearsToBreastHeight(5.4000001f); - s.siteCurveNumber(34); - s.siteGenus("H"); - }); - - var spec1 = getTestSpecies(polygonId, LayerType.PRIMARY, "B", s -> { - s.setPercentGenus(33f); - s.setFractionGenus(0.330000013f); - }); - var spec2 = getTestSpecies(polygonId, LayerType.PRIMARY, "H", s -> { - s.setPercentGenus(67f); - s.setFractionGenus(0.670000017f); + var layer = TestLayer.build(lb -> { + lb.polygonIdentifier(polygonId); + lb.layerType(LayerType.PRIMARY); + lb.crownClosure(82.8000031f); + lb.addSpecies(sb -> { + sb.genus("B"); + sb.percentGenus(33f); + sb.addSpecies("B", 100f); + }); + lb.addSpecies(sb -> { + sb.genus("H"); + sb.percentGenus(67f); + sb.addSpecies("H", 100f); + sb.addSite(ib -> { + ib.ageTotal(350f); + ib.height(80f); + ib.siteIndex(28.6000004f); + ib.yearsToBreastHeight(5.4000001f); + ib.siteCurveNumber(34); + }); + }); }); - Map allSpecies = new LinkedHashMap<>(); - allSpecies.put(spec1.getGenus(), spec1); - allSpecies.put(spec2.getGenus(), spec2); - - layer.setSpecies(allSpecies); - var result = app.estimatePrimaryQuadMeanDiameter(layer, bec, 350f - 5.4000001f, 3.13497972f); assertThat(result, closeTo(61.1f)); // Clamp to the COE043/UPPER_BA_BY_CI_S0_P DQ value for this species @@ -1035,17 +1011,16 @@ void testWithoutVeteran() throws Exception { lb.crownClosure(60f); - lb.addSite(ib -> { - ib.siteGenus("L"); - ib.ageTotal(60f); - ib.height(15f); - ib.siteIndex(5f); - ib.yearsToBreastHeight(8.5f); - }); - lb.addSpecies(sb -> { sb.genus("L"); sb.percentGenus(10); + sb.addSite(ib -> { + ib.siteGenus("L"); + ib.ageTotal(60f); + ib.height(15f); + ib.siteIndex(5f); + ib.yearsToBreastHeight(8.5f); + }); }); lb.addSpecies(sb -> { sb.genus("PL"); @@ -1088,14 +1063,6 @@ public VdypApplicationIdentifier getId() { lb.crownClosure(82.8f); - lb.addSite(ib -> { - ib.siteGenus("H"); - ib.ageTotal(45f); - ib.height(24.3f); - ib.siteIndex(28.7f); - ib.yearsToBreastHeight(7.1f); - }); - lb.addSpecies(sb -> { sb.genus("B"); sb.percentGenus(15); @@ -1107,6 +1074,13 @@ public VdypApplicationIdentifier getId() { lb.addSpecies(sb -> { sb.genus("H"); sb.percentGenus(77); + sb.addSite(ib -> { + ib.ageTotal(45f); + ib.height(24.3f); + ib.siteIndex(28.7f); + ib.yearsToBreastHeight(7.1f); + }); + }); lb.addSpecies(sb -> { sb.genus("S"); @@ -1118,14 +1092,17 @@ public VdypApplicationIdentifier getId() { lb.crownClosure(4f); - lb.addSite(ib -> { - ib.siteGenus("H"); - ib.ageTotal(105f); - ib.height(26.2f); - ib.siteIndex(16.7f); - ib.yearsToBreastHeight(7.1f); + lb.addSpecies(sb -> { + sb.genus("H"); + sb.percentGenus(100); + sb.addSite(ib -> { + ib.siteGenus("H"); + ib.ageTotal(105f); + ib.height(26.2f); + ib.siteIndex(16.7f); + ib.yearsToBreastHeight(7.1f); + }); }); - }); }); @@ -1221,122 +1198,129 @@ void testEstimate() throws ProcessingException, IOException { builder.biogeoclimaticZone("CWH"); builder.percentAvailable(Optional.of(100f)); }); - VdypLayer layer = VdypLayer.build(builder -> { - builder.polygonIdentifier("Test", 2024); - builder.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(55f); - siteBuilder.yearsToBreastHeight(1f); - siteBuilder.height(31f); - siteBuilder.siteGenus("H"); + + var layer = VdypLayer.build(lb -> { + lb.polygonIdentifier("Test", 2024); + lb.layerType(LayerType.PRIMARY); + lb.addSpecies(sb -> { + sb.genus("B"); + sb.percentGenus(20f); + sb.volumeGroup(-1); + sb.decayGroup(-1); + sb.breakageGroup(-1); + + sb.loreyHeight(38.6004372f); + sb.baseArea(0.397305071f); + sb.treesPerHectare(5.04602766f); + sb.quadMeanDiameter(31.6622887f); + sb.wholeStemVolume(635.659668f); }); - }); + lb.addSpecies(sb -> { + sb.genus("C"); + sb.percentGenus(20f); + sb.volumeGroup(-1); + sb.decayGroup(-1); + sb.breakageGroup(-1); + sb.loreyHeight(22.8001652f); + sb.baseArea(5.08774281f); + sb.treesPerHectare(92.4298019f); + sb.quadMeanDiameter(26.4735165f); + sb.wholeStemVolume(6.35662031f); + }); + lb.addSpecies(sb -> { + sb.genus("D"); + sb.percentGenus(20f); + sb.volumeGroup(-1); + sb.decayGroup(-1); + sb.breakageGroup(-1); + sb.loreyHeight(33.5375252f); + sb.baseArea(29.5411568f); + sb.treesPerHectare(326.800781f); + sb.quadMeanDiameter(33.9255791f); + sb.wholeStemVolume(44.496151f); + }); + lb.addSpecies(sb -> { + sb.genus("H"); + sb.percentGenus(20f); + sb.volumeGroup(-1); + sb.decayGroup(-1); + sb.breakageGroup(-1); + sb.loreyHeight(24.3451157f); + sb.baseArea(5.50214148f); + sb.treesPerHectare(152.482513f); + sb.quadMeanDiameter(21.4343796f); + sb.wholeStemVolume(470.388489f); + sb.addSite(siteBuilder -> { + siteBuilder.ageTotal(55f); + siteBuilder.yearsToBreastHeight(1f); + siteBuilder.height(31f); + }); - layer.getLoreyHeightByUtilization().setAll(31.3307209f); - layer.getBaseAreaByUtilization().setAll(44.6249847f); - layer.getTreesPerHectareByUtilization().setAll(620.484802f); - layer.getQuadraticMeanDiameterByUtilization().setAll(30.2606697f); - layer.getWholeStemVolumeByUtilization().setAll(635.659668f); - - var spec1 = VdypSpecies.build(layer, builder -> { - builder.genus("B"); - builder.percentGenus(20f); - builder.volumeGroup(-1); - builder.decayGroup(-1); - builder.breakageGroup(-1); - }); - spec1.getLoreyHeightByUtilization().setAll(38.6004372f); - spec1.getBaseAreaByUtilization().setAll(0.397305071f); - spec1.getTreesPerHectareByUtilization().setAll(5.04602766f); - spec1.getQuadraticMeanDiameterByUtilization().setAll(31.6622887f); - spec1.getWholeStemVolumeByUtilization().setAll(635.659668f); - var spec2 = VdypSpecies.build(layer, builder -> { - builder.genus("C"); - builder.percentGenus(20f); - builder.volumeGroup(-1); - builder.decayGroup(-1); - builder.breakageGroup(-1); - }); - spec2.getLoreyHeightByUtilization().setAll(22.8001652f); - spec2.getBaseAreaByUtilization().setAll(5.08774281f); - spec2.getTreesPerHectareByUtilization().setAll(92.4298019f); - spec2.getQuadraticMeanDiameterByUtilization().setAll(26.4735165f); - spec2.getWholeStemVolumeByUtilization().setAll(6.35662031f); - var spec3 = VdypSpecies.build(layer, builder -> { - builder.genus("D"); - builder.percentGenus(20f); - builder.volumeGroup(-1); - builder.decayGroup(-1); - builder.breakageGroup(-1); - }); - spec3.getLoreyHeightByUtilization().setAll(33.5375252f); - spec3.getBaseAreaByUtilization().setAll(29.5411568f); - spec3.getTreesPerHectareByUtilization().setAll(326.800781f); - spec3.getQuadraticMeanDiameterByUtilization().setAll(33.9255791f); - spec3.getWholeStemVolumeByUtilization().setAll(44.496151f); - var spec4 = VdypSpecies.build(layer, builder -> { - builder.genus("H"); - builder.percentGenus(20f); - builder.volumeGroup(-1); - builder.decayGroup(-1); - builder.breakageGroup(-1); - }); - spec4.getLoreyHeightByUtilization().setAll(24.3451157f); - spec4.getBaseAreaByUtilization().setAll(5.50214148f); - spec4.getTreesPerHectareByUtilization().setAll(152.482513f); - spec4.getQuadraticMeanDiameterByUtilization().setAll(21.4343796f); - spec4.getWholeStemVolumeByUtilization().setAll(470.388489f); - var spec5 = VdypSpecies.build(layer, builder -> { - builder.genus("S"); - builder.percentGenus(20f); - builder.volumeGroup(-1); - builder.decayGroup(-1); - builder.breakageGroup(-1); - }); - spec5.getLoreyHeightByUtilization().setAll(34.6888771f); - spec5.getBaseAreaByUtilization().setAll(4.0966382f); - spec5.getTreesPerHectareByUtilization().setAll(43.7256737f); - spec5.getQuadraticMeanDiameterByUtilization().setAll(34.5382729f); - spec5.getWholeStemVolumeByUtilization().setAll(57.2091446f); + }); + lb.addSpecies(sb -> { + sb.genus("S"); + sb.percentGenus(20f); + sb.volumeGroup(-1); + sb.decayGroup(-1); + sb.breakageGroup(-1); + sb.loreyHeight(34.6888771f); + sb.baseArea(4.0966382f); + sb.treesPerHectare(43.7256737f); + sb.quadMeanDiameter(34.5382729f); + sb.wholeStemVolume(57.2091446f); + }); - layer.setSpecies(Arrays.asList(spec1, spec2, spec3, spec4, spec5)); + lb.loreyHeight(31.3307209f); + lb.baseArea(44.6249847f); + lb.treesPerHectare(620.484802f); + lb.quadMeanDiameter(30.2606697f); + lb.wholeStemVolume(635.659668f); + }); app.estimateSmallComponents(fPoly, layer); - assertThat(layer.getLoreyHeightByUtilization().getSmall(), closeTo(7.14446497f)); + var spec1 = layer.getSpecies().get("B"); + var spec2 = layer.getSpecies().get("C"); + var spec3 = layer.getSpecies().get("D"); + var spec4 = layer.getSpecies().get("H"); + var spec5 = layer.getSpecies().get("S"); + assertThat(spec1.getLoreyHeightByUtilization().getSmall(), closeTo(8.39441967f)); assertThat(spec2.getLoreyHeightByUtilization().getSmall(), closeTo(6.61517191f)); assertThat(spec3.getLoreyHeightByUtilization().getSmall(), closeTo(10.8831682f)); assertThat(spec4.getLoreyHeightByUtilization().getSmall(), closeTo(7.93716192f)); assertThat(spec5.getLoreyHeightByUtilization().getSmall(), closeTo(8.63455391f)); - assertThat(layer.getBaseAreaByUtilization().getSmall(), closeTo(0.0153773092f)); assertThat(spec1.getBaseAreaByUtilization().getSmall(), closeTo(0f)); assertThat(spec2.getBaseAreaByUtilization().getSmall(), closeTo(0.0131671466f)); assertThat(spec3.getBaseAreaByUtilization().getSmall(), closeTo(0.00163476227f)); assertThat(spec4.getBaseAreaByUtilization().getSmall(), closeTo(0f)); assertThat(spec5.getBaseAreaByUtilization().getSmall(), closeTo(0.000575399841f)); - assertThat(layer.getTreesPerHectareByUtilization().getSmall(), closeTo(5.34804487f)); assertThat(spec1.getTreesPerHectareByUtilization().getSmall(), closeTo(0f)); assertThat(spec2.getTreesPerHectareByUtilization().getSmall(), closeTo(4.67143154f)); assertThat(spec3.getTreesPerHectareByUtilization().getSmall(), closeTo(0.498754263f)); assertThat(spec4.getTreesPerHectareByUtilization().getSmall(), closeTo(0f)); assertThat(spec5.getTreesPerHectareByUtilization().getSmall(), closeTo(0.17785944f)); - assertThat(layer.getQuadraticMeanDiameterByUtilization().getSmall(), closeTo(6.05059004f)); assertThat(spec1.getQuadraticMeanDiameterByUtilization().getSmall(), closeTo(6.13586617f)); assertThat(spec2.getQuadraticMeanDiameterByUtilization().getSmall(), closeTo(5.99067688f)); assertThat(spec3.getQuadraticMeanDiameterByUtilization().getSmall(), closeTo(6.46009731f)); assertThat(spec4.getQuadraticMeanDiameterByUtilization().getSmall(), closeTo(6.03505516f)); assertThat(spec5.getQuadraticMeanDiameterByUtilization().getSmall(), closeTo(6.41802597f)); - assertThat(layer.getWholeStemVolumeByUtilization().getSmall(), closeTo(0.0666879341f)); assertThat(spec1.getWholeStemVolumeByUtilization().getSmall(), closeTo(0f)); assertThat(spec2.getWholeStemVolumeByUtilization().getSmall(), closeTo(0.0556972362f)); assertThat(spec3.getWholeStemVolumeByUtilization().getSmall(), closeTo(0.0085867513f)); assertThat(spec4.getWholeStemVolumeByUtilization().getSmall(), closeTo(0f)); assertThat(spec5.getWholeStemVolumeByUtilization().getSmall(), closeTo(0.00240394124f)); + + assertThat(layer.getLoreyHeightByUtilization().getSmall(), closeTo(7.14446497f)); + assertThat(layer.getBaseAreaByUtilization().getSmall(), closeTo(0.0153773092f)); + assertThat(layer.getTreesPerHectareByUtilization().getSmall(), closeTo(5.34804487f)); + assertThat(layer.getQuadraticMeanDiameterByUtilization().getSmall(), closeTo(6.05059004f)); + assertThat(layer.getWholeStemVolumeByUtilization().getSmall(), closeTo(0.0666879341f)); + } } } @@ -1368,7 +1352,6 @@ void testApplyToBuilder() throws Exception { @Test void testApplyToObject() throws Exception { controlMap = TestUtils.loadControlMap(); - var bec = Utils.getBec("IDF", controlMap); try (var app = new TestStartApplication(controlMap, false)) { var poly = VdypPolygon.build(pb -> { @@ -1498,13 +1481,6 @@ void testComputeUtilizationComponentsPrimaryByUtilNoCV() throws ProcessingExcept var layer = VdypLayer.build(builder -> { builder.polygonIdentifier("Test", 2024); builder.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(55f); - siteBuilder.yearsToBreastHeight(3.5f); - siteBuilder.height(20f); - siteBuilder.siteGenus("H"); - }); - }); layer.getLoreyHeightByUtilization().setAll(13.0660105f); @@ -1545,6 +1521,11 @@ void testComputeUtilizationComponentsPrimaryByUtilNoCV() throws ProcessingExcept builder.volumeGroup(54); builder.decayGroup(42); builder.breakageGroup(24); + builder.addSite(siteBuilder -> { + siteBuilder.ageTotal(55f); + siteBuilder.yearsToBreastHeight(3.5f); + siteBuilder.height(20f); + }); }); spec2.getLoreyHeightByUtilization().setAll(12.9176102f); @@ -1693,13 +1674,15 @@ TestLayer getTestPrimaryLayer( var result = TestLayer.build(builder -> { builder.polygonIdentifier(polygonId); builder.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(8f); - siteBuilder.yearsToBreastHeight(7f); - siteBuilder.height(6f); - siteBuilder.siteIndex(5f); - siteBuilder.siteGenus("B"); - siteMutator.accept(siteBuilder); + builder.addSpecies(specBuilder -> { + specBuilder.genus("B"); + specBuilder.addSite(siteBuilder -> { + siteBuilder.ageTotal(8f); + siteBuilder.yearsToBreastHeight(7f); + siteBuilder.height(6f); + siteBuilder.siteIndex(5f); + siteMutator.accept(siteBuilder); + }); }); builder.crownClosure(0.9f); @@ -1716,13 +1699,15 @@ TestLayer getTestVeteranLayer( builder.polygonIdentifier(polygonId); builder.layerType(LayerType.VETERAN); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(8f); - siteBuilder.yearsToBreastHeight(7f); - siteBuilder.height(6f); - siteBuilder.siteIndex(5f); - siteBuilder.siteGenus("B"); - siteMutator.accept(siteBuilder); + builder.addSpecies(specBuilder -> { + specBuilder.genus("B"); + specBuilder.addSite(siteBuilder -> { + siteBuilder.ageTotal(8f); + siteBuilder.yearsToBreastHeight(7f); + siteBuilder.height(6f); + siteBuilder.siteIndex(5f); + siteMutator.accept(siteBuilder); + }); }); builder.crownClosure(0.9f); diff --git a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/application/test/TestLayer.java b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/application/test/TestLayer.java index 188d077d9..6001ea669 100644 --- a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/application/test/TestLayer.java +++ b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/application/test/TestLayer.java @@ -68,13 +68,5 @@ protected TestSpecies buildSpecies(Consumer config) { }); } - @Override - protected TestSite buildSite(Consumer config) { - return TestSite.build(si -> { - si.polygonIdentifier(polygonIdentifier.get()); - si.layerType(layerType.get()); - config.accept(si); - }); - } } } \ No newline at end of file diff --git a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/application/test/TestSpecies.java b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/application/test/TestSpecies.java index a9222921f..51815fb11 100644 --- a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/application/test/TestSpecies.java +++ b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/application/test/TestSpecies.java @@ -1,15 +1,19 @@ package ca.bc.gov.nrs.vdyp.application.test; +import java.util.Optional; import java.util.function.Consumer; import ca.bc.gov.nrs.vdyp.model.BaseVdypSpecies; import ca.bc.gov.nrs.vdyp.model.LayerType; import ca.bc.gov.nrs.vdyp.model.PolygonIdentifier; -public class TestSpecies extends BaseVdypSpecies { +public class TestSpecies extends BaseVdypSpecies { - protected TestSpecies(PolygonIdentifier polygonIdentifier, LayerType layerType, String genus, float percentGenus) { - super(polygonIdentifier, layerType, genus, percentGenus); + protected TestSpecies( + PolygonIdentifier polygonIdentifier, LayerType layerType, String genus, float percentGenus, + Optional site + ) { + super(polygonIdentifier, layerType, genus, percentGenus, site); } public static TestSpecies build(Consumer config) { @@ -18,11 +22,22 @@ public static TestSpecies build(Consumer config) { return builder.build(); } - public static class Builder extends BaseVdypSpecies.Builder { + public static class Builder extends BaseVdypSpecies.Builder { @Override protected TestSpecies doBuild() { - return new TestSpecies(polygonIdentifier.get(), layerType.get(), genus.get(), percentGenus.get()); + return new TestSpecies(polygonIdentifier.get(), layerType.get(), genus.get(), percentGenus.get(), site); + } + + @Override + protected TestSite buildSite(Consumer config) { + return TestSite.build(builder -> { + builder.polygonIdentifier(this.polygonIdentifier.get()); + builder.layerType(this.layerType.get()); + builder.siteGenus(this.genus.get()); + + config.accept(builder); + }); } } diff --git a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/application/test/TestStartApplication.java b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/application/test/TestStartApplication.java index 3e79770ab..49077c062 100644 --- a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/application/test/TestStartApplication.java +++ b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/application/test/TestStartApplication.java @@ -74,7 +74,7 @@ public VdypApplicationIdentifier getId() { } @Override - protected TestSpecies copySpecies(TestSpecies toCopy, Consumer> config) { + protected TestSpecies copySpecies(TestSpecies toCopy, Consumer> config) { return null; } diff --git a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/common/EstimationMethodsTest.java b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/common/EstimationMethodsTest.java index 7aafb41fb..539f91d35 100644 --- a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/common/EstimationMethodsTest.java +++ b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/common/EstimationMethodsTest.java @@ -16,7 +16,6 @@ import org.junit.jupiter.api.Test; import ca.bc.gov.nrs.vdyp.application.ProcessingException; -import ca.bc.gov.nrs.vdyp.application.VdypStartApplication; import ca.bc.gov.nrs.vdyp.common_calculators.BaseAreaTreeDensityDiameter; import ca.bc.gov.nrs.vdyp.model.BecLookup; import ca.bc.gov.nrs.vdyp.model.Coefficients; @@ -444,12 +443,6 @@ void testSimple() throws Exception { var layer = VdypLayer.build(builder -> { builder.polygonIdentifier("Test", 2024); builder.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(55f); - siteBuilder.yearsToBreastHeight(1f); - siteBuilder.height(32.2999992f); - siteBuilder.siteGenus("H"); - }); }); // sp 3, 4, 5, 8, 15 @@ -490,6 +483,11 @@ void testSimple() throws Exception { builder.decayGroup(31); builder.breakageGroup(17); builder.percentGenus(9f); + builder.addSite(siteBuilder -> { + siteBuilder.ageTotal(55f); + siteBuilder.yearsToBreastHeight(1f); + siteBuilder.height(32.2999992f); + }); }); spec4.getLoreyHeightByUtilization().setCoe(0, 24.3451157f); spec4.setFractionGenus(0.117043354f); diff --git a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/common/UtilsTest.java b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/common/UtilsTest.java index 10cc67a22..85dd869b9 100644 --- a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/common/UtilsTest.java +++ b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/common/UtilsTest.java @@ -2,7 +2,6 @@ import static ca.bc.gov.nrs.vdyp.test.VdypMatchers.coe; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.hasProperty; diff --git a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/io/write/VriAdjustInputWriterTest.java b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/io/write/VriAdjustInputWriterTest.java index 49e7806e8..91e0ca3c1 100644 --- a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/io/write/VriAdjustInputWriterTest.java +++ b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/io/write/VriAdjustInputWriterTest.java @@ -101,13 +101,20 @@ void testWritePolygon() throws IOException { builder.polygonIdentifier("082E004 615 1988"); builder.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.height(15f); - siteBuilder.siteIndex(14.7f); - siteBuilder.ageTotal(60f); - siteBuilder.yearsToBreastHeight(8.5f); - siteBuilder.siteGenus("PL"); - siteBuilder.siteCurveNumber(0); + builder.addSpecies(specBuilder -> { + specBuilder.genus("PL"); + specBuilder.percentGenus(100); + specBuilder.volumeGroup(1); + specBuilder.decayGroup(2); + specBuilder.breakageGroup(3); + + specBuilder.addSite(siteBuilder -> { + siteBuilder.height(15f); + siteBuilder.siteIndex(14.7f); + siteBuilder.ageTotal(60f); + siteBuilder.yearsToBreastHeight(8.5f); + siteBuilder.siteCurveNumber(0); + }); }); }); @@ -131,27 +138,25 @@ void testWriteSpecies() throws IOException { builder.polygonIdentifier("082E004 615 1988"); builder.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.height(15f); - siteBuilder.siteIndex(14.7f); - siteBuilder.ageTotal(60f); - siteBuilder.yearsToBreastHeight(8.5f); - siteBuilder.siteGenus("PL"); - siteBuilder.siteCurveNumber(0); + builder.addSpecies(specBuilder -> { + specBuilder.genus("PL"); + specBuilder.percentGenus(100); + specBuilder.volumeGroup(0); + specBuilder.decayGroup(0); + specBuilder.breakageGroup(0); + specBuilder.addSpecies("PL", 100); + + specBuilder.addSite(siteBuilder -> { + siteBuilder.height(15f); + siteBuilder.siteIndex(14.7f); + siteBuilder.ageTotal(60f); + siteBuilder.yearsToBreastHeight(8.5f); + siteBuilder.siteCurveNumber(0); + }); }); }); - var species = VdypSpecies.build(layer, builder -> { - builder.genus("PL"); - builder.addSpecies("PL", 100f); - - builder.percentGenus(100f); - builder.volumeGroup(0); - builder.decayGroup(0); - builder.breakageGroup(0); - }); - - unit.writeSpecies(layer, species); + unit.writeSpecies(layer, layer.getSpecies().get("PL")); } specStream.assertContent( is( @@ -170,14 +175,22 @@ void testWriteUtilizationForLayer() throws IOException { builder.polygonIdentifier("082E004 615 1988"); builder.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.height(15f); - siteBuilder.siteIndex(14.7f); - siteBuilder.ageTotal(60f); - siteBuilder.yearsToBreastHeight(8.5f); - siteBuilder.siteGenus("PL"); - siteBuilder.siteCurveNumber(0); + builder.addSpecies(specBuilder -> { + specBuilder.genus("PL"); + specBuilder.percentGenus(100); + specBuilder.volumeGroup(1); + specBuilder.decayGroup(2); + specBuilder.breakageGroup(3); + + specBuilder.addSite(siteBuilder -> { + siteBuilder.height(15f); + siteBuilder.siteIndex(14.7f); + siteBuilder.ageTotal(60f); + siteBuilder.yearsToBreastHeight(8.5f); + siteBuilder.siteCurveNumber(0); + }); }); + }); @SuppressWarnings("unused") @@ -247,13 +260,20 @@ void testWriteUtilizationZeroBaseArea() throws IOException { builder.polygonIdentifier("082E004 615 1988"); builder.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.height(15f); - siteBuilder.siteIndex(14.7f); - siteBuilder.ageTotal(60f); - siteBuilder.yearsToBreastHeight(8.5f); - siteBuilder.siteGenus("PL"); - siteBuilder.siteCurveNumber(0); + builder.addSpecies(specBuilder -> { + specBuilder.genus("PL"); + specBuilder.percentGenus(100); + specBuilder.volumeGroup(1); + specBuilder.decayGroup(2); + specBuilder.breakageGroup(3); + + specBuilder.addSite(siteBuilder -> { + siteBuilder.height(15f); + siteBuilder.siteIndex(14.7f); + siteBuilder.ageTotal(60f); + siteBuilder.yearsToBreastHeight(8.5f); + siteBuilder.siteCurveNumber(0); + }); }); }); @@ -334,25 +354,25 @@ void testWritePolygonWithChildren() throws IOException { var layer = VdypLayer.build(polygon, builder -> { builder.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.height(15f); - siteBuilder.siteIndex(14.7f); - siteBuilder.ageTotal(60f); - siteBuilder.yearsToBreastHeight(8.5f); - siteBuilder.siteGenus("PL"); - siteBuilder.siteCurveNumber(0); + builder.addSpecies(specBuilder -> { + specBuilder.genus("PL"); + specBuilder.percentGenus(100); + specBuilder.volumeGroup(0); + specBuilder.decayGroup(0); + specBuilder.breakageGroup(0); + specBuilder.addSpecies("PL", 100); + + specBuilder.addSite(siteBuilder -> { + siteBuilder.height(15f); + siteBuilder.siteIndex(14.7f); + siteBuilder.ageTotal(60f); + siteBuilder.yearsToBreastHeight(8.5f); + siteBuilder.siteCurveNumber(0); + }); }); }); - var species = VdypSpecies.build(layer, builder -> { - builder.genus("PL"); - builder.addSpecies("PL", 100f); - - builder.percentGenus(100f); - builder.volumeGroup(0); - builder.decayGroup(0); - builder.breakageGroup(0); - }); + var species = layer.getSpecies().get("PL"); // fixme add to builder layer.setEmpericalRelationshipParameterIndex(Optional.of(119)); diff --git a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/model/VdypLayerTest.java b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/model/VdypLayerTest.java index 58b1565f9..641abbe36 100644 --- a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/model/VdypLayerTest.java +++ b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/model/VdypLayerTest.java @@ -3,6 +3,7 @@ import static ca.bc.gov.nrs.vdyp.test.VdypMatchers.isPolyId; import static ca.bc.gov.nrs.vdyp.test.VdypMatchers.present; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.aMapWithSize; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.anEmptyMap; import static org.hamcrest.Matchers.containsString; @@ -28,12 +29,18 @@ void build() throws Exception { builder.polygonIdentifier("Test", 2024); builder.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.height(10f); - siteBuilder.ageTotal(42f); - siteBuilder.yearsToBreastHeight(2f); - siteBuilder.siteGenus("PL"); - siteBuilder.siteCurveNumber(0); + builder.addSpecies(specBuilder -> { + specBuilder.genus("PL"); + specBuilder.percentGenus(100); + specBuilder.volumeGroup(-1); + specBuilder.decayGroup(-1); + specBuilder.breakageGroup(-1); + specBuilder.addSite(siteBuilder -> { + siteBuilder.height(10f); + siteBuilder.ageTotal(42f); + siteBuilder.yearsToBreastHeight(2f); + siteBuilder.siteCurveNumber(0); + }); }); }); @@ -42,7 +49,7 @@ void build() throws Exception { assertThat(result, hasProperty("ageTotal", present(is(42f)))); assertThat(result, hasProperty("yearsToBreastHeight", present(is(2f)))); assertThat(result, hasProperty("height", present(is(10f)))); - assertThat(result, hasProperty("species", anEmptyMap())); + assertThat(result, hasProperty("species", aMapWithSize(1))); } @Test @@ -65,12 +72,18 @@ void buildForPolygon() throws Exception { var result = VdypLayer.build(poly, builder -> { builder.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.height(10f); - siteBuilder.ageTotal(42f); - siteBuilder.yearsToBreastHeight(2f); - siteBuilder.siteGenus("PL"); - siteBuilder.siteCurveNumber(0); + builder.addSpecies(specBuilder -> { + specBuilder.genus("PL"); + specBuilder.percentGenus(100); + specBuilder.volumeGroup(-1); + specBuilder.decayGroup(-1); + specBuilder.breakageGroup(-1); + specBuilder.addSite(siteBuilder -> { + siteBuilder.height(10f); + siteBuilder.ageTotal(42f); + siteBuilder.yearsToBreastHeight(2f); + siteBuilder.siteCurveNumber(0); + }); }); }); @@ -80,7 +93,7 @@ void buildForPolygon() throws Exception { assertThat(result, hasProperty("ageTotal", present(is(42f)))); assertThat(result, hasProperty("yearsToBreastHeight", present(is(2f)))); assertThat(result, hasProperty("height", present(is(10f)))); - assertThat(result, hasProperty("species", anEmptyMap())); + assertThat(result, hasProperty("species", aMapWithSize(1))); assertThat(poly.getLayers(), hasEntry(LayerType.PRIMARY, result)); } @@ -94,13 +107,20 @@ void buildAddSpecies() throws Exception { var result = VdypLayer.build(builder -> { builder.polygonIdentifier("Test", 2024); builder.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.height(10f); - siteBuilder.ageTotal(42f); - siteBuilder.yearsToBreastHeight(2f); - siteBuilder.siteGenus("PL"); - siteBuilder.siteCurveNumber(0); + builder.addSpecies(specBuilder -> { + specBuilder.genus("PL"); + specBuilder.percentGenus(100); + specBuilder.volumeGroup(-1); + specBuilder.decayGroup(-1); + specBuilder.breakageGroup(-1); + specBuilder.addSite(siteBuilder -> { + siteBuilder.height(10f); + siteBuilder.ageTotal(42f); + siteBuilder.yearsToBreastHeight(2f); + siteBuilder.siteCurveNumber(0); + }); }); + builder.addSpecies(specBuilder -> { specBuilder.genus("B"); specBuilder.percentGenus(90f); @@ -139,106 +159,13 @@ void buildAdapt() throws Exception { } - @Test - void buildAdaptSites() throws Exception { - - var control = EasyMock.createControl(); - - BaseVdypLayer toCopy = control.createMock(BaseVdypLayer.class); - BaseVdypSite siteToCopy = control.createMock(BaseVdypSite.class); - - EasyMock.expect(toCopy.getPolygonIdentifier()).andStubReturn(new PolygonIdentifier("Test", 2024)); - EasyMock.expect(siteToCopy.getPolygonIdentifier()).andStubReturn(new PolygonIdentifier("Test", 2024)); - EasyMock.expect(toCopy.getLayerType()).andStubReturn(LayerType.PRIMARY); - EasyMock.expect(siteToCopy.getLayerType()).andStubReturn(LayerType.PRIMARY); - EasyMock.expect(toCopy.getInventoryTypeGroup()).andStubReturn(Optional.of(12)); - EasyMock.expect(toCopy.getSites()) - .andStubReturn(new LinkedHashMap<>(Collections.singletonMap("B", siteToCopy))); - EasyMock.expect(siteToCopy.getSiteGenus()).andStubReturn("B"); - EasyMock.expect(siteToCopy.getAgeTotal()).andStubReturn(Optional.of(30f)); - EasyMock.expect(siteToCopy.getYearsToBreastHeight()).andStubReturn(Optional.of(4f)); - EasyMock.expect(siteToCopy.getHeight()).andStubReturn(Optional.of(20f)); - EasyMock.expect(siteToCopy.getSiteIndex()).andStubReturn(Optional.of(19.7f)); - EasyMock.expect(siteToCopy.getSiteCurveNumber()).andStubReturn(Optional.of(13)); - - control.replay(); - - var result = VdypLayer.build(builder -> { - - builder.adapt(toCopy); - builder.adaptSites(toCopy, (siteBuilder, site) -> { - // Do Nothing - }); - - }); - assertThat(result, hasProperty("sites", hasEntry(is("B"), hasProperty("siteGenus", is("B"))))); - var resultSite = result.getSite().get(); - assertThat(resultSite, hasProperty("polygonIdentifier", isPolyId("Test", 2024))); - assertThat(resultSite, hasProperty("layerType", is(LayerType.PRIMARY))); - assertThat(resultSite, hasProperty("siteGenus", is("B"))); - assertThat(resultSite, hasProperty("ageTotal", present(is(30f)))); - assertThat(resultSite, hasProperty("yearsToBreastHeight", present(is(4f)))); - assertThat(resultSite, hasProperty("height", present(is(20f)))); - assertThat(resultSite, hasProperty("siteIndex", present(is(19.7f)))); - assertThat(resultSite, hasProperty("siteCurveNumber", present(is(13)))); - - control.verify(); - - } - - @Test - void buildCopySites() throws Exception { - - var toCopy = VdypLayer.build(builder -> { - builder.polygonIdentifier("Test", 2024); - builder.layerType(LayerType.PRIMARY); - - builder.addSite(siteBuilder -> { - siteBuilder.height(10f); - siteBuilder.ageTotal(42f); - siteBuilder.yearsToBreastHeight(2f); - siteBuilder.siteGenus("PL"); - siteBuilder.siteIndex(19.7f); - siteBuilder.siteCurveNumber(13); - }); - - }); - - var result = VdypLayer.build(builder -> { - - builder.adapt(toCopy); - builder.adaptSites(toCopy, (siteBuilder, site) -> { - // Do Nothing - }); - - }); - assertThat(result, hasProperty("polygonIdentifier", isPolyId("Test", 2024))); - assertThat(result, hasProperty("layerType", is(LayerType.PRIMARY))); - assertThat(result, hasProperty("ageTotal", present(is(42f)))); - assertThat(result, hasProperty("yearsToBreastHeight", present(is(2f)))); - assertThat(result, hasProperty("height", present(is(10f)))); - assertThat(result, hasProperty("species", anEmptyMap())); - - assertThat(result, hasProperty("sites", hasEntry(is("PL"), hasProperty("siteGenus", is("PL"))))); - var resultSite = result.getSite().get(); - assertThat(resultSite, hasProperty("polygonIdentifier", isPolyId("Test", 2024))); - assertThat(resultSite, hasProperty("layerType", is(LayerType.PRIMARY))); - assertThat(resultSite, hasProperty("siteGenus", is("PL"))); - assertThat(resultSite, hasProperty("ageTotal", present(is(42f)))); - assertThat(resultSite, hasProperty("yearsToBreastHeight", present(is(2f)))); - assertThat(resultSite, hasProperty("height", present(is(10f)))); - assertThat(resultSite, hasProperty("siteIndex", present(is(19.7f)))); - assertThat(resultSite, hasProperty("siteCurveNumber", present(is(13)))); - - } - @Test void buildAdaptSpecies() throws Exception { var control = EasyMock.createControl(); - BaseVdypLayer toCopy = control.createMock(BaseVdypLayer.class); - BaseVdypSpecies speciesToCopy = control.createMock(BaseVdypSpecies.class); + BaseVdypLayer, BaseVdypSite> toCopy = control.createMock(BaseVdypLayer.class); + BaseVdypSpecies speciesToCopy = control.createMock(BaseVdypSpecies.class); EasyMock.expect(toCopy.getPolygonIdentifier()).andStubReturn(new PolygonIdentifier("Test", 2024)); EasyMock.expect(speciesToCopy.getPolygonIdentifier()).andStubReturn(new PolygonIdentifier("Test", 2024)); diff --git a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/model/VdypSpeciesTest.java b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/model/VdypSpeciesTest.java index cd26c893b..b66b18c8d 100644 --- a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/model/VdypSpeciesTest.java +++ b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/model/VdypSpeciesTest.java @@ -58,14 +58,6 @@ void buildForLayer() throws Exception { var layer = VdypLayer.build(builder -> { builder.polygonIdentifier("Test", 2024); builder.layerType(LayerType.PRIMARY); - - builder.addSite(siteBuilder -> { - siteBuilder.siteGenus("B"); - siteBuilder.siteCurveNumber(0); - siteBuilder.ageTotal(42f); - siteBuilder.yearsToBreastHeight(2f); - siteBuilder.height(10f); - }); }); var result = VdypSpecies.build(layer, builder -> { @@ -75,6 +67,12 @@ void buildForLayer() throws Exception { builder.volumeGroup(1); builder.decayGroup(2); builder.breakageGroup(3); + builder.addSite(siteBuilder -> { + siteBuilder.siteCurveNumber(0); + siteBuilder.ageTotal(42f); + siteBuilder.yearsToBreastHeight(2f); + siteBuilder.height(10f); + }); }); assertThat(result, hasProperty("polygonIdentifier", isPolyId("Test", 2024))); diff --git a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/test/TestUtils.java b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/test/TestUtils.java index bf6a683ea..7b45bf571 100644 --- a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/test/TestUtils.java +++ b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/test/TestUtils.java @@ -594,7 +594,7 @@ public static BiFunction> netDecayMap(i * @param id * @return The species */ - public static , S extends BaseVdypSpecies> S assertHasSpecies(L layer, String id) { + public static , S extends BaseVdypSpecies> S assertHasSpecies(L layer, String id) { assertThat(layer, hasProperty("species", hasKey(id))); @@ -613,7 +613,7 @@ public static BiFunction> netDecayMap(i * @param ids * @return the first species specified */ - public static , S extends BaseVdypSpecies> S + public static , S extends BaseVdypSpecies> S assertHasSpecies(L layer, String... ids) { assertThat(layer, hasProperty("species", aMapWithSize(ids.length))); From 91b3d454112e83a260a9223495d187c5040ec22c Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Thu, 1 Aug 2024 14:41:05 -0700 Subject: [PATCH 04/16] Improve feedback when a model builder is missing properties --- .../java/ca/bc/gov/nrs/vdyp/model/BaseVdypLayer.java | 10 ++++++++++ .../ca/bc/gov/nrs/vdyp/model/BaseVdypPolygon.java | 9 +++++++++ .../java/ca/bc/gov/nrs/vdyp/model/BaseVdypSite.java | 11 +++++++++++ .../ca/bc/gov/nrs/vdyp/model/BaseVdypSpecies.java | 11 +++++++++++ .../ca/bc/gov/nrs/vdyp/model/ModelClassBuilder.java | 7 ++++++- 5 files changed, 47 insertions(+), 1 deletion(-) diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypLayer.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypLayer.java index e2cb67cbd..16b2907f6 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypLayer.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypLayer.java @@ -1,5 +1,6 @@ package ca.bc.gov.nrs.vdyp.model; +import java.text.MessageFormat; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; @@ -198,6 +199,15 @@ protected void postProcess(T result) { result.setSpecies(species); } + @Override + protected String getBuilderId() { + return MessageFormat.format( + "Layer {0} {1}", // + polygonIdentifier.map(Object::toString).orElse("N/A"), // + layerType.map(Object::toString).orElse("N/A") // + ); + } + } } diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypPolygon.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypPolygon.java index fa1d3af5b..cdc5ce97f 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypPolygon.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypPolygon.java @@ -1,5 +1,6 @@ package ca.bc.gov.nrs.vdyp.model; +import java.text.MessageFormat; import java.util.Collection; import java.util.EnumMap; import java.util.LinkedHashMap; @@ -254,5 +255,13 @@ public void buildChildren() { layersBuilders.clear(); } + @Override + protected String getBuilderId() { + return MessageFormat.format( + "Polygon {0}", // + polygonIdentifier.map(Object::toString).orElse("N/A") // + ); + } + } } diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypSite.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypSite.java index 8710b16d0..977129378 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypSite.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypSite.java @@ -1,5 +1,6 @@ package ca.bc.gov.nrs.vdyp.model; +import java.text.MessageFormat; import java.util.Collection; import java.util.Optional; @@ -173,6 +174,16 @@ protected void check(Collection errors) { requirePresent(siteGenus, "siteGenus", errors); } + @Override + protected String getBuilderId() { + return MessageFormat.format( + "Site {0} {1} {2}", // + polygonIdentifier.map(Object::toString).orElse("N/A"), // + layerType.map(Object::toString).orElse("N/A"), // + siteGenus.map(Object::toString).orElse("N/A")// + ); + } + } } diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypSpecies.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypSpecies.java index c5603fce9..a7651955b 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypSpecies.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypSpecies.java @@ -1,5 +1,6 @@ package ca.bc.gov.nrs.vdyp.model; +import java.text.MessageFormat; import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; @@ -179,6 +180,16 @@ protected void preProcess() { site = siteBuilder.map(this::buildSite).or(() -> site); } + @Override + protected String getBuilderId() { + return MessageFormat.format( + "Species {0} {1} {2}", // + polygonIdentifier.map(Object::toString).orElse("N/A"), // + layerType.map(Object::toString).orElse("N/A"), // + genus.map(Object::toString).orElse("N/A")// + ); + } + public Builder adapt(BaseVdypSpecies toCopy) { polygonIdentifier(toCopy.getPolygonIdentifier()); layerType(toCopy.getLayerType()); diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/ModelClassBuilder.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/ModelClassBuilder.java index 88291eb7f..bd41f903d 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/ModelClassBuilder.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/ModelClassBuilder.java @@ -1,5 +1,6 @@ package ca.bc.gov.nrs.vdyp.model; +import java.text.MessageFormat; import java.util.Collection; import java.util.LinkedList; import java.util.Optional; @@ -42,13 +43,17 @@ public T build() { preProcess(); check(errors); if (!errors.isEmpty()) { - throw new IllegalStateException(String.join(", ", errors)); + throw new IllegalStateException( + MessageFormat.format("While building {0}: {1}", this.getBuilderId(), String.join(", ", errors)) + ); } var result = doBuild(); postProcess(result); return result; } + protected abstract String getBuilderId(); + /** * Additional steps before building */ From 1a1ca48e566b7f5c8d5c969474758737c0f7bee6 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Thu, 1 Aug 2024 14:42:10 -0700 Subject: [PATCH 05/16] New methods to copy/adapt a the site belonging to a species during build --- .../ca/bc/gov/nrs/vdyp/model/BaseVdypSpecies.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypSpecies.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypSpecies.java index a7651955b..a5bf9f481 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypSpecies.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/model/BaseVdypSpecies.java @@ -215,6 +215,12 @@ public Builder adaptSite(I2 toCopy, BiConsum return this; } + public , I2 extends BaseVdypSite> Builder + adaptSiteFrom(S2 specToCopy, BiConsumer config) { + specToCopy.getSite().ifPresent(toCopy -> this.adaptSite(toCopy, config)); + return this; + } + public Builder copySite(I toCopy, BiConsumer config) { this.addSite(builder -> { builder.copy(toCopy); @@ -226,6 +232,11 @@ public Builder copySite(I toCopy, BiConsumer config) { return this; } + public Builder copySiteFrom(T specToCopy, BiConsumer config) { + specToCopy.getSite().ifPresent(toCopy -> this.copySite(toCopy, config)); + return this; + } + protected abstract I buildSite(Consumer config); } From 0a16c2eb2ba2c68edc2b7e2ae19309837e727017 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Thu, 1 Aug 2024 17:31:56 -0700 Subject: [PATCH 06/16] Adapting VRIStart to use Site as child of Species --- .../bc/gov/nrs/vdyp/fip/FipLayerParser.java | 1 - .../bc/gov/nrs/vdyp/fip/model/FipLayer.java | 9 - .../bc/gov/nrs/vdyp/fip/model/FipSpecies.java | 28 +- .../java/ca/bc/gov/nrs/vdyp/vri/VriStart.java | 130 +-- .../bc/gov/nrs/vdyp/vri/model/VriLayer.java | 9 - .../bc/gov/nrs/vdyp/vri/model/VriSpecies.java | 24 +- .../nrs/vdyp/vri/VriInputValidationTest.java | 760 ++++++++---------- .../ca/bc/gov/nrs/vdyp/vri/VriStartTest.java | 530 ++++++------ 8 files changed, 679 insertions(+), 812 deletions(-) diff --git a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipLayerParser.java b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipLayerParser.java index 0e3b6ed4c..221ab27a6 100644 --- a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipLayerParser.java +++ b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipLayerParser.java @@ -109,7 +109,6 @@ protected ValueOrMarker, EndOfRecord> convert(Map config) { }); } - @Override - protected FipSite buildSite(Consumer config) { - return FipSite.build(builder -> { - config.accept(builder); - builder.polygonIdentifier(polygonIdentifier.get()); - builder.layerType(layerType.get()); - }); - } - } } diff --git a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/model/FipSpecies.java b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/model/FipSpecies.java index 8b5c1e8ab..350e7811b 100644 --- a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/model/FipSpecies.java +++ b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/model/FipSpecies.java @@ -1,19 +1,19 @@ package ca.bc.gov.nrs.vdyp.fip.model; +import java.util.Optional; import java.util.function.Consumer; import ca.bc.gov.nrs.vdyp.model.BaseVdypSpecies; import ca.bc.gov.nrs.vdyp.model.LayerType; import ca.bc.gov.nrs.vdyp.model.PolygonIdentifier; -public class FipSpecies extends BaseVdypSpecies { +public class FipSpecies extends BaseVdypSpecies { - public FipSpecies(PolygonIdentifier polygonIdentifier, LayerType layer, String genus, float percentGenus) { - super(polygonIdentifier, layer, genus, percentGenus); - } - - public FipSpecies(FipSpecies toCopy) { - super(toCopy); + public FipSpecies( + PolygonIdentifier polygonIdentifier, LayerType layer, String genus, float percentGenus, + Optional site + ) { + super(polygonIdentifier, layer, genus, percentGenus, site); } /** @@ -56,7 +56,7 @@ public static FipSpecies build(FipLayer layer, Consumer config) { return result; } - public static class Builder extends BaseVdypSpecies.Builder { + public static class Builder extends BaseVdypSpecies.Builder { @Override protected FipSpecies doBuild() { @@ -64,8 +64,18 @@ protected FipSpecies doBuild() { this.polygonIdentifier.get(), // this.layerType.get(), // this.genus.get(), // - this.percentGenus.get() + this.percentGenus.get(), this.site ); } + + @Override + protected FipSite buildSite(Consumer config) { + return FipSite.build(builder -> { + builder.siteGenus(this.genus.get()); + builder.polygonIdentifier(this.polygonIdentifier.get()); + builder.layerType(this.layerType.get()); + config.accept(builder); + }); + } } } diff --git a/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java b/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java index 9efc7f8f4..4fa35fdf4 100644 --- a/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java +++ b/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java @@ -163,6 +163,15 @@ VriPolygon getPolygon( .orElseThrow(() -> new StandProcessingException("Unknown BEC " + polygon.getBiogeoclimaticZone())); log.trace("Getting species for polygon {}", polygon.getPolygonIdentifier()); + + log.trace("Getting sites for polygon {}", polygon.getPolygonIdentifier()); + Collection sites; + try { + sites = siteStream.next(); + } catch (NoSuchElementException ex) { + throw validationError("Sites file has fewer records than polygon file.", ex); + } + Collection species; try { species = speciesStream.next(); @@ -172,48 +181,38 @@ VriPolygon getPolygon( Map layersBuilders = layerStream.next(); - for (var spec : species) { + for (final var spec : species) { var layerBuilder = layersBuilders.get(spec.getLayerType()); - // Validate that species belong to the correct polygon - if (!spec.getPolygonIdentifier().equals(polygon.getPolygonIdentifier())) { - throw validationError( - "Record in species file contains species for polygon %s when expecting one for %s.", - spec.getPolygonIdentifier(), polygon.getPolygonIdentifier() - ); - } - if (Objects.isNull(layerBuilder)) { - throw validationError( - "Species entry references layer %s of polygon %s but it is not present.", spec.getLayerType(), - polygon.getPolygonIdentifier() - ); - } - layerBuilder.addSpecies(spec); - } - log.trace("Getting sites for polygon {}", polygon.getPolygonIdentifier()); - Collection sites; - try { - sites = siteStream.next(); - } catch (NoSuchElementException ex) { - throw validationError("Sites file has fewer records than polygon file.", ex); - } + var foundSite = sites.stream().filter(site -> site.getSiteGenus().equals(spec.getGenus())).findFirst(); + final var specWithSite = VriSpecies.build(builder -> { + builder.copy(spec); + builder.addSite(foundSite); + }); + foundSite.ifPresent(sites::remove); - for (var site : sites) { - var layerBuilder = layersBuilders.get(site.getLayerType()); // Validate that species belong to the correct polygon - if (!site.getPolygonIdentifier().equals(polygon.getPolygonIdentifier())) { + if (!specWithSite.getPolygonIdentifier().equals(polygon.getPolygonIdentifier())) { throw validationError( - "Record in site file contains site for polygon %s when expecting one for %s.", - site.getPolygonIdentifier(), polygon.getPolygonIdentifier() + "Record in species file contains species for polygon %s when expecting one for %s.", + specWithSite.getPolygonIdentifier(), polygon.getPolygonIdentifier() ); } if (Objects.isNull(layerBuilder)) { throw validationError( - "Site entry references layer %s of polygon %s but it is not present.", site.getLayerType(), - polygon.getPolygonIdentifier() + "Species entry references layer %s of polygon %s but it is not present.", + specWithSite.getLayerType(), polygon.getPolygonIdentifier() ); } - layerBuilder.addSite(site); + layerBuilder.addSpecies(specWithSite); + } + if (!sites.isEmpty()) { + var specNames = sites.stream().map(site -> site.getSiteGenus()).collect(Collectors.joining(", ")); + var layerType = sites.iterator().next().getLayerType(); + throw validationError( + "Site entries reference species %s of layer %s of polygon %s but they are not present.", specNames, + layerType, polygon.getPolygonIdentifier() + ); } Map layers = getLayersForPolygon(polygon, bec, layersBuilders); @@ -457,6 +456,11 @@ void processPrimaryLayer(VriPolygon polygon, VdypLayer.Builder lBuilder) throws if (vriSite == primarySiteIn) { sBuilder.loreyHeight(primaryHeight); + + // Only use the primary site + sBuilder.adaptSite(vriSite, (iBuilder, vriSite2) -> { + iBuilder.height(vriSite2.getHeight().get()); + }); } else { float loreyHeight = vriSite.getHeight().filter((x) -> getDebugMode(2) == 1).map(height -> { @@ -487,13 +491,6 @@ void processPrimaryLayer(VriPolygon polygon, VdypLayer.Builder lBuilder) throws this.applyGroups(bec, vriSpec.getGenus(), sBuilder); }); - // Only use the primary site - var primarySite = primaryLayer.getPrimarySite().get(); - - lBuilder.adaptSite(primarySite, (sBuilder, vriSite) -> { - sBuilder.height(vriSite.getHeight().get()); - }); - lBuilder.buildChildren(); var species = lBuilder.getSpecies(); @@ -1009,7 +1006,7 @@ protected BaseControlParser getControlFileParser() { } @Override - protected VriSpecies copySpecies(VriSpecies toCopy, Consumer> config) { + protected VriSpecies copySpecies(VriSpecies toCopy, Consumer> config) { return VriSpecies.build(builder -> builder.copy(toCopy)); } @@ -1091,26 +1088,27 @@ VriPolygon processYoung(VriPolygon poly) throws ProcessingException { pBuilder.mode(PolygonMode.BATN); pBuilder.copyLayers(poly, (lBuilder, layer) -> { - lBuilder.copySites(layer, (iBuilder, site) -> { - if (layer.getLayerType() == LayerType.PRIMARY - && primaryLayer.getPrimaryGenus().map(site.getSiteGenus()::equals).orElse(false)) { - iBuilder.height(inc.dominantHeight); - } else { - iBuilder.height(Optional.empty()); - } - - site.getAgeTotal().map(x -> x + inc.ageIncrease).ifPresentOrElse(ageTotal -> { - iBuilder.ageTotal(ageTotal); - iBuilder.breastHeightAge( - site.getYearsToBreastHeight()// - .map(ytbh -> ageTotal - ytbh) - .or(() -> site.getBreastHeightAge().map(bha -> bha + inc.ageIncrease)) + lBuilder.copySpecies(layer, (sBuilder, species) -> { + sBuilder.copySiteFrom(species, (iBuilder, site) -> { + if (layer.getLayerType() == LayerType.PRIMARY + && primaryLayer.getPrimaryGenus().map(site.getSiteGenus()::equals).orElse(false)) { + iBuilder.height(inc.dominantHeight); + } else { + iBuilder.height(Optional.empty()); + } + + site.getAgeTotal().map(x -> x + inc.ageIncrease).ifPresentOrElse(ageTotal -> { + iBuilder.ageTotal(ageTotal); + iBuilder.breastHeightAge( + site.getYearsToBreastHeight()// + .map(ytbh -> ageTotal - ytbh) + .or(() -> site.getBreastHeightAge().map(bha -> bha + inc.ageIncrease)) + ); + }, () -> iBuilder + .breastHeightAge(site.getBreastHeightAge().map(bha -> bha + inc.ageIncrease)) ); - }, () -> iBuilder.breastHeightAge(site.getBreastHeightAge().map(bha -> bha + inc.ageIncrease))); - }); - lBuilder.copySpecies(layer, (sBuilder, species) -> { - // No changes, just copy + }); }); }); }); @@ -1178,6 +1176,12 @@ static final > BiConsumer noChange() { }; } + static final BiConsumer noChangeSpecies() { + return (builder, toCopy) -> { + toCopy.getSite().ifPresent(site -> builder.copySite(site, noChange())); + }; + } + VriPolygon processBatc(VriPolygon poly) throws ProcessingException { VriLayer primaryLayer = getPrimaryLayer(poly); @@ -1218,15 +1222,13 @@ VriPolygon processBatc(VriPolygon poly) throws ProcessingException { lBuilder.copy(primaryLayer); lBuilder.baseArea(primaryBaseArea * (percentForestLand / 100)); lBuilder.treesPerHectare(treesPerHectare(primaryBaseArea, primaryQuadMeanDiameter)); - lBuilder.copySites(primaryLayer, noChange()); - lBuilder.copySpecies(primaryLayer, noChange()); + lBuilder.copySpecies(primaryLayer, noChangeSpecies()); }); veteranLayer.ifPresent(vLayer -> pBuilder.addLayer(lBuilder -> { lBuilder.copy(vLayer); lBuilder.baseArea(veteranBaseArea); - lBuilder.copySites(primaryLayer, noChange()); - lBuilder.copySpecies(primaryLayer, noChange()); + lBuilder.copySpecies(primaryLayer, noChangeSpecies()); })); }); @@ -1287,15 +1289,13 @@ VriPolygon processBatn(VriPolygon poly) throws ProcessingException { lBuilder.copy(primaryLayer); lBuilder.baseArea(primaryBaseAreaFinal); lBuilder.treesPerHectare(primaryTreesPerHectare); - lBuilder.copySites(primaryLayer, noChange()); - lBuilder.copySpecies(primaryLayer, noChange()); + lBuilder.copySpecies(primaryLayer, noChangeSpecies()); }); veteranLayer.ifPresent(vLayer -> pBuilder.addLayer(lBuilder -> { lBuilder.copy(vLayer); lBuilder.baseArea(veteranBaseArea); - lBuilder.copySites(primaryLayer, noChange()); - lBuilder.copySpecies(primaryLayer, noChange()); + lBuilder.copySpecies(primaryLayer, noChangeSpecies()); })); }); diff --git a/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/model/VriLayer.java b/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/model/VriLayer.java index 18c09ddf0..80f3ec4a8 100644 --- a/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/model/VriLayer.java +++ b/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/model/VriLayer.java @@ -228,15 +228,6 @@ protected VriSpecies buildSpecies(Consumer config) { }); } - @Override - protected VriSite buildSite(Consumer config) { - return VriSite.build(builder -> { - config.accept(builder); - builder.polygonIdentifier(this.polygonIdentifier.get()); - builder.layerType(layerType.get()); - }); - } - @Override public Builder copy(VriLayer toCopy) { super.copy(toCopy); diff --git a/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/model/VriSpecies.java b/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/model/VriSpecies.java index 42d1c648a..46826b757 100644 --- a/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/model/VriSpecies.java +++ b/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/model/VriSpecies.java @@ -1,5 +1,6 @@ package ca.bc.gov.nrs.vdyp.vri.model; +import java.util.Optional; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -7,10 +8,13 @@ import ca.bc.gov.nrs.vdyp.model.LayerType; import ca.bc.gov.nrs.vdyp.model.PolygonIdentifier; -public class VriSpecies extends BaseVdypSpecies { +public class VriSpecies extends BaseVdypSpecies { - public VriSpecies(PolygonIdentifier polygonIdentifier, LayerType layer, String genus, float percentGenus) { - super(polygonIdentifier, layer, genus, percentGenus); + public VriSpecies( + PolygonIdentifier polygonIdentifier, LayerType layer, String genus, float percentGenus, + Optional site + ) { + super(polygonIdentifier, layer, genus, percentGenus, site); } /** @@ -35,7 +39,7 @@ public static VriSpecies build(Consumer config) { return builder.build(); } - public static class Builder extends BaseVdypSpecies.Builder { + public static class Builder extends BaseVdypSpecies.Builder { @Override protected VriSpecies doBuild() { @@ -43,9 +47,19 @@ protected VriSpecies doBuild() { this.polygonIdentifier.get(), // this.layerType.get(), // this.genus.get(), // - this.percentGenus.get() + this.percentGenus.get(), this.site ); } + + @Override + protected VriSite buildSite(Consumer config) { + return VriSite.build(builder -> { + config.accept(builder); + builder.polygonIdentifier(this.polygonIdentifier.get()); + builder.layerType(this.layerType.get()); + builder.siteGenus(this.genus); + }); + } } @Override diff --git a/vdyp-lib/vdyp-vri/src/test/java/ca/bc/gov/nrs/vdyp/vri/VriInputValidationTest.java b/vdyp-lib/vdyp-vri/src/test/java/ca/bc/gov/nrs/vdyp/vri/VriInputValidationTest.java index 6126be50c..be085b688 100644 --- a/vdyp-lib/vdyp-vri/src/test/java/ca/bc/gov/nrs/vdyp/vri/VriInputValidationTest.java +++ b/vdyp-lib/vdyp-vri/src/test/java/ca/bc/gov/nrs/vdyp/vri/VriInputValidationTest.java @@ -70,58 +70,52 @@ void testPassValid() throws Exception { lBuilder.utilization(7.5f); lBuilder.empiricalRelationshipParameterIndex(76); - // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("B"); - iBuilder.siteSpecies("BL"); - iBuilder.siteCurveNumber(8); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.ageTotal(200); - iBuilder.height(28.0f); - iBuilder.siteIndex(14.3f); - iBuilder.siteGenus("C"); - iBuilder.siteSpecies("CW"); - iBuilder.yearsToBreastHeight(10.9f); - iBuilder.breastHeightAge(189.1f); - iBuilder.siteCurveNumber(11); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.ageTotal(200); - iBuilder.height(32.0f); - iBuilder.siteIndex(14.6f); - iBuilder.siteGenus("H"); - iBuilder.siteSpecies("HW"); - iBuilder.yearsToBreastHeight(9.7f); - iBuilder.breastHeightAge(190.3f); - iBuilder.siteCurveNumber(37); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("S"); - iBuilder.siteSpecies("SE"); - iBuilder.siteCurveNumber(71); - }); - // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("B"); sBuilder.percentGenus(3f); sBuilder.addSpecies("BL", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("BL"); + iBuilder.siteCurveNumber(8); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("C"); sBuilder.percentGenus(30f); sBuilder.addSpecies("CW", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.ageTotal(200); + iBuilder.height(28.0f); + iBuilder.siteIndex(14.3f); + iBuilder.siteSpecies("CW"); + iBuilder.yearsToBreastHeight(10.9f); + iBuilder.breastHeightAge(189.1f); + iBuilder.siteCurveNumber(11); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("H"); sBuilder.percentGenus(48.9f); sBuilder.addSpecies("HW", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.ageTotal(200); + iBuilder.height(32.0f); + iBuilder.siteIndex(14.6f); + iBuilder.siteSpecies("HW"); + iBuilder.yearsToBreastHeight(9.7f); + iBuilder.breastHeightAge(190.3f); + iBuilder.siteCurveNumber(37); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("S"); sBuilder.percentGenus(18.1f); sBuilder.addSpecies("SE", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("SE"); + iBuilder.siteCurveNumber(71); + }); }); lBuilder.primaryGenus("H"); @@ -133,23 +127,21 @@ void testPassValid() throws Exception { lBuilder.baseArea(0f); lBuilder.treesPerHectare(0f); lBuilder.utilization(0f); - // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.ageTotal(200); - iBuilder.height(34.0f); - iBuilder.siteIndex(14.6f); - iBuilder.siteGenus("H"); - iBuilder.siteSpecies("HW"); - iBuilder.yearsToBreastHeight(9.7f); - iBuilder.breastHeightAge(190.3f); - iBuilder.siteCurveNumber(37); - }); // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("H"); sBuilder.percentGenus(100f); sBuilder.addSpecies("HW", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.ageTotal(200); + iBuilder.height(34.0f); + iBuilder.siteIndex(14.6f); + iBuilder.siteSpecies("HW"); + iBuilder.yearsToBreastHeight(9.7f); + iBuilder.breastHeightAge(190.3f); + iBuilder.siteCurveNumber(37); + }); }); lBuilder.primaryGenus("H"); @@ -182,58 +174,52 @@ void testFailPrimarySpeciesDontSumTo100() throws Exception { lBuilder.treesPerHectare(850f); lBuilder.utilization(7.5f); - // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("B"); - iBuilder.siteSpecies("BL"); - iBuilder.siteCurveNumber(8); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.ageTotal(200); - iBuilder.height(28.0f); - iBuilder.siteIndex(14.3f); - iBuilder.siteGenus("C"); - iBuilder.siteSpecies("CW"); - iBuilder.yearsToBreastHeight(10.9f); - iBuilder.breastHeightAge(189.1f); - iBuilder.siteCurveNumber(11); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.ageTotal(200); - iBuilder.height(32.0f); - iBuilder.siteIndex(14.6f); - iBuilder.siteGenus("H"); - iBuilder.siteSpecies("HW"); - iBuilder.yearsToBreastHeight(9.7f); - iBuilder.breastHeightAge(190.3f); - iBuilder.siteCurveNumber(37); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("S"); - iBuilder.siteSpecies("SE"); - iBuilder.siteCurveNumber(71); - }); - // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("B"); sBuilder.percentGenus(3f); sBuilder.addSpecies("BL", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("BL"); + iBuilder.siteCurveNumber(8); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("C"); sBuilder.percentGenus(30f); sBuilder.addSpecies("CW", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.ageTotal(200); + iBuilder.height(28.0f); + iBuilder.siteIndex(14.3f); + iBuilder.siteSpecies("CW"); + iBuilder.yearsToBreastHeight(10.9f); + iBuilder.breastHeightAge(189.1f); + iBuilder.siteCurveNumber(11); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("H"); sBuilder.percentGenus(48.7f); sBuilder.addSpecies("HW", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.ageTotal(200); + iBuilder.height(32.0f); + iBuilder.siteIndex(14.6f); + iBuilder.siteSpecies("HW"); + iBuilder.yearsToBreastHeight(9.7f); + iBuilder.breastHeightAge(190.3f); + iBuilder.siteCurveNumber(37); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("S"); sBuilder.percentGenus(18.1f); sBuilder.addSpecies("SE", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("SE"); + iBuilder.siteCurveNumber(71); + }); }); lBuilder.primaryGenus("H"); @@ -266,58 +252,52 @@ void testFailIfMissingPrimary() throws Exception { lBuilder.treesPerHectare(850f); lBuilder.utilization(7.5f); - // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("B"); - iBuilder.siteSpecies("BL"); - iBuilder.siteCurveNumber(8); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.ageTotal(200); - iBuilder.height(28.0f); - iBuilder.siteIndex(14.3f); - iBuilder.siteGenus("C"); - iBuilder.siteSpecies("CW"); - iBuilder.yearsToBreastHeight(10.9f); - iBuilder.breastHeightAge(189.1f); - iBuilder.siteCurveNumber(11); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.ageTotal(200); - iBuilder.height(32.0f); - iBuilder.siteIndex(14.6f); - iBuilder.siteGenus("H"); - iBuilder.siteSpecies("HW"); - iBuilder.yearsToBreastHeight(9.7f); - iBuilder.breastHeightAge(190.3f); - iBuilder.siteCurveNumber(37); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("S"); - iBuilder.siteSpecies("SE"); - iBuilder.siteCurveNumber(71); - }); - // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("B"); sBuilder.percentGenus(3f); sBuilder.addSpecies("BL", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("BL"); + iBuilder.siteCurveNumber(8); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("C"); sBuilder.percentGenus(30f); sBuilder.addSpecies("CW", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.ageTotal(200); + iBuilder.height(28.0f); + iBuilder.siteIndex(14.3f); + iBuilder.siteSpecies("CW"); + iBuilder.yearsToBreastHeight(10.9f); + iBuilder.breastHeightAge(189.1f); + iBuilder.siteCurveNumber(11); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("H"); sBuilder.percentGenus(48.7f); sBuilder.addSpecies("HW", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.ageTotal(200); + iBuilder.height(32.0f); + iBuilder.siteIndex(14.6f); + iBuilder.siteSpecies("HW"); + iBuilder.yearsToBreastHeight(9.7f); + iBuilder.breastHeightAge(190.3f); + iBuilder.siteCurveNumber(37); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("S"); sBuilder.percentGenus(18.1f); sBuilder.addSpecies("SE", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("SE"); + iBuilder.siteCurveNumber(71); + }); }); lBuilder.primaryGenus("H"); @@ -368,58 +348,52 @@ void testFailIfPrimaryModeYoungAndLacksAge() throws Exception { lBuilder.treesPerHectare(850f); lBuilder.utilization(7.5f); - // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("B"); - iBuilder.siteSpecies("BL"); - iBuilder.siteCurveNumber(8); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.ageTotal(200); - iBuilder.height(28.0f); - iBuilder.siteIndex(14.3f); - iBuilder.siteGenus("C"); - iBuilder.siteSpecies("CW"); - iBuilder.yearsToBreastHeight(10.9f); - iBuilder.breastHeightAge(189.1f); - iBuilder.siteCurveNumber(11); - }); - lBuilder.addSite(iBuilder -> { - // iBuilder.ageTotal(200); // don't include age on primary species - iBuilder.height(32.0f); - iBuilder.siteIndex(14.6f); - iBuilder.siteGenus("H"); - iBuilder.siteSpecies("HW"); - // iBuilder.yearsToBreastHeight(9.7f); - // iBuilder.breastHeightAge(190.3f); - iBuilder.siteCurveNumber(37); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("S"); - iBuilder.siteSpecies("SE"); - iBuilder.siteCurveNumber(71); - }); - // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("B"); sBuilder.percentGenus(3f); sBuilder.addSpecies("BL", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("BL"); + iBuilder.siteCurveNumber(8); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("C"); sBuilder.percentGenus(30f); sBuilder.addSpecies("CW", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.ageTotal(200); + iBuilder.height(28.0f); + iBuilder.siteIndex(14.3f); + iBuilder.siteSpecies("CW"); + iBuilder.yearsToBreastHeight(10.9f); + iBuilder.breastHeightAge(189.1f); + iBuilder.siteCurveNumber(11); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("H"); sBuilder.percentGenus(48.9f); sBuilder.addSpecies("HW", 100); + sBuilder.addSite(iBuilder -> { + // iBuilder.ageTotal(200); // don't include age on primary species + iBuilder.height(32.0f); + iBuilder.siteIndex(14.6f); + iBuilder.siteSpecies("HW"); + // iBuilder.yearsToBreastHeight(9.7f); + // iBuilder.breastHeightAge(190.3f); + iBuilder.siteCurveNumber(37); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("S"); sBuilder.percentGenus(18.1f); sBuilder.addSpecies("SE", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("SE"); + iBuilder.siteCurveNumber(71); + }); }); lBuilder.primaryGenus("H"); @@ -459,58 +433,52 @@ void testFailIfPrimaryModeYoungAndLacksTreesPerHectare() throws Exception { // lBuilder.treesPerHectare(850f); lBuilder.utilization(7.5f); - // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("B"); - iBuilder.siteSpecies("BL"); - iBuilder.siteCurveNumber(8); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.ageTotal(200); - iBuilder.height(28.0f); - iBuilder.siteIndex(14.3f); - iBuilder.siteGenus("C"); - iBuilder.siteSpecies("CW"); - iBuilder.yearsToBreastHeight(10.9f); - iBuilder.breastHeightAge(189.1f); - iBuilder.siteCurveNumber(11); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.ageTotal(200); - iBuilder.height(32.0f); - iBuilder.siteIndex(14.6f); - iBuilder.siteGenus("H"); - iBuilder.siteSpecies("HW"); - iBuilder.yearsToBreastHeight(9.7f); - iBuilder.breastHeightAge(190.3f); - iBuilder.siteCurveNumber(37); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("S"); - iBuilder.siteSpecies("SE"); - iBuilder.siteCurveNumber(71); - }); - // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("B"); sBuilder.percentGenus(3f); sBuilder.addSpecies("BL", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("BL"); + iBuilder.siteCurveNumber(8); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("C"); sBuilder.percentGenus(30f); sBuilder.addSpecies("CW", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.ageTotal(200); + iBuilder.height(28.0f); + iBuilder.siteIndex(14.3f); + iBuilder.siteSpecies("CW"); + iBuilder.yearsToBreastHeight(10.9f); + iBuilder.breastHeightAge(189.1f); + iBuilder.siteCurveNumber(11); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("H"); sBuilder.percentGenus(48.9f); sBuilder.addSpecies("HW", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.ageTotal(200); + iBuilder.height(32.0f); + iBuilder.siteIndex(14.6f); + iBuilder.siteSpecies("HW"); + iBuilder.yearsToBreastHeight(9.7f); + iBuilder.breastHeightAge(190.3f); + iBuilder.siteCurveNumber(37); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("S"); sBuilder.percentGenus(18.1f); sBuilder.addSpecies("SE", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("SE"); + iBuilder.siteCurveNumber(71); + }); }); lBuilder.primaryGenus("H"); @@ -552,58 +520,52 @@ void testValidPrimaryModeYoung() throws Exception { lBuilder.utilization(7.5f); lBuilder.empiricalRelationshipParameterIndex(76); - // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("B"); - iBuilder.siteSpecies("BL"); - iBuilder.siteCurveNumber(8); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.ageTotal(200); - iBuilder.height(28.0f); - iBuilder.siteIndex(14.3f); - iBuilder.siteGenus("C"); - iBuilder.siteSpecies("CW"); - iBuilder.yearsToBreastHeight(10.9f); - iBuilder.breastHeightAge(189.1f); - iBuilder.siteCurveNumber(11); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.ageTotal(200); - iBuilder.height(32.0f); - iBuilder.siteIndex(14.6f); - iBuilder.siteGenus("H"); - iBuilder.siteSpecies("HW"); - iBuilder.yearsToBreastHeight(9.7f); - iBuilder.breastHeightAge(190.3f); - iBuilder.siteCurveNumber(37); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("S"); - iBuilder.siteSpecies("SE"); - iBuilder.siteCurveNumber(71); - }); - // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("B"); sBuilder.percentGenus(3f); sBuilder.addSpecies("BL", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("BL"); + iBuilder.siteCurveNumber(8); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("C"); sBuilder.percentGenus(30f); sBuilder.addSpecies("CW", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.ageTotal(200); + iBuilder.height(28.0f); + iBuilder.siteIndex(14.3f); + iBuilder.siteSpecies("CW"); + iBuilder.yearsToBreastHeight(10.9f); + iBuilder.breastHeightAge(189.1f); + iBuilder.siteCurveNumber(11); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("H"); sBuilder.percentGenus(48.9f); sBuilder.addSpecies("HW", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.ageTotal(200); + iBuilder.height(32.0f); + iBuilder.siteIndex(14.6f); + iBuilder.siteSpecies("HW"); + iBuilder.yearsToBreastHeight(9.7f); + iBuilder.breastHeightAge(190.3f); + iBuilder.siteCurveNumber(37); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("S"); sBuilder.percentGenus(18.1f); sBuilder.addSpecies("SE", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("SE"); + iBuilder.siteCurveNumber(71); + }); }); lBuilder.primaryGenus("H"); @@ -645,58 +607,52 @@ void testValidPrimaryModeStart() throws Exception { lBuilder.utilization(7.5f); lBuilder.empiricalRelationshipParameterIndex(76); - // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("B"); - iBuilder.siteSpecies("BL"); - iBuilder.siteCurveNumber(8); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.ageTotal(200); - iBuilder.height(28.0f); - iBuilder.siteIndex(14.3f); - iBuilder.siteGenus("C"); - iBuilder.siteSpecies("CW"); - iBuilder.yearsToBreastHeight(10.9f); - iBuilder.breastHeightAge(189.1f); - iBuilder.siteCurveNumber(11); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.ageTotal(200); - iBuilder.height(32.0f); - iBuilder.siteIndex(14.6f); - iBuilder.siteGenus("H"); - iBuilder.siteSpecies("HW"); - iBuilder.yearsToBreastHeight(9.7f); - iBuilder.breastHeightAge(190.3f); - iBuilder.siteCurveNumber(37); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("S"); - iBuilder.siteSpecies("SE"); - iBuilder.siteCurveNumber(71); - }); - // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("B"); sBuilder.percentGenus(3f); sBuilder.addSpecies("BL", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("BL"); + iBuilder.siteCurveNumber(8); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("C"); sBuilder.percentGenus(30f); sBuilder.addSpecies("CW", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.ageTotal(200); + iBuilder.height(28.0f); + iBuilder.siteIndex(14.3f); + iBuilder.siteSpecies("CW"); + iBuilder.yearsToBreastHeight(10.9f); + iBuilder.breastHeightAge(189.1f); + iBuilder.siteCurveNumber(11); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("H"); sBuilder.percentGenus(48.9f); sBuilder.addSpecies("HW", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.ageTotal(200); + iBuilder.height(32.0f); + iBuilder.siteIndex(14.6f); + iBuilder.siteSpecies("HW"); + iBuilder.yearsToBreastHeight(9.7f); + iBuilder.breastHeightAge(190.3f); + iBuilder.siteCurveNumber(37); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("S"); sBuilder.percentGenus(18.1f); sBuilder.addSpecies("SE", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("SE"); + iBuilder.siteCurveNumber(71); + }); }); lBuilder.primaryGenus("H"); @@ -737,58 +693,52 @@ void testFailIfPrimaryModeStartMissingHeight() throws Exception { lBuilder.treesPerHectare(850f); lBuilder.utilization(7.5f); - // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("B"); - iBuilder.siteSpecies("BL"); - iBuilder.siteCurveNumber(8); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.ageTotal(200); - iBuilder.height(28.0f); - iBuilder.siteIndex(14.3f); - iBuilder.siteGenus("C"); - iBuilder.siteSpecies("CW"); - iBuilder.yearsToBreastHeight(10.9f); - iBuilder.breastHeightAge(189.1f); - iBuilder.siteCurveNumber(11); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.ageTotal(200); - // iBuilder.height(32.0f); // Remove height from primary species - iBuilder.siteIndex(14.6f); - iBuilder.siteGenus("H"); - iBuilder.siteSpecies("HW"); - iBuilder.yearsToBreastHeight(9.7f); - iBuilder.breastHeightAge(190.3f); - iBuilder.siteCurveNumber(37); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("S"); - iBuilder.siteSpecies("SE"); - iBuilder.siteCurveNumber(71); - }); - // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("B"); sBuilder.percentGenus(3f); sBuilder.addSpecies("BL", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("BL"); + iBuilder.siteCurveNumber(8); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("C"); sBuilder.percentGenus(30f); sBuilder.addSpecies("CW", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.ageTotal(200); + iBuilder.height(28.0f); + iBuilder.siteIndex(14.3f); + iBuilder.siteSpecies("CW"); + iBuilder.yearsToBreastHeight(10.9f); + iBuilder.breastHeightAge(189.1f); + iBuilder.siteCurveNumber(11); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("H"); sBuilder.percentGenus(48.9f); sBuilder.addSpecies("HW", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.ageTotal(200); + // iBuilder.height(32.0f); // Remove height from primary species + iBuilder.siteIndex(14.6f); + iBuilder.siteSpecies("HW"); + iBuilder.yearsToBreastHeight(9.7f); + iBuilder.breastHeightAge(190.3f); + iBuilder.siteCurveNumber(37); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("S"); sBuilder.percentGenus(18.1f); sBuilder.addSpecies("SE", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("SE"); + iBuilder.siteCurveNumber(71); + }); }); lBuilder.primaryGenus("H"); @@ -832,20 +782,17 @@ void testFailIfSiteIndexMissing(String modeName, String passFail) throws Excepti lBuilder.treesPerHectare(850f); lBuilder.utilization(7.5f); - // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("B"); - iBuilder.siteSpecies("BL"); - iBuilder.height(5f); - iBuilder.siteCurveNumber(8); - // iBuilder.ageTotal(100f); - }); - // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("B"); sBuilder.percentGenus(100f); sBuilder.addSpecies("BL", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("BL"); + iBuilder.height(5f); + iBuilder.siteCurveNumber(8); + // iBuilder.ageTotal(100f); + }); }); lBuilder.primaryGenus("B"); @@ -897,20 +844,17 @@ void testFailIfSiteIndexLow(String modeName, String passFail) throws Exception { lBuilder.treesPerHectare(850f); lBuilder.utilization(7.5f); - // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("B"); - iBuilder.siteSpecies("BL"); - iBuilder.height(5f); - iBuilder.siteCurveNumber(8); - iBuilder.siteIndex(0.0f); - }); - // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("B"); sBuilder.percentGenus(100f); sBuilder.addSpecies("BL", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("BL"); + iBuilder.height(5f); + iBuilder.siteCurveNumber(8); + iBuilder.siteIndex(0.0f); + }); }); lBuilder.primaryGenus("B"); @@ -963,20 +907,19 @@ void testFailIfAgeTotalMissing(String modeName, String passFail) throws Exceptio lBuilder.utilization(7.5f); // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("B"); - iBuilder.siteSpecies("BL"); - iBuilder.height(5f); - iBuilder.siteCurveNumber(8); - iBuilder.siteIndex(1f); - iBuilder.ageTotal(Optional.empty()); - }); // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("B"); sBuilder.percentGenus(100f); sBuilder.addSpecies("BL", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("BL"); + iBuilder.height(5f); + iBuilder.siteCurveNumber(8); + iBuilder.siteIndex(1f); + iBuilder.ageTotal(Optional.empty()); + }); }); lBuilder.primaryGenus("B"); @@ -1028,21 +971,18 @@ void testFailIfAgeTotalLow(String modeName, String passFail) throws Exception { lBuilder.treesPerHectare(850f); lBuilder.utilization(7.5f); - // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("B"); - iBuilder.siteSpecies("BL"); - iBuilder.height(5f); - iBuilder.siteCurveNumber(8); - iBuilder.siteIndex(1f); - iBuilder.ageTotal(0f); - }); - // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("B"); sBuilder.percentGenus(100f); sBuilder.addSpecies("BL", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("BL"); + iBuilder.height(5f); + iBuilder.siteCurveNumber(8); + iBuilder.siteIndex(1f); + iBuilder.ageTotal(0f); + }); }); lBuilder.primaryGenus("B"); @@ -1094,24 +1034,21 @@ void testFailIfBreastHeightAgeLow(String modeName, String passFail) throws Excep lBuilder.treesPerHectare(850f); lBuilder.utilization(7.5f); - // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("B"); - iBuilder.siteSpecies("BL"); - iBuilder.height(5f); - iBuilder.siteCurveNumber(8); - iBuilder.siteIndex(1f); - - // These are equal so computed breast height age will be 0 - iBuilder.ageTotal(10f); - iBuilder.yearsToBreastHeight(10f); - }); - // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("B"); sBuilder.percentGenus(100f); sBuilder.addSpecies("BL", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("BL"); + iBuilder.height(5f); + iBuilder.siteCurveNumber(8); + iBuilder.siteIndex(1f); + + // These are equal so computed breast height age will be 0 + iBuilder.ageTotal(10f); + iBuilder.yearsToBreastHeight(10f); + }); }); lBuilder.primaryGenus("B"); @@ -1163,22 +1100,19 @@ void testFailIfYearsToBreastHeightLow(String modeName, String passFail) throws E lBuilder.treesPerHectare(850f); lBuilder.utilization(7.5f); - // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("B"); - iBuilder.siteSpecies("BL"); - iBuilder.height(5f); - iBuilder.siteCurveNumber(8); - iBuilder.siteIndex(1f); - iBuilder.ageTotal(100f); - iBuilder.yearsToBreastHeight(0f); - }); - // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("B"); sBuilder.percentGenus(100f); sBuilder.addSpecies("BL", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("BL"); + iBuilder.height(5f); + iBuilder.siteCurveNumber(8); + iBuilder.siteIndex(1f); + iBuilder.ageTotal(100f); + iBuilder.yearsToBreastHeight(0f); + }); }); lBuilder.primaryGenus("B"); @@ -1239,22 +1173,19 @@ void testFailIfYearsToBreastHeightLow(String modeName, String heightS, String pa lBuilder.treesPerHectare(850f); lBuilder.utilization(7.5f); - // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("B"); - iBuilder.siteSpecies("BL"); - iBuilder.height(Float.valueOf(heightS)); - iBuilder.siteCurveNumber(8); - iBuilder.siteIndex(1f); - iBuilder.ageTotal(100f); - iBuilder.yearsToBreastHeight(5f); - }); - // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("B"); sBuilder.percentGenus(100f); sBuilder.addSpecies("BL", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("BL"); + iBuilder.height(Float.valueOf(heightS)); + iBuilder.siteCurveNumber(8); + iBuilder.siteIndex(1f); + iBuilder.ageTotal(100f); + iBuilder.yearsToBreastHeight(5f); + }); }); lBuilder.primaryGenus("B"); @@ -1306,22 +1237,19 @@ void testFailIfBaseAreaLow(String modeName, String passFail) throws Exception { lBuilder.treesPerHectare(850f); lBuilder.utilization(7.5f); - // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("B"); - iBuilder.siteSpecies("BL"); - iBuilder.height(5f); - iBuilder.siteCurveNumber(8); - iBuilder.siteIndex(1f); - iBuilder.ageTotal(100f); - iBuilder.yearsToBreastHeight(5f); - }); - // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("B"); sBuilder.percentGenus(100f); sBuilder.addSpecies("BL", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("BL"); + iBuilder.height(5f); + iBuilder.siteCurveNumber(8); + iBuilder.siteIndex(1f); + iBuilder.ageTotal(100f); + iBuilder.yearsToBreastHeight(5f); + }); }); lBuilder.primaryGenus("B"); @@ -1376,22 +1304,19 @@ void testFailIfTreesPerHectareLow(String modeName, String passFail) throws Excep lBuilder.treesPerHectare(0f); lBuilder.utilization(7.5f); - // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("B"); - iBuilder.siteSpecies("BL"); - iBuilder.height(5f); - iBuilder.siteCurveNumber(8); - iBuilder.siteIndex(1f); - iBuilder.ageTotal(100f); - iBuilder.yearsToBreastHeight(5f); - }); - // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("B"); sBuilder.percentGenus(100f); sBuilder.addSpecies("BL", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("BL"); + iBuilder.height(5f); + iBuilder.siteCurveNumber(8); + iBuilder.siteIndex(1f); + iBuilder.ageTotal(100f); + iBuilder.yearsToBreastHeight(5f); + }); }); lBuilder.primaryGenus("B"); @@ -1443,22 +1368,19 @@ void testFailIfCrownClosureLow(String modeName, String passFail) throws Exceptio lBuilder.treesPerHectare(850f); lBuilder.utilization(7.5f); - // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("B"); - iBuilder.siteSpecies("BL"); - iBuilder.height(5f); - iBuilder.siteCurveNumber(8); - iBuilder.siteIndex(1f); - iBuilder.ageTotal(100f); - iBuilder.yearsToBreastHeight(5f); - }); - // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("B"); sBuilder.percentGenus(100f); sBuilder.addSpecies("BL", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("BL"); + iBuilder.height(5f); + iBuilder.siteCurveNumber(8); + iBuilder.siteIndex(1f); + iBuilder.ageTotal(100f); + iBuilder.yearsToBreastHeight(5f); + }); }); lBuilder.primaryGenus("B"); @@ -1510,22 +1432,19 @@ void testModeSpecificValidationEverythingOK(String modeName, String passFail) th lBuilder.treesPerHectare(850f); lBuilder.utilization(7.5f); - // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("B"); - iBuilder.siteSpecies("BL"); - iBuilder.height(5f); - iBuilder.siteCurveNumber(8); - iBuilder.siteIndex(1f); - iBuilder.ageTotal(100f); - iBuilder.yearsToBreastHeight(5f); - }); - // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("B"); sBuilder.percentGenus(100f); sBuilder.addSpecies("BL", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("BL"); + iBuilder.height(5f); + iBuilder.siteCurveNumber(8); + iBuilder.siteIndex(1f); + iBuilder.ageTotal(100f); + iBuilder.yearsToBreastHeight(5f); + }); }); lBuilder.primaryGenus("B"); @@ -1573,58 +1492,52 @@ void testCheckVeteranHeight() throws Exception { lBuilder.utilization(7.5f); lBuilder.empiricalRelationshipParameterIndex(76); - // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("B"); - iBuilder.siteSpecies("BL"); - iBuilder.siteCurveNumber(8); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.ageTotal(200); - iBuilder.height(28.0f); - iBuilder.siteIndex(14.3f); - iBuilder.siteGenus("C"); - iBuilder.siteSpecies("CW"); - iBuilder.yearsToBreastHeight(10.9f); - iBuilder.breastHeightAge(189.1f); - iBuilder.siteCurveNumber(11); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.ageTotal(200); - iBuilder.height(32.0f); - iBuilder.siteIndex(14.6f); - iBuilder.siteGenus("H"); - iBuilder.siteSpecies("HW"); - iBuilder.yearsToBreastHeight(9.7f); - iBuilder.breastHeightAge(190.3f); - iBuilder.siteCurveNumber(37); - }); - lBuilder.addSite(iBuilder -> { - iBuilder.siteGenus("S"); - iBuilder.siteSpecies("SE"); - iBuilder.siteCurveNumber(71); - }); - // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("B"); sBuilder.percentGenus(3f); sBuilder.addSpecies("BL", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("BL"); + iBuilder.siteCurveNumber(8); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("C"); sBuilder.percentGenus(30f); sBuilder.addSpecies("CW", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.ageTotal(200); + iBuilder.height(28.0f); + iBuilder.siteIndex(14.3f); + iBuilder.siteSpecies("CW"); + iBuilder.yearsToBreastHeight(10.9f); + iBuilder.breastHeightAge(189.1f); + iBuilder.siteCurveNumber(11); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("H"); sBuilder.percentGenus(48.9f); sBuilder.addSpecies("HW", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.ageTotal(200); + iBuilder.height(32.0f); + iBuilder.siteIndex(14.6f); + iBuilder.siteSpecies("HW"); + iBuilder.yearsToBreastHeight(9.7f); + iBuilder.breastHeightAge(190.3f); + iBuilder.siteCurveNumber(37); + }); }); lBuilder.addSpecies(sBuilder -> { sBuilder.genus("S"); sBuilder.percentGenus(18.1f); sBuilder.addSpecies("SE", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.siteSpecies("SE"); + iBuilder.siteCurveNumber(71); + }); }); lBuilder.primaryGenus("H"); @@ -1638,22 +1551,21 @@ void testCheckVeteranHeight() throws Exception { lBuilder.utilization(0f); // Sites - lBuilder.addSite(iBuilder -> { - iBuilder.ageTotal(200); - iBuilder.height(34.0f); - iBuilder.siteIndex(14.6f); - iBuilder.siteGenus("H"); - iBuilder.siteSpecies("HW"); - iBuilder.yearsToBreastHeight(9.7f); - iBuilder.breastHeightAge(190.3f); - iBuilder.siteCurveNumber(37); - }); // Species lBuilder.addSpecies(sBuilder -> { sBuilder.genus("H"); sBuilder.percentGenus(100f); sBuilder.addSpecies("HW", 100); + sBuilder.addSite(iBuilder -> { + iBuilder.ageTotal(200); + iBuilder.height(34.0f); + iBuilder.siteIndex(14.6f); + iBuilder.siteSpecies("HW"); + iBuilder.yearsToBreastHeight(9.7f); + iBuilder.breastHeightAge(190.3f); + iBuilder.siteCurveNumber(37); + }); }); lBuilder.primaryGenus("H"); diff --git a/vdyp-lib/vdyp-vri/src/test/java/ca/bc/gov/nrs/vdyp/vri/VriStartTest.java b/vdyp-lib/vdyp-vri/src/test/java/ca/bc/gov/nrs/vdyp/vri/VriStartTest.java index 2ab212dd4..a30b966ca 100644 --- a/vdyp-lib/vdyp-vri/src/test/java/ca/bc/gov/nrs/vdyp/vri/VriStartTest.java +++ b/vdyp-lib/vdyp-vri/src/test/java/ca/bc/gov/nrs/vdyp/vri/VriStartTest.java @@ -2006,10 +2006,9 @@ void testProcessPrimary() throws Exception { sb.genus("B"); sb.percentGenus(10); sb.addSpecies("BL", 100); - }); - lb.addSite(sb -> { - sb.siteGenus("B"); - sb.siteSpecies("BL"); + sb.addSite(ib -> { + ib.siteSpecies("BL"); + }); }); // 2 @@ -2017,11 +2016,10 @@ void testProcessPrimary() throws Exception { sb.genus("C"); sb.percentGenus(20); sb.addSpecies("CW", 100); - }); - lb.addSite(sb -> { - sb.siteGenus("C"); - sb.siteCurveNumber(11); - sb.siteSpecies("CW"); + sb.addSite(ib -> { + ib.siteCurveNumber(11); + ib.siteSpecies("CW"); + }); }); // 3 @@ -2029,16 +2027,15 @@ void testProcessPrimary() throws Exception { sb.genus("F"); sb.percentGenus(30); sb.addSpecies("FD", 100); - }); - lb.addSite(sb -> { - sb.siteGenus("F"); - sb.siteCurveNumber(23); - sb.ageTotal(24); - sb.height(7.6f); - sb.siteIndex(19.7f); - sb.yearsToBreastHeight(9); - sb.breastHeightAge(15); - sb.siteSpecies("FD"); + sb.addSite(ib -> { + ib.siteCurveNumber(23); + ib.ageTotal(24); + ib.height(7.6f); + ib.siteIndex(19.7f); + ib.yearsToBreastHeight(9); + ib.breastHeightAge(15); + ib.siteSpecies("FD"); + }); }); // 4 @@ -2046,11 +2043,10 @@ void testProcessPrimary() throws Exception { sb.genus("H"); sb.percentGenus(30); sb.addSpecies("HW", 100); - }); - lb.addSite(sb -> { - sb.siteGenus("H"); - sb.siteCurveNumber(37); - sb.siteSpecies("HW"); + sb.addSite(ib -> { + ib.siteCurveNumber(37); + ib.siteSpecies("HW"); + }); }); // 5 @@ -2058,11 +2054,10 @@ void testProcessPrimary() throws Exception { sb.genus("S"); sb.percentGenus(10); sb.addSpecies("S", 100); - }); - lb.addSite(sb -> { - sb.siteGenus("S"); - sb.siteCurveNumber(71); - sb.siteSpecies("S"); + sb.addSite(ib -> { + ib.siteCurveNumber(71); + ib.siteSpecies("S"); + }); }); }); }); @@ -2299,57 +2294,52 @@ void testBasic() throws Exception { spb.genus("B"); spb.percentGenus(10); spb.addSpecies("BL", 100); + spb.addSite(sib -> { + sib.siteSpecies("BL"); + }); }); lb.addSpecies(spb -> { spb.genus("C"); spb.percentGenus(20); spb.addSpecies("CW", 100); + spb.addSite(sib -> { + sib.siteCurveNumber(11); + sib.siteSpecies("CW"); + }); }); lb.addSpecies(spb -> { spb.genus("F"); spb.percentGenus(30); spb.addSpecies("FD", 100); + spb.addSite(sib -> { + sib.siteSpecies("FD"); + sib.siteCurveNumber(23); + sib.siteIndex(19.7f); + sib.height(7.6f); + sib.yearsToBreastHeight(9); + sib.breastHeightAge(15); + sib.ageTotal(24); + }); }); lb.addSpecies(spb -> { spb.genus("H"); spb.percentGenus(30); spb.addSpecies("HW", 100); + spb.addSite(sib -> { + sib.siteSpecies("HW"); + sib.siteCurveNumber(37); + }); }); lb.addSpecies(spb -> { spb.genus("S"); spb.percentGenus(10); spb.addSpecies("S", 100); + spb.addSite(sib -> { + sib.siteSpecies("S"); + sib.siteCurveNumber(71); + }); }); - lb.addSite(sib -> { - sib.siteGenus("B"); - sib.siteSpecies("BL"); - }); - lb.addSite(sib -> { - sib.siteGenus("C"); - sib.siteCurveNumber(11); - sib.siteSpecies("CW"); - }); - lb.addSite(sib -> { - sib.siteGenus("F"); - sib.siteSpecies("FD"); - sib.siteCurveNumber(23); - sib.siteIndex(19.7f); - sib.height(7.6f); - sib.yearsToBreastHeight(9); - sib.breastHeightAge(15); - sib.ageTotal(24); - }); - lb.addSite(sib -> { - sib.siteGenus("H"); - sib.siteSpecies("HW"); - sib.siteCurveNumber(37); - }); - lb.addSite(sib -> { - sib.siteGenus("S"); - sib.siteSpecies("S"); - sib.siteCurveNumber(71); - }); }); }); @@ -2492,57 +2482,52 @@ void testLowPercentAvailable() throws Exception { spb.genus("B"); spb.percentGenus(10); spb.addSpecies("BL", 100); + spb.addSite(sib -> { + sib.siteSpecies("BL"); + }); }); lb.addSpecies(spb -> { spb.genus("C"); spb.percentGenus(20); spb.addSpecies("CW", 100); + spb.addSite(sib -> { + sib.siteCurveNumber(11); + sib.siteSpecies("CW"); + }); }); lb.addSpecies(spb -> { spb.genus("F"); spb.percentGenus(30); spb.addSpecies("FD", 100); + spb.addSite(sib -> { + sib.siteSpecies("FD"); + sib.siteCurveNumber(23); + sib.siteIndex(19.7f); + sib.height(7.6f); + sib.yearsToBreastHeight(9); + sib.breastHeightAge(15); + sib.ageTotal(24); + }); }); lb.addSpecies(spb -> { spb.genus("H"); spb.percentGenus(30); spb.addSpecies("HW", 100); + spb.addSite(sib -> { + sib.siteSpecies("HW"); + sib.siteCurveNumber(37); + }); }); lb.addSpecies(spb -> { spb.genus("S"); spb.percentGenus(10); spb.addSpecies("S", 100); + spb.addSite(sib -> { + sib.siteSpecies("S"); + sib.siteCurveNumber(71); + }); }); - lb.addSite(sib -> { - sib.siteGenus("B"); - sib.siteSpecies("BL"); - }); - lb.addSite(sib -> { - sib.siteGenus("C"); - sib.siteCurveNumber(11); - sib.siteSpecies("CW"); - }); - lb.addSite(sib -> { - sib.siteGenus("F"); - sib.siteSpecies("FD"); - sib.siteCurveNumber(23); - sib.siteIndex(19.7f); - sib.height(7.6f); - sib.yearsToBreastHeight(9); - sib.breastHeightAge(15); - sib.ageTotal(24); - }); - lb.addSite(sib -> { - sib.siteGenus("H"); - sib.siteSpecies("HW"); - sib.siteCurveNumber(37); - }); - lb.addSite(sib -> { - sib.siteGenus("S"); - sib.siteSpecies("S"); - sib.siteCurveNumber(71); - }); }); }); @@ -2683,57 +2668,52 @@ void testIncreaseYear() throws Exception { spb.genus("B"); spb.percentGenus(10); spb.addSpecies("BL", 100); + spb.addSite(sib -> { + sib.siteSpecies("BL"); + }); }); lb.addSpecies(spb -> { spb.genus("C"); spb.percentGenus(20); spb.addSpecies("CW", 100); + spb.addSite(sib -> { + sib.siteCurveNumber(11); + sib.siteSpecies("CW"); + }); }); lb.addSpecies(spb -> { spb.genus("F"); spb.percentGenus(30); spb.addSpecies("FD", 100); + spb.addSite(sib -> { + sib.siteSpecies("FD"); + sib.siteCurveNumber(23); + sib.siteIndex(19.7f); + sib.height(6f); // Set this low so we have to increment year + sib.yearsToBreastHeight(9); + sib.breastHeightAge(15); + sib.ageTotal(24); + }); }); lb.addSpecies(spb -> { spb.genus("H"); spb.percentGenus(30); spb.addSpecies("HW", 100); + spb.addSite(sib -> { + sib.siteSpecies("HW"); + sib.siteCurveNumber(37); + }); }); lb.addSpecies(spb -> { spb.genus("S"); spb.percentGenus(10); spb.addSpecies("S", 100); + spb.addSite(sib -> { + sib.siteSpecies("S"); + sib.siteCurveNumber(71); + }); }); - lb.addSite(sib -> { - sib.siteGenus("B"); - sib.siteSpecies("BL"); - }); - lb.addSite(sib -> { - sib.siteGenus("C"); - sib.siteCurveNumber(11); - sib.siteSpecies("CW"); - }); - lb.addSite(sib -> { - sib.siteGenus("F"); - sib.siteSpecies("FD"); - sib.siteCurveNumber(23); - sib.siteIndex(19.7f); - sib.height(6f); // Set this low so we have to increment year - sib.yearsToBreastHeight(9); - sib.breastHeightAge(15); - sib.ageTotal(24); - }); - lb.addSite(sib -> { - sib.siteGenus("H"); - sib.siteSpecies("HW"); - sib.siteCurveNumber(37); - }); - lb.addSite(sib -> { - sib.siteGenus("S"); - sib.siteSpecies("S"); - sib.siteCurveNumber(71); - }); }); }); @@ -2912,57 +2892,52 @@ controlMap, new ModifierParser(VdypApplicationIdentifier.VRI_START), "mod19813.p spb.genus("B"); spb.percentGenus(10); spb.addSpecies("BL", 100); + spb.addSite(sib -> { + sib.siteSpecies("BL"); + }); }); lb.addSpecies(spb -> { spb.genus("C"); spb.percentGenus(20); spb.addSpecies("CW", 100); + spb.addSite(sib -> { + sib.siteCurveNumber(11); + sib.siteSpecies("CW"); + }); }); lb.addSpecies(spb -> { spb.genus("F"); spb.percentGenus(30); spb.addSpecies("FD", 100); + spb.addSite(sib -> { + sib.siteSpecies("FD"); + sib.siteCurveNumber(23); + sib.siteIndex(19.7f); + sib.height(7.6f); + sib.yearsToBreastHeight(9); + sib.breastHeightAge(15); + sib.ageTotal(24); + }); }); lb.addSpecies(spb -> { spb.genus("H"); spb.percentGenus(30); spb.addSpecies("HW", 100); + spb.addSite(sib -> { + sib.siteSpecies("HW"); + sib.siteCurveNumber(37); + }); }); lb.addSpecies(spb -> { spb.genus("S"); spb.percentGenus(10); spb.addSpecies("S", 100); + spb.addSite(sib -> { + sib.siteSpecies("S"); + sib.siteCurveNumber(71); + }); }); - lb.addSite(sib -> { - sib.siteGenus("B"); - sib.siteSpecies("BL"); - }); - lb.addSite(sib -> { - sib.siteGenus("C"); - sib.siteCurveNumber(11); - sib.siteSpecies("CW"); - }); - lb.addSite(sib -> { - sib.siteGenus("F"); - sib.siteSpecies("FD"); - sib.siteCurveNumber(23); - sib.siteIndex(19.7f); - sib.height(7.6f); - sib.yearsToBreastHeight(9); - sib.breastHeightAge(15); - sib.ageTotal(24); - }); - lb.addSite(sib -> { - sib.siteGenus("H"); - sib.siteSpecies("HW"); - sib.siteCurveNumber(37); - }); - lb.addSite(sib -> { - sib.siteGenus("S"); - sib.siteSpecies("S"); - sib.siteCurveNumber(71); - }); }); }); @@ -3112,57 +3087,52 @@ controlMap, new ModifierParser(VdypApplicationIdentifier.VRI_START), "mod19813.p spb.genus("B"); spb.percentGenus(10); spb.addSpecies("BL", 100); + spb.addSite(sib -> { + sib.siteSpecies("BL"); + }); }); lb.addSpecies(spb -> { spb.genus("C"); spb.percentGenus(20); spb.addSpecies("CW", 100); + spb.addSite(sib -> { + sib.siteCurveNumber(11); + sib.siteSpecies("CW"); + }); }); lb.addSpecies(spb -> { spb.genus("F"); spb.percentGenus(30); spb.addSpecies("FD", 100); + spb.addSite(sib -> { + sib.siteSpecies("FD"); + sib.siteCurveNumber(23); + sib.siteIndex(19.7f); + sib.height(7.6f); + sib.yearsToBreastHeight(9); + sib.breastHeightAge(15); + sib.ageTotal(24); + }); }); lb.addSpecies(spb -> { spb.genus("H"); spb.percentGenus(30); spb.addSpecies("HW", 100); + spb.addSite(sib -> { + sib.siteSpecies("HW"); + sib.siteCurveNumber(37); + }); }); lb.addSpecies(spb -> { spb.genus("S"); spb.percentGenus(10); spb.addSpecies("S", 100); + spb.addSite(sib -> { + sib.siteSpecies("S"); + sib.siteCurveNumber(71); + }); }); - lb.addSite(sib -> { - sib.siteGenus("B"); - sib.siteSpecies("BL"); - }); - lb.addSite(sib -> { - sib.siteGenus("C"); - sib.siteCurveNumber(11); - sib.siteSpecies("CW"); - }); - lb.addSite(sib -> { - sib.siteGenus("F"); - sib.siteSpecies("FD"); - sib.siteCurveNumber(23); - sib.siteIndex(19.7f); - sib.height(7.6f); - sib.yearsToBreastHeight(9); - sib.breastHeightAge(15); - sib.ageTotal(24); - }); - lb.addSite(sib -> { - sib.siteGenus("H"); - sib.siteSpecies("HW"); - sib.siteCurveNumber(37); - }); - lb.addSite(sib -> { - sib.siteGenus("S"); - sib.siteSpecies("S"); - sib.siteCurveNumber(71); - }); }); pb.addLayer(lb -> { lb.layerType(LayerType.VETERAN); @@ -3179,57 +3149,52 @@ controlMap, new ModifierParser(VdypApplicationIdentifier.VRI_START), "mod19813.p spb.genus("B"); spb.percentGenus(10); spb.addSpecies("BL", 100); + spb.addSite(sib -> { + sib.siteSpecies("BL"); + }); }); lb.addSpecies(spb -> { spb.genus("C"); spb.percentGenus(20); spb.addSpecies("CW", 100); + spb.addSite(sib -> { + sib.siteCurveNumber(11); + sib.siteSpecies("CW"); + }); }); lb.addSpecies(spb -> { spb.genus("F"); spb.percentGenus(30); spb.addSpecies("FD", 100); + spb.addSite(sib -> { + sib.siteSpecies("FD"); + sib.siteCurveNumber(23); + sib.siteIndex(19.7f); + sib.height(7.6f); + sib.yearsToBreastHeight(9); + sib.breastHeightAge(15); + sib.ageTotal(24); + }); }); lb.addSpecies(spb -> { spb.genus("H"); spb.percentGenus(30); spb.addSpecies("HW", 100); + spb.addSite(sib -> { + sib.siteSpecies("HW"); + sib.siteCurveNumber(37); + }); }); lb.addSpecies(spb -> { spb.genus("S"); spb.percentGenus(10); spb.addSpecies("S", 100); + spb.addSite(sib -> { + sib.siteSpecies("S"); + sib.siteCurveNumber(71); + }); }); - lb.addSite(sib -> { - sib.siteGenus("B"); - sib.siteSpecies("BL"); - }); - lb.addSite(sib -> { - sib.siteGenus("C"); - sib.siteCurveNumber(11); - sib.siteSpecies("CW"); - }); - lb.addSite(sib -> { - sib.siteGenus("F"); - sib.siteSpecies("FD"); - sib.siteCurveNumber(23); - sib.siteIndex(19.7f); - sib.height(7.6f); - sib.yearsToBreastHeight(9); - sib.breastHeightAge(15); - sib.ageTotal(24); - }); - lb.addSite(sib -> { - sib.siteGenus("H"); - sib.siteSpecies("HW"); - sib.siteCurveNumber(37); - }); - lb.addSite(sib -> { - sib.siteGenus("S"); - sib.siteSpecies("S"); - sib.siteCurveNumber(71); - }); }); }); @@ -3358,57 +3323,52 @@ controlMap, new ModifierParser(VdypApplicationIdentifier.VRI_START), "mod19813.p spb.genus("B"); spb.percentGenus(10); spb.addSpecies("BL", 100); + spb.addSite(sib -> { + sib.siteSpecies("BL"); + }); }); lb.addSpecies(spb -> { spb.genus("C"); spb.percentGenus(20); spb.addSpecies("CW", 100); + spb.addSite(sib -> { + sib.siteCurveNumber(11); + sib.siteSpecies("CW"); + }); }); lb.addSpecies(spb -> { spb.genus("F"); spb.percentGenus(30); spb.addSpecies("FD", 100); + spb.addSite(sib -> { + sib.siteSpecies("FD"); + sib.siteCurveNumber(23); + sib.siteIndex(19.7f); + sib.height(7.6f); + sib.yearsToBreastHeight(9); + sib.breastHeightAge(15); + sib.ageTotal(24); + }); }); lb.addSpecies(spb -> { spb.genus("H"); spb.percentGenus(30); spb.addSpecies("HW", 100); + spb.addSite(sib -> { + sib.siteSpecies("HW"); + sib.siteCurveNumber(37); + }); }); lb.addSpecies(spb -> { spb.genus("S"); spb.percentGenus(10); spb.addSpecies("S", 100); + spb.addSite(sib -> { + sib.siteSpecies("S"); + sib.siteCurveNumber(71); + }); }); - lb.addSite(sib -> { - sib.siteGenus("B"); - sib.siteSpecies("BL"); - }); - lb.addSite(sib -> { - sib.siteGenus("C"); - sib.siteCurveNumber(11); - sib.siteSpecies("CW"); - }); - lb.addSite(sib -> { - sib.siteGenus("F"); - sib.siteSpecies("FD"); - sib.siteCurveNumber(23); - sib.siteIndex(19.7f); - sib.height(7.6f); - sib.yearsToBreastHeight(9); - sib.breastHeightAge(15); - sib.ageTotal(24); - }); - lb.addSite(sib -> { - sib.siteGenus("H"); - sib.siteSpecies("HW"); - sib.siteCurveNumber(37); - }); - lb.addSite(sib -> { - sib.siteGenus("S"); - sib.siteSpecies("S"); - sib.siteCurveNumber(71); - }); }); }); @@ -3562,57 +3522,52 @@ controlMap, new ModifierParser(VdypApplicationIdentifier.VRI_START), "mod19813.p spb.genus("B"); spb.percentGenus(10); spb.addSpecies("BL", 100); + spb.addSite(sib -> { + sib.siteSpecies("BL"); + }); }); lb.addSpecies(spb -> { spb.genus("C"); spb.percentGenus(20); spb.addSpecies("CW", 100); + spb.addSite(sib -> { + sib.siteCurveNumber(11); + sib.siteSpecies("CW"); + }); }); lb.addSpecies(spb -> { spb.genus("F"); spb.percentGenus(30); spb.addSpecies("FD", 100); + spb.addSite(sib -> { + sib.siteSpecies("FD"); + sib.siteCurveNumber(23); + sib.siteIndex(19.7f); + sib.height(7.6f); + sib.yearsToBreastHeight(9); + sib.breastHeightAge(15); + sib.ageTotal(24); + }); }); lb.addSpecies(spb -> { spb.genus("H"); spb.percentGenus(30); spb.addSpecies("HW", 100); + spb.addSite(sib -> { + sib.siteSpecies("HW"); + sib.siteCurveNumber(37); + }); }); lb.addSpecies(spb -> { spb.genus("S"); spb.percentGenus(10); spb.addSpecies("S", 100); + spb.addSite(sib -> { + sib.siteSpecies("S"); + sib.siteCurveNumber(71); + }); }); - lb.addSite(sib -> { - sib.siteGenus("B"); - sib.siteSpecies("BL"); - }); - lb.addSite(sib -> { - sib.siteGenus("C"); - sib.siteCurveNumber(11); - sib.siteSpecies("CW"); - }); - lb.addSite(sib -> { - sib.siteGenus("F"); - sib.siteSpecies("FD"); - sib.siteCurveNumber(23); - sib.siteIndex(19.7f); - sib.height(7.6f); - sib.yearsToBreastHeight(9); - sib.breastHeightAge(15); - sib.ageTotal(24); - }); - lb.addSite(sib -> { - sib.siteGenus("H"); - sib.siteSpecies("HW"); - sib.siteCurveNumber(37); - }); - lb.addSite(sib -> { - sib.siteGenus("S"); - sib.siteSpecies("S"); - sib.siteCurveNumber(71); - }); }); pb.addLayer(lb -> { lb.layerType(LayerType.VETERAN); @@ -3629,57 +3584,52 @@ controlMap, new ModifierParser(VdypApplicationIdentifier.VRI_START), "mod19813.p spb.genus("B"); spb.percentGenus(10); spb.addSpecies("BL", 100); + spb.addSite(sib -> { + sib.siteSpecies("BL"); + }); }); lb.addSpecies(spb -> { spb.genus("C"); spb.percentGenus(20); spb.addSpecies("CW", 100); + spb.addSite(sib -> { + sib.siteCurveNumber(11); + sib.siteSpecies("CW"); + }); }); lb.addSpecies(spb -> { spb.genus("F"); spb.percentGenus(30); spb.addSpecies("FD", 100); + spb.addSite(sib -> { + sib.siteSpecies("FD"); + sib.siteCurveNumber(23); + sib.siteIndex(19.7f); + sib.height(7.6f); + sib.yearsToBreastHeight(9); + sib.breastHeightAge(15); + sib.ageTotal(24); + }); }); lb.addSpecies(spb -> { spb.genus("H"); spb.percentGenus(30); spb.addSpecies("HW", 100); + spb.addSite(sib -> { + sib.siteSpecies("HW"); + sib.siteCurveNumber(37); + }); }); lb.addSpecies(spb -> { spb.genus("S"); spb.percentGenus(10); spb.addSpecies("S", 100); + spb.addSite(sib -> { + sib.siteSpecies("S"); + sib.siteCurveNumber(71); + }); }); - lb.addSite(sib -> { - sib.siteGenus("B"); - sib.siteSpecies("BL"); - }); - lb.addSite(sib -> { - sib.siteGenus("C"); - sib.siteCurveNumber(11); - sib.siteSpecies("CW"); - }); - lb.addSite(sib -> { - sib.siteGenus("F"); - sib.siteSpecies("FD"); - sib.siteCurveNumber(23); - sib.siteIndex(19.7f); - sib.height(7.6f); - sib.yearsToBreastHeight(9); - sib.breastHeightAge(15); - sib.ageTotal(24); - }); - lb.addSite(sib -> { - sib.siteGenus("H"); - sib.siteSpecies("HW"); - sib.siteCurveNumber(37); - }); - lb.addSite(sib -> { - sib.siteGenus("S"); - sib.siteSpecies("S"); - sib.siteCurveNumber(71); - }); }); }); From cda0e37bb8d8af1b235a18ff0fe749277a4a2447 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Fri, 2 Aug 2024 16:31:09 -0700 Subject: [PATCH 07/16] Adapting FIPStart to use sit as child of species --- .../bc/gov/nrs/vdyp/fip/FipLayerParser.java | 6 +- .../java/ca/bc/gov/nrs/vdyp/fip/FipStart.java | 27 +-- .../bc/gov/nrs/vdyp/fip/model/FipLayer.java | 73 ++++++- .../nrs/vdyp/fip/model/FipLayerPrimary.java | 9 +- .../ca/bc/gov/nrs/vdyp/fip/FipStartTest.java | 186 +++++++++--------- 5 files changed, 178 insertions(+), 123 deletions(-) diff --git a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipLayerParser.java b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipLayerParser.java index 221ab27a6..803cf2ddf 100644 --- a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipLayerParser.java +++ b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipLayerParser.java @@ -4,12 +4,14 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.function.Consumer; import java.util.stream.Collectors; import ca.bc.gov.nrs.vdyp.common.ControlKey; import ca.bc.gov.nrs.vdyp.common.ValueOrMarker; import ca.bc.gov.nrs.vdyp.fip.model.FipLayer; import ca.bc.gov.nrs.vdyp.fip.model.FipLayerPrimary; +import ca.bc.gov.nrs.vdyp.fip.model.FipSite; import ca.bc.gov.nrs.vdyp.io.EndOfRecord; import ca.bc.gov.nrs.vdyp.io.FileResolver; import ca.bc.gov.nrs.vdyp.io.parse.common.LineParser; @@ -101,7 +103,7 @@ protected ValueOrMarker, EndOfRecord> convert(Map { flBuilder.polygonIdentifier(polygonId); - flBuilder.addSite(siteBuilder -> { + flBuilder.addSiteWithoutSpecies(siteBuilder -> { siteBuilder.ageTotal(ageTotal); siteBuilder.yearsToBreastHeight(yearsToBreastHeight); siteBuilder.height(height); @@ -121,7 +123,7 @@ protected ValueOrMarker, EndOfRecord> convert(Map { flBuilder.polygonIdentifier(polygonId); flBuilder.layerType(LayerType.VETERAN); - flBuilder.addSite(siteBuilder -> { + flBuilder.addSiteWithoutSpecies(siteBuilder -> { siteBuilder.ageTotal(ageTotal); siteBuilder.yearsToBreastHeight(yearsToBreastHeight); siteBuilder.height(height); diff --git a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java index c57687d75..ffd93af12 100644 --- a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java +++ b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java @@ -282,12 +282,6 @@ VdypLayer processLayerAsPrimary(FipPolygon fipPolygon, FipLayerPrimary fipLayer, builder.adapt(fipLayer); builder.inventoryTypeGroup(itg); builder.empiricalRelationshipParameterIndex(empiricalRelationshipParameterIndex); - fipLayer.getSite().ifPresent(site -> { - builder.addSite(siteBuilder -> { - siteBuilder.adapt(site); - }); - }); - }); // EMP040 @@ -313,7 +307,10 @@ VdypLayer processLayerAsPrimary(FipPolygon fipPolygon, FipLayerPrimary fipLayer, // LVCOM4/SP64DISTL1=FIPSA/VDISTRV // LVCOM1/PCLT1=FIPS/PCTVOLV var vdypSpecies = fipLayer.getSpecies().values().stream() // - .map(VdypSpecies::new) // + .map(fipSpec -> VdypSpecies.build(sb -> { + sb.adapt(fipSpec); + sb.adaptSiteFrom(fipSpec, (ib, fipSite)->{}); + })) // .collect(Collectors.toMap(VdypSpecies::getGenus, Function.identity())); var vdypPrimarySpecies = vdypSpecies.get(primarySpecies.get(0).getGenus()); @@ -621,7 +618,10 @@ VdypLayer processLayerAsVeteran(FipPolygon fipPolygon, FipLayer fipLayer) throws // LVCOM1/HL=FIPL_V/HT_LV var vdypSpecies = fipLayer.getSpecies().values().stream() // .map(fipSpec -> { - var vs = new VdypSpecies(fipSpec); + var vs = VdypSpecies.build(sb -> { + sb.adapt(fipSpec); + sb.adaptSiteFrom(fipSpec, (ib, fipSite)->{}); + }); vs.setLoreyHeightByUtilization(new UtilizationVector(0f, height)); return vs; }) // @@ -663,14 +663,6 @@ VdypLayer processLayerAsVeteran(FipPolygon fipPolygon, FipLayer fipLayer) throws builder.polygonIdentifier(polygonIdentifier); builder.layerType(layer); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(ageTotal); - siteBuilder.yearsToBreastHeight(yearsToBreastHeight); - siteBuilder.height(height); - siteBuilder.siteGenus(fipLayer.getSiteGenus()); - siteBuilder.siteIndex(fipLayer.getSiteIndex()); - }); - builder.addSpecies(vdypSpecies.values()); }); @@ -1167,7 +1159,8 @@ protected BaseControlParser getControlFileParser() { } @Override - protected FipSpecies copySpecies(FipSpecies toCopy, Consumer> config) { + protected FipSpecies + copySpecies(FipSpecies toCopy, Consumer> config) { return FipSpecies.build(builder -> { builder.copy(toCopy); }); diff --git a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/model/FipLayer.java b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/model/FipLayer.java index 93b93eb8e..7d46c9b40 100644 --- a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/model/FipLayer.java +++ b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/model/FipLayer.java @@ -1,6 +1,7 @@ package ca.bc.gov.nrs.vdyp.fip.model; import java.util.Collection; +import java.util.Map; import java.util.Optional; import java.util.function.Consumer; @@ -15,12 +16,15 @@ public class FipLayer extends SingleSiteLayer implements In private float crownClosure; // FIPL_1/CC_L1 or FIP:_V/CC_V1 + private Optional siteWithoutSpecies; + public FipLayer( PolygonIdentifier polygonIdentifier, LayerType layer, Optional inventoryTypeGroup, - float crownClosure + float crownClosure, Optional siteWithoutSpecies ) { super(polygonIdentifier, layer, inventoryTypeGroup); this.crownClosure = crownClosure; + this.siteWithoutSpecies = siteWithoutSpecies; } @Override @@ -51,6 +55,41 @@ public Optional getSiteSpecies() { return getSite().flatMap(FipSite::getSiteSpecies); } + @Override + public Optional getSite() { + return siteWithoutSpecies.or(() -> super.getSite()); + } + + // This is a bit of a hack. The Layer holds on to a site until populated with Species at which point the site is + // attached to the correct Species. + private void applySiteWithoutSpecies() { + siteWithoutSpecies.ifPresent(site -> { + + var spec = this.getSpecies().get(site.getSiteGenus()); + if (spec != null) { + FipSpecies.build(sb -> { + sb.copy(spec); + sb.addSite(siteWithoutSpecies); + }); + siteWithoutSpecies = Optional.empty(); + } + + }); + + } + + @Override + public void setSpecies(Map species) { + super.setSpecies(species); + applySiteWithoutSpecies(); + } + + @Override + public void setSpecies(Collection species) { + super.setSpecies(species); + applySiteWithoutSpecies(); + } + /** * Accepts a configuration function that accepts a builder to configure. * @@ -61,7 +100,7 @@ public Optional getSiteSpecies() { builder.ageTotal(8f); builder.yearsToBreastHeight(7f); builder.height(6f); - + builder.siteIndex(5f); builder.crownClosure(0.9f); builder.siteGenus("B"); @@ -97,6 +136,23 @@ public Builder crownClosure(float crownClosure) { return this; } + protected Optional siteWithoutSpecies; + protected Optional> siteWithoutSpeciesBuilder; + + public Builder addSiteWithoutSpecies(Optional siteWithoutSpecies) { + this.siteWithoutSpecies = siteWithoutSpecies; + return this; + } + + public Builder addSiteWithoutSpecies(FipSite siteWithoutSpecies) { + return this.addSiteWithoutSpecies(Optional.of(siteWithoutSpecies)); + } + + public Builder addSiteWithoutSpecies(Consumer config) { + this.siteWithoutSpeciesBuilder = Optional.empty(); + return this; + } + @Override protected void check(Collection errors) { super.check(errors); @@ -115,7 +171,8 @@ protected FipLayer doBuild() { polygonIdentifier.get(), // layerType.get(), // inventoryTypeGroup, // - crownClosure.get() // + crownClosure.get(), // + siteWithoutSpecies )); } @@ -128,5 +185,15 @@ protected FipSpecies buildSpecies(Consumer config) { }); } + @Override + protected void preProcess() { + super.preProcess(); + siteWithoutSpeciesBuilder.map(config -> FipSite.build(builder -> { + config.accept(builder); + builder.polygonIdentifier(this.polygonIdentifier.get()); + builder.layerType(layerType.get()); + })); + } + } } diff --git a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/model/FipLayerPrimary.java b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/model/FipLayerPrimary.java index d90951e21..efd06e76a 100644 --- a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/model/FipLayerPrimary.java +++ b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/model/FipLayerPrimary.java @@ -15,9 +15,9 @@ public class FipLayerPrimary extends FipLayer { public FipLayerPrimary( PolygonIdentifier polygonIdentifier, Optional inventoryTypeGroup, float crownClosure, - Optional stockingClass, Optional primaryGenus + Optional stockingClass, Optional primaryGenus, Optional siteWithoutSpecies ) { - super(polygonIdentifier, LayerType.PRIMARY, inventoryTypeGroup, crownClosure); + super(polygonIdentifier, LayerType.PRIMARY, inventoryTypeGroup, crownClosure, siteWithoutSpecies); this.stockingClass = stockingClass; this.primaryGenus = primaryGenus; @@ -53,7 +53,7 @@ public Optional getPrimarySpeciesRecord() { builder.ageTotal(8f); builder.yearsToBreastHeight(7f); builder.height(6f); - + @Override builder.siteIndex(5f); builder.crownClosure(0.9f); @@ -116,7 +116,8 @@ protected FipLayerPrimary doBuild() { inventoryTypeGroup, // crownClosure.get(), // stockingClass, // - primaryGenus + primaryGenus, + siteWithoutSpecies ); } diff --git a/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java b/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java index 1cc3a3b44..1fd79d0bf 100644 --- a/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java +++ b/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java @@ -1989,12 +1989,7 @@ void testFindRootsForPrimaryLayerDiameterAndAreaOneSpecies() throws Exception { var layer = VdypLayer.build(builder -> { builder.polygonIdentifier(polygonId); builder.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(285f); - siteBuilder.yearsToBreastHeight(11.3999996f); - siteBuilder.height(24.3999996f); - siteBuilder.siteGenus("Y"); - }); + }); layer.getBaseAreaByUtilization().setCoe(0, 76.5122147f); layer.getTreesPerHectareByUtilization().setCoe(0, 845.805969f); @@ -2006,6 +2001,11 @@ void testFindRootsForPrimaryLayerDiameterAndAreaOneSpecies() throws Exception { builder.volumeGroup(-1); builder.decayGroup(-1); builder.breakageGroup(-1); + builder.addSite(siteBuilder -> { + siteBuilder.ageTotal(285f); + siteBuilder.yearsToBreastHeight(11.3999996f); + siteBuilder.height(24.3999996f); + }); }); spec.setVolumeGroup(74); spec.setDecayGroup(63); @@ -2073,12 +2073,6 @@ void testFindRootsForPrimaryLayerDiameterAndAreaMultipleSpeciesPass1() throws Ex var layer = VdypLayer.build(builder -> { builder.polygonIdentifier(polygonId); builder.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(55f); - siteBuilder.yearsToBreastHeight(1f); - siteBuilder.height(35.2999992f); - siteBuilder.siteGenus("B"); - }); }); layer.getBaseAreaByUtilization().setCoe(0, 44.6249847f); layer.getTreesPerHectareByUtilization().setCoe(0, 620.504883f); @@ -2099,6 +2093,11 @@ void testFindRootsForPrimaryLayerDiameterAndAreaMultipleSpeciesPass1() throws Ex builder.volumeGroup(12); builder.decayGroup(7); builder.breakageGroup(5); + builder.addSite(siteBuilder -> { + siteBuilder.ageTotal(55f); + siteBuilder.yearsToBreastHeight(1f); + siteBuilder.height(35.2999992f); + }); }); spec1.getLoreyHeightByUtilization().setCoe(0, 38.7456512f); var spec2 = VdypSpecies.build(layer, builder -> { @@ -2352,12 +2351,6 @@ void testFindRootsForPrimaryLayerDiameterAndAreaMultipleSpeciesPass1Test2() thro var layer = VdypLayer.build(builder -> { builder.polygonIdentifier(polygonId); builder.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(45f); - siteBuilder.yearsToBreastHeight(5.4000001f); - siteBuilder.height(24.2999992f); - siteBuilder.siteGenus("H"); - }); }); layer.getBaseAreaByUtilization().setCoe(0, 44.9531403f); @@ -2395,6 +2388,11 @@ void testFindRootsForPrimaryLayerDiameterAndAreaMultipleSpeciesPass1Test2() thro builder.volumeGroup(37); builder.decayGroup(54); builder.breakageGroup(28); + builder.addSite(siteBuilder -> { + siteBuilder.ageTotal(45f); + siteBuilder.yearsToBreastHeight(5.4000001f); + siteBuilder.height(24.2999992f); + }); }); spec3.getLoreyHeightByUtilization().setCoe(0, 20.5984688f); var spec4 = VdypSpecies.build(layer, builder -> { @@ -2615,14 +2613,6 @@ void testCreateVdypPolygon() throws ProcessingException { var fipPrimaryLayer = FipLayerPrimary.buildPrimary(fipPolygon, builder -> { builder.crownClosure(60f); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(60f); - siteBuilder.yearsToBreastHeight(8.5f); - siteBuilder.height(15f); - siteBuilder.siteGenus("L"); - siteBuilder.siteSpecies("L"); - siteBuilder.siteIndex(5f); - }); }); @@ -2630,17 +2620,23 @@ void testCreateVdypPolygon() throws ProcessingException { processedLayers.put(LayerType.PRIMARY, VdypLayer.build(builder -> { builder.polygonIdentifier("Test", 2024); builder.layerType(LayerType.PRIMARY); + /* + * builder.addSite(siteBuilder -> { siteBuilder.ageTotal(60f); siteBuilder.yearsToBreastHeight(8.5f); + * siteBuilder.height(15f); siteBuilder.siteGenus("H"); }); + */ + })); + + FipSpecies.build(fipPrimaryLayer, builder -> { + builder.genus("L"); + builder.percentGenus(10f); builder.addSite(siteBuilder -> { siteBuilder.ageTotal(60f); siteBuilder.yearsToBreastHeight(8.5f); siteBuilder.height(15f); - siteBuilder.siteGenus("H"); + siteBuilder.siteSpecies("L"); + siteBuilder.siteIndex(5f); }); - })); - FipSpecies.build(fipPrimaryLayer, builder -> { - builder.genus("L"); - builder.percentGenus(10f); }); FipSpecies.build(fipPrimaryLayer, builder -> { builder.genus("PL"); @@ -2664,56 +2660,52 @@ void testCreateVdypPolygonPercentForestLandGiven() throws ProcessingException { try (var app = new FipStart()) { ApplicationTestUtils.setControlMap(app, controlMap); - var fipPolygon = FipPolygon.build(builder -> { - builder.polygonIdentifier("Test", 2024); - builder.forestInventoryZone("D"); - builder.biogeoclimaticZone("IDF"); - builder.mode(PolygonMode.START); - builder.yieldFactor(1f); + var fipPolygon = FipPolygon.build(pb -> { + pb.polygonIdentifier("Test", 2024); + pb.forestInventoryZone("D"); + pb.biogeoclimaticZone("IDF"); + pb.mode(PolygonMode.START); + pb.yieldFactor(1f); - builder.percentAvailable(42f); + pb.percentAvailable(42f); }); // var fipVeteranLayer = new FipLayer("Test", LayerType.VETERAN); - var fipPrimaryLayer = FipLayerPrimary.buildPrimary(fipPolygon, builder -> { - builder.crownClosure(60f); + var fipPrimaryLayer = FipLayerPrimary.buildPrimary(fipPolygon, lb -> { + lb.crownClosure(60f); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(60f); - siteBuilder.yearsToBreastHeight(8.5f); - siteBuilder.height(15f); + lb.addSpecies(sb -> { + sb.genus("L"); + sb.percentGenus(10f); - siteBuilder.siteIndex(5f); - siteBuilder.siteGenus("L"); - siteBuilder.siteSpecies("L"); + sb.addSite(siteBuilder -> { + siteBuilder.ageTotal(60f); + siteBuilder.yearsToBreastHeight(8.5f); + siteBuilder.height(15f); + + siteBuilder.siteIndex(5f); + siteBuilder.siteSpecies("L"); + }); + + }); + + lb.addSpecies(sb -> { + sb.genus("PL"); + sb.percentGenus(90f); }); + }); var processedLayers = new HashMap(); processedLayers.put(LayerType.PRIMARY, VdypLayer.build(builder -> { builder.polygonIdentifier("Test", 2024); builder.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(60f); - siteBuilder.yearsToBreastHeight(8.5f); - siteBuilder.height(15f); - siteBuilder.siteGenus("L"); - }); + /* + * builder.addSite(siteBuilder -> { siteBuilder.ageTotal(60f); siteBuilder.yearsToBreastHeight(8.5f); + * siteBuilder.height(15f); siteBuilder.siteGenus("L"); }); + */ })); - FipSpecies.build(fipPrimaryLayer, builder -> { - builder.polygonIdentifier("Test", 2024); - builder.layerType(LayerType.PRIMARY); - builder.genus("L"); - builder.percentGenus(10f); - }); - FipSpecies.build(fipPrimaryLayer, builder -> { - builder.polygonIdentifier("Test", 2024); - builder.layerType(LayerType.PRIMARY); - builder.genus("PL"); - builder.percentGenus(90f); - }); - var vdypPolygon = app.createVdypPolygon(fipPolygon, processedLayers); assertThat(vdypPolygon, notNullValue()); @@ -2731,50 +2723,50 @@ void testCreateVdypPolygonFipYoung() throws ProcessingException { try (var app = new FipStart()) { ApplicationTestUtils.setControlMap(app, controlMap); - var fipPolygon = FipPolygon.build(builder -> { - builder.polygonIdentifier("Test", 2024); - builder.forestInventoryZone("D"); - builder.biogeoclimaticZone("IDF"); - builder.mode(PolygonMode.YOUNG); - builder.yieldFactor(1f); + var fipPolygon = FipPolygon.build(pb -> { + pb.polygonIdentifier("Test", 2024); + pb.forestInventoryZone("D"); + pb.biogeoclimaticZone("IDF"); + pb.mode(PolygonMode.YOUNG); + pb.yieldFactor(1f); }); // var fipVeteranLayer = new FipLayer("Test", LayerType.VETERAN); - var fipPrimaryLayer = FipLayerPrimary.buildPrimary(fipPolygon, builder -> { - builder.crownClosure(60f); - - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(60f); - siteBuilder.yearsToBreastHeight(8.5f); - siteBuilder.height(15f); - - siteBuilder.siteIndex(5f); - siteBuilder.siteGenus("L"); - siteBuilder.siteSpecies("L"); + var fipPrimaryLayer = FipLayerPrimary.buildPrimary(fipPolygon, lb -> { + lb.crownClosure(60f); + + lb.addSpecies(sb -> { + sb.genus("L"); + sb.percentGenus(10f); + sb.addSite(ib-> { + ib.ageTotal(60f); + ib.yearsToBreastHeight(8.5f); + ib.height(15f); + + ib.siteIndex(5f); + ib.siteSpecies("L"); + }); + }); + + lb.addSpecies(sb -> { + sb.genus("PL"); + sb.percentGenus(90f); }); + }); var processedLayers = new HashMap(); - processedLayers.put(LayerType.PRIMARY, VdypLayer.build(builder -> { - builder.polygonIdentifier("Test", 2024); - builder.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { + processedLayers.put(LayerType.PRIMARY, VdypLayer.build(lb -> { + lb.polygonIdentifier("Test", 2024); + lb.layerType(LayerType.PRIMARY); + /*lb.addSite(siteBuilder -> { siteBuilder.ageTotal(60f); siteBuilder.yearsToBreastHeight(8.5f); siteBuilder.height(15f); siteBuilder.siteGenus("L"); - }); + });*/ })); - FipSpecies.build(fipPrimaryLayer, builder -> { - builder.genus("L"); - builder.percentGenus(10f); - }); - FipSpecies.build(fipPrimaryLayer, builder -> { - builder.genus("PL"); - builder.percentGenus(90f); - }); - var vdypPolygon = app.createVdypPolygon(fipPolygon, processedLayers); assertThat(vdypPolygon, notNullValue()); From df3636855423d43d16bae197e53ef161fdaf93c5 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Tue, 6 Aug 2024 12:06:17 -0700 Subject: [PATCH 08/16] Fixing FIPStart unit tests --- .../application/VdypStartApplication.java | 25 +- .../java/ca/bc/gov/nrs/vdyp/fip/FipStart.java | 13 +- .../bc/gov/nrs/vdyp/fip/model/FipLayer.java | 25 +- .../nrs/vdyp/fip/model/FipLayerPrimary.java | 5 +- .../ca/bc/gov/nrs/vdyp/fip/FipStartTest.java | 297 +++++++++--------- .../bc/gov/nrs/vdyp/fip/RootFinderTest.java | 18 +- .../java/ca/bc/gov/nrs/vdyp/vri/VriStart.java | 7 +- 7 files changed, 200 insertions(+), 190 deletions(-) diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java index e9372e8dd..e5dc3aca6 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java @@ -896,12 +896,17 @@ protected float estimatePrimaryQuadMeanDiameter( return quadMeanDiameter; } - protected Map - applyGroups(BaseVdypPolygon fipPolygon, Collection vdypSpecies) - throws ProcessingException { - // Lookup volume group, Decay Group, and Breakage group for each species. + protected Map applyGroupsAndGetTargetPercentages( + BaseVdypPolygon fipPolygon, Collection vdypSpecies + ) throws ProcessingException { - Map targetPercentages = new HashMap<>(vdypSpecies.size()); + applyGroups(fipPolygon, vdypSpecies); + return getTargetPercentages(vdypSpecies); + } + + protected void applyGroups(BaseVdypPolygon fipPolygon, Collection vdypSpecies) + throws ProcessingException { + // Lookup volume group, Decay Group, and Breakage group for each species. BecDefinition bec = Utils.getBec(fipPolygon.getBiogeoclimaticZone(), controlMap); var volumeGroupMap = getGroupMap(ControlKey.VOLUME_EQN_GROUPS); @@ -919,6 +924,15 @@ protected float estimatePrimaryQuadMeanDiameter( vSpec.setDecayGroup(decayGroup); vSpec.setBreakageGroup(breakageGroup); + } + + } + + protected Map getTargetPercentages(Collection vdypSpecies) { + Map targetPercentages = new HashMap<>(vdypSpecies.size()); + + for (var vSpec : vdypSpecies) { + targetPercentages.put(vSpec.getGenus(), vSpec.getPercentGenus()); } @@ -945,6 +959,7 @@ protected void applyGroups(BecDefinition bec, String genus, VdypSpecies.Builder } + protected MatrixMap2 getGroupMap(ControlKey key) { return Utils.expectParsedControl(controlMap, key, ca.bc.gov.nrs.vdyp.model.MatrixMap2.class); } diff --git a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java index ffd93af12..116ea4332 100644 --- a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java +++ b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java @@ -309,13 +309,16 @@ VdypLayer processLayerAsPrimary(FipPolygon fipPolygon, FipLayerPrimary fipLayer, var vdypSpecies = fipLayer.getSpecies().values().stream() // .map(fipSpec -> VdypSpecies.build(sb -> { sb.adapt(fipSpec); - sb.adaptSiteFrom(fipSpec, (ib, fipSite)->{}); + applyGroups(bec,fipSpec.getGenus(), sb); + sb.adaptSiteFrom(fipSpec, (ib, fipSite) -> { + }); })) // .collect(Collectors.toMap(VdypSpecies::getGenus, Function.identity())); var vdypPrimarySpecies = vdypSpecies.get(primarySpecies.get(0).getGenus()); - Map targetPercentages = applyGroups(fipPolygon, vdypSpecies.values()); + Map targetPercentages = getTargetPercentages(vdypSpecies.values()); + var maxPass = fipLayer.getSpecies().size() > 1 ? 2 : 1; @@ -620,15 +623,15 @@ VdypLayer processLayerAsVeteran(FipPolygon fipPolygon, FipLayer fipLayer) throws .map(fipSpec -> { var vs = VdypSpecies.build(sb -> { sb.adapt(fipSpec); - sb.adaptSiteFrom(fipSpec, (ib, fipSite)->{}); + applyGroups(bec,fipSpec.getGenus(), sb); + sb.adaptSiteFrom(fipSpec, (ib, fipSite) -> { + }); }); vs.setLoreyHeightByUtilization(new UtilizationVector(0f, height)); return vs; }) // .collect(Collectors.toMap(VdypSpecies::getGenus, Function.identity())); - applyGroups(fipPolygon, vdypSpecies.values()); - /* * From VDYP7 * diff --git a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/model/FipLayer.java b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/model/FipLayer.java index 7d46c9b40..650f877f1 100644 --- a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/model/FipLayer.java +++ b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/model/FipLayer.java @@ -16,7 +16,7 @@ public class FipLayer extends SingleSiteLayer implements In private float crownClosure; // FIPL_1/CC_L1 or FIP:_V/CC_V1 - private Optional siteWithoutSpecies; + private Optional siteWithoutSpecies = Optional.empty(); public FipLayer( PolygonIdentifier polygonIdentifier, LayerType layer, Optional inventoryTypeGroup, @@ -67,10 +67,10 @@ private void applySiteWithoutSpecies() { var spec = this.getSpecies().get(site.getSiteGenus()); if (spec != null) { - FipSpecies.build(sb -> { + this.getSpecies().put(site.getSiteGenus(), FipSpecies.build(sb -> { sb.copy(spec); sb.addSite(siteWithoutSpecies); - }); + })); siteWithoutSpecies = Optional.empty(); } @@ -100,7 +100,7 @@ public void setSpecies(Collection species) { builder.ageTotal(8f); builder.yearsToBreastHeight(7f); builder.height(6f); - + builder.siteIndex(5f); builder.crownClosure(0.9f); builder.siteGenus("B"); @@ -136,8 +136,8 @@ public Builder crownClosure(float crownClosure) { return this; } - protected Optional siteWithoutSpecies; - protected Optional> siteWithoutSpeciesBuilder; + protected Optional siteWithoutSpecies = Optional.empty(); + protected Optional> siteWithoutSpeciesBuilder = Optional.empty(); public Builder addSiteWithoutSpecies(Optional siteWithoutSpecies) { this.siteWithoutSpecies = siteWithoutSpecies; @@ -149,7 +149,7 @@ public Builder addSiteWithoutSpecies(FipSite siteWithoutSpecies) { } public Builder addSiteWithoutSpecies(Consumer config) { - this.siteWithoutSpeciesBuilder = Optional.empty(); + this.siteWithoutSpeciesBuilder = Optional.of(config); return this; } @@ -188,11 +188,12 @@ protected FipSpecies buildSpecies(Consumer config) { @Override protected void preProcess() { super.preProcess(); - siteWithoutSpeciesBuilder.map(config -> FipSite.build(builder -> { - config.accept(builder); - builder.polygonIdentifier(this.polygonIdentifier.get()); - builder.layerType(layerType.get()); - })); + this.siteWithoutSpecies = siteWithoutSpecies + .or(() -> siteWithoutSpeciesBuilder.map(config -> FipSite.build(builder -> { + config.accept(builder); + builder.polygonIdentifier(this.polygonIdentifier.get()); + builder.layerType(layerType.get()); + }))); } } diff --git a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/model/FipLayerPrimary.java b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/model/FipLayerPrimary.java index efd06e76a..e3e04baa0 100644 --- a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/model/FipLayerPrimary.java +++ b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/model/FipLayerPrimary.java @@ -53,7 +53,7 @@ public Optional getPrimarySpeciesRecord() { builder.ageTotal(8f); builder.yearsToBreastHeight(7f); builder.height(6f); - + @Override builder.siteIndex(5f); builder.crownClosure(0.9f); @@ -116,8 +116,7 @@ protected FipLayerPrimary doBuild() { inventoryTypeGroup, // crownClosure.get(), // stockingClass, // - primaryGenus, - siteWithoutSpecies + primaryGenus, siteWithoutSpecies ); } diff --git a/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java b/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java index 1fd79d0bf..f69f92e88 100644 --- a/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java +++ b/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java @@ -1140,7 +1140,7 @@ void testProcessPrimary() throws Exception { assertThat( result, allOf( - hasProperty("loreyHeightByUtilization", coe(-1, 7.14446497f, 31.3307228f)), + hasProperty("loreyHeightByUtilization", VdypMatchers.utilizationHeight(7.14446497f, 31.3307228f)), hasProperty( "baseAreaByUtilization", VdypMatchers.utilization( @@ -1555,7 +1555,7 @@ result, hasProperty( assertThat( speciesResult, allOf( - hasProperty("loreyHeightByUtilization", coe(-1, 7.00809479f, 20.9070625f)), + hasProperty("loreyHeightByUtilization", VdypMatchers.utilizationHeight(7.00809479f, 20.9070625f)), hasProperty( "baseAreaByUtilization", VdypMatchers.utilization( @@ -2738,7 +2738,7 @@ void testCreateVdypPolygonFipYoung() throws ProcessingException { lb.addSpecies(sb -> { sb.genus("L"); sb.percentGenus(10f); - sb.addSite(ib-> { + sb.addSite(ib -> { ib.ageTotal(60f); ib.yearsToBreastHeight(8.5f); ib.height(15f); @@ -2747,7 +2747,7 @@ void testCreateVdypPolygonFipYoung() throws ProcessingException { ib.siteSpecies("L"); }); }); - + lb.addSpecies(sb -> { sb.genus("PL"); sb.percentGenus(90f); @@ -2759,12 +2759,10 @@ void testCreateVdypPolygonFipYoung() throws ProcessingException { processedLayers.put(LayerType.PRIMARY, VdypLayer.build(lb -> { lb.polygonIdentifier("Test", 2024); lb.layerType(LayerType.PRIMARY); - /*lb.addSite(siteBuilder -> { - siteBuilder.ageTotal(60f); - siteBuilder.yearsToBreastHeight(8.5f); - siteBuilder.height(15f); - siteBuilder.siteGenus("L"); - });*/ + /* + * lb.addSite(siteBuilder -> { siteBuilder.ageTotal(60f); siteBuilder.yearsToBreastHeight(8.5f); + * siteBuilder.height(15f); siteBuilder.siteGenus("L"); }); + */ })); var vdypPolygon = app.createVdypPolygon(fipPolygon, processedLayers); @@ -2792,47 +2790,55 @@ void testApplyStockingFactor() throws ProcessingException { ApplicationTestUtils.setControlMap(app, controlMap); // var fipVeteranLayer = new FipLayer("Test", LayerType.VETERAN); - var fipPrimaryLayer = FipLayerPrimary.buildPrimary(builder -> { - builder.polygonIdentifier("Test", 2024); - builder.crownClosure(0.9f); + var fipPrimaryLayer = FipLayerPrimary.buildPrimary(lb -> { + lb.polygonIdentifier("Test", 2024); + lb.crownClosure(0.9f); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(60f); - siteBuilder.yearsToBreastHeight(8.5f); - siteBuilder.height(20f); + lb.addSpecies(sb -> { + sb.genus("L"); + sb.percentGenus(50f); + sb.addSite(ib -> { + ib.ageTotal(60f); + ib.yearsToBreastHeight(8.5f); + ib.height(20f); - siteBuilder.siteIndex(5f); - siteBuilder.siteGenus("L"); - siteBuilder.siteSpecies("L"); + ib.siteIndex(5f); + ib.siteSpecies("L"); + }); + }); + lb.addSpecies(sb -> { + sb.genus("PL"); + sb.percentGenus(50f); }); - builder.stockingClass('R'); + lb.stockingClass('R'); }); - var processedLayers = new HashMap(); - processedLayers.put(LayerType.PRIMARY, VdypLayer.build(builder -> { - builder.polygonIdentifier("Test", 2024); - builder.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(60f); - siteBuilder.yearsToBreastHeight(8.5f); - siteBuilder.height(20f); + var vdypLayer = VdypLayer.build(lb -> { + lb.polygonIdentifier("Test", 2024); + lb.layerType(LayerType.PRIMARY); - siteBuilder.siteIndex(5f); - siteBuilder.siteGenus("L"); - }); - })); + lb.addSpecies(sb -> { + sb.genus("L"); + sb.percentGenus(50f); + sb.volumeGroup(-1); + sb.decayGroup(-1); + sb.breakageGroup(-1); + sb.addSite(ib -> { + ib.ageTotal(60f); + ib.yearsToBreastHeight(8.5f); + ib.height(20f); - var vdypLayer = VdypLayer.build(builder -> { - builder.polygonIdentifier("Test", 2024); - builder.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(60f); - siteBuilder.yearsToBreastHeight(8.5f); - siteBuilder.height(20f); + ib.siteIndex(5f); + }); + }); - siteBuilder.siteIndex(5f); - siteBuilder.siteGenus("L"); + lb.addSpecies(sb -> { + sb.genus("PL"); + sb.percentGenus(50f); + sb.volumeGroup(-1); + sb.decayGroup(-1); + sb.breakageGroup(-1); }); }); @@ -2851,13 +2857,7 @@ void testApplyStockingFactor() throws ProcessingException { Utils.utilizationVector(1f, 1f, 1f, 1f, 1f) ); - var spec1 = VdypSpecies.build(vdypLayer, builder -> { - builder.genus("L"); - builder.percentGenus(50f); - builder.volumeGroup(-1); - builder.decayGroup(-1); - builder.breakageGroup(-1); - }); + var spec1 = vdypLayer.getSpecies().get("L"); spec1.setLoreyHeightByUtilization(Utils.utilizationVector(1f, 1f, 1f, 1f, 1f, 1f)); spec1.setQuadraticMeanDiameterByUtilization(Utils.utilizationVector(1f, 1f, 1f, 1f, 1f, 1f)); @@ -2871,13 +2871,7 @@ void testApplyStockingFactor() throws ProcessingException { Utils.utilizationVector(1f, 1f, 1f, 1f, 1f) ); - var spec2 = VdypSpecies.build(vdypLayer, builder -> { - builder.genus("PL"); - builder.percentGenus(50f); - builder.volumeGroup(-1); - builder.decayGroup(-1); - builder.breakageGroup(-1); - }); + var spec2 = vdypLayer.getSpecies().get("PL"); spec2.setLoreyHeightByUtilization(Utils.utilizationVector(1f, 1f, 1f, 1f, 1f, 1f)); spec2.setQuadraticMeanDiameterByUtilization(Utils.utilizationVector(1f, 1f, 1f, 1f, 1f, 1f)); @@ -2949,49 +2943,56 @@ void testApplyStockingFactorNoFactorForLayer() throws ProcessingException { ApplicationTestUtils.setControlMap(app, controlMap); // var fipVeteranLayer = new FipLayer("Test", LayerType.VETERAN); - var fipPrimaryLayer = FipLayerPrimary.buildPrimary(builder -> { - builder.polygonIdentifier("Test", 2024); - builder.crownClosure(60f); + var fipPrimaryLayer = FipLayerPrimary.buildPrimary(lb -> { + lb.polygonIdentifier("Test", 2024); + lb.crownClosure(60f); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(60f); - siteBuilder.yearsToBreastHeight(8.5f); - siteBuilder.height(15f); + lb.addSpecies(sb -> { + sb.genus("L"); + sb.percentGenus(50f); + sb.addSite(ib -> { + ib.ageTotal(60f); + ib.yearsToBreastHeight(8.5f); + ib.height(20f); - siteBuilder.siteIndex(5f); - siteBuilder.siteGenus("L"); - siteBuilder.siteSpecies("L"); + ib.siteIndex(5f); + ib.siteSpecies("L"); + }); }); - }); - - var processedLayers = new HashMap(); - processedLayers.put(LayerType.PRIMARY, VdypLayer.build(builder -> { - builder.polygonIdentifier("Test", 2024); - builder.layerType(LayerType.PRIMARY); - - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(60f); - siteBuilder.yearsToBreastHeight(8.5f); - siteBuilder.height(20f); - - siteBuilder.siteIndex(5f); - siteBuilder.siteGenus("L"); + lb.addSpecies(sb -> { + sb.genus("PL"); + sb.percentGenus(50f); }); - })); + + }); fipPrimaryLayer.setStockingClass(Optional.empty()); - var vdypLayer = VdypLayer.build(builder -> { - builder.polygonIdentifier("Test", 2024); - builder.layerType(LayerType.PRIMARY); + var vdypLayer = VdypLayer.build(lb -> { + lb.polygonIdentifier("Test", 2024); + lb.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(60f); - siteBuilder.yearsToBreastHeight(8.5f); - siteBuilder.height(20f); + lb.addSpecies(sb -> { + sb.genus("L"); + sb.percentGenus(50f); + sb.volumeGroup(-1); + sb.decayGroup(-1); + sb.breakageGroup(-1); + sb.addSite(ib -> { + ib.ageTotal(60f); + ib.yearsToBreastHeight(8.5f); + ib.height(20f); - siteBuilder.siteIndex(5f); - siteBuilder.siteGenus("L"); + ib.siteIndex(5f); + }); + }); + + lb.addSpecies(sb -> { + sb.genus("PL"); + sb.percentGenus(50f); + sb.volumeGroup(-1); + sb.decayGroup(-1); + sb.breakageGroup(-1); }); }); vdypLayer.setLoreyHeightByUtilization(Utils.utilizationVector(1f, 1f, 1f, 1f, 1f, 1f)); @@ -3009,13 +3010,7 @@ void testApplyStockingFactorNoFactorForLayer() throws ProcessingException { Utils.utilizationVector(1f, 1f, 1f, 1f, 1f) ); - var spec1 = VdypSpecies.build(vdypLayer, builder -> { - builder.genus("L"); - builder.percentGenus(50f); - builder.volumeGroup(-1); - builder.decayGroup(-1); - builder.breakageGroup(-1); - }); + var spec1 = vdypLayer.getSpecies().get("L"); spec1.setLoreyHeightByUtilization(Utils.utilizationVector(1f, 1f, 1f, 1f, 1f, 1f)); spec1.setQuadraticMeanDiameterByUtilization(Utils.utilizationVector(1f, 1f, 1f, 1f, 1f, 1f)); @@ -3029,13 +3024,7 @@ void testApplyStockingFactorNoFactorForLayer() throws ProcessingException { Utils.utilizationVector(1f, 1f, 1f, 1f, 1f) ); - var spec2 = VdypSpecies.build(vdypLayer, builder -> { - builder.genus("PL"); - builder.percentGenus(50f); - builder.volumeGroup(-1); - builder.decayGroup(-1); - builder.breakageGroup(-1); - }); + var spec2 = vdypLayer.getSpecies().get("PL"); spec2.setLoreyHeightByUtilization(Utils.utilizationVector(1f, 1f, 1f, 1f, 1f, 1f)); spec2.setQuadraticMeanDiameterByUtilization(Utils.utilizationVector(1f, 1f, 1f, 1f, 1f, 1f)); @@ -3126,49 +3115,55 @@ void testApplyStockingFactorNoFactorForClass() throws ProcessingException { ApplicationTestUtils.setControlMap(app, controlMap); // var fipVeteranLayer = new FipLayer("Test", LayerType.VETERAN); - var fipPrimaryLayer = FipLayerPrimary.buildPrimary(builder -> { - builder.polygonIdentifier("Test", 2024); - builder.crownClosure(60f); + var fipPrimaryLayer = FipLayerPrimary.buildPrimary(lb -> { + lb.polygonIdentifier("Test", 2024); + lb.crownClosure(60f); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(60f); - siteBuilder.yearsToBreastHeight(8.5f); - siteBuilder.height(15f); + lb.addSpecies(sb -> { + sb.genus("L"); + sb.percentGenus(50f); + sb.addSite(ib -> { + ib.ageTotal(60f); + ib.yearsToBreastHeight(8.5f); + ib.height(20f); - siteBuilder.siteIndex(5f); - siteBuilder.siteGenus("L"); - siteBuilder.siteSpecies("L"); + ib.siteIndex(5f); + ib.siteSpecies("L"); + }); }); - }); - - var processedLayers = new HashMap(); - processedLayers.put(LayerType.PRIMARY, VdypLayer.build(builder -> { - builder.polygonIdentifier("Test", 2024); - builder.layerType(LayerType.PRIMARY); - - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(60f); - siteBuilder.yearsToBreastHeight(3.5f); - siteBuilder.height(20f); - - siteBuilder.siteIndex(5f); - siteBuilder.siteGenus("L"); + lb.addSpecies(sb -> { + sb.genus("PL"); + sb.percentGenus(50f); }); - })); + }); fipPrimaryLayer.setStockingClass(Optional.of('R')); - var vdypLayer = VdypLayer.build(builder -> { - builder.polygonIdentifier("Test", 2024); - builder.layerType(LayerType.PRIMARY); + var vdypLayer = VdypLayer.build(lb -> { + lb.polygonIdentifier("Test", 2024); + lb.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(60f); - siteBuilder.yearsToBreastHeight(3.5f); - siteBuilder.height(20f); + lb.addSpecies(sb -> { + sb.genus("L"); + sb.percentGenus(50f); + sb.volumeGroup(-1); + sb.decayGroup(-1); + sb.breakageGroup(-1); + sb.addSite(ib -> { + ib.ageTotal(60f); + ib.yearsToBreastHeight(8.5f); + ib.height(20f); - siteBuilder.siteIndex(5f); - siteBuilder.siteGenus("L"); + ib.siteIndex(5f); + }); + }); + + lb.addSpecies(sb -> { + sb.genus("PL"); + sb.percentGenus(50f); + sb.volumeGroup(-1); + sb.decayGroup(-1); + sb.breakageGroup(-1); }); }); @@ -3303,17 +3298,21 @@ void testProcessPolygon() throws ProcessingException, IOException { builder.mode(PolygonMode.START); }); - var layer = FipLayerPrimary.buildPrimary(poly, builder -> { - builder.crownClosure(0.9f); + var layer = FipLayerPrimary.buildPrimary(poly, lb -> { + lb.crownClosure(0.9f); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(50f); - siteBuilder.yearsToBreastHeight(2f); - siteBuilder.height(20f); + lb.addSpecies(sb -> { + sb.genus("B"); + sb.percentGenus(100); - siteBuilder.siteIndex(1f); - siteBuilder.siteGenus("B"); - siteBuilder.siteSpecies("B"); + sb.addSite(ib -> { + ib.ageTotal(50f); + ib.yearsToBreastHeight(2f); + ib.height(20f); + + ib.siteIndex(1f); + ib.siteSpecies("B"); + }); }); }); @@ -3445,7 +3444,7 @@ FipLayerPrimary getTestPrimaryLayer( ) { return FipLayerPrimary.buildPrimary(builder -> { builder.polygonIdentifier(polygonId); - builder.addSite(siteBuilder -> { + builder.addSiteWithoutSpecies(siteBuilder -> { siteBuilder.ageTotal(8f); siteBuilder.yearsToBreastHeight(7f); siteBuilder.height(6f); @@ -3467,7 +3466,7 @@ FipLayer getTestVeteranLayer( builder.polygonIdentifier(polygonId); builder.layerType(LayerType.VETERAN); - builder.addSite(siteBuilder -> { + builder.addSiteWithoutSpecies(siteBuilder -> { siteBuilder.ageTotal(8f); siteBuilder.yearsToBreastHeight(7f); siteBuilder.height(6f); diff --git a/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/RootFinderTest.java b/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/RootFinderTest.java index 38635197e..689852b1c 100644 --- a/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/RootFinderTest.java +++ b/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/RootFinderTest.java @@ -113,18 +113,10 @@ VdypLayer mockLayer1(Map control) { builder.polygonIdentifier("Test", 2024); builder.layerType(LayerType.PRIMARY); - builder.addSite(siteBuilder -> { - siteBuilder.ageTotal(50f); - siteBuilder.yearsToBreastHeight(1f); - siteBuilder.height(20f); - - siteBuilder.siteIndex(5f); - siteBuilder.siteGenus("L"); - }); }); var spec3 = VdypSpecies.build(layer, builder -> { - builder.genus(GenusDefinitionParser.getSpeciesByIndex(3, control).getAlias()); + builder.genus(GenusDefinitionParser.getSpeciesByIndex(3, control).getAlias()); // B builder.percentGenus(20f); builder.volumeGroup(-1); builder.decayGroup(-1); @@ -133,7 +125,7 @@ VdypLayer mockLayer1(Map control) { spec3.getLoreyHeightByUtilization().setAll(38.7456512f); var spec4 = VdypSpecies.build(layer, builder -> { - builder.genus(GenusDefinitionParser.getSpeciesByIndex(4, control).getAlias()); + builder.genus(GenusDefinitionParser.getSpeciesByIndex(4, control).getAlias()); // C builder.percentGenus(20f); builder.volumeGroup(-1); builder.decayGroup(-1); @@ -142,7 +134,7 @@ VdypLayer mockLayer1(Map control) { spec4.getLoreyHeightByUtilization().setAll(22.8001652f); var spec5 = VdypSpecies.build(layer, builder -> { - builder.genus(GenusDefinitionParser.getSpeciesByIndex(5, control).getAlias()); + builder.genus(GenusDefinitionParser.getSpeciesByIndex(5, control).getAlias()); // D builder.percentGenus(20f); builder.volumeGroup(-1); builder.decayGroup(-1); @@ -151,7 +143,7 @@ VdypLayer mockLayer1(Map control) { spec5.getLoreyHeightByUtilization().setAll(33.6889763f); var spec8 = VdypSpecies.build(layer, builder -> { - builder.genus(GenusDefinitionParser.getSpeciesByIndex(8, control).getAlias()); + builder.genus(GenusDefinitionParser.getSpeciesByIndex(8, control).getAlias()); // 8 builder.percentGenus(20f); builder.volumeGroup(-1); builder.decayGroup(-1); @@ -160,7 +152,7 @@ VdypLayer mockLayer1(Map control) { spec8.getLoreyHeightByUtilization().setAll(24.3451157f); var spec15 = VdypSpecies.build(layer, builder -> { - builder.genus(GenusDefinitionParser.getSpeciesByIndex(15, control).getAlias()); + builder.genus(GenusDefinitionParser.getSpeciesByIndex(15, control).getAlias()); // S builder.percentGenus(20f); builder.volumeGroup(-1); builder.decayGroup(-1); diff --git a/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java b/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java index 4fa35fdf4..73f8e288c 100644 --- a/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java +++ b/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java @@ -8,6 +8,7 @@ import java.util.EnumSet; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; @@ -167,7 +168,7 @@ VriPolygon getPolygon( log.trace("Getting sites for polygon {}", polygon.getPolygonIdentifier()); Collection sites; try { - sites = siteStream.next(); + sites = new LinkedList<>( siteStream.next()); } catch (NoSuchElementException ex) { throw validationError("Sites file has fewer records than polygon file.", ex); } @@ -453,6 +454,8 @@ void processPrimaryLayer(VriPolygon polygon, VdypLayer.Builder lBuilder) throws lBuilder.adaptSpecies(primaryLayer, (sBuilder, vriSpec) -> { var vriSite = primaryLayer.getSites().get(vriSpec.getGenus()); float factor = primaryLayer.getSpecies().size() == 1 ? 1 : vriSpec.getFractionGenus(); + + applyGroups(bec, vriSpec.getGenus(), sBuilder); if (vriSite == primarySiteIn) { sBuilder.loreyHeight(primaryHeight); @@ -511,8 +514,6 @@ void processPrimaryLayer(VriPolygon polygon, VdypLayer.Builder lBuilder) throws lBuilder.loreyHeight(sumBaseAreaLoreyHeight / primaryBaseArea); - this.applyGroups(polygon, species); - } // ROOTV01 From 6e86c22c736dfa1acc7eac45eed2becdcba091d1 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Wed, 7 Aug 2024 13:28:45 -0700 Subject: [PATCH 09/16] Unit tests for finding primary height --- .../java/ca/bc/gov/nrs/vdyp/fip/FipStart.java | 75 ++--- .../ca/bc/gov/nrs/vdyp/fip/FipStartTest.java | 256 ++++++++++++++++++ 2 files changed, 297 insertions(+), 34 deletions(-) diff --git a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java index c57687d75..9127b0836 100644 --- a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java +++ b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java @@ -324,42 +324,9 @@ VdypLayer processLayerAsPrimary(FipPolygon fipPolygon, FipLayerPrimary fipLayer, result.setSpecies(vdypSpecies); - float primaryHeight; float leadHeight = fipLayer.getHeight().orElse(0f); for (var iPass = 1; iPass <= maxPass; iPass++) { - if (iPass == 2) { - for (var vSpec : vdypSpecies.values()) { - vSpec.setPercentGenus(targetPercentages.get(vSpec.getGenus())); - } - } - // Estimate lorey height for primary species - if (iPass == 1 && vdypSpecies.size() == 1) { - primaryHeight = estimationMethods.primaryHeightFromLeadHeight( - leadHeight, vdypPrimarySpecies.getGenus(), bec.getRegion(), tphTotal - ); - } else if (iPass == 1) { - primaryHeight = estimationMethods - .primaryHeightFromLeadHeightInitial(leadHeight, vdypPrimarySpecies.getGenus(), bec.getRegion()); - } else { - primaryHeight = estimationMethods.primaryHeightFromLeadHeight( - leadHeight, vdypPrimarySpecies.getGenus(), bec.getRegion(), - vdypPrimarySpecies.getTreesPerHectareByUtilization().getAll() - ); - } - vdypPrimarySpecies.getLoreyHeightByUtilization().setAll(primaryHeight); - - // Estimate lorey height for non-primary species - for (var vspec : vdypSpecies.values()) { - if (vspec == vdypPrimarySpecies) - continue; - - // EMP053 - vspec.getLoreyHeightByUtilization().setAll( - estimationMethods.estimateNonPrimaryLoreyHeight( - vspec, vdypPrimarySpecies, bec, leadHeight, primaryHeight - ) - ); - } + findPrimaryHeightPass(bec, tphTotal, vdypSpecies, vdypPrimarySpecies, targetPercentages, leadHeight, iPass); // ROOTF01 findRootsForDiameterAndBaseArea(result, fipLayer, bec, iPass + 1); @@ -373,6 +340,46 @@ VdypLayer processLayerAsPrimary(FipPolygon fipPolygon, FipLayerPrimary fipLayer, return result; } + void findPrimaryHeightPass( + BecDefinition bec, float tphTotal, Map vdypSpecies, VdypSpecies vdypPrimarySpecies, + Map targetPercentages, float leadHeight, int iPass + ) throws ProcessingException { + float primaryHeight; + if (iPass == 2) { + for (var vSpec : vdypSpecies.values()) { + vSpec.setPercentGenus(targetPercentages.get(vSpec.getGenus())); + } + } + // Estimate lorey height for primary species + if (iPass == 1 && vdypSpecies.size() == 1) { + primaryHeight = estimationMethods.primaryHeightFromLeadHeight( + leadHeight, vdypPrimarySpecies.getGenus(), bec.getRegion(), tphTotal + ); + } else if (iPass == 1) { + primaryHeight = estimationMethods + .primaryHeightFromLeadHeightInitial(leadHeight, vdypPrimarySpecies.getGenus(), bec.getRegion()); + } else { + primaryHeight = estimationMethods.primaryHeightFromLeadHeight( + leadHeight, vdypPrimarySpecies.getGenus(), bec.getRegion(), + vdypPrimarySpecies.getTreesPerHectareByUtilization().getAll() + ); + } + vdypPrimarySpecies.getLoreyHeightByUtilization().setAll(primaryHeight); + + // Estimate lorey height for non-primary species + for (var vspec : vdypSpecies.values()) { + if (vspec == vdypPrimarySpecies) + continue; + + // EMP053 + vspec.getLoreyHeightByUtilization().setAll( + estimationMethods.estimateNonPrimaryLoreyHeight( + vspec, vdypPrimarySpecies, bec, leadHeight, primaryHeight + ) + ); + } + } + public static List utilizationArray(VdypLayer layer, Function accessor) { return Stream.concat(Stream.of(layer), layer.getSpecies().values().stream()).map(accessor).toList(); } diff --git a/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java b/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java index 1cc3a3b44..25269048e 100644 --- a/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java +++ b/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java @@ -3,6 +3,7 @@ import static ca.bc.gov.nrs.vdyp.test.VdypMatchers.closeTo; import static ca.bc.gov.nrs.vdyp.test.VdypMatchers.coe; import static ca.bc.gov.nrs.vdyp.test.VdypMatchers.present; +import static ca.bc.gov.nrs.vdyp.test.VdypMatchers.utilizationHeight; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.aMapWithSize; import static org.hamcrest.Matchers.allOf; @@ -37,6 +38,9 @@ import org.easymock.IMocksControl; import org.hamcrest.Matcher; import org.hamcrest.Matchers; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import ca.bc.gov.nrs.vdyp.application.ApplicationTestUtils; @@ -58,6 +62,7 @@ import ca.bc.gov.nrs.vdyp.io.parse.control.BaseControlParser; import ca.bc.gov.nrs.vdyp.io.parse.streaming.MockStreamingParser; import ca.bc.gov.nrs.vdyp.io.parse.streaming.StreamingParserFactory; +import ca.bc.gov.nrs.vdyp.model.BecDefinition; import ca.bc.gov.nrs.vdyp.model.Coefficients; import ca.bc.gov.nrs.vdyp.model.PolygonMode; import ca.bc.gov.nrs.vdyp.model.LayerType; @@ -1607,6 +1612,257 @@ result, hasProperty( } } + @Nested + class FindPrimaryHeightPass { + Map controlMap = FipTestUtils.loadControlMap(); + + BecDefinition bec; + + FipStart app; + + @BeforeEach + void setup() throws ProcessingException { + app = new FipStart(); + ApplicationTestUtils.setControlMap(app, controlMap); + bec = Utils.getBec("CWH", controlMap); + } + + @AfterEach + void teardown() throws IOException { + app.close(); + } + + @Test + void testPass1() throws ProcessingException { + var targets = Utils.constMap(map -> { + map.put("H", 9.0f); + map.put("B", 1.0f); + map.put("C", 7.0f); + map.put("S", 9.0f); + map.put("D", 74.0f); + }); + var layer = VdypLayer.build(lb -> { + lb.polygonIdentifier("Test", 2024); + lb.layerType(LayerType.PRIMARY); + + lb.addSpecies(sb -> { + sb.genus("B"); + sb.percentGenus(1); + + sb.volumeGroup(12); + sb.decayGroup(7); + sb.breakageGroup(5); + + sb.addSpecies("B", 100); + }); + lb.addSpecies(sb -> { + sb.genus("C"); + sb.percentGenus(7); + + sb.volumeGroup(20); + sb.decayGroup(14); + sb.breakageGroup(6); + + sb.addSpecies("C", 100); + }); + lb.addSpecies(sb -> { + sb.genus("S"); + sb.percentGenus(9); + + sb.volumeGroup(66); + sb.decayGroup(54); + sb.breakageGroup(28); + + sb.addSpecies("S", 100); + }); + lb.addSpecies(sb -> { + sb.genus("D"); + sb.percentGenus(74); + + sb.volumeGroup(25); + sb.decayGroup(19); + sb.breakageGroup(12); + + sb.addSpecies("D", 100); + }); + lb.addSpecies(sb -> { + sb.genus("H"); + sb.percentGenus(9); + + sb.volumeGroup(37); + sb.decayGroup(31); + sb.breakageGroup(17); + + sb.addSpecies("H", 100); + }); + }); + var species = layer.getSpecies(); + var primary = species.get("D"); + app.findPrimaryHeightPass(bec, 620.50494f, species, primary, targets, 35.3f, 1); + + assertThat( + species, hasEntry( + is("B"), // + hasProperty("loreyHeightByUtilization", utilizationHeight(0, 38.74565f)) + ) + ); + assertThat( + species, hasEntry( + is("C"), // + hasProperty("loreyHeightByUtilization", utilizationHeight(0, 22.800163f)) + ) + ); + assertThat( + species, hasEntry( + is("S"), // + hasProperty("loreyHeightByUtilization", utilizationHeight(0, 34.688877f)) + ) + ); + assertThat( + species, hasEntry( + is("D"), // + hasProperty("loreyHeightByUtilization", utilizationHeight(0, 33.688976f)) + ) + ); + assertThat( + species, hasEntry( + is("H"), // + hasProperty("loreyHeightByUtilization", utilizationHeight(0, 24.345116f)) + ) + ); + } + + @Test + void testPass2() throws ProcessingException { + var targets = Utils.constMap(map -> { + map.put("H", 9.0f); + map.put("B", 1.0f); + map.put("C", 7.0f); + map.put("S", 9.0f); + map.put("D", 74.0f); + }); + var layer = VdypLayer.build(lb -> { + lb.polygonIdentifier("Test", 2024); + lb.layerType(LayerType.PRIMARY); + + lb.addSpecies(sb -> { + sb.genus("B"); + sb.percentGenus(0.8918811f); + + sb.volumeGroup(12); + sb.decayGroup(7); + sb.breakageGroup(5); + + sb.addSpecies("B", 100); + + sb.baseArea(0.3980018f); + sb.loreyHeight(38.74565f); + sb.quadMeanDiameter(31.716667f); + sb.treesPerHectare(5.037558f); + // sb.wholeStemVolume(6.3858347f); + }); + lb.addSpecies(sb -> { + sb.genus("C"); + sb.percentGenus(11.449178f); + + sb.volumeGroup(20); + sb.decayGroup(14); + sb.breakageGroup(6); + + sb.addSpecies("C", 100); + + sb.baseArea(5.1091933f); + sb.loreyHeight(22.800163f); + sb.quadMeanDiameter(26.453901f); + sb.treesPerHectare(92.95719f); + // sb.wholeStemVolume(44.700314f); + }); + lb.addSpecies(sb -> { + sb.genus("S"); + sb.percentGenus(9.215943f); + + sb.volumeGroup(66); + sb.decayGroup(54); + sb.breakageGroup(28); + + sb.addSpecies("S", 100); + + sb.baseArea(4.1126127f); + sb.loreyHeight(34.688877f); + sb.quadMeanDiameter(34.462196f); + sb.treesPerHectare(44.0902f); + // sb.wholeStemVolume(57.47183f); + }); + lb.addSpecies(sb -> { + sb.genus("D"); + sb.percentGenus(66.05741f); + + sb.volumeGroup(25); + sb.decayGroup(19); + sb.breakageGroup(12); + + sb.addSpecies("D", 100); + + sb.baseArea(29.478107f); + sb.loreyHeight(33.688976f); + sb.quadMeanDiameter(33.973206f); + sb.treesPerHectare(325.1896f); + // sb.wholeStemVolume(472.54596f); + }); + lb.addSpecies(sb -> { + sb.genus("H"); + sb.percentGenus(12.385582f); + + sb.volumeGroup(37); + sb.decayGroup(31); + sb.breakageGroup(17); + + sb.addSpecies("H", 100); + + sb.baseArea(5.5270634f); + sb.loreyHeight(24.345116f); + sb.quadMeanDiameter(21.430225f); + sb.treesPerHectare(153.23257f); + // sb.wholeStemVolume(57.471436f); + }); + }); + var species = layer.getSpecies(); + var primary = species.get("D"); + app.findPrimaryHeightPass(bec, 620.50494f, species, primary, targets, 35.3f, 2); + + assertThat( + species, hasEntry( + is("B"), // + hasProperty("loreyHeightByUtilization", utilizationHeight(0, 38.600403f)) + ) + ); + assertThat( + species, hasEntry( + is("C"), // + hasProperty("loreyHeightByUtilization", utilizationHeight(0, 22.800163f)) + ) + ); + assertThat( + species, hasEntry( + is("S"), // + hasProperty("loreyHeightByUtilization", utilizationHeight(0, 34.688877f)) + ) + ); + assertThat( + species, hasEntry( + is("D"), // + hasProperty("loreyHeightByUtilization", utilizationHeight(0, 33.53749f)) + ) + ); + assertThat( + species, hasEntry( + is("H"), // + hasProperty("loreyHeightByUtilization", utilizationHeight(0, 24.345116f)) + ) + ); + } + } + @Test void testEstimateVeteranLayerBaseArea() throws Exception { From a9fcdf043488dccb277f73f0b9f076ce112c5fb1 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Wed, 7 Aug 2024 14:42:28 -0700 Subject: [PATCH 10/16] Fix incorrect ages --- .../java/ca/bc/gov/nrs/vdyp/fip/FipStart.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java index 42ac7845a..429138d59 100644 --- a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java +++ b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java @@ -284,16 +284,17 @@ VdypLayer processLayerAsPrimary(FipPolygon fipPolygon, FipLayerPrimary fipLayer, builder.empiricalRelationshipParameterIndex(empiricalRelationshipParameterIndex); }); + var breastHeightAge = fipLayer.getSite() + .flatMap(x -> Utils.mapBoth(x.getAgeTotal(), x.getYearsToBreastHeight(), (at, ytbh) -> at - ytbh)) + .orElse(0f); // EMP040 var baseArea = estimatePrimaryBaseArea( - fipLayer, bec, fipPolygon.getYieldFactor(), result.getBreastHeightAge().orElse(0f), baseAreaOverstory + fipLayer, bec, fipPolygon.getYieldFactor(), breastHeightAge, baseAreaOverstory ); // BA_TOT result.getBaseAreaByUtilization().setAll(baseArea); - var quadMeanDiameter = estimatePrimaryQuadMeanDiameter( - fipLayer, bec, result.getBreastHeightAge().orElse(0f), baseAreaOverstory - ); + var quadMeanDiameter = estimatePrimaryQuadMeanDiameter(fipLayer, bec, breastHeightAge, baseAreaOverstory); result.getQuadraticMeanDiameterByUtilization().setAll(quadMeanDiameter); @@ -309,7 +310,7 @@ VdypLayer processLayerAsPrimary(FipPolygon fipPolygon, FipLayerPrimary fipLayer, var vdypSpecies = fipLayer.getSpecies().values().stream() // .map(fipSpec -> VdypSpecies.build(sb -> { sb.adapt(fipSpec); - applyGroups(bec,fipSpec.getGenus(), sb); + applyGroups(bec, fipSpec.getGenus(), sb); sb.adaptSiteFrom(fipSpec, (ib, fipSite) -> { }); })) // @@ -319,7 +320,6 @@ VdypLayer processLayerAsPrimary(FipPolygon fipPolygon, FipLayerPrimary fipLayer, Map targetPercentages = getTargetPercentages(vdypSpecies.values()); - var maxPass = fipLayer.getSpecies().size() > 1 ? 2 : 1; result.setSpecies(vdypSpecies); @@ -352,9 +352,8 @@ void findPrimaryHeightPass( } // Estimate lorey height for primary species if (iPass == 1 && vdypSpecies.size() == 1) { - primaryHeight = estimationMethods.primaryHeightFromLeadHeight( - leadHeight, vdypPrimarySpecies.getGenus(), bec.getRegion(), tphTotal - ); + primaryHeight = estimationMethods + .primaryHeightFromLeadHeight(leadHeight, vdypPrimarySpecies.getGenus(), bec.getRegion(), tphTotal); } else if (iPass == 1) { primaryHeight = estimationMethods .primaryHeightFromLeadHeightInitial(leadHeight, vdypPrimarySpecies.getGenus(), bec.getRegion()); @@ -373,9 +372,8 @@ void findPrimaryHeightPass( // EMP053 vspec.getLoreyHeightByUtilization().setAll( - estimationMethods.estimateNonPrimaryLoreyHeight( - vspec, vdypPrimarySpecies, bec, leadHeight, primaryHeight - ) + estimationMethods + .estimateNonPrimaryLoreyHeight(vspec, vdypPrimarySpecies, bec, leadHeight, primaryHeight) ); } } @@ -601,7 +599,7 @@ VdypLayer processLayerAsVeteran(FipPolygon fipPolygon, FipLayer fipLayer) throws .getGenus(); // ageTotal copy, LVCOM3/AGETOTLV copied from FIPL_V/AGETOT_LV - var ageTotal = fipLayer.getAgeTotal().orElse(0f); + var ageTotal = fipLayer.getAgeTotal(); // yearsToBreastHeight copy, minimum 6.0, LVCOM3/YTBHLV copied from // FIPL_V/YTBH_L @@ -630,8 +628,10 @@ VdypLayer processLayerAsVeteran(FipPolygon fipPolygon, FipLayer fipLayer) throws .map(fipSpec -> { var vs = VdypSpecies.build(sb -> { sb.adapt(fipSpec); - applyGroups(bec,fipSpec.getGenus(), sb); + applyGroups(bec, fipSpec.getGenus(), sb); sb.adaptSiteFrom(fipSpec, (ib, fipSite) -> { + ib.ageTotal(ageTotal); + ib.yearsToBreastHeight(yearsToBreastHeight); }); }); vs.setLoreyHeightByUtilization(new UtilizationVector(0f, height)); From 0ddc8b8ab04b3f0f692157b58c336869842a0a7e Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Wed, 7 Aug 2024 15:05:52 -0700 Subject: [PATCH 11/16] Fix incorrect breast height age breaking base area and diameter --- .../src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java | 8 ++++++-- .../test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java | 7 ++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java index 429138d59..992c402cc 100644 --- a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java +++ b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java @@ -897,9 +897,13 @@ void checkPolygon(FipPolygon polygon) throws ProcessingException { // consider changing it. if (primaryLayer.getAgeTotal().orElse(0f) - primaryLayer.getYearsToBreastHeight().orElse(0f) < 0.5f) { + var ageTotal = primaryLayer.getAgeTotal().map(Object::toString).orElse("N/A (0)"); + var ytbh = primaryLayer.getYearsToBreastHeight().map(Object::toString).orElse("N/A (0)"); throw validationError( - "Polygon %s has %s layer where total age is less than YTBH.", polygon.getPolygonIdentifier(), - LayerType.PRIMARY + "Polygon %s has %s layer where total age (%s) is less than YTBH (%s).", polygon.getPolygonIdentifier(), + LayerType.PRIMARY, + ageTotal, + ytbh ); } diff --git a/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java b/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java index 5e08868b1..b58ce0f94 100644 --- a/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java +++ b/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java @@ -287,7 +287,7 @@ void testPrimaryLayerTotalAgeLessThanYearsToBreastHeight() throws Exception { "message", is( "Polygon " + polygonId + " has " + LayerType.PRIMARY - + " layer where total age is less than YTBH." + + " layer where total age (7.0) is less than YTBH (8.0)." ) ) ); @@ -3574,10 +3574,7 @@ void testProcessPolygon() throws ProcessingException, IOException { }); @SuppressWarnings("unused") - var spec = FipSpecies.build(layer, builder -> { - builder.genus("B"); - builder.percentGenus(100f); - }); + var spec = layer.getSpecies().get("B"); var app = new FipStart(); ApplicationTestUtils.setControlMap(app, controlMap); From 62159bdfd960e4d33a5385dd8e4f1d41d309d5ea Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Thu, 8 Aug 2024 10:56:26 -0700 Subject: [PATCH 12/16] Clean up warnings. --- vdyp-lib/pom.xml | 2 -- .../main/java/ca/bc/gov/nrs/vdyp/fip/FipLayerParser.java | 2 -- .../src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java | 9 ++++----- .../ca/bc/gov/nrs/vdyp/vri/VriInputValidationTest.java | 2 +- 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/vdyp-lib/pom.xml b/vdyp-lib/pom.xml index 0282fd2e2..63566ca19 100644 --- a/vdyp-lib/pom.xml +++ b/vdyp-lib/pom.xml @@ -3,9 +3,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - ca.bc.gov.nrs.vdyp vdyp-lib - 0.0.1-SNAPSHOT pom Variable Density Yield Project - Library diff --git a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipLayerParser.java b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipLayerParser.java index 803cf2ddf..8b8585aab 100644 --- a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipLayerParser.java +++ b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipLayerParser.java @@ -4,14 +4,12 @@ import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.function.Consumer; import java.util.stream.Collectors; import ca.bc.gov.nrs.vdyp.common.ControlKey; import ca.bc.gov.nrs.vdyp.common.ValueOrMarker; import ca.bc.gov.nrs.vdyp.fip.model.FipLayer; import ca.bc.gov.nrs.vdyp.fip.model.FipLayerPrimary; -import ca.bc.gov.nrs.vdyp.fip.model.FipSite; import ca.bc.gov.nrs.vdyp.io.EndOfRecord; import ca.bc.gov.nrs.vdyp.io.FileResolver; import ca.bc.gov.nrs.vdyp.io.parse.common.LineParser; diff --git a/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java b/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java index 73f8e288c..e1064de84 100644 --- a/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java +++ b/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java @@ -453,7 +453,6 @@ void processPrimaryLayer(VriPolygon polygon, VdypLayer.Builder lBuilder) throws lBuilder.adaptSpecies(primaryLayer, (sBuilder, vriSpec) -> { var vriSite = primaryLayer.getSites().get(vriSpec.getGenus()); - float factor = primaryLayer.getSpecies().size() == 1 ? 1 : vriSpec.getFractionGenus(); applyGroups(bec, vriSpec.getGenus(), sBuilder); @@ -818,7 +817,7 @@ float upperBoundsQuadMeanDiameter(int baseAreaGroup) { // EMP106 float estimateBaseAreaYield( float dominantHeight, float breastHeightAge, Optional baseAreaOverstory, boolean fullOccupancy, - Collection species, BecDefinition bec, int baseAreaGroup + Collection> species, BecDefinition bec, int baseAreaGroup ) throws StandProcessingException { var coe = estimateBaseAreaYieldCoefficients(species, bec); @@ -867,7 +866,7 @@ float estimateBaseAreaYield( return bap; } - Coefficients estimateBaseAreaYieldCoefficients(Collection species, BecDefinition bec) { + Coefficients estimateBaseAreaYieldCoefficients(Collection> species, BecDefinition bec) { var coe = sumCoefficientsWeightedBySpeciesAndDecayBec(species, bec, ControlKey.BA_YIELD, 7); // TODO confirm going over 0.5 should drop to 0 as this seems odd. @@ -876,7 +875,7 @@ Coefficients estimateBaseAreaYieldCoefficients(Collection species, BecDefinition bec, ControlKey key, int size + Collection> species, BecDefinition bec, ControlKey key, int size ) { var coeMap = Utils .>expectParsedControl(controlMap, key, MatrixMap2.class); @@ -906,7 +905,7 @@ Coefficients sumCoefficientsWeightedBySpeciesAndDecayBec( */ float estimateQuadMeanDiameterYield( float dominantHeight, float breastHeightAge, Optional veteranBaseArea, - Collection species, BecDefinition bec, int baseAreaGroup + Collection> species, BecDefinition bec, int baseAreaGroup ) throws StandProcessingException { final var coe = sumCoefficientsWeightedBySpeciesAndDecayBec(species, bec, ControlKey.DQ_YIELD, 6); diff --git a/vdyp-lib/vdyp-vri/src/test/java/ca/bc/gov/nrs/vdyp/vri/VriInputValidationTest.java b/vdyp-lib/vdyp-vri/src/test/java/ca/bc/gov/nrs/vdyp/vri/VriInputValidationTest.java index be085b688..9dcaff4e7 100644 --- a/vdyp-lib/vdyp-vri/src/test/java/ca/bc/gov/nrs/vdyp/vri/VriInputValidationTest.java +++ b/vdyp-lib/vdyp-vri/src/test/java/ca/bc/gov/nrs/vdyp/vri/VriInputValidationTest.java @@ -240,7 +240,7 @@ void testFailIfMissingPrimary() throws Exception { app.init(resolver, controlMap); - var poly = VriPolygon.build(pBuilder -> { + VriPolygon.build(pBuilder -> { pBuilder.polygonIdentifier("082F074/0071 2001"); pBuilder.biogeoclimaticZone("IDF"); pBuilder.forestInventoryZone(" "); From d705568eb2a7257faebdba6687f10b85a60d8983 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Thu, 8 Aug 2024 12:30:40 -0700 Subject: [PATCH 13/16] Fix Unit test failure --- .../application/VdypStartApplication.java | 1 - .../java/ca/bc/gov/nrs/vdyp/fip/FipStart.java | 16 ++-- .../ca/bc/gov/nrs/vdyp/fip/FipStartTest.java | 88 ++++++++++++------- .../java/ca/bc/gov/nrs/vdyp/vri/VriStart.java | 7 +- 4 files changed, 70 insertions(+), 42 deletions(-) diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java index e5dc3aca6..b407f2e6e 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java @@ -959,7 +959,6 @@ protected void applyGroups(BecDefinition bec, String genus, VdypSpecies.Builder } - protected MatrixMap2 getGroupMap(ControlKey key) { return Utils.expectParsedControl(controlMap, key, ca.bc.gov.nrs.vdyp.model.MatrixMap2.class); } diff --git a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java index 992c402cc..a5cf929a9 100644 --- a/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java +++ b/vdyp-lib/vdyp-fip/src/main/java/ca/bc/gov/nrs/vdyp/fip/FipStart.java @@ -835,6 +835,8 @@ protected FipPolygon getPolygon( throw validationError("Species file has fewer records than polygon file.", ex); } + var speciesPerLayerMap = new HashMap>(); + // Validate that layers belong to the correct polygon for (var layer : layers.values()) { if (!layer.getPolygonIdentifier().equals(polygon.getPolygonIdentifier())) { @@ -843,7 +845,7 @@ protected FipPolygon getPolygon( layer.getPolygonIdentifier(), polygon.getPolygonIdentifier() ); } - layer.setSpecies(new HashMap<>()); + speciesPerLayerMap.put(layer.getLayerType(), new HashMap<>()); } for (var spec : species) { @@ -861,7 +863,11 @@ protected FipPolygon getPolygon( polygon.getPolygonIdentifier() ); } - layer.getSpecies().put(spec.getGenus(), spec); + speciesPerLayerMap.get(spec.getLayerType()).put(spec.getGenus(), spec); + } + + for (var entry : speciesPerLayerMap.entrySet()) { + layers.get(entry.getKey()).setSpecies(entry.getValue()); } polygon.setLayers(layers); @@ -900,10 +906,8 @@ void checkPolygon(FipPolygon polygon) throws ProcessingException { var ageTotal = primaryLayer.getAgeTotal().map(Object::toString).orElse("N/A (0)"); var ytbh = primaryLayer.getYearsToBreastHeight().map(Object::toString).orElse("N/A (0)"); throw validationError( - "Polygon %s has %s layer where total age (%s) is less than YTBH (%s).", polygon.getPolygonIdentifier(), - LayerType.PRIMARY, - ageTotal, - ytbh + "Polygon %s has %s layer where total age (%s) is less than YTBH (%s).", + polygon.getPolygonIdentifier(), LayerType.PRIMARY, ageTotal, ytbh ); } diff --git a/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java b/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java index b58ce0f94..ba5d99e71 100644 --- a/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java +++ b/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java @@ -10,6 +10,7 @@ import static org.hamcrest.Matchers.anEmptyMap; import static org.hamcrest.Matchers.any; import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.hasProperty; @@ -547,32 +548,51 @@ void testFractionGenusCalculationWithSlightError() throws Exception { var polygonId = polygonId("Test Polygon", 2023); var layer = LayerType.PRIMARY; - final var speciesList = Arrays.asList( - // - getTestSpecies(polygonId, layer, "B", x -> { - x.setPercentGenus(75 + 0.009f); - }), getTestSpecies(polygonId, layer, "C", x -> { - x.setPercentGenus(25f); - }) - ); - testWith( - FipTestUtils.loadControlMap(), Arrays.asList(getTestPolygon(polygonId, TestUtils.valid())), // - Arrays.asList(layerMap(getTestPrimaryLayer(polygonId, TestUtils.valid(), TestUtils.valid()))), // - Arrays.asList(speciesList), // - (app, controlMap) -> { + var polygon = FipPolygon.build(pb -> { + pb.polygonIdentifier("Test Polygon", 2024); + pb.forestInventoryZone("0"); + pb.biogeoclimaticZone("BG"); + pb.mode(PolygonMode.START); + pb.yieldFactor(1.0f); - app.process(); + pb.addLayer(lb -> { + lb.layerType(LayerType.PRIMARY); + lb.crownClosure(0.9f); - // Testing exact floating point equality is intentional - assertThat( - speciesList, contains( - // - allOf(hasProperty("genus", is("B")), hasProperty("fractionGenus", is(0.75002253f))), // - allOf(hasProperty("genus", is("C")), hasProperty("fractionGenus", is(0.2499775f)))// - ) - ); - } - ); + lb.addSpecies(sb -> { + sb.genus("B"); + sb.percentGenus(75f + 0.009f); + sb.addSite(ib -> { + ib.ageTotal(8f); + ib.yearsToBreastHeight(7f); + ib.height(6f); + ib.siteIndex(5f); + ib.siteSpecies("B"); + }); + }); + lb.addSpecies(sb -> { + sb.genus("C"); + sb.percentGenus(25f); + }); + }); + + }); + + var controlMap = FipTestUtils.loadControlMap(); + + try (var app = new FipStart()) { + ApplicationTestUtils.setControlMap(app, controlMap); + + app.checkPolygon(polygon); + var speciesList = polygon.getLayers().get(LayerType.PRIMARY).getSpecies().values(); + assertThat( + speciesList, containsInAnyOrder( + // + allOf(hasProperty("genus", is("B")), hasProperty("fractionGenus", is(0.75002253f))), // + allOf(hasProperty("genus", is("C")), hasProperty("fractionGenus", is(0.2499775f)))// + ) + ); + } } @@ -1145,7 +1165,9 @@ void testProcessPrimary() throws Exception { assertThat( result, allOf( - hasProperty("loreyHeightByUtilization", VdypMatchers.utilizationHeight(7.14446497f, 31.3307228f)), + hasProperty( + "loreyHeightByUtilization", VdypMatchers.utilizationHeight(7.14446497f, 31.3307228f) + ), hasProperty( "baseAreaByUtilization", VdypMatchers.utilization( @@ -1560,7 +1582,9 @@ result, hasProperty( assertThat( speciesResult, allOf( - hasProperty("loreyHeightByUtilization", VdypMatchers.utilizationHeight(7.00809479f, 20.9070625f)), + hasProperty( + "loreyHeightByUtilization", VdypMatchers.utilizationHeight(7.00809479f, 20.9070625f) + ), hasProperty( "baseAreaByUtilization", VdypMatchers.utilization( @@ -1731,7 +1755,7 @@ species, hasEntry( ) ); } - + @Test void testPass2() throws ProcessingException { var targets = Utils.constMap(map -> { @@ -1754,7 +1778,7 @@ void testPass2() throws ProcessingException { sb.breakageGroup(5); sb.addSpecies("B", 100); - + sb.baseArea(0.3980018f); sb.loreyHeight(38.74565f); sb.quadMeanDiameter(31.716667f); @@ -1770,7 +1794,7 @@ void testPass2() throws ProcessingException { sb.breakageGroup(6); sb.addSpecies("C", 100); - + sb.baseArea(5.1091933f); sb.loreyHeight(22.800163f); sb.quadMeanDiameter(26.453901f); @@ -1786,7 +1810,7 @@ void testPass2() throws ProcessingException { sb.breakageGroup(28); sb.addSpecies("S", 100); - + sb.baseArea(4.1126127f); sb.loreyHeight(34.688877f); sb.quadMeanDiameter(34.462196f); @@ -1802,7 +1826,7 @@ void testPass2() throws ProcessingException { sb.breakageGroup(12); sb.addSpecies("D", 100); - + sb.baseArea(29.478107f); sb.loreyHeight(33.688976f); sb.quadMeanDiameter(33.973206f); @@ -1818,7 +1842,7 @@ void testPass2() throws ProcessingException { sb.breakageGroup(17); sb.addSpecies("H", 100); - + sb.baseArea(5.5270634f); sb.loreyHeight(24.345116f); sb.quadMeanDiameter(21.430225f); diff --git a/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java b/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java index e1064de84..06e711217 100644 --- a/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java +++ b/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java @@ -168,7 +168,7 @@ VriPolygon getPolygon( log.trace("Getting sites for polygon {}", polygon.getPolygonIdentifier()); Collection sites; try { - sites = new LinkedList<>( siteStream.next()); + sites = new LinkedList<>(siteStream.next()); } catch (NoSuchElementException ex) { throw validationError("Sites file has fewer records than polygon file.", ex); } @@ -453,7 +453,7 @@ void processPrimaryLayer(VriPolygon polygon, VdypLayer.Builder lBuilder) throws lBuilder.adaptSpecies(primaryLayer, (sBuilder, vriSpec) -> { var vriSite = primaryLayer.getSites().get(vriSpec.getGenus()); - + applyGroups(bec, vriSpec.getGenus(), sBuilder); if (vriSite == primarySiteIn) { @@ -866,7 +866,8 @@ float estimateBaseAreaYield( return bap; } - Coefficients estimateBaseAreaYieldCoefficients(Collection> species, BecDefinition bec) { + Coefficients + estimateBaseAreaYieldCoefficients(Collection> species, BecDefinition bec) { var coe = sumCoefficientsWeightedBySpeciesAndDecayBec(species, bec, ControlKey.BA_YIELD, 7); // TODO confirm going over 0.5 should drop to 0 as this seems odd. From 214b362192b5804666030460e8a2a65f24db7201 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Thu, 8 Aug 2024 14:23:32 -0700 Subject: [PATCH 14/16] Improve unit test coverage --- .../gov/nrs/vdyp/model/VdypSpeciesTest.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/model/VdypSpeciesTest.java b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/model/VdypSpeciesTest.java index b66b18c8d..f6164178f 100644 --- a/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/model/VdypSpeciesTest.java +++ b/vdyp-lib/vdyp-common/src/test/java/ca/bc/gov/nrs/vdyp/model/VdypSpeciesTest.java @@ -1,6 +1,7 @@ package ca.bc.gov.nrs.vdyp.model; import static ca.bc.gov.nrs.vdyp.test.VdypMatchers.isPolyId; +import static ca.bc.gov.nrs.vdyp.test.VdypMatchers.present; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.anEmptyMap; @@ -102,4 +103,44 @@ void buildAddSpeciesPercent() throws Exception { assertThat(result, hasProperty("speciesPercent", hasEntry("B", 100f))); } + @Test + void adaptSite() throws Exception { + var toCopy = VdypSpecies.build(builder -> { + builder.polygonIdentifier("Test", 2024); + builder.layerType(LayerType.PRIMARY); + builder.genus("B"); + builder.percentGenus(50f); + builder.volumeGroup(1); + builder.decayGroup(2); + builder.breakageGroup(3); + builder.addSpecies("B", 100f); + builder.addSite(ib -> { + ib.ageTotal(42); + ib.yearsToBreastHeight(5); + ib.siteCurveNumber(2); + ib.siteIndex(5.5f); + }); + }); + var result = VdypSpecies.build(builder -> { + builder.adapt(toCopy); + + builder.volumeGroup(1); + builder.decayGroup(2); + builder.breakageGroup(3); + + builder.adaptSiteFrom(toCopy, (ib, siteToCopy) -> { + }); + }); + + var siteResult = result.getSite().get(); + + assertThat(siteResult, hasProperty("polygonIdentifier", isPolyId("Test", 2024))); + assertThat(siteResult, hasProperty("layerType", is(LayerType.PRIMARY))); + assertThat(siteResult, hasProperty("siteGenus", is("B"))); + assertThat(siteResult, hasProperty("yearsToBreastHeight", present(is(5f)))); + assertThat(siteResult, hasProperty("ageTotal", present(is(42f)))); + assertThat(siteResult, hasProperty("siteCurveNumber", present(is(2)))); + assertThat(siteResult, hasProperty("siteIndex", present(is(5.5f)))); + } + } From 72a0ec80c607f4f49c973db619aa5250b693aa7c Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Fri, 9 Aug 2024 11:37:35 -0700 Subject: [PATCH 15/16] Sonar Qube Cleanup --- .../java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java | 12 ------------ .../main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java | 10 +++------- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java b/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java index ba5d99e71..00bce0ad9 100644 --- a/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java +++ b/vdyp-lib/vdyp-fip/src/test/java/ca/bc/gov/nrs/vdyp/fip/FipStartTest.java @@ -2900,10 +2900,6 @@ void testCreateVdypPolygon() throws ProcessingException { processedLayers.put(LayerType.PRIMARY, VdypLayer.build(builder -> { builder.polygonIdentifier("Test", 2024); builder.layerType(LayerType.PRIMARY); - /* - * builder.addSite(siteBuilder -> { siteBuilder.ageTotal(60f); siteBuilder.yearsToBreastHeight(8.5f); - * siteBuilder.height(15f); siteBuilder.siteGenus("H"); }); - */ })); FipSpecies.build(fipPrimaryLayer, builder -> { @@ -2980,10 +2976,6 @@ void testCreateVdypPolygonPercentForestLandGiven() throws ProcessingException { processedLayers.put(LayerType.PRIMARY, VdypLayer.build(builder -> { builder.polygonIdentifier("Test", 2024); builder.layerType(LayerType.PRIMARY); - /* - * builder.addSite(siteBuilder -> { siteBuilder.ageTotal(60f); siteBuilder.yearsToBreastHeight(8.5f); - * siteBuilder.height(15f); siteBuilder.siteGenus("L"); }); - */ })); var vdypPolygon = app.createVdypPolygon(fipPolygon, processedLayers); @@ -3039,10 +3031,6 @@ void testCreateVdypPolygonFipYoung() throws ProcessingException { processedLayers.put(LayerType.PRIMARY, VdypLayer.build(lb -> { lb.polygonIdentifier("Test", 2024); lb.layerType(LayerType.PRIMARY); - /* - * lb.addSite(siteBuilder -> { siteBuilder.ageTotal(60f); siteBuilder.yearsToBreastHeight(8.5f); - * siteBuilder.height(15f); siteBuilder.siteGenus("L"); }); - */ })); var vdypPolygon = app.createVdypPolygon(fipPolygon, processedLayers); diff --git a/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java b/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java index 06e711217..3e8ee399d 100644 --- a/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java +++ b/vdyp-lib/vdyp-vri/src/main/java/ca/bc/gov/nrs/vdyp/vri/VriStart.java @@ -460,26 +460,22 @@ void processPrimaryLayer(VriPolygon polygon, VdypLayer.Builder lBuilder) throws sBuilder.loreyHeight(primaryHeight); // Only use the primary site - sBuilder.adaptSite(vriSite, (iBuilder, vriSite2) -> { - iBuilder.height(vriSite2.getHeight().get()); - }); + sBuilder.adaptSite(vriSite, (iBuilder, vriSite2) -> iBuilder.height(vriSite2.getHeight().get())); } else { float loreyHeight = vriSite.getHeight().filter((x) -> getDebugMode(2) == 1).map(height -> { float speciesQuadMeanDiameter = Math.max(7.5f, height / leadHeight * layerQuadMeanDiameter); float speciesDensity = treesPerHectare(primaryBaseArea, speciesQuadMeanDiameter); // EMP050 Method 1 - float speciesLoreyHeight = estimationMethods.primaryHeightFromLeadHeight( + return estimationMethods.primaryHeightFromLeadHeight( vriSite.getHeight().get(), vriSite.getSiteGenus(), bec.getRegion(), speciesDensity ); - return speciesLoreyHeight; }).orElseGet(() -> { try { // EMP053 - float speciesLoreyHeight = estimationMethods.estimateNonPrimaryLoreyHeight( + return estimationMethods.estimateNonPrimaryLoreyHeight( vriSite.getSiteGenus(), primarySiteIn.getSiteGenus(), bec, leadHeight, primaryHeight ); - return speciesLoreyHeight; } catch (ProcessingException e) { throw new RuntimeProcessingException(e); } From ad1337b2d8a6f79682aad357efbb196c842e9a7c Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Tue, 13 Aug 2024 10:45:31 -0700 Subject: [PATCH 16/16] Constrain wildcard generic --- .../ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java index b407f2e6e..fbd564506 100644 --- a/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java +++ b/vdyp-lib/vdyp-common/src/main/java/ca/bc/gov/nrs/vdyp/application/VdypStartApplication.java @@ -633,7 +633,8 @@ protected float estimatePrimaryBaseArea( public S leadGenus(L fipLayer) { return fipLayer.getSpecies().values().stream() - .sorted(Utils.compareUsing(BaseVdypSpecies::getFractionGenus).reversed()).findFirst().orElseThrow(); + .sorted(Utils.compareUsing(BaseVdypSpecies::getFractionGenus).reversed()) + .findFirst().orElseThrow(); } protected L getPrimaryLayer(P poly) throws StandProcessingException {