[101] | 1 | package com.framsticks.test; |
---|
| 2 | |
---|
[103] | 3 | import java.util.Iterator; |
---|
| 4 | import java.util.LinkedList; |
---|
| 5 | import java.util.List; |
---|
| 6 | |
---|
[102] | 7 | import org.apache.logging.log4j.Logger; |
---|
| 8 | import org.apache.logging.log4j.LogManager; |
---|
| 9 | |
---|
[103] | 10 | import com.framsticks.core.ValueChange; |
---|
[101] | 11 | import com.framsticks.experiment.Experiment; |
---|
[102] | 12 | import com.framsticks.experiment.WorkPackageLogic; |
---|
[103] | 13 | import com.framsticks.params.EventListener; |
---|
| 14 | import com.framsticks.params.EventListeners; |
---|
[101] | 15 | import com.framsticks.params.annotations.FramsClassAnnotation; |
---|
[102] | 16 | import com.framsticks.params.annotations.ParamAnnotation; |
---|
[103] | 17 | import com.framsticks.test.prime.ExpParams; |
---|
[102] | 18 | import com.framsticks.test.prime.PrimePackage; |
---|
[103] | 19 | import com.framsticks.util.FramsticksException; |
---|
[102] | 20 | import com.framsticks.util.dispatching.Future; |
---|
[101] | 21 | |
---|
| 22 | @FramsClassAnnotation |
---|
| 23 | public class PrimeExperiment extends Experiment { |
---|
[102] | 24 | private static final Logger log = LogManager.getLogger(PrimeExperiment.class); |
---|
[101] | 25 | |
---|
[102] | 26 | @ParamAnnotation |
---|
| 27 | public final WorkPackageLogic<PrimePackage> workPackageLogic; |
---|
| 28 | |
---|
[103] | 29 | final PrimePackage task = new PrimePackage(); |
---|
| 30 | |
---|
[102] | 31 | protected int step = 100; |
---|
| 32 | |
---|
[103] | 33 | protected int nextWaitNumber = 1; |
---|
| 34 | protected List<PrimePackage> waitingPackages = new LinkedList<>(); |
---|
| 35 | protected List<Integer> primes = new LinkedList<>(); |
---|
| 36 | |
---|
| 37 | protected final EventListeners<ValueChange> primesListeners = new EventListeners<>(); |
---|
| 38 | |
---|
[102] | 39 | /** |
---|
| 40 | * |
---|
| 41 | */ |
---|
| 42 | public PrimeExperiment() { |
---|
| 43 | setExpdef("prime"); |
---|
| 44 | |
---|
[103] | 45 | task.params.from_number = 1; |
---|
| 46 | task.params.to_number = 1000; |
---|
| 47 | task.state.current_number = 1; |
---|
[102] | 48 | |
---|
[103] | 49 | workPackageLogic = new WorkPackageLogic<PrimePackage>(this, PrimePackage.class) { |
---|
| 50 | |
---|
[102] | 51 | @Override |
---|
| 52 | protected void generateNextPackage(Future<PrimePackage> future) { |
---|
| 53 | assert isActive(); |
---|
[103] | 54 | if (task.state.current_number > task.params.to_number) { |
---|
| 55 | log.debug("no more packages in range left"); |
---|
| 56 | future.pass(null); |
---|
| 57 | return; |
---|
| 58 | } |
---|
[102] | 59 | |
---|
[103] | 60 | PrimePackage wp = PrimePackage.compose(task.state.current_number, Math.min(task.params.to_number, task.state.current_number + step - 1)); |
---|
[102] | 61 | |
---|
[103] | 62 | task.state.current_number += step; |
---|
| 63 | |
---|
| 64 | log.debug("generated package: {}", wp.getShortDescription()); |
---|
| 65 | |
---|
[102] | 66 | future.pass(wp); |
---|
| 67 | } |
---|
[103] | 68 | |
---|
| 69 | @Override |
---|
| 70 | protected void returnPackage(PrimePackage result) { |
---|
| 71 | log.debug("returned package: {}", result); |
---|
| 72 | |
---|
| 73 | if (tryAddResult(result)) { |
---|
| 74 | while (tryMergeWaitingPackages()) { |
---|
| 75 | } |
---|
| 76 | } else if (result.params.from_number > nextWaitNumber) { |
---|
| 77 | waitingPackages.add(result); |
---|
| 78 | } |
---|
| 79 | |
---|
| 80 | try { |
---|
| 81 | isComplete(); |
---|
| 82 | } catch (FramsticksException e) { |
---|
| 83 | log.debug("experiment is not done yet: {}", e.getShortMessage(new StringBuilder())); |
---|
| 84 | return; |
---|
| 85 | } |
---|
| 86 | log.info("experiment is done, {} primes found", primes.size()); |
---|
| 87 | log.debug("primes: {}", primes); |
---|
| 88 | } |
---|
[102] | 89 | }; |
---|
| 90 | } |
---|
| 91 | |
---|
[103] | 92 | protected boolean tryAddResult(PrimePackage result) { |
---|
| 93 | if (result.params.from_number > nextWaitNumber) { |
---|
| 94 | return false; |
---|
| 95 | } |
---|
| 96 | if (result.params.from_number < nextWaitNumber) { |
---|
| 97 | throw new FramsticksException().msg("duplicate result").arg("result", result); |
---|
| 98 | } |
---|
| 99 | |
---|
| 100 | primes.addAll(result.state.getResultList()); |
---|
| 101 | nextWaitNumber = result.params.to_number + 1; |
---|
| 102 | |
---|
| 103 | primesListeners.actionForAll(new ValueChange(getDescription())); |
---|
| 104 | |
---|
| 105 | return true; |
---|
[102] | 106 | } |
---|
| 107 | |
---|
[103] | 108 | protected boolean tryMergeWaitingPackages() { |
---|
| 109 | Iterator<PrimePackage> i = waitingPackages.iterator(); |
---|
| 110 | while (i.hasNext()) { |
---|
| 111 | if (tryAddResult(i.next())) { |
---|
| 112 | i.remove(); |
---|
| 113 | return true; |
---|
| 114 | } |
---|
| 115 | } |
---|
| 116 | return false; |
---|
| 117 | } |
---|
| 118 | |
---|
| 119 | protected void isComplete() { |
---|
| 120 | if (nextWaitNumber - 1 != task.params.to_number) { |
---|
| 121 | throw new FramsticksException().msg("not ready yet").arg("done to", nextWaitNumber - 1); |
---|
| 122 | } |
---|
| 123 | } |
---|
| 124 | |
---|
| 125 | /** |
---|
| 126 | * @return the maxNumber |
---|
| 127 | */ |
---|
| 128 | @ParamAnnotation |
---|
| 129 | public int getMaxNumber() { |
---|
| 130 | return task.params.to_number; |
---|
| 131 | } |
---|
| 132 | |
---|
| 133 | /** |
---|
| 134 | * @param maxNumber the maxNumber to set |
---|
| 135 | */ |
---|
| 136 | @ParamAnnotation |
---|
| 137 | public void setMaxNumber(int maxNumber) { |
---|
| 138 | task.params.to_number = maxNumber; |
---|
| 139 | } |
---|
| 140 | |
---|
| 141 | @ParamAnnotation |
---|
| 142 | public String getDescription() { |
---|
| 143 | return primes.size() + " found in range " + new ExpParams(task.params.from_number, nextWaitNumber - 1); |
---|
| 144 | } |
---|
| 145 | |
---|
| 146 | @ParamAnnotation(id = "description_changed") |
---|
| 147 | public void addPrimesListener(EventListener<ValueChange> listener) { |
---|
| 148 | primesListeners.add(listener); |
---|
| 149 | } |
---|
| 150 | |
---|
| 151 | @ParamAnnotation(id = "description_changed") |
---|
| 152 | public void removePrimesListener(EventListener<ValueChange> listener) { |
---|
| 153 | primesListeners.remove(listener); |
---|
| 154 | } |
---|
| 155 | |
---|
[101] | 156 | } |
---|