Transpiled version (12467L) is out of date.
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 | bool scaleDownPreviewImage; |
18 | int previewPosterization = 256; |
19 | S uiURL = "Home"; |
20 | //bool deepCompression; |
21 | |
22 | PersistableThrowable lastProcessingError; |
23 | transient WithTimestamp<OKOrError<BufferedImage>> lastScreen; |
24 | transient new Average screenShotTime; |
25 | transient new Average iiTime; |
26 | transient Timestamp loopStarted; |
27 | transient Sleeping screenShotCountdown; |
28 | transient long screenShotCountdownTotalSleepTime; |
29 | //transient ImageSurface imageSurface; |
30 | transient IIImageSurface imageSurface; |
31 | transient Throwable currentProcessingError; |
32 | transient JComponent topControls; |
33 | transient long screenShotsTaken; |
34 | transient double fps; |
35 | transient Compression ongoingCompression, completedCompression; |
36 | transient S longTermCompressionProbability; |
37 | transient S longTermCompressionScore; |
38 | transient JComponent topControls2; |
39 | transient JTabbedPane tabs; |
40 | transient ThreadPool threadPool; |
41 | transient SingleComponentPanel mainArea; |
42 | transient DMPopOutHandler popOutHandler = new { |
43 | void addControl(JComponent c) { GazelleV.this.addControl(c); } |
44 | }; |
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_safe(lookAtScreen); |
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 | |
159 | popOutHandler.start(); |
160 | |
161 | print("Screen bounds: " + allScreenBounds()); |
162 | |
163 | initUIMap(); |
164 | |
165 | // We are making some UI elements even if the module is hidden |
166 | // because that's easier. |
167 | |
168 | tabs = jtabs( |
169 | "Log", super.visualize(), |
170 | "Local Data", jcenteredlabel("TODO")); |
171 | |
172 | dm_doEvery(min(statsEvery, 10.0), statsEvery, r { if (enabled) printStats(); }); |
173 | |
174 | loopStarted = tsNow(); |
175 | shootAndAnalyze(); |
176 | } |
177 | |
178 | void shootAndAnalyze { |
179 | backgroundPingSource.do(r shootAndAnalyze_impl); |
180 | } |
181 | |
182 | void shootAndAnalyze_impl enter { |
183 | if (!enabled) ret; |
184 | |
185 | var targetTime = tsNow().plus(1.0/maxFPS); |
186 | long time = nanoTime(); |
187 | |
188 | try { |
189 | lastScreen = withTimestamp(okOrError(-> screenshot(area()))); |
190 | ++screenShotsTaken; |
191 | setField(fps := doubleRatio(screenShotsTaken, elapsedSeconds(loopStarted))); |
192 | screenShotTime.add(nanosToSeconds(nanoTime()-time)); |
193 | time = nanoTime(); |
194 | ping(); |
195 | if (lastScreen->isOK()) { |
196 | var img = lastScreen!!; |
197 | var ii = BWIntegralImage(img); |
198 | //var ii = BWIntegralImage_luminosity(lastScreen!!); |
199 | iiTime.add(nanosToSeconds(nanoTime()-time)); |
200 | |
201 | if (!deepCompression()) |
202 | showPreview(ii, null); |
203 | else |
204 | startCompression(ii); |
205 | } |
206 | |
207 | cpuTotal(); |
208 | currentProcessingError = null; |
209 | } catch print e { |
210 | setField(lastProcessingError := currentProcessingError = e); |
211 | //sleepSeconds(60); // errors in processing are no good |
212 | } |
213 | |
214 | screenShotCountdown = sleeper().doLater(targetTime, r shootAndAnalyze); |
215 | screenShotCountdownTotalSleepTime += screenShotCountdown.remainingMS(); |
216 | } |
217 | |
218 | bool deepCompression() { ret !scaleDownPreviewImage; } |
219 | |
220 | void showPreview(BWIntegralImage ii, Compression completedCompression) { |
221 | IBWIntegralImage ii2 = ii; |
222 | if (scaleDownPreviewImage) { |
223 | ii2 = ScaledIBWIntegralImage(gridCols(ii2), gridRows, ii2); |
224 | ii2 = TruncatedIBWIntegralImage(ii2); |
225 | |
226 | if (previewPosterization < 256) |
227 | imageSurface?.setImage(posterizeIBWImage(previewPosterization, ii2)); |
228 | else |
229 | imageSurface?.setImage(ii2); |
230 | |
231 | imageSurface.setOverlay(null); |
232 | } else { |
233 | imageSurface?.setImage(completedCompression.ii, completedCompression.image); |
234 | if (completedCompression != null) |
235 | imageSurface.setOverlay(g -> completedCompression.drawOverlay(imageSurface, g)); |
236 | } |
237 | } |
238 | |
239 | void startCompression(BWIntegralImage ii) { |
240 | if (ongoingCompression == null) { |
241 | ping(); |
242 | ongoingCompression = new Compression() |
243 | .image(lastScreen!!) |
244 | .ii(ii); |
245 | ongoingCompression.onCompressionDone(-> { |
246 | completedCompression = ongoingCompression; |
247 | ongoingCompression = null; |
248 | |
249 | showPreview(ii, completedCompression); |
250 | }); |
251 | ongoingCompression.run(); |
252 | } |
253 | } |
254 | |
255 | void printStats() { print(stats()); } |
256 | |
257 | S stats() { |
258 | var screen = lastScreen?!; |
259 | ret formatColonProperties_noNulls( |
260 | "Monitored area", area(), |
261 | "Error", screen?.getError(), |
262 | "Last screenshot taken", lastScreen?.timeStamp(), |
263 | "Average time to take a screenshot", screenShotTime, |
264 | "Average time to make integral image", iiTime, |
265 | "Capacity left in first core", percentRatioStrOneDigit(freeInCore()), |
266 | "Total CPU used", cpuTotal(), |
267 | ); |
268 | } |
269 | |
270 | S cpuTotal() { |
271 | ret setFieldAndReturn(cpuTotal := percentRatioStrOneDigit((1-freeInCore())/numberOfCores())); |
272 | } |
273 | |
274 | double freeInCore() { |
275 | ret ratio(toSeconds(screenShotCountdownTotalSleepTime), |
276 | elapsedSeconds(loopStarted)); |
277 | } |
278 | |
279 | replace jSection with jCenteredSection. |
280 | {} |
281 | visualize { |
282 | imageSurface = new IIImageSurface; |
283 | imageSurface.setAutoZoomToDisplay(true); |
284 | setDoubleBuffered(imageSurface, true); |
285 | imageSurface.setPixelated(true); |
286 | imageSurface.noAlpha = true; |
287 | |
288 | var vis = 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 | setHorizontalMarginForAllButtons(vis, 4); |
298 | ret vis; |
299 | } |
300 | |
301 | BufferedImage lastScreenImage() { ret getVar(getVar(lastScreen)); } |
302 | |
303 | public bool useErrorHandling() { false; } |
304 | |
305 | JComponent renderUIUrl aka renderUIURL aka uiGet(S url) { |
306 | var maker = uiMap.get(url); |
307 | var component = callF(maker); |
308 | if (component != null) ret component; |
309 | ret jCenteredLabel("URL not found: " + url); |
310 | } |
311 | |
312 | void showUIURL(S url) enter { |
313 | url = trim(url); |
314 | setComponent(mainArea, renderUIUrl(url)); |
315 | } |
316 | |
317 | <A extends JComponent> A uiMapPut(S url, IF0<A> maker) { |
318 | uiMap.put(url, -> maker!); |
319 | ret maker!; |
320 | } |
321 | |
322 | void uiPut(S url, IF0<JComponent> maker) { |
323 | uiMap.put(url, maker); |
324 | } |
325 | |
326 | void initUIMap { |
327 | uiPut("FPS", -> jSection("FPS", dm_calculatedCenteredLabel(() -> iround(fps)))); |
328 | |
329 | uiPut("Screen Selector", -> { |
330 | var screenSelectors = jRadioButtons( |
331 | countIteratorAsList(screenCount(), |
332 | i -> "Screen " + (i+1))); |
333 | selectRadioButton(screenSelectors, lookAtScreen); |
334 | onRadioButtonChange(screenSelectors, i -> { setField(lookAtScreen := i); }); |
335 | ret jline(buttonsInGroup(screenSelectors)); |
336 | }); |
337 | |
338 | uiPut("Screenshot with controls", -> northAndCenterWithMargin( |
339 | topControls2 = /*jflowCenter*/ jPanel(new WrapLayout, flattenList2( |
340 | dm_checkBox enabled(), |
341 | getChildren(renderUIURL("Screen Selector")), |
342 | dm_spinnerWithLabel gridRows("Rows", 1, 500), |
343 | dm_checkBox("Scale down", "scaleDownPreviewImage"), |
344 | dm_spinnerWithLabel previewPosterization("Posterize", 2, 256) |
345 | )), |
346 | jscroll_center(imageSurface))); |
347 | |
348 | uiPut("Enabled", -> dm_checkBox enabled()); |
349 | |
350 | uiPut("Home", -> |
351 | hsplit(northAndCenterWithMargin( |
352 | topControls = hgrid( |
353 | renderUIUrl("FPS"), |
354 | jSection("Compression", dm_centeredFieldLabel longTermCompressionScore()), |
355 | //jSection("Probability", dm_centeredFieldLabel longTermCompressionProbability()), |
356 | jSection("CPU (" + numberOfCores() + ")", dm_centeredFieldLabel cpuTotal()) |
357 | ), |
358 | tabs), |
359 | renderUIUrl("Screenshot with controls") |
360 | )); |
361 | } |
362 | } // end of module |
Began life as a copy of #1033526
download show line numbers debug dex old transpilations
Travelled to 2 computer(s): bhatertpkbcr, mqqgnosmbjvj
No comments. add comment
Snippet ID: | #1033653 |
Snippet name: | Gazelle 22 (old) |
Eternal ID of this version: | #1033653/10 |
Text MD5: | a32d4ae934f2177829c38f8caca6a354 |
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-28 01:02:02 |
Source code size: | 11806 bytes / 362 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 150 / 223 |
Version history: | 9 change(s) |
Referenced in: | [show references] |