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

379
LINES

< > BotCompany Repo | #1033526 - Gazelle V, November Edition [dev.]

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

Transpiled version (11818L) is out of date.

!7

need latest onSelectedItem.

!include early #1033506 // Compact Module Include Gazelle V

module GazelleV > DynPrintLogAndEnabled {
  /*switchable int x1;
  switchable int y1;
  switchable int w = screenWidth();
  switchable int h = screenHeight();*/
  switchable double maxFPS = 10;
  switchable int previewWidth = 200;
  switchable double statsEvery = 5;
  switchable volatile bool brokenMethod;
  int lookAtScreen;
  S previewMode;
  int gridRows = 20;
  bool scaleDownPreviewImage;
  int previewPosterization = 256;
  S uiURL = "Home";
  //bool deepCompression;

  PersistableThrowable lastProcessingError;
  transient WithTimestamp<OKOrError<BufferedImage>> lastScreen;
  transient new Average screenShotTime;
  transient new Average iiTime;
  transient Timestamp loopStarted;
  transient Sleeping screenShotCountdown;
  transient long screenShotCountdownTotalSleepTime;
  //transient ImageSurface imageSurface;
  transient IIImageSurface imageSurface;
  transient Throwable currentProcessingError;
  transient JButton popDownButton;
  transient JComponent topControls;
  transient long screenShotsTaken;
  transient double fps;
  transient Compression ongoingCompression, completedCompression;
  transient S longTermCompressionProbability;
  transient S longTermCompressionScore;
  transient JComponent topControls2;
  transient JTabbedPane tabs;
  transient ThreadPool threadPool;
  transient SingleComponentPanel mainArea;
  
  // key:   ui URL
  // value: component maker
  transient Map<S, IF0<JComponent>> uiMap = syncCIMap();
  
  // ping source for everything we do in the background, including
  // analyzing current screen.
  // normally limited to 50% of one core.
  transient PingSource backgroundPingSource;
  
  transient OnOffOscillator onOffOscillator;

  Rect area() {
    ret screenBounds(min(lookAtScreen, screenCount()-1));
  }

  class Compression {
    settable BufferedImage image;
    settable BWIntegralImage ii;
    CompressionSearch_AnyType search;
    int baseLineLength; // length of trivial compression
    GridCodec1 codec;
    double compressionPercentage;

    S score() {
      var submission = search?.bestSubmission();
      Int compressedSize = or(submission.compressedSize(), baseLineLength);
      compressionPercentage = 100-doubleRatio(compressedSize, baseLineLength)*100;
      ret iround(compressionPercentage) + "%";
    }

    IProbabilisticScheduler scheduler() {
      ret search?.scheduler();
    }

    S probability() {
      var scheduler = scheduler();
      if (scheduler == null) ret "-";
      var prob = scheduler.lastExecutedProbability();
      ret formatDouble(prob, 3);
    }

    event compressionDone;
      
    run {
      int lHex = pixelCount(image)*8;
      baseLineLength = calculateLengthOfFunctionCall imageFromHex(lHex+2);
      print(+baseLineLength);

      codec = new GridCodec1(image);
      codec.rows = gridRows;
      search = codec.forward();
      //showImage(codec.renderCellsLinearly());

      repeat 60 {
        stepForNSeconds(1, search);
        //print(stepCount := search.scheduler().stepCount());
        setFields(
          longTermCompressionProbability := probability(),
          longTermCompressionScore := score());
      }

      try {
        compressionDone();
        
        L<IJavaExpr> cellCompressions = codec.strat.codeForElements();
        //showText("Compression", lines(map shorten_str(cellCompressions)));

        /*S code = str(codec.winnerCode());
        S name = "Screenshot " + ymdMinusHMS();
        File f = makeFileNameUnique_beforeExtension(
          javaxDataDir("Compressed Screenshots/" + name + ".javax"));
        saveTextFile(f, code);
        printFileInfo(f);          
        saveGZTextFile(f = replaceExtension(f, ".jgz"), code);
        printFileInfo(f);*/

        /*
        print("Evaling " + nChars(code));
        //LL<Int> lol = cast dm_javaEval(code);
        BufferedImage restored = cast dm_javaEval(code);
        assertImagesIdentical(restored, image);
        print("Image restored!");

        dm_showImage("Restored from " + nChars(code), restored);
        */
      } catch e { printStackTrace(e); }
    }
    
    void drawOverlay(ImageSurface is, Graphics2D g) pcall {
      codec.drawOverlay(is, g);
    }
    
