diff --git a/src/main/java/job4j/Job.java b/src/main/java/job4j/Job.java index 98c705fc..7b4fd3c9 100644 --- a/src/main/java/job4j/Job.java +++ b/src/main/java/job4j/Job.java @@ -266,7 +266,7 @@ void runNow() { private void onOwnProgressChange(double progress) { validateProgress(progress); - if (progress < 0.995 && Math.abs(progress - ownProgress) < 0.005) { + if (progress < 1f - Util.floatError && Math.abs(progress - ownProgress) < 0.005) { // Avoid time consuming computations for // unnoticeable progress deltas return; @@ -282,24 +282,28 @@ private void onSubJobProgressChange(double progress) { } protected void validateProgress(double progress) { - if (progress >= 1.001) { + if (progress > 1f + Util.floatError) { throw new IllegalArgumentException("Progress has to be a value between -INF and 1!"); } } protected void onProgressChange() { double progress = 0; - List progresses = new ArrayList<>(subJobs.size() + 1); + List progresses; - for (Job job : List.copyOf(this.subJobs)) { - progresses.add(job.getProgress()); - } - - if (ownProgress > 0) { + if (ownProgress < 0 - Util.floatError || ownProgress > 0 + Util.floatError) { + // Own progress has been set. This overrides the automatic + // progress calculation dependent on subjob progress. + progresses = List.of(ownProgress); + } else { // Don't use own progress if it's never been set. // This happens if the current job is only used as an // empty shell for hosting subjobs. - progresses.add(ownProgress); + progresses = new ArrayList<>(subJobs.size()); + + for (Job job : List.copyOf(this.subJobs)) { + progresses.add(job.getProgress()); + } } for (double value : progresses) { @@ -307,7 +311,7 @@ protected void onProgressChange() { progress = -1; break; } else { - if (value >= 1.001) { + if (value > 1f + Util.floatError) { throw new IllegalArgumentException("Progress has to be a value between -INF and 1!"); } @@ -316,7 +320,6 @@ protected void onProgressChange() { } this.overallProgress = Math.min(1.0, progress); - List.copyOf(this.progressListeners).forEach(listener -> listener.accept(this.overallProgress)); } diff --git a/src/main/java/job4j/README.md b/src/main/java/job4j/README.md index 4ae2c671..b4d4bc03 100644 --- a/src/main/java/job4j/README.md +++ b/src/main/java/job4j/README.md @@ -91,7 +91,7 @@ A few things to note: - Subjobs are executed synchronously. - Once added, subjobs cannot be removed, only canceled. - Jobs are smart and automatically handle progress correctly. In the example above, when `importantSubJob`'s progress reaches 50%, the overall progress of `job` will be set to 25%. -- When you have subjobs, you usually don't want to pass the parent job's `progressReceiver` any values, as progress is automatically calculated from the subjobs' progress stats anyway. If you _do_ modify the parent jobs' progress, it won't modify the overall progress directly, instead it will be counted like progress from another subjob. +- When you have subjobs, you usually don't want to pass the parent job's `progressReceiver` any values, as progress is automatically calculated from the subjobs' progress stats anyway. If you _do_ modify the parent jobs' progress, that mechanism gets disabled. - The second argument passed to `addSubJob` defines whether or not the parent job should be canceled as well, should the passed subjob be canceled or have an error. This is useful for job groups where all other subjobs depend on the calculated result from the preceding subjob. ### Invisible jobs diff --git a/src/main/java/matcher/Util.java b/src/main/java/matcher/Util.java index c86c42d3..c27fcc7c 100644 --- a/src/main/java/matcher/Util.java +++ b/src/main/java/matcher/Util.java @@ -370,4 +370,6 @@ public static int compareNatural(String a, String b) { } public static final Object asmNodeSync = new Object(); + /** Max accepted float rounding error. */ + public static final float floatError = 1e-5f; } diff --git a/src/main/java/matcher/gui/MatchPaneSrc.java b/src/main/java/matcher/gui/MatchPaneSrc.java index 2a3d36a9..1ca94f8a 100644 --- a/src/main/java/matcher/gui/MatchPaneSrc.java +++ b/src/main/java/matcher/gui/MatchPaneSrc.java @@ -266,12 +266,11 @@ private void setCellStyle(Cell cell, Matchable item) { styleClass = CellStyleClass.HIGH_MATCH_SIMILARITY; } } else { - final float epsilon = 1e-5f; // float rounding error float similarity = item.getSimilarity(); - if (similarity < epsilon) { + if (similarity < Util.floatError) { styleClass = CellStyleClass.LOW_MATCH_SIMILARITY; - } else if (similarity > 1 - epsilon) { + } else if (similarity > 1 - Util.floatError) { styleClass = CellStyleClass.HIGH_MATCH_SIMILARITY; } else { cell.setTextFill(null);