playing with an early jif draft on dev.passist.org

26 views
Skip to first unread message

Christian Helbling

unread,
Feb 7, 2021, 8:22:04 AM2/7/21
to juggling-interchange-format
Hi

I managed to do some work on passist to get its internal jif draft to the current state of discussion on the list.

I also made a page to play with the format and animation. The animation is not yet generic enough, easily gets overwhelmed
and does funny, unintended stuff. I have not yet implemented the possibility of setting physical timings through jif.
As this is all pretty much work-in-progress it is not featured on the main passist page, but on dev.passist.org.
The timing is based on two-handed siteswaps but there is a timeStretchFactor to have a common denominator:
beatsPerSecond = options.jugglingSpeed * jif.timeStretchFactor

To try it out go to any siteswap and press the "</> JIF" button on the top right of any siteswap page.
https://dev.passist.org/siteswap/975?jugglers=2

Nothing in my draft is set in stone but I hope it helps to see some real-live examples and to get a step further in the
format discussion.


I also compiled the animation into code that can be included into other pages.
The code includes its css and three.js (3d javascript framework it's based on):
https://dev.passist.org/api/animation-widget-standalone.js

Demo page showing how to use it:
https://dev.passist.org/api/animation-widget-demo.html

This is thought to play around with jif as well and to test how an animation widget integration could look like.
It's definitely not stable yet, use it at your own risk.

A similar widget for the causal diagram is planned as well.


In the jif discussion, we've covered the basics so far.
A big topic still to discussed will be defining movements (of props, limbs and jugglers).
Another one will be repetition relabeling:

As you can see, holy grail (975, 2 jugglers) will currently compile to 36 throws until finally
all props are back in their initial starting hands at the same time and at the beginning of the throw sequence.
I'll write a proposal to get the number of throws to specify down to three using limb relabeling (separate email
to not mix topics).

Cheers
Christian



JaCo Stuifbergen

unread,
Feb 7, 2021, 5:15:00 PM2/7/21
to Christian Helbling, juggling-interchange-format
It looks good Christian!

it would indeed be nice if you don't have to write the full cycle, so relabeling is a good idea.

I have a comment about 2 details:
  1. I think that this should be part of the metadata
    "highLevelDescription": {
        "type": "vanillaSiteswap",
        "description": "78677"
      }, 
  2.  Is this part of JIF?
      "timeStretchFactor": 2,
    I think that I understand its meaning ( it seems equal to the number of jugglers, so the animator throws 3 times as often as an individual jugglers) and then it seems more like a timeCompressionFactor to me.
I think that the first physical parameters to be included should be the specification of launch times and catch times (perhaps I should write "launch timestamps and catch timestamps").

Co Stuifbergen
=========================
in...@jacos.nl
www.jacos.nl
+31 6 13 02 44 69 (mobile)

Kloosterwei 102
2361 XN  Warmond
the Netherlands
=========================



--
You received this message because you are subscribed to the Google Groups "juggling-interchange-format" group.
To unsubscribe from this group and stop receiving emails from it, send an email to juggling-interchang...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/juggling-interchange-format/09ed323e-8038-842f-fecf-2dfc30c10fee%40helch.ch.

Lukas Bonauer

unread,
Feb 7, 2021, 7:45:12 PM2/7/21
to Christian Helbling, juggling-interchange-format

Excellent work! The JIF format looks pretty much exactly like I imagined it.

A while ago I also started implementing my "club orbit analysis in manipulation patterns" project, which uses my barebones definition of JIF under the hood. Sadly it's a not very polished, but it has several working components that act both as producers and consumers of JIF:

(1) high_level_converter: Converts basic prechac notation to JIF (being very minimalistic about which fields it populates).

(2) jif_loader: Fills in default values for all unspecified fields and returns a "all fields required" version so the rest of the code does not need to care about checking for optional values.

(3) manipulation: Modifies input JIF with n jugglers. Adds a manipulator based on high level instructions ("substitute", "intercept + 1 beat carry", "intercept + 2 beat carry"). Returns modified JIF with n+1 jugglers and modified throws. Makes some assumptions about the underlying pattern.

(4) orbits: Takes input JIF and builds a list of prop orbits by tracking throws across period repetitions. Requires non-fractional throw times/durations.

In my code I added juggler relabeling (the "becomes" property), but didn't care about prop identity at all.

