Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

379
LINES

< > BotCompany Repo | #1033526 // Gazelle V, November Edition

JavaX source code (Dynamic Module) [tags: use-pretranspiled] - run with: Stefan's OS

Uses 1482K of libraries. Click here for Pure Java version (12308L/65K).

1  
!7
2  
3  
need latest onSelectedItem.
4  
5  
!include early #1033506 // Compact Module Include Gazelle V
6  
7  
module GazelleV > DynPrintLogAndEnabled {
8  
  /*switchable int x1;
9  
  switchable int y1;
10  
  switchable int w = screenWidth();
11  
  switchable int h = screenHeight();*/
12  
  switchable double maxFPS = 10;
13  
  switchable int previewWidth = 200;
14  
  switchable double statsEvery = 5;
15  
  switchable volatile bool brokenMethod;
16  
  int lookAtScreen;
17  
  S previewMode;
18  
  int gridRows = 20;
19  
  bool scaleDownPreviewImage;
20  
  int previewPosterization = 256;
21  
  S uiURL = "Home";
22  
  //bool deepCompression;
23  
24  
  PersistableThrowable lastProcessingError;
25  
  transient WithTimestamp<OKOrError<BufferedImage>> lastScreen;
26  
  transient new Average screenShotTime;
27  
  transient new Average iiTime;
28  
  transient Timestamp loopStarted;
29  
  transient Sleeping screenShotCountdown;
30  
  transient long screenShotCountdownTotalSleepTime;
31  
  //transient ImageSurface imageSurface;
32  
  transient IIImageSurface imageSurface;
33  
  transient Throwable currentProcessingError;
34  
  transient JButton popDownButton;
35  
  transient JComponent topControls;
36  
  transient long screenShotsTaken;
37  
  transient double fps;
38  
  transient Compression ongoingCompression, completedCompression;
39  
  transient S longTermCompressionProbability;
40  
  transient S longTermCompressionScore;
41  
  transient JComponent topControls2;
42  
  transient JTabbedPane tabs;
43  
  transient ThreadPool threadPool;
44  
  transient SingleComponentPanel mainArea;
45  
  
46  
  // key:   ui URL
47  
  // value: component maker
48  
  transient Map<S, IF0<JComponent>> uiMap = syncCIMap();
49  
  
50  
  // ping source for everything we do in the background, including
51  
  // analyzing current screen.
52  
  // normally limited to 50% of one core.
53  
  transient PingSource backgroundPingSource;
54  
  
55  
  transient OnOffOscillator onOffOscillator;
56  
57  
  Rect area() {
58  
    ret screenBounds(min(lookAtScreen, screenCount()-1));
59  
  }
60  
61  
  class Compression {
62  
    settable BufferedImage image;
63  
    settable BWIntegralImage ii;
64  
    CompressionSearch_AnyType search;
65  
    int baseLineLength; // length of trivial compression
66  
    GridCodec1 codec;
67  
    double compressionPercentage;
68  
69  
    S score() {
70  
      var submission = search?.bestSubmission();
71  
      Int compressedSize = or(submission.compressedSize(), baseLineLength);
72  
      compressionPercentage = 100-doubleRatio(compressedSize, baseLineLength)*100;
73  
      ret iround(compressionPercentage) + "%";
74  
    }
75  
76  
    IProbabilisticScheduler scheduler() {
77  
      ret search?.scheduler();
78  
    }
79  
80  
    S probability() {
81  
      var scheduler = scheduler();
82  
      if (scheduler == null) ret "-";
83  
      var prob = scheduler.lastExecutedProbability();
84  
      ret formatDouble(prob, 3);
85  
    }
86  
87  
    event compressionDone;
88  
      
89  
    run {
90  
      int lHex = pixelCount(image)*8;
91  
      baseLineLength = calculateLengthOfFunctionCall imageFromHex(lHex+2);
92  
      print(+baseLineLength);
93  
94  
      codec = new GridCodec1(image);
95  
      codec.rows = gridRows;
96  
      search = codec.forward();
97  
      //showImage(codec.renderCellsLinearly());
98  
99  
      repeat 60 {
100  
        stepForNSeconds(1, search);
101  
        //print(stepCount := search.scheduler().stepCount());
102  
        setFields(
103  
          longTermCompressionProbability := probability(),
104  
          longTermCompressionScore := score());
105  
      }
106  
107  
      try {
108  
        compressionDone();
109  
        
110  
        L<IJavaExpr> cellCompressions = codec.strat.codeForElements();
111  
        //showText("Compression", lines(map shorten_str(cellCompressions)));
112  
113  
        /*S code = str(codec.winnerCode());
114  
        S name = "Screenshot " + ymdMinusHMS();
115  
        File f = makeFileNameUnique_beforeExtension(
116  
          javaxDataDir("Compressed Screenshots/" + name + ".javax"));
117  
        saveTextFile(f, code);
118  
        printFileInfo(f);          
119  
        saveGZTextFile(f = replaceExtension(f, ".jgz"), code);
120  
        printFileInfo(f);*/
121  
122  
        /*
123  
        print("Evaling " + nChars(code));
124  
        //LL<Int> lol = cast dm_javaEval(code);
125  
        BufferedImage restored = cast dm_javaEval(code);
126  
        assertImagesIdentical(restored, image);
127  
        print("Image restored!");
128  
129  
        dm_showImage("Restored from " + nChars(code), restored);
130  
        */
131  
      } catch e { printStackTrace(e); }
132  
    }
133  
    
134  
    void drawOverlay(ImageSurface is, Graphics2D g) pcall {
135  
      codec.drawOverlay(is, g);
136  
    }
137  
    
138  
    int gridCols() { ret widthForHeight(ii.getWidth(), ii.getHeight(), gridRows); }
139  
  } // end of Compression
140  
  
141  
  int gridCols(MakesBufferedImage ii) { ret widthForHeight(ii.getWidth(), ii.getHeight(), gridRows); }
142  
  
143  
  start {
144  
    if (threadPool == null) threadPool = maxThreadPool();
145  
    
146  
    backgroundPingSource = new PingSource(threadPool, "Background");
147  
    
148  
    onOffOscillator = new OnOffOscillator(backgroundPingSource);
149  
    ownResource(onOffOscillator);
150  
    onOffOscillator.start();
151  
    
152  
    componentFieldsToKeep = litset("tabs");
153  
    
154  
    dm_registerAs_direct gazelleV();
155  
    dm_watchField enabled(r { if (enabled) dm_reload(); });
156  
157  
    // TODO: react to event sent by OS
158  
    dm_doEvery(1.0, r {
159  
      if (dm_moduleIsPoppedOut()) adjustUIForPoppedOutWindow();
160  
    });
161  
    
162  
    print("Screen bounds: " + allScreenBounds());
163  
    
164  
    initUIMap();
165  
    
166  
    // We are making some UI elements even if the module is hidden
167  
    // because that's easier.
168  
    
169  
    tabs = jtabs(
170  
      "Log", super.visualize(),
171  
      "Local Data", jcenteredlabel("TODO"));
172  
173  
    dm_doEvery(min(statsEvery, 10.0), statsEvery, r { if (enabled) printStats(); });
174  
    
175  
    loopStarted = tsNow();
176  
    shootAndAnalyze();
177  
  }
178  
  
179  
  void shootAndAnalyze {
180  
    backgroundPingSource.do(r shootAndAnalyze_impl);
181  
  }
182  
183  
  void shootAndAnalyze_impl enter {
184  
    if (!enabled) ret;
185  
186  
    var targetTime = tsNow().plus(1.0/maxFPS);
187  
    long time = nanoTime();
188  
189  
    try {
190  
      lastScreen = withTimestamp(okOrError(-> screenshot(area())));
191  
      ++screenShotsTaken;
192  
      setField(fps := doubleRatio(screenShotsTaken, elapsedSeconds(loopStarted)));
193  
      screenShotTime.add(nanosToSeconds(nanoTime()-time));
194  
      time = nanoTime();
195  
      ping();
196  
      if (lastScreen->isOK()) {
197  
        var img = lastScreen!!;
198  
        var ii = BWIntegralImage(img);
199  
        //var ii = BWIntegralImage_luminosity(lastScreen!!);
200  
        iiTime.add(nanosToSeconds(nanoTime()-time));
201  
      
202  
        if (!deepCompression())
203  
          showPreview(ii, null);
204  
        else
205  
          startCompression(ii);
206  
      }
207  
      
208  
      cpuTotal();
209  
      currentProcessingError = null;
210  
    } catch print e {
211  
      setField(lastProcessingError := currentProcessingError = e);
212  
      //sleepSeconds(60); // errors in processing are no good
213  
    }
214  
    
215  
    screenShotCountdown = sleeper().doLater(targetTime, r shootAndAnalyze);
216  
    screenShotCountdownTotalSleepTime += screenShotCountdown.remainingMS();
217  
  }
218  
  
219  
  bool deepCompression() { ret !scaleDownPreviewImage; }
220  
  
221  
  void showPreview(BWIntegralImage ii, Compression completedCompression) {
222  
    IBWIntegralImage ii2 = ii;
223  
    if (scaleDownPreviewImage) {
224  
      ii2 = ScaledIBWIntegralImage(gridCols(ii2), gridRows, ii2);
225  
      ii2 = TruncatedIBWIntegralImage(ii2);
226  
      
227  
      if (previewPosterization < 256)
228  
        imageSurface?.setImage(posterizeIBWImage(previewPosterization, ii2));
229  
      else
230  
        imageSurface?.setImage(ii2);
231  
        
232  
      imageSurface.setOverlay(null);
233  
    } else {
234  
      imageSurface?.setImage(completedCompression.ii, completedCompression.image);
235  
      if (completedCompression != null)
236  
        imageSurface.setOverlay(g -> completedCompression.drawOverlay(imageSurface, g));
237  
    }
238  
  }
239  
240  
  void startCompression(BWIntegralImage ii) {
241  
    if (ongoingCompression == null) {
242  
      ping();
243  
      ongoingCompression = new Compression()
244  
        .image(lastScreen!!)
245  
        .ii(ii);
246  
      ongoingCompression.onCompressionDone(-> {
247  
        completedCompression = ongoingCompression;
248  
        ongoingCompression = null;
249  
        
250  
        showPreview(ii, completedCompression);
251  
      });
252  
      ongoingCompression.run();
253  
    }
254  
  }
255  
256  
  void printStats() { print(stats()); }
257  
258  
  S stats() {
259  
    var screen = lastScreen?!;
260  
    ret formatColonProperties_noNulls(
261  
      "Monitored area", area(),
262  
      "Error", screen?.getError(),
263  
      "Last screenshot taken", lastScreen?.timeStamp(),
264  
      "Average time to take a screenshot", screenShotTime,
265  
      "Average time to make integral image", iiTime,
266  
      "Capacity left in first core", percentRatioStrOneDigit(freeInCore()),
267  
      "Total CPU used", cpuTotal(),
268  
    );
269  
  }
270  
271  
  S cpuTotal() {
272  
    ret setFieldAndReturn(cpuTotal := percentRatioStrOneDigit((1-freeInCore())/numberOfCores()));
273  
  }
274  
275  
  double freeInCore() {
276  
    ret ratio(toSeconds(screenShotCountdownTotalSleepTime),
277  
      elapsedSeconds(loopStarted));
278  
  }
279  
280  
  replace jSection with jCenteredSection.  
281  
  {}
282  
  visualize {
283  
    imageSurface = new IIImageSurface;
284  
    setDoubleBuffered(imageSurface, true);
285  
    imageSurface.setPixelated(true);
286  
    imageSurface.noAlpha = true;
287  
    
288  
    ret northAndCenterWithMargin(
289  
      withMargin(withLabel("Show",
290  
        comboBoxAndButton(
291  
          onSelectedItem(
292  
            bindComboBoxToLiveValue(centerComboBox(autoComboBox(uiURL, cloneKeys(uiMap))), dm_fieldLiveValue uiURL()),
293  
            url -> showUIURL(url)
294  
          ),
295  
          "Go", url -> showUIURL(url)))),
296  
      mainArea = singleComponentPanel(renderUIUrl(uiURL)));
297  
  }
298  
  
299  
  BufferedImage lastScreenImage() { ret getVar(getVar(lastScreen)); }
300  
301  
  void adjustUIForPoppedOutWindow swing {
302  
    if (popDownButton == null) {
303  
      Window window = cast getWindow(dm_vis());
304  
305  
      var popBackInButton = findButton(window, "Pop Back In");
306  
      var parent = getParent(popBackInButton);
307  
      print(+parent);
308  
      
309  
      removeFromParent(parent); // hide controls
310  
      
311  
      popDownButton = jPopDownButton_noText(
312  
        "Pop Back In", r { dm_popInModule(me()) },
313  
        jCheckBoxMenuItem("Always On Top", isAlwaysOnTop(window),
314  
          rEnter dm_toggleAlwaysOnTop),
315  
      );
316  
      addControl(popDownButton);      
317  
    }
318  
  }
319  
  
320  
  public bool useErrorHandling() { false; }
321  
  
322  
  JComponent renderUIUrl aka renderUIURL aka uiGet(S url) {
323  
    var maker = uiMap.get(url);
324  
    var component = callF(maker);
325  
    if (component != null) ret component;
326  
    ret jCenteredLabel("URL not found: " + url);
327  
  }
328  
  
329  
  void showUIURL(S url) enter {
330  
    url = trim(url);
331  
    setComponent(mainArea, renderUIUrl(url));
332  
  }
333  
  
334  
  <A extends JComponent> A uiMapPut(S url, IF0<A> maker) {
335  
    uiMap.put(url, -> maker!);
336  
    ret maker!;
337  
  }
338  
  
339  
  void uiPut(S url, IF0<JComponent> maker) {
340  
    uiMap.put(url, maker);
341  
  }
342  
  
343  
  void initUIMap {
344  
    uiPut("FPS", -> jSection("FPS", dm_calculatedCenteredLabel(() -> iround(fps))));
345  
346  
    uiPut("Screen Selector", -> {    
347  
      var screenSelectors = jRadioButtons(
348  
        countIteratorAsList(screenCount(),
349  
          i -> "Screen " + (i+1)));
350  
      selectRadioButton(screenSelectors, lookAtScreen);
351  
      onRadioButtonChange(screenSelectors, i -> { setField(lookAtScreen := i); });
352  
      ret jline(buttonsInGroup(screenSelectors));
353  
    });
354  
    
355  
    uiPut("Screenshot with controls", -> northAndCenterWithMargin(
356  
      topControls2 = /*jflowCenter*/ jPanel(new WrapLayout, flattenList2(
357  
        dm_checkBox enabled(),
358  
        getChildren(renderUIURL("Screen Selector")),
359  
        dm_spinnerWithLabel gridRows("Rows", 1, 500),
360  
        dm_checkBox("Scale down", "scaleDownPreviewImage"),
361  
        dm_spinnerWithLabel previewPosterization("Posterize", 2, 256)
362  
      )),
363  
      jscroll_center(imageSurface)));
364  
      
365  
    uiPut("Enabled", -> dm_checkBox enabled());
366  
367  
    uiPut("Home", ->
368  
      hsplit(northAndCenterWithMargin(
369  
        topControls = hgrid(
370  
          renderUIUrl("FPS"),
371  
          jSection("Compression", dm_centeredFieldLabel longTermCompressionScore()),
372  
          //jSection("Probability", dm_centeredFieldLabel longTermCompressionProbability()),
373  
          jSection("CPU (" + numberOfCores() + ")", dm_centeredFieldLabel cpuTotal())
374  
        ),
375  
        tabs),
376  
        renderUIUrl("Screenshot with controls")
377  
      ));
378  
  }
379  
} // end of module

Author comment

Began life as a copy of #1033508

download  show line numbers  debug dex  old transpilations   

Travelled to 2 computer(s): bhatertpkbcr, mqqgnosmbjvj

No comments. add comment

Snippet ID: #1033526
Snippet name: Gazelle V, November Edition
Eternal ID of this version: #1033526/70
Text MD5: 7e31572c1a1a6c6d683edf8c477da725
Transpilation MD5: c466d7399a6a381f7245d715acbbc9c7
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-12-25 23:25:12
Source code size: 12322 bytes / 379 lines
Pitched / IR pitched: No / No
Views / Downloads: 195 / 475
Version history: 69 change(s)
Referenced in: [show references]