    int gridCols() { ret widthForHeight(ii.getWidth(), ii.getHeight(), gridRows); }
  } // end of Compression
  
  int gridCols(MakesBufferedImage ii) { ret widthForHeight(ii.getWidth(), ii.getHeight(), gridRows); }
  
  start {
    if (threadPool == null) threadPool = maxThreadPool();
    
    backgroundPingSource = new PingSource(threadPool, "Background");
    
    onOffOscillator = new OnOffOscillator(backgroundPingSource);
    ownResource(onOffOscillator);
    onOffOscillator.start();
    
    componentFieldsToKeep = litset("tabs");
    
    dm_registerAs_direct gazelleV();
    dm_watchField enabled(r { if (enabled) dm_reload(); });

    // TODO: react to event sent by OS
    dm_doEvery(1.0, r {
      if (dm_moduleIsPoppedOut()) adjustUIForPoppedOutWindow();
    });
    
    print("Screen bounds: " + allScreenBounds());
    
    initUIMap();
    
    // We are making some UI elements even if the module is hidden
    // because that's easier.
    
    tabs = jtabs(
      "Log", super.visualize(),
      "Local Data", jcenteredlabel("TODO"));

    dm_doEvery(min(statsEvery, 10.0), statsEvery, r { if (enabled) printStats(); });
    
    loopStarted = tsNow();
    shootAndAnalyze();
  }
  
  void shootAndAnalyze {
    backgroundPingSource.do(r shootAndAnalyze_impl);
  }

  void shootAndAnalyze_impl enter {
    if (!enabled) ret;

    var targetTime = tsNow().plus(1.0/maxFPS);
    long time = nanoTime();

    try {
      lastScreen = withTimestamp(okOrError(-> screenshot(area())));
      ++screenShotsTaken;
      setField(fps := doubleRatio(screenShotsTaken, elapsedSeconds(loopStarted)));
      screenShotTime.add(nanosToSeconds(nanoTime()-time));
      time = nanoTime();
      ping();
      if (lastScreen->isOK()) {
        var img = lastScreen!!;
        var ii = BWIntegralImage(img);
        //var ii = BWIntegralImage_luminosity(lastScreen!!);
        iiTime.add(nanosToSeconds(nanoTime()-time));
      
        if (!deepCompression())
          showPreview(ii, null);
        else
          startCompression(ii);
      }
      
      cpuTotal();
      currentProcessingError = null;
    } catch print e {
      setField(lastProcessingError := currentProcessingError = e);
      //sleepSeconds(60); // errors in processing are no good
    }
    
    screenShotCountdown = sleeper().doLater(targetTime, r shootAndAnalyze);
    screenShotCountdownTotalSleepTime += screenShotCountdown.remainingMS();
  }
  
  bool deepCompression() { ret !scaleDownPreviewImage; }
  
  void showPreview(BWIntegralImage ii, Compression completedCompression) {
    IBWIntegralImage ii2 = ii;
    if (scaleDownPreviewImage) {
      ii2 = ScaledIBWIntegralImage(gridCols(ii2), gridRows, ii2);
      ii2 = TruncatedIBWIntegralImage(ii2);
      
      if (previewPosterization < 256)
        imageSurface?.setImage(posterizeIBWImage(previewPosterization, ii2));
      else
        imageSurface?.setImage(ii2);
        
      imageSurface.setOverlay(null);
    } else {
      imageSurface?.setImage(completedCompression.ii, completedCompression.image);
      if (completedCompression != null)
        imageSurface.setOverlay(g -> completedCompression.drawOverlay(imageSurface, g));
    }
  }

  void startCompression(BWIntegralImage ii) {
    if (ongoingCompression == null) {
      ping();
      ongoingCompression = new Compression()
        .image(lastScreen!!)
        .ii(ii);
      ongoingCompression.onCompressionDone(-> {
        completedCompression = ongoingCompression;
        ongoingCompression = null;
        
        showPreview(ii, completedCompression);
      });
      ongoingCompression.run();
    }
  }

  void printStats() { print(stats()); }

  S stats() {
    var screen = lastScreen?!;
    ret formatColonProperties_noNulls(
      "Monitored area", area(),
      "Error", screen?.getError(),
      "Last screenshot taken", lastScreen?.timeStamp(),
      "Average time to take a screenshot", screenShotTime,
      "Average time to make integral image", iiTime,
      "Capacity left in first core", percentRatioStrOneDigit(freeInCore()),
      "Total CPU used", cpuTotal(),
    );
  }

