Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does this physics interactive buttons can be done in Pluto.jl [1] #2986

Open
f0nzie opened this issue Aug 11, 2024 · 5 comments
Open

Does this physics interactive buttons can be done in Pluto.jl [1] #2986

f0nzie opened this issue Aug 11, 2024 · 5 comments

Comments

@f0nzie
Copy link

f0nzie commented Aug 11, 2024

I have been looking for examples in Julia and Pluto to reproduce these simulations done in Java a long time ago.

Screenshot from 2024-08-10 22-18-02

The "Start" button starts the simulation. Immediately after pressing "Start", the button changes its label to "Stop", and the two buttons on the right "Step" and "New" are greyed out (disabled). The button "Step" would allow the user to advance the simulation one $\Delta t$ at a time. The "New" button just enable the input panel for a new entry and offers the user the options of "Initialize" (stores the changes) and "Reset" (clear all values preset to default).

Screenshot from 2024-08-10 22-22-56

After the simulation is stopped, the buttons "Step" and "New" are enabled again, allowing the user to resume the simulation by clicking step by step, or start over with a new set of values with New.

Screenshot from 2024-08-10 22-29-18

The "New" button will bring a new front end, with the buttons "Initialize" and "Reset".

Screenshot from 2024-08-10 22-31-15

I have been playing a bit with the buttons and the JS custom made button but I am not versed enough in JS to make the label change (from Initialize) to a new one (Start), and then to another one (Stop), when the state of the simulation is changed by the user.

Any thoughts?

@f0nzie
Copy link
Author

f0nzie commented Aug 11, 2024

I think I've got something:

using HypertextLiteral, PlutoUI
@htl("""
<!-- the wrapper span -->
<span>
	<button id="left">Start</button>
	<button id="center">Step</button>
 	<button id="right">New</button>

	<script>
		const wrapper_span = currentScript.parentElement
		const leftButton = wrapper_span.querySelector("button#left")
		const centerButton = wrapper_span.querySelector("button#center")
		const rightButton = wrapper_span.querySelector("button#right")

		// console.log(leftButton)

		leftButton.addEventListener("click", (e) => {
			console.log(leftButton.innerText + " button clicked")
			wrapper_span.dispatchEvent(new CustomEvent("input"))
			leftButton.innerText = "Stop"
			centerButton.disabled = true
			rightButton.disabled = true
			setTimeout(function(){
    			//do what you need here
				leftButton.innerText = "Start"
				centerButton.disabled = false
				rightButton.disabled = false
				}, 4000);
			e.preventDefault()
		})

		centerButton.addEventListener("click", (e) => {
			console.log(centerButton.innerText + " button clicked")
			wrapper_span.dispatchEvent(new CustomEvent("input"))
		
			e.preventDefault()
		})

		rightButton.addEventListener("click", (e) => {
			console.log(rightButton.innerText + " button clicked")
			wrapper_span.dispatchEvent(new CustomEvent("input"))
			e.preventDefault()
		})

	</script>
</span>
""")

This script will capture the click event for any of the three buttons. If the user clicks the leftButton, it will disable the buttons on the right for 4000 ms, then re-enable them right after. The leftButton also changes its inner text from Start to Stop for 4000 ms. After that, it is restored to Start.

image

image

@fonsp
Copy link
Owner

fonsp commented Aug 11, 2024

Hey @f0nzie !

That looks super fun! I love the picture on the top left :) Consider sending the notebook file when you're done, I would love to see!

The solution you came up with is exactly what I would suggest, great! I would say that this JS widget should also fire tick events, just like PlutoUI.Clock(). So when you click Step, wrapper_span.dispatchEvent(new CustomEvent("input")) gets called once, but when you click Start, an interval starts that fires wrapper_span.dispatchEvent(new CustomEvent("input")) every 100ms.

You can also set wrapper_span.value = 20 or something, and then if you do @bind x @htl(...), then x will get the value 20 when the input event is fired.

In your Julia code, you can use x as the current timestamp. The easiest way to use it is:

@bind x MyTimeWidget()
begin
	x # refernce for trigger
	update_simulation!(state)
end

Stateless

Something I prefer is to make it stateless:

states = Dict(0 => initial_state)
get_state_at(time::Integer) = 
	get!(states, time) do
		prev_state = get_state_at(time - 1)
		step_simulation(prev_state)
	end
@bind x MyTimeWidget()
get_state_at(x)

-fonzie

@f0nzie
Copy link
Author

f0nzie commented Aug 11, 2024

Hi @fonsp ,

Consider sending the notebook file when you're done

This is the notebook:
https://gist.github.com/f0nzie/5e6b69f7e561751093632c637c247b4a

and a newer one, passing an argument:
https://gist.github.com/f0nzie/acd51ebda291abb1c97c49dd64f1a142

@f0nzie
Copy link
Author

f0nzie commented Aug 11, 2024

You can also set wrapper_span.value = 20 or something, and then if you do @bind x @htl(...), then x will get the value 20 when the input event is fired.

What is the purpose of making the wrapper_span.value = 20?

@f0nzie
Copy link
Author

f0nzie commented Aug 11, 2024

If you are interested in seeing how the simulation buttons work in the original Java application, I am sharing a JAR file with a whole bunch of simulation demos. The one I showed in the post is in Chapter 12. See screenshot. To run the app, simply unzip the file. On the location where you have osp_csm.jar open a terminal and run java -jar osp_csm.jar. A launcher will open. At the bottom, select the tab "Programs". Select the chapter on the sidebar. Finally, run the app by double-clicking on ClustersApp or PercolationApp.

image

osp_csm.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants