Uses 1482K of libraries. Click here for Pure Java version (10357L/55K).
| 1 | !7 | 
| 2 | |
| 3 | !include early #1033506 // Compact Module Include Gazelle V | 
| 4 | |
| 5 | module GazelleV > DynPrintLogAndEnabled {
 | 
| 6 | /*switchable int x1; | 
| 7 | switchable int y1; | 
| 8 | switchable int w = screenWidth(); | 
| 9 | switchable int h = screenHeight();*/ | 
| 10 | switchable double maxFPS = 10; | 
| 11 | switchable int previewWidth = 200; | 
| 12 | switchable double statsEvery = 5; | 
| 13 | switchable volatile bool brokenMethod; | 
| 14 | int lookAtScreen; | 
| 15 | S previewMode; | 
| 16 | int gridRows = 20; | 
| 17 | |
| 18 | PersistableThrowable lastProcessingError; | 
| 19 | transient WithTimestamp<OKOrError<BufferedImage>> lastScreen; | 
| 20 | transient new Average screenShotTime; | 
| 21 | transient new Average iiTime; | 
| 22 | transient Timestamp loopStarted; | 
| 23 | transient new RestartableCountdown screenShotCountdown; | 
| 24 | //transient ImageSurface imageSurface; | 
| 25 | transient IIImageSurface imageSurface; | 
| 26 | transient Throwable currentProcessingError; | 
| 27 | transient BufferedImage previewImage; | 
| 28 | transient JButton popDownButton; | 
| 29 | transient JComponent topControls; | 
| 30 | transient long screenShotsTaken; | 
| 31 | transient double fps; | 
| 32 | transient Compression ongoingCompression, completedCompression; | 
| 33 | transient S longTermCompressionProbability; | 
| 34 | transient S longTermCompressionScore; | 
| 35 | transient JComponent topControls2; | 
| 36 | |
| 37 |   Rect area() {
 | 
| 38 | ret screenBounds(min(lookAtScreen, screenCount()-1)); | 
| 39 | } | 
| 40 | |
| 41 |   class Compression {
 | 
| 42 | settable BufferedImage image; | 
| 43 | settable BWIntegralImage ii; | 
| 44 | CompressionSearch_AnyType search; | 
| 45 | int baseLineLength; // length of trivial compression | 
| 46 | GridCodec1 codec; | 
| 47 | double compressionPercentage; | 
| 48 | |
| 49 |     S score() {
 | 
| 50 | var submission = search?.bestSubmission(); | 
| 51 | Int compressedSize = or(submission.compressedSize(), baseLineLength); | 
| 52 | compressionPercentage = doubleRatio(compressedSize, baseLineLength)*100; | 
| 53 | ret formatDouble(compressionPercentage, 3) + "%"; | 
| 54 | } | 
| 55 | |
| 56 |     IProbabilisticScheduler scheduler() {
 | 
| 57 | ret search?.scheduler(); | 
| 58 | } | 
| 59 | |
| 60 |     S probability() {
 | 
| 61 | var scheduler = scheduler(); | 
| 62 | if (scheduler == null) ret "-"; | 
| 63 | var prob = scheduler.lastExecutedProbability(); | 
| 64 | ret formatDouble(prob, 3); | 
| 65 | } | 
| 66 | |
| 67 | event compressionDone; | 
| 68 | |
| 69 |     run {
 | 
| 70 | int lHex = pixelCount(image)*8; | 
| 71 | baseLineLength = calculateLengthOfFunctionCall imageFromHex(lHex+2); | 
| 72 | print(+baseLineLength); | 
| 73 | |
| 74 | codec = new GridCodec1(image); | 
| 75 | codec.rows = gridRows; | 
| 76 | search = codec.forward(); | 
| 77 | //showImage(codec.renderCellsLinearly()); | 
| 78 | |
| 79 |       thread "Gazelle Visual" {
 | 
| 80 |         repeat 60 {
 | 
| 81 | stepForNSeconds(1, search); | 
| 82 | //print(stepCount := search.scheduler().stepCount()); | 
| 83 | setFields( | 
| 84 | longTermCompressionProbability := probability(), | 
| 85 | longTermCompressionScore := score()); | 
| 86 | } | 
| 87 | |
| 88 |         try {
 | 
| 89 | compressionDone(); | 
| 90 | |
| 91 | L<IJavaExpr> cellCompressions = codec.strat.codeForElements(); | 
| 92 |           //showText("Compression", lines(map shorten_str(cellCompressions)));
 | 
| 93 | |
| 94 | /*S code = str(codec.winnerCode()); | 
| 95 | S name = "Screenshot " + ymdMinusHMS(); | 
| 96 | File f = makeFileNameUnique_beforeExtension( | 
| 97 |             javaxDataDir("Compressed Screenshots/" + name + ".javax"));
 | 
| 98 | saveTextFile(f, code); | 
| 99 | printFileInfo(f); | 
| 100 | saveGZTextFile(f = replaceExtension(f, ".jgz"), code); | 
| 101 | printFileInfo(f);*/ | 
| 102 | |
| 103 | /* | 
| 104 |           print("Evaling " + nChars(code));
 | 
| 105 | //LL<Int> lol = cast dm_javaEval(code); | 
| 106 | BufferedImage restored = cast dm_javaEval(code); | 
| 107 | assertImagesIdentical(restored, image); | 
| 108 |           print("Image restored!");
 | 
| 109 | |
| 110 |           dm_showImage("Restored from " + nChars(code), restored);
 | 
| 111 | */ | 
| 112 |         } catch e { printStackTrace(e); }
 | 
| 113 | } | 
| 114 | } | 
| 115 | |
| 116 |     void drawOverlay(ImageSurface is, Graphics2D g) pcall {
 | 
| 117 | codec.drawOverlay(is, g); | 
| 118 | } | 
| 119 | } | 
| 120 | |
| 121 |   start-thread {
 | 
| 122 | dm_registerAs_direct gazelleV(); | 
| 123 |     dm_watchField enabled(r { if (enabled) dm_reload(); });
 | 
| 124 | |
| 125 | // TODO: react to event sent by OS | 
| 126 |     dm_doEvery(1.0, r {
 | 
| 127 | if (dm_moduleIsPoppedOut()) adjustUIForPoppedOutWindow(); | 
| 128 | }); | 
| 129 | |
| 130 |     print("Screen bounds: " + allScreenBounds());
 | 
| 131 | |
| 132 |     dm_doEvery(min(statsEvery, 10.0), statsEvery, r { if (enabled) printStats(); });
 | 
| 133 | |
| 134 | loopStarted = tsNow(); | 
| 135 | shoot(); | 
| 136 | } | 
| 137 | |
| 138 |   void shoot enter {
 | 
| 139 | if (!enabled) ret; | 
| 140 | |
| 141 | long targetTime = sysNow()+iround(1000/maxFPS); | 
| 142 | long time = nanoTime(); | 
| 143 | |
| 144 |     try {
 | 
| 145 | lastScreen = withTimestamp(okOrError(-> screenshot(area()))); | 
| 146 | ++screenShotsTaken; | 
| 147 | setField(fps := doubleRatio(screenShotsTaken, elapsedSeconds(loopStarted))); | 
| 148 | screenShotTime.add(nanosToSeconds(nanoTime()-time)); | 
| 149 | time = nanoTime(); | 
| 150 |       if (lastScreen->isOK()) {
 | 
| 151 | var img = lastScreen!!; | 
| 152 | var ii = BWIntegralImage(img); | 
| 153 | //var ii = BWIntegralImage_luminosity(lastScreen!!); | 
| 154 | iiTime.add(nanosToSeconds(nanoTime()-time)); | 
| 155 | |
| 156 | if (eq(previewMode, "showLatestGrabbed")) | 
| 157 | imageSurface?.setImage(ii, img); | 
| 158 | |
| 159 | if (ongoingCompression == null) | 
| 160 | startCompression(ii); | 
| 161 | } | 
| 162 | |
| 163 | cpuTotal(); | 
| 164 | currentProcessingError = null; | 
| 165 |     } catch print e {
 | 
| 166 | setField(lastProcessingError := currentProcessingError = e); | 
| 167 | sleepSeconds(60); // errors in processing are no good | 
| 168 | } | 
| 169 | |
| 170 | screenShotCountdown.setTargetTime(targetTime, r shoot); | 
| 171 | } | 
| 172 | |
| 173 |   void startCompression(BWIntegralImage ii) {  
 | 
| 174 |     if (ongoingCompression == null) {
 | 
| 175 | ongoingCompression = new Compression() | 
| 176 | .image(lastScreen!!) | 
| 177 | .ii(ii); | 
| 178 |       ongoingCompression.onCompressionDone(-> {
 | 
| 179 | completedCompression = ongoingCompression; | 
| 180 | ongoingCompression = null; | 
| 181 | |
| 182 | imageSurface?.setImage(completedCompression.ii, completedCompression.image); | 
| 183 | imageSurface.setOverlay(g -> completedCompression.drawOverlay(imageSurface, g)); | 
| 184 | }); | 
| 185 | ongoingCompression.run(); | 
| 186 | } | 
| 187 | } | 
| 188 | |
| 189 |   void printStats() { print(stats()); }
 | 
| 190 | |
| 191 |   S stats() {
 | 
| 192 | var screen = lastScreen?!; | 
| 193 | ret formatColonProperties_noNulls( | 
| 194 | "Monitored area", area(), | 
| 195 | "Error", screen?.getError(), | 
| 196 | "Last screenshot taken", lastScreen?.timeStamp(), | 
| 197 | "Average time to take a screenshot", screenShotTime, | 
| 198 | "Average time to make integral image", iiTime, | 
| 199 | "Capacity left in first core", percentRatioStrOneDigit(freeInCore()), | 
| 200 | "Total CPU used", cpuTotal(), | 
| 201 | ); | 
| 202 | } | 
| 203 | |
| 204 |   S cpuTotal() {
 | 
| 205 | ret setFieldAndReturn(cpuTotal := percentRatioStrOneDigit((1-freeInCore())/numberOfCores())); | 
| 206 | } | 
| 207 | |
| 208 |   double freeInCore() {
 | 
| 209 | ret ratio(toSeconds(screenShotCountdown.totalSleepTime), | 
| 210 | elapsedSeconds(loopStarted)); | 
| 211 | } | 
| 212 | |
| 213 | replace jSection with jCenteredSection. | 
| 214 |   {}
 | 
| 215 |   visualize {
 | 
| 216 | imageSurface = new IIImageSurface; | 
| 217 | setDoubleBuffered(imageSurface, true); | 
| 218 | imageSurface.noAlpha = true; | 
| 219 | |
| 220 | var screenSelectors = jRadioButtons( | 
| 221 | countIteratorAsList(screenCount(), | 
| 222 | i -> "Screen " + (i+1))); | 
| 223 |     onRadioButtonChange(screenSelectors, i -> { lookAtScreen = i; });
 | 
| 224 | |
| 225 | ret hsplit(northAndCenterWithMargin( | 
| 226 | topControls = hgrid( | 
| 227 |         jSection("FPS", dm_calculatedCenteredLabel(() -> iround(fps))),
 | 
| 228 |         jSection("Compression", dm_centeredFieldLabel longTermCompressionScore()),
 | 
| 229 |         jSection("Probability", dm_centeredFieldLabel longTermCompressionProbability()),
 | 
| 230 |         jSection("CPU (" + numberOfCores() + ")", dm_centeredFieldLabel cpuTotal())
 | 
| 231 | ), | 
| 232 | super.visualize() /* print log */), | 
| 233 | northAndCenterWithMargin( | 
| 234 | topControls2 = jCenteredLine(listPlus(wideningListCast Component(buttonsInGroup(screenSelectors)), | 
| 235 | dm_spinnerWithLabel gridRows(1, 500))), | 
| 236 | jscroll_center(imageSurface))); | 
| 237 | } | 
| 238 | |
| 239 |   BufferedImage lastScreenImage() { ret getVar(getVar(lastScreen)); }
 | 
| 240 | |
| 241 |   void adjustUIForPoppedOutWindow swing {
 | 
| 242 |     if (popDownButton == null) {
 | 
| 243 | Window window = cast getWindow(dm_vis()); | 
| 244 | |
| 245 | var popBackInButton = findButton(window, "Pop Back In"); | 
| 246 | var parent = getParent(popBackInButton); | 
| 247 | print(+parent); | 
| 248 | |
| 249 | removeFromParent(parent); // hide controls | 
| 250 | |
| 251 | popDownButton = jPopDownButton_noText( | 
| 252 |         "Pop Back In", r { dm_popInModule(me()) },
 | 
| 253 |         jCheckBoxMenuItem("Always On Top", isAlwaysOnTop(window),
 | 
| 254 | rEnter dm_toggleAlwaysOnTop), | 
| 255 | ); | 
| 256 | addControl(popDownButton); | 
| 257 | } | 
| 258 | } | 
| 259 | } | 
Began life as a copy of #1033309
download show line numbers debug dex old transpilations
Travelled to 2 computer(s): bhatertpkbcr, mqqgnosmbjvj
No comments. add comment
| Snippet ID: | #1033508 | 
| Snippet name: | Gazelle V, New UI [compacted, HEAD] | 
| Eternal ID of this version: | #1033508/30 | 
| Text MD5: | bd7d10c8bdc89e397aa60b3f87a1db17 | 
| Transpilation MD5: | 004f911c2f86b1d408ea8fce1769d700 | 
| Author: | stefan | 
| Category: | javax / screen recognition | 
| Type: | JavaX source code (Dynamic Module) | 
| Public (visible to everyone): | Yes | 
| Archived (hidden from active list): | No | 
| Created/modified: | 2021-10-30 18:45:21 | 
| Source code size: | 8561 bytes / 259 lines | 
| Pitched / IR pitched: | No / No | 
| Views / Downloads: | 402 / 600 | 
| Version history: | 29 change(s) | 
| Referenced in: | [show references] |