  S cpuTotal() {
    ret setFieldAndReturn(cpuTotal := percentRatioStrOneDigit((1-freeInCore())/numberOfCores()));
  }

  double freeInCore() {
    ret ratio(toSeconds(screenShotCountdownTotalSleepTime),
      elapsedSeconds(loopStarted));
  }

  replace jSection with jCenteredSection.  
  {}
  visualize {
    imageSurface = new IIImageSurface;
    setDoubleBuffered(imageSurface, true);
    imageSurface.setPixelated(true);
    imageSurface.noAlpha = true;
    
    ret northAndCenterWithMargin(
      withMargin(withLabel("Show",
        comboBoxAndButton(
          onSelectedItem(
            bindComboBoxToLiveValue(centerComboBox(autoComboBox(uiURL, cloneKeys(uiMap))), dm_fieldLiveValue uiURL()),
            url -> showUIURL(url)
          ),
          "Go", url -> showUIURL(url)))),
      mainArea = singleComponentPanel(renderUIUrl(uiURL)));
  }
  
  BufferedImage lastScreenImage() { ret getVar(getVar(lastScreen)); }

  void adjustUIForPoppedOutWindow swing {
    if (popDownButton == null) {
      Window window = cast getWindow(dm_vis());

      var popBackInButton = findButton(window, "Pop Back In");
      var parent = getParent(popBackInButton);
      print(+parent);
      
      removeFromParent(parent); // hide controls
      
      popDownButton = jPopDownButton_noText(
        "Pop Back In", r { dm_popInModule(me()) },
        jCheckBoxMenuItem("Always On Top", isAlwaysOnTop(window),
          rEnter dm_toggleAlwaysOnTop),
      );
      addControl(popDownButton);      
    }
  }
  
  public bool useErrorHandling() { false; }
  
  JComponent renderUIUrl aka renderUIURL aka uiGet(S url) {
    var maker = uiMap.get(url);
    var component = callF(maker);
    if (component != null) ret component;
    ret jCenteredLabel("URL not found: " + url);
  }
  
  void showUIURL(S url) enter {
    url = trim(url);
    setComponent(mainArea, renderUIUrl(url));
  }
  
  <A extends JComponent> A uiMapPut(S url, IF0<A> maker) {
    uiMap.put(url, -> maker!);
    ret maker!;
  }
  
  void uiPut(S url, IF0<JComponent> maker) {
    uiMap.put(url, maker);
  }
  
  void initUIMap {
    uiPut("FPS", -> jSection("FPS", dm_calculatedCenteredLabel(() -> iround(fps))));

    uiPut("Screen Selector", -> {    
      var screenSelectors = jRadioButtons(
        countIteratorAsList(screenCount(),
          i -> "Screen " + (i+1)));
      selectRadioButton(screenSelectors, lookAtScreen);
      onRadioButtonChange(screenSelectors, i -> { setField(lookAtScreen := i); });
      ret jline(buttonsInGroup(screenSelectors));
    });
    
    uiPut("Screenshot with controls", -> northAndCenterWithMargin(
      topControls2 = /*jflowCenter*/ jPanel(new WrapLayout, flattenList2(
        dm_checkBox enabled(),
        getChildren(renderUIURL("Screen Selector")),
        dm_spinnerWithLabel gridRows("Rows", 1, 500),
        dm_checkBox("Scale down", "scaleDownPreviewImage"),
        dm_spinnerWithLabel previewPosterization("Posterize", 2, 256)
      )),
      jscroll_center(imageSurface)));
      
    uiPut("Enabled", -> dm_checkBox enabled());

    uiPut("Home", ->
      hsplit(northAndCenterWithMargin(
        topControls = hgrid(
          renderUIUrl("FPS"),
          jSection("Compression", dm_centeredFieldLabel longTermCompressionScore()),
          //jSection("Probability", dm_centeredFieldLabel longTermCompressionProbability()),
          jSection("CPU (" + numberOfCores() + ")", dm_centeredFieldLabel cpuTotal())
        ),
        tabs),
        renderUIUrl("Screenshot with controls")
      ));
  }
} // 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 [dev.]
Eternal ID of this version: #1033526/69
Text MD5: 7e31572c1a1a6c6d683edf8c477da725
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-11-05 04:59:39
Source code size: 12322 bytes / 379 lines
Pitched / IR pitched: No / No
Views / Downloads: 108 / 321
Version history: 68 change(s)
Referenced in: [show references]