The manipulation code heavily relies on the "JIF period" being exactly like the period you would write down when describing a manipulation pattern -- for example 6 throws per juggler for Scrambled patterns before the relabeling happens.

I am not sure how that code could work if you had to repeat the throws to fix the prop identities, because then the juggler relabeling no longer matches the A/B/C role relabeling of the "high level" manipulation.

If prop identities become a required field for throws, I am not sure how to even calculate prop identities without requiring the code of (4) to be included in all JIF generators.

I think these two pieces of software are a great foundation for "bridging the gap" between a high level generator and an animator. I would love to animate the output of my manipulation script using your widget (doesn't matter if the manipulated throws look wonky for now), so let's try and find the missing pieces --- which I think is mainly prop relabeling and prop identities?

Looking forward to your ideas!

Cheers,
Lukas

example_9_club_walking_feed.png
example_scrambled_v.png

Lukas Bonauer

unread,
Feb 7, 2021, 7:51:33 PM2/7/21
to Christian Helbling, juggling-interchange-format

Sorry, forgot to actually include the link to my code:

https://github.com/Bone008/jif-playground/tree/main/src

There are also some more example inputs/outputs in the unit tests:

https://github.com/Bone008/jif-playground/blob/main/spec/manipulation.spec.ts

--
You received this message because you are subscribed to the Google Groups "juggling-interchange-format" group.
To unsubscribe from this group and stop receiving emails from it, send an email to juggling-interchang...@googlegroups.com.

Christian Helbling

unread,
Feb 8, 2021, 3:43:49 AM2/8/21
to JaCo Stuifbergen, juggling-interchange-format
Hi Co

On 07.02.21 22:32, JaCo Stuifbergen wrote:
> It looks good Christian!
Thanks!

> it would indeed be nice if you don't have to write the full cycle, so relabeling is a good idea.
Working on it.

> I have a comment about 2 details:
>
> 1. I think that this should be part of the metadata
>
> "highLevelDescription": {
> "type": "vanillaSiteswap",
> "description": "78677"
> },

Yes, we can move that part into meta if you wish.

> 2.
> Is this part of JIF?
>
> "timeStretchFactor": 2,
>
> I think that I understand its meaning ( it seems equal to the number of jugglers, so the animator throws 3 times as often as an individual jugglers) and then it seems more like a timeCompressionFactor to me.

Yes, this is my proposed solution as a common denominator for timings. This way exact timings for fractions can be given
without having to specify all timing values all over the place with fractions. This way most of the code can just use
normal floating point or integer values for dealing with times.
The value can be set freely, I just happened to set it to the number of jugglers in my vanilla siteswap implementation but in other use cases other values might be better.

Adrian suggested we should find a better name for this parameter.


> I think that the first physical parameters to be included should be the specification of launch times and catch times (perhaps I should write "launch timestamps and catch timestamps").
Yes, that was discussed on the list but is still missing in my implementation.


> It is nice that you have shared the code for the animation>
> I also compiled the animation into code that can be included into other pages.
> The code includes its css and three.js (3d javascript framework it's based on):
> https://dev.passist.org/api/animation-widget-standalone.js <https://dev.passist.org/api/animation-widget-standalone.js>
>
>
> Can it be included in HTML by
>
> <script source="./animation-widget-standalone.js" >
> </script>
>
> ?
>

Yes (except it should be src=), see the demo for an example:
https://github.com/helbling/passist/blob/main/static/api/animation-widget-demo.html
https://dev.passist.org/api/animation-widget-demo.html

Cheers
Christian

JaCo Stuifbergen

unread,
Feb 9, 2021, 9:13:37 AM2/9/21
to Christian Helbling, juggling-interchange-format

Oops... Chrome and Firefox seemed to understand "source" as well.

Christian,
it might be due to my ignorance, but the Chromium web browser showed the following error:
DevTools failed to load SourceMap: Could not load content for file:///home/jacos/Descargas/JIF%20widget/animation-widget-standalone.js.map: System error: net::ERR_FILE_NOT_FOUND
Should I download a file "animation-widget-standalone.js.map" ?

Co Stuifbergen
=========================
in...@jacos.nl
www.jacos.nl
+31 6 13 02 44 69 (mobile)

Kloosterwei 102
2361 XN  Warmond
the Netherlands
=========================


--
You received this message because you are subscribed to the Google Groups "juggling-interchange-format" group.
To unsubscribe from this group and stop receiving emails from it, send an email to juggling-interchang...@googlegroups.com.

JaCo Stuifbergen

unread,
Feb 9, 2021, 9:20:42 AM2/9/21
to Christian Helbling, juggling-interchange-format
On Mon, 8 Feb 2021 at 09:43, Christian Helbling <he...@helch.ch> wrote:
Yes, this is my proposed solution as a common denominator for timings. This way exact timings for fractions can be given
without having to specify all timing values all over the place with fractions. This way most of the code can just use
normal floating point or integer values for dealing with times.
The value can be set freely, I just happened to set it to the number of jugglers in my vanilla siteswap implementation but in other use cases other values might be better.

Adrian suggested we should find a better name for this parameter.
How silly of me, considering that I have so much insisted on proper handling of fractions!
I am glad that you have implemented this solution, and I agree that we should think of a better name.
timePartitioning ? timeDivisor?

Technically, "timeStretchFactor" is a denominator. but "timeDenominator" is not very intuitive I think.

JaCo Stuifbergen

unread,
Feb 9, 2021, 9:48:41 AM2/9/21
to Lukas Bonauer, Christian Helbling, juggling-interchange-format

A tiny comment:
JSON names require double quotes. JavaScript names don't.

Another tiny comment:
Christian defined a "type" attribute, Lukas used "kind".
 "limbs": [
    {
      "juggler": 0,
      "type": "right hand"
    },
I prefer "type" .

Christian Helbling

unread,
Feb 9, 2021, 10:29:04 AM2/9/21
to JaCo Stuifbergen, juggling-interchange-format
On 09.02.21 15:13, JaCo Stuifbergen wrote:
> Christian,
> it might be due to my ignorance, but the Chromium web browser showed the following error:
>
> DevTools failed to load SourceMap: Could not load content for file:///home/jacos/Descargas/JIF%20widget/animation-widget-standalone.js.map: System error: net::ERR_FILE_NOT_FOUND
>
> Should I download a file "animation-widget-standalone.js.map" ?
>

This is not neccessary. Everything will work fine without that.

*.js.map files contain debug information. It is a mapping of the code in the corresponding js file,
which was automatically made short and unreadable, with the corresponding js source files it was generated from.
As those files are currently not viewable on the web, the *.map file won't help anyway.


-Christian

JaCo Stuifbergen

unread,
Feb 9, 2021, 10:36:02 AM2/9/21
to Lukas Bonauer, Christian Helbling, juggling-interchange-format
Lukas,

relabeling
I thought that it would be better to re-label limbs in stead of jugglers.
In that way, a pattern like 531 can be repeated after 3 throws, not 6.

I do however understand that in manipulation patterns, it will seem redundant to re-label left and right hands separately.

Because every limb has a juggler attribute, it would be possible to derive the limb relabelings from the juggler relabelings.

So I think that JIF could allow both ways to specify the relabeling. Something like this:
"relabeling": [
{ "type"="byJuggler", "period" = 6,
"successors"=[ {"original":0, "becomes":1} , {"original":1, "becomes":2} , {"original":2, "becomes":0} ]} ,
{ "type"="byJuggler", "period" = 5,
"successors"=[ {"original":3, "becomes":4} , {"original":4, "becomes":3}]} ,
{ "type"="byHand", "period" = 3,
"successors"=[ {"original":8, "becomes":9} , {"original":9, "becomes":11} , {"original":11, "becomes":10}, {"original":10, "becomes":8} ]}
]
Note that if the relabeling is an array, it will be possible to mix "byJuggler" and "byHand", or to specify different periods for different groups.

But I think that the abstraction to the juggler level should take place in the generator, not in JIF!

In theory, the relabeling of the props follows from the re-labeling of the limbs.
I think that we could add a relabeling "byProp" though, to make work easier for the animators.

Note: if we have a limb relabeling 3-->4 and 4-->3, and a period ends at time 10, and we have a throw:
{
      "time": 9,
      "duration": 7,
      "from": 3,
      "to": 4,
    },
Does the throw go to limb 3 or to limb 4?

manipulators
I frown a bit on the attribute "isManipulated".
At the moment, I prefer to consider a manipulation as a catch and a throw. Higher levels of abstraction are possible in the pattern generator, but at this moment, I think that JIF would not be suitable for it.
Also, "isManipulated" is insufficient if you have 2 manipulators.

Co Stuifbergen
=========================
in...@jacos.nl
www.jacos.nl
+31 6 13 02 44 69 (mobile)

Kloosterwei 102
2361 XN  Warmond
the Netherlands
=========================


--
You received this message because you are subscribed to the Google Groups "juggling-interchange-format" group.
To unsubscribe from this group and stop receiving emails from it, send an email to juggling-interchang...@googlegroups.com.

Lukas Bonauer

unread,
Feb 9, 2021, 11:49:14 AM2/9/21
to JaCo Stuifbergen, juggling-interchange-format

Hi Co,

On 2021-02-09 16:35, JaCo Stuifbergen wrote:
Lukas,

relabeling
I thought that it would be better to re-label limbs in stead of jugglers.
In that way, a pattern like 531 can be repeated after 3 throws, not 6.

I do however understand that in manipulation patterns, it will seem redundant to re-label left and right hands separately.
Because every limb has a juggler attribute, it would be possible to derive the limb relabelings from the juggler relabelings.

Good point, relabeling limbs instead of jugglers makes the code to track throws across boundaries easier, definitely in favor of that. Also helps with ambidextrous manipulation patterns.

If you derive juggler relabeling from it, I think we need to require for example that A's limbs are all relabeled to the same new juggler? If A's right hand becomes B's left hand, but A's left hand becomes C's right hand, that messes with limb ownership a lot. I cannot think of a reason why anyone would want that, so I would be inclined to call that an error, but who knows.


So I think that JIF could allow both ways to specify the relabeling. Something like this:
"relabeling": [
{ "type"="byJuggler", "period" = 6,
"successors"=[ {"original":0, "becomes":1} , {"original":1, "becomes":2} , {"original":2, "becomes":0} ]} ,
{ "type"="byJuggler", "period" = 5,
"successors"=[ {"original":3, "becomes":4} , {"original":4, "becomes":3}]} ,
{ "type"="byHand", "period" = 3,
"successors"=[ {"original":8, "becomes":9} , {"original":9, "becomes":11} , {"original":11, "becomes":10}, {"original":10, "becomes":8} ]}
]
Note that if the relabeling is an array, it will be possible to mix "byJuggler" and "byHand", or to specify different periods for different groups.

I would be against allowing to specify both ways as it's just more work to implement support for both options and one (by limbs) seems like a strict superset of the other (by juggler).

Can you give an example where you need to relabel over multiple different periods? I like the conciseness of writing "becomes" inline with the limb (xor juggler), but I can see how it is more flexible to decouple the "relabeling period" from the "throw period". What could we need it for?


But I think that the abstraction to the juggler level should take place in the generator, not in JIF!

In theory, the relabeling of the props follows from the re-labeling of the limbs.
I think that we could add a relabeling "byProp" though, to make work easier for the animators.

Note: if we have a limb relabeling 3-->4 and 4-->3, and a period ends at time 10, and we have a throw:
{
      "time": 9,
      "duration": 7,
      "from": 3,
      "to": 4,
    },
Does the throw go to limb 3 or to limb 4?

In my code that is interpreted as "to limb 4, before relabeling". I think it is more intuitive to refer to both limbs at the time of the instruction (t=9), not when the throw lands.



manipulators
I frown a bit on the attribute "isManipulated".
At the moment, I prefer to consider a manipulation as a catch and a throw. Higher levels of abstraction are possible in the pattern generator, but at this moment, I think that JIF would not be suitable for it.
Also, "isManipulated" is insufficient if you have 2 manipulators.

Ah sorry, I forgot to clarify "isManipulated": That's only a temporary marker that I needed to filter for patterns with certain properties, it's not supposed to be part of JIF and it's not necessary to parse it to derive the correct logical pattern.

Manipulations are in fact already encoded as a "catch + throw". For simplicity, for now I turned a substitute of duration 3 into a simultaneous 1p (juggler --> M) and a 3p (M --> juggler). Because I was interested in "low throws" (for beer passing), as a hacky workaround I set isManipulated=true on the generated 3p to indicate it's actually handed over directly. A slightly less bad representation of a substitute is "1p 2p", then I don't need that hack any more. But that's a bit off topic here.

I would call the field a "program-specific extension" that others need not worry about -- I guess I should have also prefixed its name with something to highlight that.

@Christian: Sorry for derailing this thread a bit!

Cheers,
Lukas

JaCo Stuifbergen

unread,
Feb 9, 2021, 2:28:37 PM2/9/21
to Lukas Bonauer, juggling-interchange-format
On Tue, 9 Feb 2021 at 17:49, Lukas Bonauer <lukas....@yahoo.de> wrote:
relabeling
If you derive juggler relabeling from it, I think we need to require for example that A's limbs are all relabeled to the same new juggler? If A's right hand becomes B's left hand, but A's left hand becomes C's right hand, that messes with limb ownership a lot. I cannot think of a reason why anyone would want that, so I would be inclined to call that an error, but who knows.
I agree. One can derive the limb relabeling from the juggler relabeling, but the reverse could go wrong.
So I think that JIF could allow both ways to specify the relabeling. Something like this:
"relabeling": [
{ "type"="byJuggler", "period" = 6,
"successors"=[ {"original":0, "becomes":1} , {"original":1, "becomes":2} , {"original":2, "becomes":0} ]} ,
{ "type"="byJuggler", "period" = 5,
"successors"=[ {"original":3, "becomes":4} , {"original":4, "becomes":3}]} ,
{ "type"="byHand", "period" = 3,
"successors"=[ {"original":8, "becomes":9} , {"original":9, "becomes":11} , {"original":11, "becomes":10}, {"original":10, "becomes":8} ]}
]
Note that if the relabeling is an array, it will be possible to mix "byJuggler" and "byHand", or to specify different periods for different groups.

I would be against allowing to specify both ways as it's just more work to implement support for both options and one (by limbs) seems like a strict superset of the other (by juggler).

I am glad that you're happy with just limb relabeling.

Can you give an example where you need to relabel over multiple different periods? I like the conciseness of writing "becomes" inline with the limb (xor juggler), but I can see how it is more flexible to decouple the "relabeling period" from the "throw period". What could we need it for?

I am not sure that there ever will be a need for this, I can imagine 1 concrete example:
- an animation of 2 patterns at the same time that have different periods

And perhaps the option might become useful for
- a walking pattern in which the walks are repeated with a longer period than the throws
- a passing pattern of period 4, with a manipulation that is repeated every 3 passes
But I am not quite sure.

It will not be difficult to specify that "relabeling" is an array in JIF.
To implement it is a different matter, but programs don't have to implement every option.


But I think that the abstraction to the juggler level should take place in the generator, not in JIF!

In theory, the relabeling of the props follows from the re-labeling of the limbs.
I think that we could add a relabeling "byProp" though, to make work easier for the animators.

Note: if we have a limb relabeling 3-->4 and 4-->3, and a period ends at time 10, and we have a throw:
{
      "time": 9,
      "duration": 7,
      "from": 3,
      "to": 4,
    },
Does the throw go to limb 3 or to limb 4?

In my code that is interpreted as "to limb 4, before relabeling". I think it is more intuitive to refer to both limbs at the time of the instruction (t=9), not when the throw lands.

In some situations (e.g. state diagrams) you may have to look up a throw that was made some counts earlier, so then you have to check whether relabeling should be applied zero, 1, 2, or more times.
But the most important is to define a standard in JIF, and I don't have a strong preference.

I would call the field a "program-specific extension" that others need not worry about -- I guess I should have also prefixed its name with something to highlight that.

A prefix will be a good idea, to make sure that JIF will never reserve a word that has been used with a different meaning by some software.

(by the way, I think that the discussion hasn't derailed).

Co Stuifbergen
=========================
in...@jacos.nl
www.jacos.nl
+31 6 13 02 44 69 (mobile)

Kloosterwei 102
2361 XN  Warmond
the Netherlands
=========================


manipulators
I frown a bit on the attribute "isManipulated".
At the moment, I prefer to consider a manipulation as a catch and a throw. Higher levels of abstraction are possible in the pattern generator, but at this moment, I think that JIF would not be suitable for it.
Also, "isManipulated" is insufficient if you have 2 manipulators.

Ah sorry, I forgot to clarify "isManipulated": That's only a temporary marker that I needed to filter for patterns with certain properties, it's not supposed to be part of JIF and it's not necessary to parse it to derive the correct logical pattern.

Manipulations are in fact already encoded as a "catch + throw". For simplicity, for now I turned a substitute of duration 3 into a simultaneous 1p (juggler --> M) and a 3p (M --> juggler). Because I was interested in "low throws" (for beer passing), as a hacky workaround I set isManipulated=true on the generated 3p to indicate it's actually handed over directly. A slightly less bad representation of a substitute is "1p 2p", then I don't need that hack any more. But that's a bit off topic here.


Reply all
Reply to author
Forward
0 new messages