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

219
LINES

< > BotCompany Repo | #1033309 // Gazelle V, New UI [HEAD]

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

Uses 1113K of libraries. Click here for Pure Java version (24075L/129K).

!7

cm 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;

  PersistableThrowable lastProcessingError;
  transient WithTimestamp<OKOrError<BufferedImage>> lastScreen;
  transient new Average screenShotTime;
  transient new Average iiTime;
  transient Timestamp loopStarted;
  transient new RestartableCountdown screenShotCountdown;
  transient ImageSurface imageSurface;
  transient Throwable currentProcessingError;
  transient BufferedImage previewImage;
  transient JButton popDownButton;
  transient JComponent topControls;
  transient long screenShotsTaken;
  transient double fps;
  transient Compression longTermCompression;
  transient S longTermCompressionProbability;
  transient S longTermCompressionScore;

  Rect area() { ret rect(x1, y1, w, h); }

  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 = doubleRatio(compressedSize, baseLineLength)*100;
      ret formatDouble(compressionPercentage, 3) + "%";
    }

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

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

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

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

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

        try {
          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); }
      }
    }
  }
  
  start-thread {
    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());

    dm_doEvery(min(statsEvery, 10.0), statsEvery, r { if (enabled) printStats(); });

    loopStarted = tsNow();
    shoot();
  }

  void shoot enter {
    if (!enabled) ret;
    
    long targetTime = sysNow()+iround(1000/maxFPS);
    long time = nanoTime();

    try {
      lastScreen = withTimestamp(okOrError(-> screenshot(area())));
      ++screenShotsTaken;
      setField(fps := doubleRatio(screenShotsTaken, elapsedSeconds(loopStarted)));
      screenShotTime.add(nanosToSeconds(nanoTime()-time));
      if (lastScreen->isOK()) {
        time = nanoTime();
        var ii = BWIntegralImage(lastScreen!!);
        //var ii = BWIntegralImage_luminosity(lastScreen!!);
        iiTime.add(nanosToSeconds(nanoTime()-time));

        if (longTermCompression == null) {
          longTermCompression = new Compression()
            .image(lastScreen!!)
            .ii(ii);
          longTermCompression.run();
        }
  
        previewImage =
            // FAST BUT BROKEN!! 
            brokenMethod ? scaledBufferedImageFromBWIntegralImage(ii, previewWidth)
            : scaleDownUsingIntegralImageBW(ii, previewWidth).getBufferedImage();
        imageSurface?.setImage(previewImage);
        
        cpuTotal();
      }

      currentProcessingError = null;
    } catch print e {
      setField(lastProcessingError := currentProcessingError = e);
      sleepSeconds(60); // errors in processing are no good
    }
    
    screenShotCountdown.setTargetTime(targetTime, r shoot);
  }

  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(screenShotCountdown.totalSleepTime),
      elapsedSeconds(loopStarted));
  }

  replace jSection with jCenteredSection.  
  {}
  visual
    hsplit(northAndCenterWithMargin(
      topControls = hgrid(
        jSection("FPS", dm_calculatedCenteredLabel(() -> iround(fps))),
        jSection("Compression", dm_centeredFieldLabel longTermCompressionScore()),
        jSection("Probability", dm_centeredFieldLabel longTermCompressionProbability()),
        jSection("CPU (" + numberOfCores() + ")", dm_centeredFieldLabel cpuTotal())
      ),
      super /* print log */),
    jscroll_center(imageSurface = doubleBufferedImageSurface_noAlpha()));
  
  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);      
    }
  }
}

Author comment

Began life as a copy of #1033298

download  show line numbers  debug dex  old transpilations   

Travelled to 3 computer(s): bhatertpkbcr, mowyntqkapby, mqqgnosmbjvj

No comments. add comment

Snippet ID: #1033309
Snippet name: Gazelle V, New UI [HEAD]
Eternal ID of this version: #1033309/71
Text MD5: e71398d1cc9e39e9a5dfdd2b3728de2a
Transpilation MD5: aed26719c25275e8488ed8d04259585a
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-28 19:38:43
Source code size: 7285 bytes / 219 lines
Pitched / IR pitched: No / No
Views / Downloads: 202 / 988
Version history: 70 change(s)
Referenced in: [show references]