srecord noeq G22ChallengePanel(G22Challenge challenge) extends HasChangeListeners is Swingable { long randomSeed = 1; //randomUnsignedInt(); //transient JPanel imagesPanel = jline(); transient DynamicHStack imagesPanel; transient L entries = syncL(); transient JComponent imagesSection; transient GazelleV_LeftArrowScript.Script parsedScript; transient settable new G22Utils g22utils; settable double timeoutPerImage = 10.0; settable int imagesToPaint = 3; settable int interval = 100; settable int imageDisplaySize = 100; settable Color imageBorderColor1 = Color.green; settable Color imageBorderColor2 = Color.red; settable int imageBorderSize = 1; visualize { imagesPanel = (DynamicHStack) dynamicHStack().spacing(20); awtCalcEvery(imagesPanel, interval, r _paintAnImage); ret withCenteredBoldTitle(str(challenge), withTopMargin(jvsplit( northAndCenterWithMargin( jRightAlignedLine( withLabel("Random seed:", liveValueLabel(liveValue_hasChangeListeners(this, -> randomSeed, x -> randomSeed = x)))), imagesSection = jCenteredRaisedSection("Images", jHigherScrollPane(imagesPanel)) ), jCenteredSection("Analysis", jTodo() ) ))); } void _paintAnImage { if (l(entries) >= imagesToPaint) ret; int index = l(entries)+1; Entry entry = new(index, (int) (randomSeed+index-1)); entries.add(entry); try { if (parsedScript == null) { var parser = g22utils.leftArrowParser(); parsedScript = parser.parse(challenge.code); } new VarContext ctx; var result = evalWithTimeout(timeoutPerImage, -> { temp tempSetRandomSeed(entry.seed); ret parsedScript.get(ctx); }); if (result.isA()) { var returnedObject = result.a(); if (returnedObject instanceof MakesBufferedImage || returnedObject instanceof Image) returnedObject = toBufferedImage(returnedObject); if (returnedObject cast BufferedImage) { entry.solution(ctx.get("solution")); addImage(entry, returnedObject); } else { addImage(entry, null, jcenteredlabel("Script did not return an image but instead " + aOrAn(className(returnedObject)))); } } else { addImage(entry, null, jcenteredlabel("Script timed out after " + nSeconds(iceil(timeoutPerImage)))); } } catch print e { entry.error(e); addImage(entry, null, jError(e)); } finally { entry.calculating(false); } } void addImage(Entry entry, BufferedImage image, JComponent component) { entry.image(image).component(component); addAndRevalidate(imagesPanel, component); setSectionTitle(imagesSection, firstToUpper(nImages(images)) + " calculated"); } void addImage(Entry entry, BufferedImage image) { addImage(entry, image, imageToComponent(image)); } JComponent imageToComponent(BufferedImage image) { // var is = g22utils.stdImageSurface(image); // jFixedSize(image.getWidth(), image.getHeight(), is); // ret is; var image2 = scaleBufferedImageToFit(image, imageDisplaySize); for (color : ll(imageBorderColor1, imageBorderColor2)) image2 = addBorderToImage(image2, color, imageBorderSize); JButton b = jimageButton(image2, "Image " + l(image) + " of challenge"); setMargin(10, b); ret b; } class Entry { int indexInSequence; long seed; // seed for randomizer settable BufferedImage image; settable Throwable error; settable O solution; settable bool calculating = true; settable JComponent component; *(int *indexInSequence, long *seed) {} } }