from causal diagram to physical throw

58 views
Skip to first unread message

JaCo Stuifbergen

unread,
Oct 14, 2020, 5:12:17 PM10/14/20
to juggling-interchange-format

This is my reaction to:
=================================================
On Wed, 14 Oct 2020 at 15:11, Adrian Goldwaser <ad.gol...@gmail.com> wrote:
Physical throws:  
- I don't think animation data should override throw time - a causal diagram (i.e. 'logical throws') should show the actual throw time IMO, animators shouldn't need to change that, modifying catch time is enough

Do we want to split throws/catches as separate events? Again, it's something that JML does but I'm not sure why it has it that way, it would make simple cases more complex but may help with more complex cases?

Other pattern definition links that might be useful:
- Gunswap (much higher level, not sure if there's an internal one too): http://www.gunswap.co/about/syntax

Cheers,
Adrian
===================================================
I will use the following terms:

throw duration: the site-swap value
flight duration: the time that an object spends in the air (not held) between 2 throws
throw time: the time mark when the object is thrown
catch time: the time mark when the object is caught
hold duration: dwell time. how long an object is in the hand
empty duration: how long a hand is empty between throws

The unit of time is a "beat": this is the regular time between two throws of 1 juggler.
(I will ignore poly-rhythms for a moment)

## general comment
throw duration = flight duration + hold duration.
The causal diagram specifies throw durations, not flight durations.

So we need some parameter (like "empty duration = 0.3 beat") to arrive at the actual flight durations

## early zips versus late zips

you will see a causal diagram for <531> at the bottom, and the corresponding ladder diagram above.
Note that I use a different height for each hand.

Because there is a catch on every beat, the ball that is zipped ("1") cannot be held long, so the hold times (and empty times) vary.
In fact, the throw is done early.
This is how I juggle zips. I want to hear a catch on every beat, so I throw the zips early.

If I make the zip on the (next) beat, the catch will be late, so the hold time after the zip will be shorter.
It seems to me that the animators Joepass and passist.org do this.

By the way, if the empty time is made longer for every throw, this problem disappears.
But that will make an animation (or a ladder diagram) less realistic.

In my opinion, a causal diagram does not specify whether the zips should be late or early.

So this should be a parameter in the pattern description, if we want to describe the physical pattern.

I think of a simple flag like "EARLY_ZIPS = true", but I can imagine that someone wants a value between "earliest" (catch on the beat) and "latest" (throw on the beat)
This might explain why JML splits throws/catches as separate events.
(Or does it indicate the start of a new move in the animator?)

Co Stuifbergen

Adrian Goldwaser

unread,
Oct 15, 2020, 6:58:12 AM10/15/20
to juggling-interchange-format
Interesting example with zips, it happens with JugglingLab too (I normally set BPS and when you do that it stops throwing them early so hadn't realised before you mentioned it). I think I agree then that we need the information there,

> I think of a simple flag like "EARLY_ZIPS = true", but I can imagine that someone wants a value between "earliest" (catch on the beat) and "latest" (throw on the beat)
Agreed, e.g. JugglingLab's default is a bit early and lands a bit late - we want that flexibility.

> This might explain why JML splits throws/catches as separate events.
How so? They could easily be put into the throw event still - I feel like the reasoning there is so that each event does one thing and they can be sorted.

Cheers,
Adrian

--
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/265a3e84-8157-4876-909c-93851f27325an%40googlegroups.com.

JaCo Stuifbergen

unread,
Oct 17, 2020, 4:48:30 PM10/17/20
to juggling-interchange-format

I will give some examples of notation that (I think) can be interpreted without ambiguity.

Perhaps I should have included the causal diagrams for some patterns, to make the reading more easy.

Many patterns can be written in different ways, and some parameters may be optional.

We should decide whether such parameters should always be given, or the program should work them out.

vanilla site-swap

{ "pattern": "<5 3 1>"}

A simpel solo site-swap, without synchronous throws.

passing whole counts

{ "pattern":"< 4p 3 3 | 3 5p 3 >"}

The pipe symbol ("|") separates the instructions for the next juggler.

{ "pattern":"< 4p_B 3 3 | 3 4p_C 3 | 3 3 4p_A >"}

With 3 jugglers, we must specify to which jugglers the passes go

{"nJugglers":3, "pattern":"< 4p_B 3 3 >"}

This is the same as the previous pattern. The computer should be able to work out that the jugglers are shifted by 1 count, because the period is 3

{"nJugglers":3, "pattern":"< 4 4p_B 3 3 3 3>"}

The computer should be able to work out that the jugglers are shifted by 2 counts, because the period is 6. So

{ "pattern":""<4 4p_B 3 3 3 3 | 3 3 4 4p_C 3 3 | 3 3 3 3 4 4p_A >"}

is the same as the previous pattern.

{ "pattern":"<3 3 4 4p >"}

The number of jugglers is not given, but there is a pass, so there are 2 jugglers. The period is 4, so the second juggler is shifted by 2 counts (4/2 = 2).

{ "pattern":"<3 3 4 4p | 4 4p 3 3 >"}

{ "nJugglers":2, "pattern":"<3 3 4 4p >"}

This is the same as the previous pattern.

passing fractions half-beat shift

{ "pattern":"< 4 3.5 3.5 3 3.5 | 1 3.5 1 3.5 3.5 >",

"jugglerShift": "[0, 0.5]"}

The sequence of the second juggler will start 0.5 beat later

{"nJugglers":2,

"pattern":"< 4 3.5 3.5 3 3.5 | 3 3.5 4 3.5 3.5 >",

"jugglerShift": "[0, 0.5]"}

Both jugglers juggle the same sequence, but the second juggler will start 0.5 beat later

{ "pattern":"< 4 3.5 3.5 3 3.5 >"}

The fraction indicates that there is a pass to a juggler that is shifted 0.5 count. The period of the pattern is 5. The shift is 5/2 = 2.5 So this is the same as the previous pattern.

{"nJugglers":2,

"pattern":"< 4 3.5 3.5

| 3 3.5 >",

"jugglerShift": "[0, 0.5]",

"period": 2.5,

"jugglerPermutation":"(A,B)" }

This is the same as the previous pattern. The pattern is repeated after 2.5 counts, with jugglers A and B exchanged

multi-handed site-swap

{"nJugglers":2,

"pattern":"< 8 6 7 7 7>",

}

Again the same pattern. There are 2 jugglers, so the shift must be 5/2 = 2.5. There are no fractions, so this is a multi-handed notation.

other fractions

{"nJugglers":5, "pattern":"< 3.6 3 3>"}

The fraction indicates that there is a pass to a juggler that is shifted 0.6 count. (after 5 jugglers, this makes 3 counts, so the last pass fits in the pattern) {"nJugglers":5, "pattern":"< 3.6 3 3>",

"jugglerShift": "[0, 0.6, 1.2, 1.8, 2.4 ]"}

This is the same as the previous pattern. {"nJugglers":5, "pattern":"< 3.6 3 3 | 3.6 3 3 | 3 3.6 3 | 3 3.6 3 | 3 3 3.6 >",

"jugglerShift": "[0, 0.6, 0.2, 0.8, 0.4 ]"}

This is the same as the previous pattern. (note: the shifts are different, so the patterns had to be shifted for jugglers 3,4 and 5)

{"pattern":"< 3.33 3 1 3 3>"}

or

{"nJugglers":3, "pattern":"< 3.33 3 1 3 3>"}

"jugglerShift": "[0, 1.67, 2.33]"}

Of course, .33 means 1/3 and .67 mean 2/3. If only the sequence for juggler 1 is given, the shifts will be period/3, 2 * period/3 etc. or

{"nJugglers":3, "pattern":"< 3.33 3 1 3 3 | 3 3.33 3 1 3 | 1 3 3 3.33 3 >",

"jugglerShift": "[0, 0.67, 0.33]"}

or

{"nJugglers":3, "pattern":"< 3.33 3 1 3 3 | 1 3 3 3.33 3 | 3 3.33 3 1 3 >",

"jugglerShift": "[0, 0.33, 0.67]"} (note: the shifts are different, so the patterns are in a different order)

or

{"nJugglers":3, "pattern":"< 3.33 3 1 3 3 | 1 3 3 3.33 3 | 3 3.33 3 1 3 >"}

If there is a separate sequence for each juggler, and no shift is indicated, the shift will be 1/3, 2/3 etc.

Perhaps there should be a parameter that states the desired denominator of the fraction, so wil wil know that 0.7 means 2/3. (for poly-rhythmic patterns, this will also be useful)

Like: {"nJugglers":3, "denominator":3, "pattern":"< 3.3 3 1 3 3>"}

(in this case, the only possible fractions are .3 and 0.7 (=.66666....) so 1 digit is sufficiently accurate.

synchronous throws 2 in each hand

Now come some patterns with 2 balls in each hand, 1 hand throws every 2nd beat, the other hand throws every 3rd beat. We would expect that the hand that throws more often, will throw lower. However, it can also throw at the same height, and have a longer empty duration.

{ "pattern":"< (4,6) (,) (4,) (,6) (4,) (,) >"}

This is a pattern that has synchronous and a-synchronous throws. Perhaps you are used to the notation:

< (4,6) (0,0) (4,0) (0,6) (4,0) (0,0) > But the "0" suggest that the hand is empty, and it may hold an object at those times.

flight durations

{ "pattern":"< (4,6) (,) (4,) (,6) (4,) (,) >",

"flight_durations": "< (2.2,3.2) (,) (3.2,) (,2.2) (3.2,) (,) >" }

So the hold durations of these throws are: < (1.8,2.8) (,) (1.8,) (,2.8) (1.8,) (,) >

And the empty duration is 0.2 for each throw. < (0.2 0,2) (,) (0.2,) (,0.2) (0.2,) (,) > (hold duration = siteswap value - flight duration empty duration = time between throws - hold duration)

{ "pattern":"< (4,6) (,) (4,) (,6) (4,) (,) >",

"flight_durations": "< (3.2,3.2) (,) (3.2,) (0,3.2) (3.2,0) (,) > " }

Now, all throws are at the same height. Some hold durations will be shorter: < (0.8,2.8) (,) (0.8,) (,2.8) (0.8,) (,) >

And the empty durations will be different: < (1.2,0.2) (,) (1.2,) (,0.2) (1.2,) (,) >

3 balls vs 2 balls

The hand that juggles more balls, will either throw higher, or more often. Or both, for example:

{ "pattern":"< (6,6) (,) (6,) (,6) (6,) (,) >",

"flight_durations": "< (4.2,3.2) (,) (4.2,) (0,3.2) (4.2,0) (,) > " }

So the hold durations of these throws are: < (1.8,2.8) (,) (1.8,) (,2.8) (1.8,) (,) >

And the empty duration is 0.2 for each throw. < (0.2 , 0.2) (,) (0.2,) (,0.2) (0.2,) (,) >

Throws at the same height: { "pattern":"< (6,6) (,) (6,) (,6) (6,) (,) >",

"flight_durations": "< (4.2,4.2) (,) (4.2,) (,4.2) (4.2,) (,) > " }

Now all throws are the same height, and have the same hold duration: < (1.8,1.8) (,) (1.8,) (,1.8) (1.8,) (,) >

The empty times are now different: < (0.2, 1.2) (,) (0.2,) (,1.2) (0.2,) (,) > (the hand that juggles fewer objects is more often empty)

Just throwing higher:

{ "pattern":"< (6,4) (,) >"}

alternating hands:

{ "pattern":"< (6x,4) (,) (4,6x) (,) >"}

The alternation of hands may be indicated by a symbol: { "pattern":"< (6x,4) (,) % >"}

Of course, passing patterns can also be written: { "pattern":"< (4x,3p) (,) | (,) (4x,3p) >"}

(this is passing 7 clubs, double selfs, single passes)

or {"nJugglers":2, "pattern":"< (4x,3p) (,) >" "jugglerShift": "[0, 1]"}

The pass implies that there are 2 jugglers, so the following notation would be sufficient:

{ "pattern":"< (4x,3p) (,) >"}

A more complicated pattern would be: (synchronous self/pass, then some selfs)

{ "pattern":"< (3,4xp) (,4x) (,) (3,) >"}

poly-rhythmic

If the frequencies relate as 2/3 or 2/4, patterns can easily be described using synchronous throws. For ratios like 3/4 or 3/5 etc, we would need many (,) in the pattern. So I want to use a notation that has fractions.

(to be expanded)

Florian Pesth

unread,
Oct 17, 2020, 6:03:27 PM10/17/20
to juggling-interchange-format
Hello everyone,

thinking about it I think I agree that we might not need the state
information as this can probably be deduced completely from the throws.

But I think it would be a mistake to repeat the handwritten notation in
the juggling information format as it should be good for computers to
read and write, not for humans (The program should be able to make
nice human readable text from the JIF and vice versa but we don't need
to save it very human readable).

I'm thinking more of the lines like this (for 531, if it is specified
with two "beatgroups" which are 0.5 beats apart):

(I'm aware that it is overly wordly, but this is to transport the idea)

{
beatgroups: [
{name: "right-hand-beatgroup",
type: "one-handed-siteswap",
positions: [{name: "juggler1-right-hand",
first-throw-at-beat: 0
throws: [{to: "juggler1-left-hand",
beats-till-landing: 2.5}, {to:
"juggler1-left-hand", beats-till-landing:
0.5}, {to:
"juggler1-left-hand", beats-till-landing:
1.5}]
}]
},
{name: "left-hand-beatgroup",
type: "one-handed-siteswap",
time-ratio-to-previous-beatgroup: 1.0,
delay-to-previous-beatgroup: {"0.5", "beat"},
positions: [{name: "juggler1-left-hand",
first-throw-at-beat: 1
throws: [{to: "juggler1-right-hand",
beats-till-landing: 1.5}, {to:
"juggler1-right-hand", beats-till-landing:
2.5}, {to: "juggler1-right-hand",
beats-till-landing: 0.5}]
}]
}
]
}

I think this - while looking maybe a bit complicated - would allow for
a lot of flexibility. Of course one could write it without fractions if
one uses 0 throws for empty hands or introduces a "two-handed-siteswap"
type as well which assumes alternating between two hands:

{
beatgroups: [
{name: "juggler1-beatgroup",
type: "two-handed-siteswap",
positions: [{name: "juggler1-right-hand",
first-throw-at-beat: 0
throws: [{to: "juggler1-left-hand",
beats-till-landing: 5}, {to:
"juggler1-left-hand", beats-till-landing:
1}, {to:
"juggler1-left-hand", beats-till-landing:
3}]
},
{name: "juggler1-left-hand",
first-throw-at-beat: 1
throws: [{to: "juggler1-right-hand",
beats-till-landing: 3}, {to:
"juggler1-right-hand", beats-till-landing:
5}, {to:
"juggler1-right-hand", beats-till-landing:
1}]
}]
}
]
}

This also allows easily for polyrythmic patterns and passing patterns.
Maybe the throws field should be an array for each throw as well to
allow for multiplex splits.

Cheers,
Florian

Am Sat, 17 Oct 2020 13:48:30 -0700 (PDT)
schrieb JaCo Stuifbergen <j.c.stu...@gmail.com>:

> I will give some examples of notation that (I think) can be
> interpreted without ambiguity.
>
> Perhaps I should have included the causal diagrams for some patterns,
> to make the reading more easy.
>
> Many patterns can be written in different ways, and some parameters
> may be optional.
>
> We should decide whether such parameters should always be given, or
> the program should work them out.
> *vanilla site-swap*
>
> { "pattern": "<5 3 1>"}
>
> A simpel solo site-swap, without synchronous throws.
> *passing whole counts*
>
> { "pattern":"< 4p 3 3 | 3 5p 3 >"}
>
> The pipe symbol ("|") separates the instructions for the next juggler.
>
> { "pattern":"< 4p_B 3 3 | 3 4p_C 3 | 3 3 4p_A >"}
>
> With 3 jugglers, we must specify to which jugglers the passes go
>
> {"nJugglers":3, "pattern":"< 4p_B 3 3 >"}
>
> This is the same as the previous pattern. The computer should be able
> to work out that the jugglers are shifted by 1 count, because the
> period is 3
>
> {"nJugglers":3, "pattern":"< 4 4p_B 3 3 3 3>"}
>
> The computer should be able to work out that the jugglers are shifted
> by 2 counts, because the period is 6. So
>
> { "pattern":""<4 4p_B 3 3 3 3 | 3 3 4 4p_C 3 3 | 3 3 3 3 4 4p_A >"}
>
> is the same as the previous pattern.
>
> { "pattern":"<3 3 4 4p >"}
>
> The number of jugglers is not given, but there is a pass, so there
> are 2 jugglers. The period is 4, so the second juggler is shifted by
> 2 counts (4/2 = 2).
>
> { "pattern":"<3 3 4 4p | 4 4p 3 3 >"}
>
> { "nJugglers":2, "pattern":"<3 3 4 4p >"}
>
> This is the same as the previous pattern.
> *passing fractions half-beat shift *
>
> { "pattern":"< 4 3.5 3.5 3 3.5 | 1 3.5 1 3.5 3.5 >",
>
> "jugglerShift": "[0, 0.5]"}
>
> The sequence of the second juggler will start 0.5 beat later
>
> {"nJugglers":2,
>
> "pattern":"< 4 3.5 3.5 3 3.5 | 3 3.5 4 3.5 3.5 >",
>
> "jugglerShift": "[0, 0.5]"}
>
> Both jugglers juggle the same sequence, but the second juggler will
> start 0.5 beat later
>
> { "pattern":"< 4 3.5 3.5 3 3.5 >"}
>
> The fraction indicates that there is a pass to a juggler that is
> shifted 0.5 count. The period of the pattern is 5. The shift is 5/2 =
> 2.5 So this is the same as the previous pattern.
>
> {"nJugglers":2,
>
> "pattern":"< 4 3.5 3.5
> | 3 3.5 >",
>
> "jugglerShift": "[0, 0.5]",
>
> "period": 2.5,
>
> "jugglerPermutation":"(A,B)" }
>
> This is the same as the previous pattern. The pattern is repeated
> after 2.5 counts, with jugglers A and B exchanged
> *multi-handed site-swap *
>
> {"nJugglers":2,
>
> "pattern":"< 8 6 7 7 7>",
>
> }
>
> Again the same pattern. There are 2 jugglers, so the shift must be
> 5/2 = 2.5. There are no fractions, so this is a multi-handed notation.
> *other fractions *
> *synchronous throws 2 in each hand *
>
> Now come some patterns with 2 balls in each hand, 1 hand throws every
> 2nd beat, the other hand throws every 3rd beat. We would expect that
> the hand that throws more often, will throw lower. However, it can
> also throw at the same height, and have a longer empty duration.
>
> { "pattern":"< (4,6) (,) (4,) (,6) (4,) (,) >"}
>
> This is a pattern that has synchronous and a-synchronous throws.
> Perhaps you are used to the notation:
>
> < (4,6) (0,0) (4,0) (0,6) (4,0) (0,0) > But the "0" suggest that the
> hand is empty, and it may hold an object at those times.
> *flight durations*
>
> { "pattern":"< (4,6) (,) (4,) (,6) (4,) (,) >",
>
> "flight_durations": "< (2.2,3.2) (,) (3.2,) (,2.2) (3.2,) (,) >" }
>
> So the hold durations of these throws are: < (1.8,2.8) (,) (1.8,)
> (,2.8) (1.8,) (,) >
>
> And the empty duration is 0.2 for each throw. < (0.2 0,2) (,) (0.2,)
> (,0.2) (0.2,) (,) > (hold duration = siteswap value - flight duration
> empty duration = time between throws - hold duration)
>
> { "pattern":"< (4,6) (,) (4,) (,6) (4,) (,) >",
>
> "flight_durations": "< (3.2,3.2) (,) (3.2,) (0,3.2) (3.2,0) (,) > " }
>
> Now, all throws are at the same height. Some hold durations will be
> shorter: < (0.8,2.8) (,) (0.8,) (,2.8) (0.8,) (,) >
>
> And the empty durations will be different: < (1.2,0.2) (,) (1.2,)
> (,0.2) (1.2,) (,) >
> *3 balls vs 2 balls *
> *poly-rhythmic*
> >> *Physical throws*:
> >> - I don't think animation data should override throw time - a
> >> causal diagram (i.e. 'logical throws') should show the actual
> >> throw time IMO, animators shouldn't need to change that, modifying
> >> catch time is enough
> >>
> >> Do we want to split throws/catches as separate events? Again, it's
> >> something that JML does but I'm not sure why it has it that way,
> >> it would make simple cases more complex but may help with more
> >> complex cases?
> >>
> >> Other pattern definition links that might be useful:
> >> - JML (JugglingLab): https://jugglinglab.org/html/jml.html,
> >> https://github.com/jkboyce/jugglinglab/tree/master/source/jugglinglab/jml
> >> - Gunswap (much higher level, not sure if there's an internal one
> >> too): http://www.gunswap.co/about/syntax
> >>
> >> Cheers,
> >> Adrian
> >> ===================================================
> >> I will use the following terms:
> >>
> >> *throw duration:* the site-swap value
> >> *flight duration: *the time that an object spends in the air (not
> >> held) between 2 throws
> >> *throw time:* the time mark when the object is thrown
> >> *catch time: *the time mark when the object is caught
> >> *hold duration: *dwell time. how long an object is in the hand
> >> *empty duration: *how long a hand is empty between throws
> >> <https://groups.google.com/d/msgid/juggling-interchange-format/265a3e84-8157-4876-909c-93851f27325an%40googlegroups.com?utm_medium=email&utm_source=footer>
> >> .
> >>
> >
>

Christian Helbling

unread,
Oct 17, 2020, 6:59:58 PM10/17/20
to juggling-inte...@googlegroups.com
Hi Co

For me, this all goes into the category "description in some high-level language".

I agree, that the format should be able to have a way to store compact high-level information.
For example, a vanilla siteswap and number of hands is enough to draw a causal diagram.

The software stack could look as following:
JIF with only high-level description => code => JIF with logical throws for the causal diagram
=> code => JIF with more exact information about animation

The pieces of code in-between know how to fill in missing information or can ask the user about that.
And it should be possible to replace every piece of code which an alternative one.


Maybe we can do some specification like:

highLevel: {
type: "vanillaSiteswap",
description: "531"
}

or

highLevel: {
type: "cosExtendedSiteswap",
description: ""< 3.33 3 1 3 3 | 1 3 3 3.33 3 | 3 3.33 3 1 3 >"
}

BTW: there is also an extendes siteswap notation from juggling lab which might be similar to yours:
https://jugglinglab.org/html/ssnotation.html


Should one high-level description be enough or are there cases where we want to represent multiple different
high-level descriptions for the same pattern?

Or should we declare our own description(s) in the same way, maybe even splitting the logical from the physical description?

descriptions: [
{
type: "vanillaSiteswap",
description: "531"
},
{
type: "logical", # what we would need for a causal diagram
description: {
throws: [
{ time:0, duration:10, fromHand:0, toHand:2, label:"a" },
{ time:1, duration:7, fromHand:1, toHand:0, label:"7" },
{ time:2, duration:7, fromHand:2, toHand:1, label:"7" },
...
],
}
},
{
type: "physical", # what we would need for an animation
description: {
propMovements: [
...
],
handMovements: [
...
],
jugglerMovements: [
...
]
}

},

]

This way, every piece of software mentioned above would write its own description
section by refining the previous one.

When writing the passist animation I saw there is much code dedicated to filling
missing information like defining dwell times, hand positions, hand movements (during dwell time and in-between),
calculating prop rotations, ...
The "physical" representation above would allow this kind of logical code to be split away from the actual 3d code.

Cheers
Christian


On 17.10.20 22:48, JaCo Stuifbergen wrote:
> I will give some examples of notation that (I think) can be interpreted without ambiguity.
>
> Perhaps I should have included the causal diagrams for some patterns, to make the reading more easy.
>
> Many patterns can be written in different ways, and some parameters may be optional.
>
> We should decide whether such parameters should always be given, or the program should work them out.
>
> *vanilla site-swap*
>
> { "pattern": "<5 3 1>"}
>
> A simpel solo site-swap, without synchronous throws.
>
> *passing whole counts*
>
> { "pattern":"< 4p 3 3 | 3 5p 3 >"}
>
> The pipe symbol ("|") separates the instructions for the next juggler.
>
> { "pattern":"< 4p_B 3 3 | 3 4p_C 3 | 3 3 4p_A >"}
>
> With 3 jugglers, we must specify to which jugglers the passes go
>
> {"nJugglers":3, "pattern":"< 4p_B 3 3 >"}
>
> This is the same as the previous pattern. The computer should be able to work out that the jugglers are shifted by 1 count, because the period is 3
>
> {"nJugglers":3, "pattern":"< 4 4p_B 3 3 3 3>"}
>
> The computer should be able to work out that the jugglers are shifted by 2 counts, because the period is 6. So
>
> { "pattern":""<4 4p_B 3 3 3 3 | 3 3 4 4p_C 3 3 | 3 3 3 3 4 4p_A >"}
>
> is the same as the previous pattern.
>
> { "pattern":"<3 3 4 4p >"}
>
> The number of jugglers is not given, but there is a pass, so there are 2 jugglers. The period is 4, so the second juggler is shifted by 2 counts (4/2
> = 2).
>
> { "pattern":"<3 3 4 4p | 4 4p 3 3 >"}
>
> { "nJugglers":2, "pattern":"<3 3 4 4p >"}
>
> This is the same as the previous pattern.
>
> *passing fractions half-beat shift *
>
> { "pattern":"< 4 3.5 3.5 3 3.5 | 1 3.5 1 3.5 3.5 >",
>
> "jugglerShift": "[0, 0.5]"}
>
> The sequence of the second juggler will start 0.5 beat later
>
> {"nJugglers":2,
>
> "pattern":"< 4 3.5 3.5 3 3.5 | 3 3.5 4 3.5 3.5 >",
>
> "jugglerShift": "[0, 0.5]"}
>
> Both jugglers juggle the same sequence, but the second juggler will start 0.5 beat later
>
> { "pattern":"< 4 3.5 3.5 3 3.5 >"}
>
> The fraction indicates that there is a pass to a juggler that is shifted 0.5 count. The period of the pattern is 5. The shift is 5/2 = 2.5 So this is
> the same as the previous pattern.
>
> {"nJugglers":2,
>
> "pattern":"< 4 3.5 3.5
>
> | 3 3.5 >",
>
> "jugglerShift": "[0, 0.5]",
>
> "period": 2.5,
>
> "jugglerPermutation":"(A,B)" }
>
> This is the same as the previous pattern. The pattern is repeated after 2.5 counts, with jugglers A and B exchanged
>
> *multi-handed site-swap *
>
> {"nJugglers":2,
>
> "pattern":"< 8 6 7 7 7>",
>
> }
>
> Again the same pattern. There are 2 jugglers, so the shift must be 5/2 = 2.5. There are no fractions, so this is a multi-handed notation.
>
> *other fractions *
>
> {"nJugglers":5, "pattern":"< 3.6 3 3>"}
>
> The fraction indicates that there is a pass to a juggler that is shifted 0.6 count. (after 5 jugglers, this makes 3 counts, so the last pass fits in
> the pattern) {"nJugglers":5, "pattern":"< 3.6 3 3>",
>
> "jugglerShift": "[0, 0.6, 1.2, 1.8, 2.4 ]"}
>
> This is the same as the previous pattern. {"nJugglers":5, "pattern":"< 3.6 3 3 | 3.6 3 3 | 3 3.6 3 | 3 3.6 3 | 3 3 3.6 >",
>
> "jugglerShift": "[0, 0.6, 0.2, 0.8, 0.4 ]"}
>
> This is the same as the previous pattern. (note: the shifts are different, so the patterns had to be shifted for jugglers 3,4 and 5)
>
> {"pattern":"< 3.33 3 1 3 3>"}
>
> or
>
> {"nJugglers":3, "pattern":"< 3.33 3 1 3 3>"}
>
> "jugglerShift": "[0, 1.67, 2.33]"}
>
> Of course, .33 means 1/3 and .67 mean 2/3. If only the sequence for juggler 1 is given, the shifts will be period/3, 2 * period/3 etc. or
>
> {"nJugglers":3, "pattern":"< 3.33 3 1 3 3 | 3 3.33 3 1 3 | 1 3 3 3.33 3 >",
>
> "jugglerShift": "[0, 0.67, 0.33]"}
>
> or
>
> {"nJugglers":3, "pattern":"< 3.33 3 1 3 3 | 1 3 3 3.33 3 | 3 3.33 3 1 3 >",
>
> "jugglerShift": "[0, 0.33, 0.67]"} (note: the shifts are different, so the patterns are in a different order)
>
> or
>
> {"nJugglers":3, "pattern":"< 3.33 3 1 3 3 | 1 3 3 3.33 3 | 3 3.33 3 1 3 >"}
>
> If there is a separate sequence for each juggler, and no shift is indicated, the shift will be 1/3, 2/3 etc.
>
> Perhaps there should be a parameter that states the desired denominator of the fraction, so wil wil know that 0.7 means 2/3. (for poly-rhythmic
> patterns, this will also be useful)
>
> Like: {"nJugglers":3, "denominator":3, "pattern":"< 3.3 3 1 3 3>"}
>
> (in this case, the only possible fractions are .3 and 0.7 (=.66666....) so 1 digit is sufficiently accurate.
>
> *synchronous throws 2 in each hand *
>
> Now come some patterns with 2 balls in each hand, 1 hand throws every 2nd beat, the other hand throws every 3rd beat. We would expect that the hand
> that throws more often, will throw lower. However, it can also throw at the same height, and have a longer empty duration.
>
> { "pattern":"< (4,6) (,) (4,) (,6) (4,) (,) >"}
>
> This is a pattern that has synchronous and a-synchronous throws. Perhaps you are used to the notation:
>
> < (4,6) (0,0) (4,0) (0,6) (4,0) (0,0) > But the "0" suggest that the hand is empty, and it may hold an object at those times.
>
> */flight durations/*
>
> { "pattern":"< (4,6) (,) (4,) (,6) (4,) (,) >",
>
> "flight_durations": "< (2.2,3.2) (,) (3.2,) (,2.2) (3.2,) (,) >" }
>
> So the hold durations of these throws are: < (1.8,2.8) (,) (1.8,) (,2.8) (1.8,) (,) >
>
> And the empty duration is 0.2 for each throw. < (0.2 0,2) (,) (0.2,) (,0.2) (0.2,) (,) > (hold duration = siteswap value - flight duration empty
> duration = time between throws - hold duration)
>
> { "pattern":"< (4,6) (,) (4,) (,6) (4,) (,) >",
>
> "flight_durations": "< (3.2,3.2) (,) (3.2,) (0,3.2) (3.2,0) (,) > " }
>
> Now, all throws are at the same height. Some hold durations will be shorter: < (0.8,2.8) (,) (0.8,) (,2.8) (0.8,) (,) >
>
> And the empty durations will be different: < (1.2,0.2) (,) (1.2,) (,0.2) (1.2,) (,) >
>
> *3 balls vs 2 balls *
>
> The hand that juggles more balls, will either throw higher, or more often. Or both, for example:
>
> { "pattern":"< (6,6) (,) (6,) (,6) (6,) (,) >",
>
> "flight_durations": "< (4.2,3.2) (,) (4.2,) (0,3.2) (4.2,0) (,) > " }
>
> So the hold durations of these throws are: < (1.8,2.8) (,) (1.8,) (,2.8) (1.8,) (,) >
>
> And the empty duration is 0.2 for each throw. < (0.2 , 0.2) (,) (0.2,) (,0.2) (0.2,) (,) >
>
> Throws at the same height: { "pattern":"< (6,6) (,) (6,) (,6) (6,) (,) >",
>
> "flight_durations": "< (4.2,4.2) (,) (4.2,) (,4.2) (4.2,) (,) > " }
>
> Now all throws are the same height, and have the same hold duration: < (1.8,1.8) (,) (1.8,) (,1.8) (1.8,) (,) >
>
> The empty times are now different: < (0.2, 1.2) (,) (0.2,) (,1.2) (0.2,) (,) > (the hand that juggles fewer objects is more often empty)
>
> Just throwing higher:
>
> { "pattern":"< (6,4) (,) >"}
>
> alternating hands:
>
> { "pattern":"< (6x,4) (,) (4,6x) (,) >"}
>
> The alternation of hands may be indicated by a symbol: { "pattern":"< (6x,4) (,) % >"}
>
> Of course, passing patterns can also be written: { "pattern":"< (4x,3p) (,) | (,) (4x,3p) >"}
>
> (this is passing 7 clubs, double selfs, single passes)
>
> or {"nJugglers":2, "pattern":"< (4x,3p) (,) >" "jugglerShift": "[0, 1]"}
>
> The pass implies that there are 2 jugglers, so the following notation would be sufficient:
>
> { "pattern":"< (4x,3p) (,) >"}
>
> A more complicated pattern would be: (synchronous self/pass, then some selfs)
>
> { "pattern":"< (3,4xp) (,4x) (,) (3,) >"}
>
> *poly-rhythmic*
>
> If the frequencies relate as 2/3 or 2/4, patterns can easily be described using synchronous throws. For ratios like 3/4 or 3/5 etc, we would need many
> (,) in the pattern. So I want to use a notation that has fractions.
>
> (to be expanded)
>
>
>
> On Thursday, 15 October 2020 at 12:58:12 UTC+2 ad.gol...@gmail.com wrote:
>
> Interesting example with zips, it happens with JugglingLab too (I normally set BPS and when you do that it stops throwing them early so hadn't
> realised before you mentioned it). I think I agree then that we need the information there,
>
> > I think of a simple flag like "EARLY_ZIPS = true", but I can imagine that someone wants a value between "earliest" (catch on the beat) and
> "latest" (throw on the beat)
> Agreed, e.g. JugglingLab's default is a bit early and lands a bit late - we want that flexibility.
>
> > This might explain why JML splits throws/catches as separate events.
> How so? They could easily be put into the throw event still - I feel like the reasoning there is so that each event does one thing and they can be
> sorted.
>
> Cheers,
> Adrian
>
> On Thu, Oct 15, 2020 at 8:12 AM JaCo Stuifbergen <j.c.stu...@gmail.com> wrote:
>
>
> This is my reaction to:
> =================================================
> On Wed, 14 Oct 2020 at 15:11, Adrian Goldwaser <ad.gol...@gmail.com> wrote:
> *Physical throws*:  
> - I don't think animation data should override throw time - a causal diagram (i.e. 'logical throws') should show the actual throw time IMO,
> animators shouldn't need to change that, modifying catch time is enough
>
> Do we want to split throws/catches as separate events? Again, it's something that JML does but I'm not sure why it has it that way, it would
> make simple cases more complex but may help with more complex cases?
>
> Other pattern definition links that might be useful:
> - JML (JugglingLab): https://jugglinglab.org/html/jml.html
> <https://jugglinglab.org/html/jml.html>, https://github.com/jkboyce/jugglinglab/tree/master/source/jugglinglab/jml
> <https://github.com/jkboyce/jugglinglab/tree/master/source/jugglinglab/jml>
> - Gunswap (much higher level, not sure if there's an internal one too): http://www.gunswap.co/about/syntax <http://www.gunswap.co/about/syntax>
>
> Cheers,
> Adrian
> ===================================================
> I will use the following terms:
>
> *throw duration:* the site-swap value
> *flight duration: *the time that an object spends in the air (not held) between 2 throws
> *throw time:* the time mark when the object is thrown
> *catch time: *the time mark when the object is caught
> *hold duration: *dwell time. how long an object is in the hand
> *empty duration: *how long a hand is empty between throws
>
> The unit of time is a "beat": this is the regular time between two throws of 1 juggler.
> (I will ignore poly-rhythms for a moment)
>
> ## general comment
> throw duration = flight duration + hold duration.
> The causal diagram specifies throw durations, not flight durations.
>
> So we need some parameter (like "empty duration = 0.3 beat") to arrive at the actual flight durations
>
> ## early zips versus late zips
>
> On my web-site http://jacos.nl/causal-diagrams/ <http://jacos.nl/causal-diagrams/>
> you will see a causal diagram for <531> at the bottom, and the corresponding ladder diagram above.
> Note that I use a different height for each hand.
>
> Because there is a catch on every beat, the ball that is zipped ("1") cannot be held long, so the hold times (and empty times) vary.
> In fact, the throw is done early.
> This is how I juggle zips. I want to hear a catch on every beat, so I throw the zips early.
>
> If I make the zip on the (next) beat, the catch will be late, so the hold time after the zip will be shorter.
> It seems to me that the animators Joepass and passist.org <http://passist.org> do this.
>
> By the way, if the empty time is made longer for every throw, this problem disappears.
> But that will make an animation (or a ladder diagram) less realistic.
>
> In my opinion, a causal diagram does not specify whether the zips should be late or early.
>
> So this should be a parameter in the pattern description, if we want to describe the physical pattern.
>
> I think of a simple flag like "EARLY_ZIPS = true", but I can imagine that someone wants a value between "earliest" (catch on the beat) and
> "latest" (throw on the beat)
> This might explain why JML splits throws/catches as separate events.
> (Or does it indicate the start of a new move in the animator?)
>
> Co Stuifbergen
>
> --
> 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/265a3e84-8157-4876-909c-93851f27325an%40googlegroups.com
> <https://groups.google.com/d/msgid/juggling-interchange-format/265a3e84-8157-4876-909c-93851f27325an%40googlegroups.com?utm_medium=email&utm_source=footer>.
>
> --
> 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
> <mailto:juggling-interchang...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/juggling-interchange-format/27811d53-ae51-42ba-bb90-1b34d97f1b85n%40googlegroups.com
> <https://groups.google.com/d/msgid/juggling-interchange-format/27811d53-ae51-42ba-bb90-1b34d97f1b85n%40googlegroups.com?utm_medium=email&utm_source=footer>.


JaCo Stuifbergen

unread,
Oct 18, 2020, 4:41:21 AM10/18/20
to juggling-interchange-format
In reply to Florian:

I like the idea of specifying throws per hand (or foot, head etc.).

Your notation still makes the tacit assumption that between two throws is 1 beat.
And I think that time ratio's can be specified relative to absolute time.

I propose the following:

{
beatgroups: [
    {name: "juggler1-right-hand",
    period: 6,
        throws: [
        { atBeat: 0, to: "juggler1-left-hand",
        beats-till-landing: 5},
         {atBeat: 2, to: "juggler1-left-hand",
        beats-till-landing: 1},
         {atBeat: 4, to: "juggler1-left-hand",
        beats-till-landing: 3}]
                           
             },
     {name: "juggler1-left-hand",
    period: 6,
        throws: [
        { atBeat: 1, to: "juggler1-right-hand",
        beats-till-landing: 3},
         {atBeat: 3, to: "juggler1-right-hand",
        beats-till-landing: 5},
         {atBeat: 5, to: "juggler1-right-hand",
        beats-till-landing: 1}]
                           }]
}

I have removed some "meta-data" like:
- the time between throws is 1 count
- hands are alternating, the left hand starts 1 count later
- each hand juggles the same sequence, only shifted in time

If a program is aware of such things, it can simplify the pattern for humans.

Should programs be able to figure such things out by themselves?
- this is vanilla site-swap
- this is 4-handed or 6-handed siteswap
- this is a social siteswap
- after half the period, L and R are exchanged (like (6x,4) (,) (4,6x) (,) )

Or should it be added as optional information?
(Or not added at all)

By the way, the extension to poly-rhythms is indeed easy, here is a ration of 3/4 :

{
beatgroups: [
    {name: "juggler1-right-hand",
    period: 3,
        throws: [
        { atBeat: 0, to: "juggler1-right-hand",
        beats-till-landing: 1.5},
         {atBeat: 0.75, to: "juggler1-left-hand",
        beats-till-landing: 2.25},
         {atBeat: 1.5, to: "juggler1-right-hand",
        beats-till-landing: 1.5},
         {atBeat: 2.25, to: "juggler1-right-hand",
        beats-till-landing: 1.5}]
                           
             },
    {name: "juggler1-left-hand",
    period: 3,
        throws: [
         {atBeat: 0, to: "juggler1-left-hand",
        beats-till-landing: 2},
        { atBeat: 1, to: "juggler1-right-hand",
        beats-till-landing: 1.25},
         {atBeat: 2, to: "juggler1-left-hand",
        beats-till-landing: 2}]
                           }]
}


JaCo Stuifbergen

unread,
Oct 18, 2020, 5:02:02 AM10/18/20
to juggling-interchange-format
Christian,

Your proposal sounds good.
In your proposal, software will not convert back to a higher-level description.
That seems reasonable.

There may be some discussion which higher level languages should be accepted, but of course, we can make every higher-level language optional.
Each programmer may then decide which types will be recognized: "vanillaSiteswap", "multiJugglerSiteSwap", "takeOutNotation", etc.

I am tempted to add a layer "ladder diagram" which contains information about the hold durations etc.

JIF with only high-level description => code =>
JIF with logical throws for the causal diagram  (Florian's proposal would apply to this level, I think)=> code =>
JIF with logical throws for the ladder diagram => code =>
JIF with more exact information about animation

(by the way, I don't like the term "hold duration".  Normally, we say hold time, but I want to distinguish between time-marks (like 12:04) and intervals ( 2 minutes). Perhaps "hold interval" is better)

Adrian Goldwaser

unread,
Oct 18, 2020, 9:42:35 AM10/18/20
to juggling-interchange-format
Combining my responses to all emails together...

> But I think it would be a mistake to repeat the handwritten notation in
> the juggling information format as it should be good for computers to
> read and write, not for humans (The program should be able to make

> nice human readable text from the JIF and vice versa but we don't need
> to save it very human readable).
I agree, I think handwritten notation should more be in a free-text form rather than part of the spec - we can have tools that convert takeout notation to JIF, SS to JIF, etc. The JIF to human readable text may be difficult in some cases but we can probably get the simple cases easily at least. I think it makes more sense to have a lower level description with JIF and have it as a common format, otherwise we fall into the same situation as now where there's a whole lot that people need to support.

> beatgroups [...]
I think I'd prefer it linked directly to times (e.g. similar to how Co put it) rather than having to look at beats and a type of siteswap to extract the time out, but otherwise seems reasonable (though merging hands together would make things more readable IMO).

> Should one high-level description be enough or are there cases where we want to represent multiple different
> high-level descriptions for the same pattern?
> Or should we declare our own description(s) in the same way, maybe even splitting the logical from the physical description?
I think we want to minimise this as much as possible (personally I think there should only be one representation), otherwise things can get out of sync and now we need an ordering too (does a simulator prefer the JugglingLab extended SS which can support bounce throws or the logical throws which can support polyrhythms?). I think human readable parts (e.g. siteswap) should go in the human readable free-text description and not be 'part' of the JIF standard. I'd also still prefer logical/physical joined as there is a lot of shared information, let's say I want to have a logical pattern then I decide I need to also specify number of spins (or hand location, or maybe I want early zips), I now need to copy the entire thing just for that. Having it slowly extensible to the level needed seems simpler and less error-prone for things to be out of sync. Of the things in the 'logical' part, from/to hand are already in physical throws, as is label (might be needed for annotating simulations), duration/time are already there implicitly almost all of the time (for time, except for e.g. early zips, it's there and for duration it's almost always there implicitly for the same reason).

> When writing the passist animation I saw there is much code dedicated to filling
> missing information like defining dwell times, hand positions, hand movements (during dwell time and in-between),
> calculating prop rotations, ...
> The "physical" representation above would allow this kind of logical code to be split away from the actual 3d code.
I feel like you can do this anyway? Take a JIF input which has very little to no physical information and you have a section first that fills in any missing information, creating a 'full' JIF for the purposes of your animator, then pass that to be simulated.

> Should programs be able to figure such things out by themselves?
> - this is vanilla site-swap
I don't think things that are taking in JIF will care about this, but it's easy for them to check if needed.

- this is 4-handed or 6-handed siteswap
Again should be simple to work out

- this is a social siteswap
What does this mean?

- after half the period, L and R are exchanged (like (6x,4) (,) (4,6x) (,) )
I think this should be explicit as a symmetry if it's needed.

> I am tempted to add a layer "ladder diagram" which contains information about the hold durations etc.
This is a strict subset of physical throws - I'd definitely agree this hierarchy exists but it makes things cleaner if it's implicit.

--
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,
Oct 18, 2020, 2:55:20 PM10/18/20
to juggling-interchange-format
High level / low level descriptions.

In the scheme that Christian proposed, information can be passed in 1 direction:
JIF with only high-level description => code =>
JIF with logical throws for the causal diagram  (Florian's proposal would apply to this level, I think)=> code =>
JIF with more exact information about animation

In simple cases, the high-level description can be reconstructed, but I think that it does not have to be a requirement.

I am inclined to allow many high-level description types.
Some can be defined soon (like vanilla siteswap), some may have to be invented (a human-readable form of polyrhythms).
And some may contain many physical instructions (number of spins of a club, catches behind the back, body rolls, balances).
Depending on the type chosen, a different conversion will be required.

If we allow only 1 high-level description, that will describe all possible patterns, it might be difficult to write a converter, although I think that the exampels that I gave yesterday, can be converted without ambiguity \_(ツ)_/    .

Of course, a program may also give a causal diagram as output, without ever requiring a higher-level description.

splitting the logical from the physical description?
I am inclined to add the physical description as an option to the logical description in the 2nd layer.
{ name: "juggler1-right-hand",
    period: 3,
    physical: { position:[ {atBeat:0, x:0, y:0}, {atBeat:1.5, x:10, y:20}}
    throws: [
{ atBeat: 0, to: "juggler1-left-hand",
        beats-till-landing: 5,
     physical: {hold_duration: 1.2, club_manipulation: "chop", spins: 3}},
{ atBeat: 1, to: "juggler1-left-hand",
etcetera

The main reason is that if the high-level description contains physical information, it has to be passed to the second layer.

social siteswap notation
Just nice to know:
Those are the patterns of the kind
<3 3 4 4p > in which the other juggler does the same thing, but shifted half a period.
or < 3.6 3 3 > in which 5 jugglers are shifted by 3/5 = 0.6

A social siteswap can be obtained from a solo siteswap by the following procedure:
  1. take a solo site-swap.
  2. calculate period/nJugglers
  3. the jugglers must be shifted in time by this number
  4. add or subtract this number (or a multiple) to any site-swap value in the sequence.
Originally, it was called "Prechac notation" but apparently, Mr Prechac was too modest to lend his name to it.
(or, being a professional mathematician, he didn't want to be associated with such a trivial notation).
The procedure also works for solo siteswaps that contain synchronous throws, multiplexes or poly-rhythms.

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

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

JaCo Stuifbergen

unread,
Oct 19, 2020, 4:02:29 PM10/19/20
to juggling-interchange-format
I still have to reply to Adrian's comment
> I am tempted to add a layer "ladder diagram" which contains information about the hold durations etc.
This is a strict subset of physical throws - I'd definitely agree this hierarchy exists but it makes things cleaner if it's implicit.
 
I agree that 3 layers look better than 4 layers of which 2 layers look similar.

You are also right that "hold durations" (sorry for the ugly word) are part of the physical description, not the logical description.

There is a parameter that should, in my opinion, be part of the logical layer:
- Throw_On_The_Beat (late zips) versus Catch_On_The_Beat (early zips)

I cling to this distinction because I like to hear the rhythm of the catches (especially in poly-rhythmic patterns).
You can imagine that late zips change the rhythm significantly.

Because of the early zip, a pattern that is described by "5 3 1" using Catch_On_The_Beat,
might be described as " 5 (3,1) 0 " using Throw_On_The_Beat

And vice versa: " 5 3 1 3 3 3" using Throw_On_The_Beat may have the 3 and 1 land at the same time,
so it might be written "5 3 0 (1,3) 3 3" using Catch_On_The_Beat

I write "might" because it also depends on the hold duration: if the hold duration is small enough, there is no difference.
"small enough" would be: less than the time between two beats.
But of course, this is a physical parameter that we don't want to impose by JIF.


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

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


On Sun, 18 Oct 2020 at 15:42, Adrian Goldwaser <ad.gol...@gmail.com> wrote:

Adrian Goldwaser

unread,
Oct 21, 2020, 9:23:05 AM10/21/20
to juggling-interchange-format

> In simple cases, the high-level description can be reconstructed, but I think that it does not have to be a requirement.
Agreed, I think any case where it came from a siteswap should theoretically be able to be converted back to one.

> I am inclined to allow many high-level description types.
> Some can be defined soon (like vanilla siteswap), some may have to be invented (a human-readable form of polyrhythms).
> And some may contain many physical instructions (number of spins of a club, catches behind the back, body rolls, balances).
> Depending on the type chosen, a different conversion will be required.
> If we allow only 1 high-level description, that will describe all possible patterns, it might be difficult to write a converter, although I think that the exampels that I gave yesterday, can be converted without ambiguity \_(ツ)_/    .
My issue with allowing high level description types is that now in order to support JIF, a program has to understand a whole lot of different options. I like the idea of JIF only explaining the 'low level' part (maybe with some extra metadata so some higher level features can be extracted), because then it becomes a common language for any simulator/ladder diagram editor, etc. I think these high level languages are really useful, but, e.g. I don't think simulators should need to know about polyrhythms, instead you design a polyrhythm notation then you can write a converter to JIF and then send the JIF to a simulator, the same for the many SS variants, manipulator notation, etc etc. These are all incredibly useful notations that we should really develop tools for - I just don't think they should be 'baked in' to JIF. Additionally they can get out of sync with each other.

> I am inclined to add the physical description as an option to the logical description in the 2nd layer.
This makes sense to me - though we can have them as 'top level' attributes rather than nested in a 'physical' sub-object for clarity - we can always leave individual ones out that we don't care about.

> Originally, it was called "Prechac notation"
Ah yes, I know them as 'Prechacs' - good to know I should be calling them social siteswaps instead.

> There is a parameter that should, in my opinion, be part of the logical layer: Throw_On_The_Beat (late zips) versus Catch_On_The_Beat (early zips)
I think if we set this out right then it doesn't need to be a separate parameter or specific to zips etc. For example:

throws = [
  {time:0, type:'throw', height:5, catchTime:4, fromHand:0, toHand:1},
  {time:1, type:'throw', height:3, catchTime:3, fromHand:1, toHand:0},
  {time:2, type:'throw', height:1, catchTime:2, fromHand:0, toHand:1, throwOffset;-0.5},
  {time:3, type:'throw', height:5, catchTime:7, fromHand:1, toHand:0},
  {time:4, type:'throw', height:3, catchTime:6, fromHand:0, toHand:1},
  {time:5, type:'throw', height:1, catchTime:5, fromHand:1, toHand:0, throwOffset:-0.5},
]

Here the time, height, from/toHand are used for the logical layer and the physical layer adds the fact that there's always 1 beat of dwell time (through the catchTimes - maybe that should be entered using dwell instead but they're equivalent so I just chose randomly for now) and that the 1s are thrown early so they have nonzero flight time. If catchTime and throwOffset are left blank then simulators can use smart defaults to make things look good (like most simulators already do) or we can define some JIF recommended smart defaults (e.g. 1 dwell beat and zips have a throw offset of -0.5, the rest have a throwOffset of 0). To describe Throw_On_The_Beat, we'd set throwOffset=0 and catchTime=1.5 and 4.5 for the zips.

My main issue with this at the moment is just that they can still get slightly out of sync (the throwOffset can be anything really), however it's at least explicitly tied to the time.

JaCo Stuifbergen

unread,
Oct 21, 2020, 3:26:53 PM10/21/20
to juggling-interchange-format
high-level descriptions (level 1 of JIF).
I think that for level 1, we have a few options:
  1. not define level 1.
    Each programmer can choose her/his favorite high-level language, and format the output according to level 2
  2. set specifications for the high-level input that programs should conform to, and which does not have to be able to describe every possible pattern.
    E.g. not poly-rhythms or take-out notation.
    Software that generates such patterns, should convert the pattern to standard notation, or directly to level 2.
    (my current poly-rhythm generator (http://www.jacos.nl/jongleren/polyrhythm/) only has graphical output)
  3. allow multiple specifications for level 1, and let programmers decide which varieties they support.
    (my original proposal).
    Probably, some varieties will become widely supported (e.g. vanilla siteswap) and some only by specialized software, but the exchange of files will more often be possible (I hope) than if we set no specification.
Throw_On_The_Beat (late zips) versus Catch_On_The_Beat (early zips):

In Adrian's exampel, throws that should land on the beat, do land on the beat. That makes me very happy.
But it assumes that the dwell time (empty time) will be 0.5, and dwell time is a physical parameter.

instead, we might take something like
throws = [  {launchTime:0, duration:5, catchTime:4, fromHand:0, toHand:1}, 
 {launchTime:1, duration:3, catchTime:3, fromHand:1, toHand:0},
  {launchTime:2, duration:1, catchTime:2, fromHand:0, toHand:1, throwOffset;LessThanZero},
  {launchTime:3, duration:5, catchTime:7, fromHand:1, toHand:0}, 
 {launchTime:4, duration:3, catchTime:6, fromHand:0, toHand:1},
  {launchTime:5, duration:1, catchTime:5, fromHand:1, toHand:0, throwOffset:LessThanZero},]
where "LessThanZero" specifies that if the flight time is too short, launchTime should become less.
But because this applies to every throw where launchTime==catchTime, it may just as well be a general parameter

By the way, I replaced "height" by "duration", because height is related to the physical parameters.

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

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



Adrian Goldwaser

unread,
Oct 22, 2020, 7:34:08 AM10/22/20
to juggling-interchange-format
That seems like a good summary of the options. I'd definitely be leaning towards option 1 there for the reasons I stated previously, though I think it's worth including the original string it came from in whichever notation as a metadata field. That way simulators can easily give a human readable version of the pattern (we can rely on converters to fill this in).

> But it assumes that the dwell time (empty time) will be 0.5, and dwell time is a physical parameter.
Yep, dwell time (or catch time in thi format) is physical, but so is whether or not it's early/late zips (i.e. it's not something we'd care about in a causal or siteswap), so I'm not sure why it matters that dwell time is physical? I think I'm misunderstanding you here.

> But because this applies to every throw where launchTime==catchTime, it may just as well be a general parameter
Agreed, if we do it as a high level 'should they be early or late' offset then yes it can be a general parameter, also interestingly if we do it that way then we no longer really need the 'duration' part because we can extract it based off when the object is next thrown, and add 2s as needed to deal with long holds.

> By the way, I replaced "height" by "duration", because height is related to the physical parameters.
I agree duration is a better name.


JaCo Stuifbergen

unread,
Oct 22, 2020, 2:43:51 PM10/22/20
to juggling-interchange-format
high-level descriptions (level 1 of JIF).
When I wrote option
3. allow multiple specifications for level 1, and let programmers decide which varieties they support.
I meant that, apart from specified notations, there would be a variety "custom" or "unspecified" where a programmer could store whatever kind of notation she/he likes.
Or actually, that the standard allows them to define any name that starts by "custom" (like "custom_poly", "custom_ScrambledV", "custom_passist", "custom_the_best_J_generator_ever") and hope that no other programmer chooses the same name.

That would allow programmers to choose their favorite pattern description format, while JIF indicates a preferred standard.
Or indicates a preferred standard for ordinary patterns, and another preferred standard  for contact juggling, and another for bouncing between walls, etc.

In my opinion, option 3 is then better than option 1.

Throw_On_The_Beat (late zips) versus Catch_On_The_Beat (early zips)
I agree that dwell duration is a physical parameter, and should not be in the causal diagram.

But throw/catch_on_the_beat is a logical parameter.

My main argument to include such a parameter is:
If a program supposes that throws are on the beat, and I want to describe a pattern that has catches on the beat, I must write different causal diagrams for different dwell durations.
(for example, 5 3 1 versus 5 (3,1) 0 )
And if I want poly-rhythms to sound correctly, the catches must be on the beat.

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

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


Christian Helbling

unread,
Oct 22, 2020, 5:38:23 PM10/22/20
to juggling-inte...@googlegroups.com
On 22.10.20 20:43, JaCo Stuifbergen wrote:
> *high-level descriptions (level 1 of JIF).*
> When I wrote option
>
> 3. allow multiple specifications for level 1, and let programmers decide which varieties they support.
>
> I meant that, apart from specified notations, there would be a variety "custom" or "unspecified" where a programmer could store whatever kind of
> notation she/he likes.
> Or actually, that the standard allows them to define any name that starts by "custom" (like "custom_poly", "custom_ScrambledV", "custom_passist",
> "custom_the_best_J_generator_ever") and hope that no other programmer chooses the same name.
>
> That would allow programmers to choose their favorite pattern description format, while JIF indicates a preferred standard.
> Or indicates a preferred standard for ordinary patterns, and another preferred standard  for contact juggling, and another for bouncing between walls,
> etc.
>
> In my opinion, option 3 is then better than option 1.

I generally agree with Adrian on this one. The jif standard should neither focus nor define any high-level notations.
Being able to define the logical throws more and more in the same data structure sounds reasonable.

Your options 1 and 3 were confusing me a bit and I didn't quite get which one fits my opinion :)
It's probably something in-between:

I would allow putting high-level descriptions into jif, as the original notation is usually of interest. Maybe even the converter parameters that were
used.
I would not include any specification of high-level descriptions into the jif specification.
However, I'd specify where such information can be included into a jif.
For commonly used and well defined notations we can specify type names to use and link to its specification in our jif specification.

I'm thinking of those, but maybe we know/find some more well defined ones:
vanilla siteswap: https://en.wikipedia.org/wiki/Siteswap#Vanilla
jugglinglab siteswap: https://jugglinglab.org/html/ssnotation.html#notation
jml: https://jugglinglab.org/html/jml.html (not so high-level anymore, but it should be convertible to jif)

everyone is encuraged to invent and use their own notations and use custom type strings freely.
one of my incentives to create jif was exactly that people can play with some creative new notations,
write one converter and then have a fully grown software stack available for generating various visualizations,
animations, verifiers, editors and so on.


software dealing with jif should not need to know anything about any of those notations.
the only things they need to be able to handle is our own notation about logical and physical throws,
movements, jugglers, hands and so on (but only the data that is relevant for the scope of the program).

> *Throw_On_The_Beat (late zips) versus Catch_On_The_Beat (early zips)*
> I agree that dwell duration is a physical parameter, and should not be in the causal diagram.
>
> But throw/catch_on_the_beat is a logical parameter.
>
> My main argument to include such a parameter is:
> If a program supposes that throws are on the beat, and I want to describe a pattern that has catches on the beat, I must write different causal
> diagrams for different dwell durations.
> (for example, 5 3 1 versus 5 (3,1) 0 )
> And if I want poly-rhythms to sound correctly, the catches must be on the beat.

I think this is all on the level of converting a high-level notation to jif. It might be even different converter parameters.
Like: please convert my the vanilla siteswap 531 into jif but with all the catches on the beat.
But yes, we will need to be careful that not all the physical parameters need to be written just to convert a catch-on-the-beat throw.

As I understand, in the current proposal, the pysical throws can be quite different than the logical throws.
We choose to do that because the logical throws are a simplification of reality in order to simplify editing and
thinking about patterns.
In reverse that means, that for the same physical pattern we are allowed to have multiple logical representations and thats fine.
For example, is the siteswap 522 different than the siteswap 3 juggled really high and with late throws?

I think Adrians proposal goes into the right direction in that the logical throws can be slowly extendible and its also possible
to have something in-between throw-on-the-beat and catch-on-the-beat. Im not even sure those two are used most often in real juggling..
I still have to look at the proposal more deeply, didn't have the time yet.


Also I think I never actually sent my answer to the following question :)

> Because there is a catch on every beat, the ball that is zipped ("1") cannot be held long, so the hold times (and empty times) vary.
> In fact, the throw is done early.
> This is how I juggle zips. I want to hear a catch on every beat, so I throw the zips early.
> If I make the zip on the (next) beat, the catch will be late, so the hold time after the zip will be shorter.
> It seems to me that the animators Joepass and passist.org do this.

Currently passist has the dwells implemented as Adrian described them. The logical throw time (as in the causal diagram)
is split up into the actual throw time followed by the dwell time.

Dwell formula is currently this:
const soloHeight = e.duration / jif.nJugglers;
e.dwell = (soloHeight > 2 ? 1 : (soloHeight < 1 ? 0 : 0.5)) * jif.nJugglers;

This means a zip would be 0.5 beats throw time followed by 0.5 beats dwell time.
However, there is an additional trick which modifies the throw and catch positions in case of zips.

In my current model throw times of causal and animation are always exactly the same and catch times
depend on the dwell values.

Cheers
Christian

JaCo Stuifbergen

unread,
Oct 24, 2020, 3:10:24 AM10/24/20
to juggling-interchange-format
I would allow putting high-level descriptions into jif, as the original notation is usually of interest. Maybe even the converter parameters that were
used.
I would not include any specification of high-level descriptions into the jif specification.
However, I'd specify where such information can be included into a jif.
For commonly used and well defined notations we can specify type names to use and link to its specification in our jif specification
.

I had not thought of this option, and it is a sensible solution. OK for me.

But yes, we will need to be careful that not all the physical parameters need to be written just to convert a catch-on-the-beat throw.
The problem with Adrian's proposal is different: it requires that, to specify catch-on-the-beat, the logical description may have to be rewritten when longer or shorter dwell times are chosen.

If we want to stick to purely causal notation, it might be something like:
throws = [ 
 {startBeat:0, endBeat:5, fromHand:0, toHand:1},  //duration = 5
 {startBeat:1, endBeat:4, fromHand:1, toHand:0},  // duration = 3
 {startBeat:2, endBeat:3, fromHand:0, toHand:1},  // duration = 1
 {startBeat:3, endBeat:8, fromHand:1, toHand:0}, 
 {startBeat:4, endBeat:7, fromHand:0, toHand:1},
 {startBeat:5, endBeat:6, fromHand:1, toHand:0}] 
// (My apologies for avoiding the word "time". It can mean "beat" or "duration" and I want to avoid confusion.)

throw-on-the-beat or catch-on-the-beat should then be a physical parameter.
I have some worry that half of the programmers will only animate throw-on-the-beat.

something in-between throw-on-the-beat and catch-on-the-beat. Im not even sure those two are used most often in real juggling.
I think that if you measure precisely, no one throws or catches exactly on the beat. It is difficult to measure when a throw starts, because throws make less sound then catches.
It might be conceivable that an animator modifies both throw beat and catch beat (adds some hold duration before and after the flight of an object).

e.dwell = (soloHeight > 2 ? 1 : (soloHeight < 1 ? 0 : 0.5)) * jif.nJugglers;
Thanks for the explanation! (So for really short siteswap values, the dwell time is zero. Those must be quick throws!)


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.

Florian Pesth

unread,
Oct 24, 2020, 4:21:59 AM10/24/20
to JaCo Stuifbergen, juggling-interchange-format
Hi everyone,

sorry for not taking part in the latest discussion, I did not have a
lot of time (still dont) but I tried to follow the discussion.

Am Sat, 24 Oct 2020 09:10:11 +0200
schrieb JaCo Stuifbergen <j.c.stu...@gmail.com>:

> >
> > I would allow putting high-level descriptions into jif, as the
> > original notation is usually of interest. Maybe even the converter
> > parameters that were
> > used.
> > I would not include any specification of high-level descriptions
> > into the jif specification.
> >
> > *However, I'd specify where such information can be included into a
> > jif. For commonly used and well defined notations we can specify
> > type names to use and link to its specification in our jif
> > specification*.
>

I think this is a good idea, I agree mostly with Adrians
and Christians points.

> I had not thought of this option, and it is a sensible solution. OK
> for me.
>
> But yes, we will need to be careful that not all the physical
> parameters
> > need to be written just to convert a catch-on-the-beat throw.
> >
> The problem with Adrian's proposal is different: it requires that, to
> specify catch-on-the-beat, the logical description may have to be
> rewritten when longer or shorter dwell times are chosen.
>
> If we want to stick to purely causal notation, it might be something
> like: throws = [
> {startBeat:0, endBeat:5, fromHand:0, toHand:1}, //duration = 5
> {startBeat:1, endBeat:4, fromHand:1, toHand:0}, // duration = 3
> {startBeat:2, endBeat:3, fromHand:0, toHand:1}, // duration = 1
> {startBeat:3, endBeat:8, fromHand:1, toHand:0},
> {startBeat:4, endBeat:7, fromHand:0, toHand:1},
> {startBeat:5, endBeat:6, fromHand:1, toHand:0}]
> // (My apologies for avoiding the word "time". It can mean "beat" or
> "duration" and I want to avoid confusion.)

That looks good to me (and I think it is good to distinguish between
beat and time - we can define the time of the beat but this should be
optional IMO). I think I have a slight preference for numbers references
to strings instead of strings (and make strings optional) because it
makes the files smaller but this is probably not priority as the files
will probably never get really large. But names could be optional if
one justs ones to describe the causal pattern (If I just want to write
531 without caring if it is juggled by hands or feet).

I first didn't understand the need to map to keywords for hands instead
of just naming them - on the causal level - but I overlooked that if
there are two programs capable of animation they might want to
understand both that the same throwing position is a hand so we should
standardize this naming (but maybe allow for arbitrary additional names
not to restrict what to describe).

>
> throw-on-the-beat or catch-on-the-beat should then be a physical
> parameter. I have some worry that half of the programmers will only
> animate throw-on-the-beat.
>

I think we should think of the causal notation as a mechanism to avoid
certain patterns if one wishes to do so - not as a description of exact
throws or catches.

Than we can define the catch and throw as delays to the beat.

> something in-between throw-on-the-beat and catch-on-the-beat. Im not
> even
> > sure those two are used most often in real juggling.
> >
> I think that if you measure precisely, no one throws or catches
> exactly on the beat. It is difficult to measure when a throw starts,
> because throws make less sound then catches.

Maybe something like this?

{startBeat:0, endBeat:5, fromHand:0, toHand:1,
catchTimeRelativeToBeat:-0.1 throwTimeRelativeToBeat:0.3},
{startBeat:1, endBeat:4, fromHand:1,
toHand:0, catchTimeRelativeToBeat:-0.1 throwTimeRelativeToBeat:0.2}, //
duration = 3
{startBeat:2, endBeat:3, fromHand:0, toHand:1,
toHand:0, catchTimeRelativeToBeat:-0.1
throwTimeRelativeToBeat:0.1}, // duration = 1

This would allow to describe the irregularities of the 531 (Throw the
3 earlier than the 5 and the 1 earlier than the 3) and also to check
programatically if there are times when our "hand constraint" of for
example catching only one ball in the hand would be violated. That
would be an optional parameter, so if one program decides not to store
this information another program reading this file and wanting to
animate it could come up with reasonable values itself - or might even
ignore stored values to "improve" the pattern.

One might think about allowing at least two units in the program -
beats and time (above notation assumes beat as a unit).

One thing I wanted to mention about the idea of beatgroups (i.e. the
idea to be able to define throws/catches in terms of beats with
multiple different beat durations) is that it might be nice to allow
for this to avoid having to write floating point numbers for
polyrythmic patterns (I think this should probably go in a different
thread). Otherwise we get computationaly nasty numbers like 1.3333333.

Maybe we should also allow real fractions?

Side remark: If we have the general concept of beats this maps nicely
to columns in the Eshkol Wachman movement notation or in the Harmonic
Throws notation as well I think (Unfortunately I didn't find much
online information about the harmonic throws notation and I'm not sure
how "open" it is). We should be able to map the throwing / catching
positions to body parts in the movement notation as well so that we can
describe the movement of the hand until the throw for example - which
would allow to describe patterns like "fake columns" to name a simple
example.

Cheers,
Florian

JaCo Stuifbergen

unread,
Oct 24, 2020, 5:20:50 PM10/24/20
to juggling-interchange-format
PS about:
- Eshkol Wachman movement notation
- the Harmonic Throws notation 

From the wikipedia, I gather that the Eshkol Wagman notation describes the relative orientations (angles) between feet, legs, body, arms etc. And positions can be calculated from the positions of the feet (for someone standing. When you hang on an arm, you should start by the hand I think).
That should allow to describe all positions of jugglers and limbs.

The Harmonic throws notation does not describe the body positions as precisely, but more schematically.


A short description of the harmonic throws notation:
imagen.png
The upper left rectangel indicates the number of objects in each hand at the start.
The upper row simply indicates the site-swaps that are thrown (a 1 is a dot on the lowest line, a 2 one line higher, etc.)

The lower row contains schematic drawings of the body, that indicate the juggler's position.
e.g. this drawing means that the head is turned right: ├

Between those rows, the letters indicate where a ball would pass, according to the drawing at 2:08

So, the harmonic throws notation is meant to be read by humans. In my opinion, it is not very helpful for software specifications.

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

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



Florian Pesth

unread,
Oct 24, 2020, 6:17:40 PM10/24/20
to juggling-interchange-format
Yes, you might be right about that. I looked more deeply into Eshkol
Wachman (which has been used programatically although pretty early -
there is a PDF about that but I can't find it now - I sent a link to
Christian who might still have a copy of it) but not so deeply into
harmonic throw notation but mentioned it because it seemed to be quite
popular.

I have now the physical books "Moving Writing Reading" by
Noah Eshkol which was defining the notation system and the book "The
Hand Book", also by Noah Eshkol which describes how to use and extend
the notation for sign language.

The notation has also been used for describing animal movements and for
behavioural studies of children, so I think it is quite versatile and
it seems to translate well into skeletal animation (rigging).

Noah Eshkol herself writes in the preface of the book:

"In 1958 the proposition was set forth (in the original textbook
"Movement Notation"), that by using Eshkol-Wachmann Movement Notation
it would be possible to write any movements of the human body. This
ambitious claim had a simple and apparently firm theoretical basis;
nevertheless the claim naturally required further testing.

I was aware of the possibility that the system might well be, or become
a shorthand for my own personal mode of observation, coloured by my
interests, tastes and inclinations. I therefore found it expressly
important to avoid using examples of my own work as proofs for the
validity and possible universality of the system. It is for this reason
that all of the scores in EW Movement Notation hitherto published have
dealt with styles of moving which have no direct relation to my own
daily work. The notation was (and continues to be) applied to
established modes of communication in which movement of the human body
plays the main role, such as classical ballet, the sign language of the
deaf, folk dance, athletics, and others. ..."

Am Sat, 24 Oct 2020 23:20:36 +0200

Adrian Goldwaser

unread,
Oct 25, 2020, 12:07:24 AM10/25/20
to juggling-interchange-format
> If a program supposes that throws are on the beat, and I want to describe a pattern that has catches on the beat, I must write different causal diagrams for different dwell durations.
> (for example, 5 3 1 versus 5 (3,1) 0 )

I'd argue that if you want a different causal then the 'time' parameter should be different, e.g. 

throws: [
{time:0, duration:5, from:0, to:1},
{time:1, duration:3, from:1, to:0},
{time:2, duration:1, from:0, to:1},
]
vs
throws: [
{time:0, duration:5, from:0, to:1},
{time:1, duration:3, from:1, to:0},
{time:1, duration:1, from:0, to:1},
]
or if you want it with a fast zip, something like this (note that casuals don't care about dwell times so that parameter would be ignored when viewing it)
throws: [
{time:0, duration:5, from:0, to:1},
{time:1, duration:3, from:1, to:0},
{time:1.5, duration:1, catchTime:2, from:0, to:1},
]

I think some of our difference here is coming from you defining a beat as a logical thing and then an offset for the actual throw time, in which case to show a causal correctly you need both, whereas I'm treating them by time rather than beat so the causal only needs the time, with the idea that you can now define a 'normal' causal for 531 not caring about any of this and animators will deal with it nicely by default by deciding to shift times slightly. I guess the issue with my version is if you want the animators to not shift times at all you might need to pass throwOffset:0 explicitly or something.

> I have some worry that half of the programmers will only animate throw-on-the-beat.
This is a fair point, however in my version you can still 'force' them to do it properly by setting the times like I did above, the main issue is that it's now harder to extract the original siteswap, but I don't think we should optimise for that as it should be a rare thing to do.
Though this is kind of making me think that we shouldn't have a throwOffset at all, and maybe just use the actual time, yes this will mean that unless you modify timing explicitly (which seems OK seeing as you want throw vs catch on beat visible on the causal) converting from a causal will by default give throw-on-the-beat, we can have converters from siteswaps that have options for all of this (and smart defaults) however. This would also avoid animators doing a bad job at this because it would always be specified explicitly. I feel like this is very much heading towards JML's way of only specifying throw/catch times (i.e. only the physical layer) and maybe that's the way to go, because siteswaps technically only care about order, you can normally extract them back out, and causals always specify exact throw times so it's only the awkward part of extracting the causal chain that needs to be done here (which is a problem causal viewers would need to solve anyway IMO), the issue with this would be that simple patterns are more complex - I don't know if that's a reasonable tradeoff.


JaCo Stuifbergen

unread,
Oct 25, 2020, 2:51:00 AM10/25/20
to juggling-interchange-format
Hello,

A procedural remark:
There is a risk that a discussion on the internet is dominated by persons who have too much time on their hands, and that the input of real experts is neglected.
I think that the discussion is going well, but when 2 persons write that they have to catch up, I should perhaps take longer breaks.

Back to JIF: (this is a reply to Sat, 24 Oct 2020 at 10:21, Florian Pesth <fpe...@gmx.de> )

Some of you may have noticed that I struggle with the word "time".
For the moment, I will use "beat" to describe time-marks, and "duration" for intervals.

Maybe something like this?

{startBeat:1, endBeat:4, fromHand:1,
toHand:0, catchTimeRelativeToBeat:-0.2 throwTimeRelativeToBeat:0.2},  //
duration = 3
I like the concept:
- it contains the causal diagram
- it can describe throws on the beat, or catches on the beat (or neither)

But would the example above mean that there will be a catch at beat 0.8 (startBeat + catchTimeRelativeToBeat = 1 - 0.2 = 0.8) ?
In that case, it would make the programmer's work very difficult.

Or would it be at 3.8? (endBeat + catchTimeRelativeToBeat)
In that case, I would use it for my ladder diagrams (ladder diagrams resemble causal diagrams a bit, but also show when balls are in the hand).

Hold durations are physical parameters.
So the parameters catchTimeRelativeToBeat and throwTimeRelativeToBeat should be part of level 3, I think.

One thing I wanted to mention about the idea of beatgroups
Can you explain what a beatgroup is?
Do you mean that you specify at which beats juggler A juggles, and at which beats juggler B juggles?

So you create some arrays?
And do you require that A and B have the same period?

JaCo Stuifbergen

unread,
Oct 25, 2020, 11:37:13 AM10/25/20
to juggling-interchange-format
I will, in a few minutes, give this group access to 2 google documents.

The first tries to summarize the results of this discussion so far.

The second document was written to explain a technical issue.

Greetings,

Co Stuifbergen

JaCo Stuifbergen

unread,
Oct 26, 2020, 10:10:54 AM10/26/20
to juggling-interchange-format
(this is a reply to Christian's comment in the thread "how to write real fractions")

BTW:
I'm perfectly fine having "time" as a reference to timestamps and "duration" for durations. I think most programming libraries have the naming that like that.

I agree that "beat" suggests only integer numbers.
For me, "time" is all right.

"duration" sounds a bit artificial to me, but it is used in music for time intervals, so it should be correct english.
(I have considered "interval" but I prefer to save that word for musical intervals.
And "length", but that can be confused with a distance.)
Reply all
Reply to author
Forward
0 new messages