pax_global_header00006660000000000000000000000064132375460330014520gustar00rootroot0000000000000052 comment=9d7ecb0874cee7539da4bda74ca06580f8aab6b2 jugglinglab-0.6.2+ds.1/000077500000000000000000000000001323754603300145535ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/COPYING.txt000077500000000000000000000431311323754603300164310ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. jugglinglab-0.6.2+ds.1/JugglingLab000077500000000000000000000000711323754603300166640ustar00rootroot00000000000000#!/bin/sh cd `dirname $0` java -jar bin/JugglingLab.jar jugglinglab-0.6.2+ds.1/README.html000077500000000000000000000142731323754603300164100ustar00rootroot00000000000000 Juggling Lab

Juggling Lab screenshot
Juggling Lab
~ Current release: 0.6.2 (May 20, 2014) ~

Juggling Lab is an application for creating and animating juggling patterns. Its main goals are to help people learn juggling patterns, and to assist in inventing new ones.

This software is released under the GNU General Public License.

How to run Juggling Lab

Juggling Lab is written entirely in Java and will run on most platforms. For Windows and Mac it is packaged as an easy-to-use standalone application.

Windows and Mac OS X: Launch the Juggling Lab application icon.

Other: The executable jar file is bin/JugglingLab.jar. Consult your Java installation's documentation for instructions on how to run a jar file. On Unix-like systems: (1) make sure your shell search path includes the "java" command (try 'which java' in the shell to verify it's working), and (2) execute the "JugglingLab.sh" shell script.

Documentation

Read these to get up to speed on how to use Juggling Lab:

This more specialized material covers topics the average user won't need to know:

How to compile Juggling Lab

As distributed, Juggling Lab is already compiled so there is no need to do so again unless you want to change the source code. If you are interested in adding new features to Juggling Lab, please consider becoming a developer on the Juggling Lab project so that your features become a part of the standard distribution; contact the Juggling Lab project administrator.

The distribution includes build.xml, which is a build file for use with the Apache Ant Java build system. Ant is free software that is available for most platforms at ant.apache.org. The default build target is bin/JugglingLab.jar.

Interested in Juggling Lab?

Stay informed of future updates to Juggling Lab by subscribing to the Juggling Lab announcement mailing list (expect low traffic).

You can also contribute directly to the project by:

  • Finding bugs and reporting them on the bug tracking page.
  • Thinking of interesting ideas for the feature requests page.
  • Creating new patterns for Juggling Lab, and emailing them to one of the project admins.
  • Localizing into new languages. Juggling Lab is currently localized into Spanish, French, Portuguese, and Hebrew. Email one of the project admins if you can help us translate into more languages.
  • Developing code.

Contributors

  • Jack Boyce – Most Juggling Lab code, project administration
  • Brian Campbell – Juggling Lab bookmarklet
  • Vincent Bruel – Suggestions for improved bouncing support (hyperlift/hyperforce patterns), ball-bounce audio sample
  • Jason Haslam – Ring prop, bitmapped-image prop, improved ball graphic, visual editor enhancements, internationalization of user interface including Spanish and Portuguese translations, and many bug fixes
  • Steve Healy (JAG) – Many invaluable design suggestions and bug reports, especially of siteswap notation component
  • Anselm Heaton – Orbit-finding code, other design suggestions
  • Lewis Jardine – Apache Ant build file, GPL clarifications
  • Ken Matsuoka – JuggleMaster pattern library, used here with his permission
  • Rupert Millard – Implementation of '*' shortcut for synch notation
  • Herve Nicol – Bug fixes
  • Denis Paumier – Suggestions for passing and multiplexing improvements to siteswap generator
  • Andrew Peterson – Performance profiling of animation routines
  • Xavier Verne – French translation of user interface
  • Johannes Waldmann – Doxygen-generated source code documentation
jugglinglab-0.6.2+ds.1/bin/000077500000000000000000000000001323754603300153235ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/bin/j2000077500000000000000000000001231323754603300155600ustar00rootroot00000000000000#!/bin/csh -f java -cp JugglingLab.jar jugglinglab/generator/siteswapGenerator $* jugglinglab-0.6.2+ds.1/build.xml000066400000000000000000000125061323754603300164000ustar00rootroot00000000000000 jugglinglab-0.6.2+ds.1/html/000077500000000000000000000000001323754603300155175ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/html/applet.html000077500000000000000000000153531323754603300177040ustar00rootroot00000000000000 Juggling Lab applet documentation

Applet basics

All of the code to use Juggling Lab at your site is in the single file JugglingLab.jar. This archive includes the applet class JugglingLab.class, which is configurable to contain any or all of the following elements: An animation view, a pattern input text field, a pattern browser list, a siteswap generator, and a ladder diagram editor.

Also the following classes within JugglingLab.jar can be run as command line applications:

  • JugglingLab.class, which is an application version of the applet.
  • siteswapGenerator.class, which gives command line access to the siteswap generator. Use no command line options for a help message (e.g., "java -cp JugglingLab.jar jugglinglab/generator/siteswapGenerator").

Juggling Lab applet parameters

Juggling Lab recognizes six parameters within the <applet> tag, called config, animprefs, notation, pattern, jmldir, and jmlfile. Each of these parameters is optional, and set as follows:

config
This parameter configures which interface elements are included in the applet display. It is comprised of semicolon-separated assignment settings, for example "entry=siteswap;view=jml;locale=he"
  • entry – determines which notation (if any) is used in the pattern input panel shown on the left of the applet display. Values are 'none' and 'siteswap'; default value is 'siteswap'.
  • view – determines which type of animation view is shown on the right of the applet display. Values are 'none', 'simple', 'edit', 'selection', and 'jml'; default value is 'simple'.
  • locale – determines the user interface language, overriding the system default. Values are in the form 'xx_YY', where 'xx' is an ISO 639-1 two-letter language code and 'YY' is an optional ISO 3166 two-letter country code. Examples are 'en_US' (US English) and 'fr' (French). Default is the system-supplied locale.
animprefs
This parameter defines how the animator itself will work. (These settings are made in the "Animation Preferences" panel when Juggling Lab is run as an application.) It is comprised of semicolon-separated assignment settings, for example "slowdown=1.0;fps=10"
  • stereo – determines whether to display a stereo pair of images. Values are true/false; default value is false.
  • dbuffer – determines if the display will be double-buffered to minimize flicker. Values are true/false; default value is true.
  • startpaused – causes the animator to wait for a prompt from the user to begin animation. Values are true/false; default value is false.
  • catchsound – determines whether catches are audible. Values are true/false; default value is false.
  • bouncesound – determines whether bounces off the ground are audible. Values are true/false; default value is true.
  • fps – sets the number of frames per second to be drawn by the animator. Values are floating point numbers greater than 0.0; default value is 30.0.
  • slowdown – defines an overall time slowdown factor (e.g., slowdown=1.0 is actual speed, slowdown=2.0 is half actual speed). Values are floating point numbers greater than 0.0; default value is 2.0.
  • border – defines a border (in pixels) around the animation. Values are integers greater than or equal to 0; default value is 0.
notation
This parameter determines which notation component will be used to parse the pattern specified in the pattern parameter below. Currently recognized values are 'jml' and 'siteswap'; default is 'siteswap'.
pattern
This parameter defines the pattern to be juggled. The text string provided here is sent to the notation component defined in the notation parameter above, for conversion to JML and animation. The expected input format varies by notation; for the notations currently implemented it is:
  • jml – the text string should be in standard JML format, described in the JML documentation. To get examples, use the "Save as HTML" feature in the application and look at the HTML generated.
  • siteswap – text string should be in one of two formats (the applet will auto-detect which you're using):
    1. A siteswap pattern alone, using the same format as in the "Pattern" input box on the siteswap input panel. For example "(4x,4x)".
    2. A list of settings in the form used in the "Manual settings" field of the siteswap input panel.
jmldir
An absolute link to a directory used as a base for jmlfile below.
jmlfile
This parameter causes the applet to load a JML file from the server. If the JML file contains a pattern, it is loaded into the animator and the pattern parameter above is ignored. If the file is a pattern list, it is displayed in a "Patterns" tab attached to the left side of the applet. The format of this parameter is a UNIX-like path to the pattern file, relative to either jmldir if defined, or to the HTML document containing the applet. For example, patterns/demo.jml.

Examples

Look at the HTML files in the Juggling Lab distribution for examples of how you can use the applet within a web page.

jugglinglab-0.6.2+ds.1/html/editor.html000066400000000000000000000075471323754603300177100ustar00rootroot00000000000000 Juggling Lab visual editor

Using the visual editor

The visual JML editor included with Juggling Lab is shown in the graphic below. The editor display is on the right side, next to the juggler display.

visual editor screenshot

The components in the editor display

The editor display shows a spacetime diagram of the pattern, oriented so that time runs vertically (and increasing downward). You can think of this spacetime diagram as an abstract "movie" of the pattern. The spacetime diagram really extends to all times in the past and future, but since all patterns eventually repeat in Juggling Lab, we just show the repeating portion. In the graphic above, visualize pasting another copy of the spacetime diagram immediately below the one shown; you can verify that all of the lines representing paths match up perfectly.

Descriptions of the individual components:

  • Tracker. As time within the animator advances, the red tracker bar moves downward to match. Clicking the mouse in the editor display area will move the tracker to the point chosen. Dragging the tracker while the animator is paused is a good way of seeing the details of a particular point in the pattern.
  • Left hand/Right hand. In the display, two heavy black vertical lines represent the juggler's hands. The view is reversed relative to the juggler display, since we are looking at the juggler from the front (its left is our right).
  • Paths. A path represents the movement of a single prop as it is thrown and caught by the two hands. Notice that there are three continuous paths in the graphic above, matching the number of balls in the pattern. Right-clicking on a path will pull up a menu that allows you to change the characteristics of the prop on the path (e.g., type, color, size).
  • Events. The spatial aspects of the juggling are described by events, which appear as the filled black circles along the hand lines. An event defines a point in space and time, and other actions such as throws and catches can be attached to events. Change the time of an event by dragging it up and down with the mouse. Change the spatial position by clicking on it with the mouse, which will show a green square in the juggler display; dragging this square around sets the event location.
  • Throws and Catches ("Transitions"). These are represented by the open circles in the graphic above. Right click on a transition to evoke a popup menu with editing options.
  • Switch-delay symmetry indicator. Some patterns have a switch-delay symmetry, where the right and left hands take turns doing the same thing. (For example, any odd-period siteswap like 441 has this property.) Juggling Lab understands this kind of symmetry in the spacetime diagram, and indicates the presence of a switch-delay symmetry with a faint gray horizontal bar in the middle of the diagram. Notice that if you take the top half of the diagram and flip it horizontally ("switch" hands), and move it down to overlap the lower half of the diagram ("delay" it), the two portions of the diagram line up exactly. Juggling Lab will maintain this symmetry; any edits made to an event will cause corresponding edits to other events linked by the symmetry.

Using the editor

Under construction. For now, just left-click and right-click on everything and you'll figure it out.

jugglinglab-0.6.2+ds.1/html/jml.html000066400000000000000000000131671323754603300171770ustar00rootroot00000000000000 Juggling Markup Language (JML)

Juggling Markup Language (JML) description

Juggling Markup Language (JML) is the primary juggling pattern description language used by the Juggling Lab animation program. This document describes JML and the pattern model it enables.

JML is a detailed juggling notation

JML is quite detailed compared with other popular juggling notations such as siteswap notation, causal diagrams, or Multi-Hand Notation. This reflects the primary design goals of Juggling Lab, which are to:

  • Develop an internal pattern model (JML) with sufficient detail to encompass all of the "common" juggling notations
  • Use an architecture of notation components to animate common juggling notations via conversion to JML
  • Animate patterns in a physically-realistic manner, with correct timing and trajectory of throws and hands

As JML is a detailed description language, it is primarily intended to be read and written by machine. Users will likely create JML using a notation component as described above, and edit JML using graphical tools (for example, the visual editor within Juggling Lab).

JML is a type of XML

As you might have guessed from the name, JML is based on Extensible Markup Language (XML). This choice was made because:

  • XML allows us to define our own juggling-specific tags using a JML Document Type Definition (DTD)
  • Many free parsers to read and validate XML are available in Java; in fact this functionality is included in the standard Java 1.4 libraries
  • The syntax provided by XML is sufficient for our purpose

JML examples

There are two basic kinds of JML documents: Patterns and pattern lists. The pattern type describes a single juggling pattern, while the pattern list type describes multiple patterns in a single document.

Example 1 - Pattern type

Below is an example of the pattern type of JML document, in this case Burke's Barrage with three balls. Here the JML is simply describing the elements required to construct a spacetime diagram: A bunch of setup information, followed by at least one <event> tag to do the real work. The individual tags are described in a section below.

<jml>
   <pattern>
      <title>Burke's Barrage</title>
      <prop type="ball"/>
      <setup jugglers="1" paths="3" props="1,1,1"/>
      <symmetry type="delay" pperm="(1)(2)(3)" delay="1.3714"/>
      <symmetry type="switchdelay" jperm="(1,1*)" pperm="(1,2)(3)"/>

      <event x="1.2854" y="11.6921" z="0" t="0.0919" hand="1:left">
         <throw path="1" type="toss"/>
      </event>
      <event x="-0.0837" y="77.4015" z="0" t="0.1505" hand="1:right">
         <holding path="2"/>
      </event>
      <event x="-18.5196" y="18.3529" z="0" t="0.2143" hand="1:left">
         <catch path="3"/>
      </event>
      <event x="33.9434" y="51.0847" z="0" t="0.3763" hand="1:right">
         <holding path="2"/>
      </event>
      <event x="-20" y="0" z="0" t="0.4027" hand="1:left">
         <throw path="3" type="toss"/>
      </event>
      <event x="16.9726" y="44.0451" z="0" t="0.5586" hand="1:left">
         <catch path="1"/>
      </event>
   </pattern>
</jml>
Example 2 -- Pattern list type

The JML pattern list document type is simpler than the pattern type; see the example below. Each line in the list requires four items to define it:

  1. "display" attribute. This defines the text to represent the pattern in the visual pattern list displayed by Juggling Lab.
  2. "animprefs" attribute (optional). Settings for the animator, in the same format used for the applet "animprefs" setting.
  3. "notation" attribute (optional). Name of a notation component within Juggling Lab ("siteswap" and "jml" are the most common examples).
  4. "pattern" attribute (optional). This text is sent to the notation component for conversion to JML, and then animated.
<jml>
   <patternlist>
      <title>Siteswap Patterns</title>

      <line display="3 cascade" animprefs="stereo=true" notation="siteswap"
         pattern="pattern=3;dratio=0.5;tps=3.572;hands={(32.5)(10)}"/>
      <line display="42 two in one hand" notation="siteswap"
         pattern="pattern=42;dratio=0.5;tps=4.331;hands={(32.5)(10)}"/>
      <line display="423" notation="siteswap"
         pattern="pattern=423;dratio=0.5;tps=4.331;hands={(20)(20)}"/>
      <line display="441" notation="siteswap"
         pattern="pattern=441;tps=5.371;hands={(32.5)(10)}"/>
      <line display="531" notation="siteswap"
         pattern="pattern=531;tps=4.98;hands={(32.5)(10)}"/>
   </patternlist>
</jml>

JML tag reference

Under construction

jugglinglab-0.6.2+ds.1/html/jml_dtd.html000066400000000000000000000044041323754603300200240ustar00rootroot00000000000000 JML document type definition
<!ELEMENT jml (pattern|patternlist)>
<!ATTLIST jml
          version  CDATA   "1.0">

<!ELEMENT pattern (title?,prop*,setup,symmetry+,event+)>

<!ELEMENT title (#PCDATA)>

<!ELEMENT prop EMPTY>
<!ATTLIST prop
          type     CDATA   "ball"
          mod      CDATA   #IMPLIED>

<!ELEMENT setup EMPTY>
<!ATTLIST setup
          jugglers CDATA   "1"
          paths    CDATA   #REQUIRED
          props    CDATA   #IMPLIED>

<!ELEMENT symmetry EMPTY>
<!ATTLIST symmetry
          type     CDATA   #REQUIRED
          jperm    CDATA   #IMPLIED
          pperm    CDATA   #REQUIRED
          delay    CDATA   #IMPLIED>

<!ELEMENT event (throw|catch|softcatch|holding)*>
<!ATTLIST event
          x        CDATA   #REQUIRED
          y        CDATA   "0.0"
          z        CDATA   "0.0"
          t        CDATA   #REQUIRED
          hand     CDATA   #REQUIRED>

<!ELEMENT throw EMPTY>
<!ATTLIST throw
          path     CDATA   #REQUIRED
          type     CDATA   "toss"
          mod      CDATA   #IMPLIED>

<!ELEMENT catch EMPTY>
<!ATTLIST catch
          path     CDATA   #REQUIRED>

<!ELEMENT softcatch EMPTY>
<!ATTLIST softcatch
          path     CDATA   #REQUIRED>
		  
<!ELEMENT holding EMPTY>
<!ATTLIST holding
          path     CDATA   #REQUIRED>

<!ELEMENT position EMPTY>
<!ATTLIST position
          x        CDATA   #REQUIRED
          y        CDATA   #REQUIRED
          z        CDATA   "100.0"
          t        CDATA   #REQUIRED
          angle    CDATA   "0.0"
          juggler  CDATA   "1">

<!ELEMENT patternlist (title?,line*)>

<!ELEMENT line EMPTY>
<!ATTLIST line
          display    CDATA   #REQUIRED
          animprefs  CDATA   #IMPLIED
          notation   CDATA   #IMPLIED
          pattern    CDATA   #IMPLIED>
jugglinglab-0.6.2+ds.1/html/jugglinglab.css000066400000000000000000000034711323754603300205230ustar00rootroot00000000000000/* First reset browser default css for the elements we use */ body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td {margin:0; padding:0;} table {border-collapse:separate; border-spacing:2px;} fieldset,img {border:0;} address,caption,cite,code,dfn,em,strong,th,var {font-style:normal; font-weight:normal;} h1,h2,h3,h4,h5,h6 {font-size:100%; font-weight:bold;} input, textarea, select {font-family:inherit; font-size:inherit; font-weight:normal;} h1,h2,h3,h4,h5,h6,p,ul,ol { text-align: left; } body, p { font-family: Times New Roman, Times, serif; font-size: 12pt; } h1, h2, h3, h4, h5, h6 { font-family: georgia, serif; font-weight: bold; margin: 2em 0 0 0; } h1 { font-size: 22pt; } h2 { font-size: 18pt; } h3 { font-size: 14pt; } h4 { font-size: 12pt; } h5 { font-size: 10pt; } h6 { font-size: 9pt; } p { margin: 1em 0; } ul, ol { margin: 1em 0; padding-left: 40px; } pre, dl { text-align: left; margin-top: 1em; } blockquote { text-align: left; padding-left: 40px; } table { width: 100%; } a:link, a:visited { font-family: georgia, serif; font-weight: normal; text-decoration: none; } a:hover { text-decoration: underline; } a:active { font-family: georgia, serif; font-weight: normal; text-decoration: none; } ul { font-family: Times New Roman, Times, serif; font-weight: normal; list-style-type: disc; } #all { position: relative; margin: 0 90px 50px 90px; background-color: #FFF; text-align: center; } #standalone { position: relative; margin: 0 30px 10px 30px; background-color: #FFF; text-align: center; } .def { font-weight: bold; } .userinput { padding: 8px; border: 1px dashed #999999; background-color: #f1f1f1; font: 13px/20px "Courier New", Courier, monospace; } jugglinglab-0.6.2+ds.1/html/ladderkey.gif000066400000000000000000000623141323754603300201600ustar00rootroot00000000000000GIF89acoM___```-* ooo//..ZZqqq}}r%$,,qq222 ???s6t5w((JJEDD^%XXX"""ccNNNvvvUUVMM!!ammHHOQQQ`` W >>uh ѴSGmmeee龾ޱyyytt.;;هyyHHH9977DŽdd񁁁؛PPxNNJJ飣óDDUU999[[!!11$$::H㟟|||Ͽhhh哓??͠ף޽lll//ooOO__Qo*hZӗcC|KHmc_>2ÙStSXmRR˙"75<ScEY:vWFAFJ$>6?8*C>ZcGYc~)n#JC)RcftJ#)ٖ_v)}Hc' ?婉O%"$Jj?3+q f??R'Fɬ0` C8Vd-POj& Zj"XFj~(X-pH똻 ͫ’~/r 1D*Y(~ m9mtlc#dLbJ?`)F@0p-zxlCh9Ā!n^h*J檯pGXSز}⌃ұ R7L5k|\#i㲈1BIG6V`'B@ -{+)Ri9~oM۴. cd'nBCv!VcrCQF2bG}Gc-YH$'(=fJSF/KaFlD.b^Ɛ'y?JTUpLpjSymą۫F+VZ૭Eu-ښ񉃕*'-j=FאD9酒P!@`NcBMd2!Hg I d9dGaHQN HɌ!L&#+)!zЖZ:48 `lI!?i /)ӞX 0kI)N^ ] Ba3SxG}gP C9PWuz mn, т2mh Q62F{lgK4}\F&.@0g[um 㒦-G"M7.h{ⴹȵks{]4{Ho + I aA<˯~_<6 _0S)⬆6dbq;Dmo؀;oc`nX@G$an(`gGO; \@GDuS:z*%=w/!<=!6/z%(>;A\}৴Ȼ c#1эSyar@8X 3@Lv^p d{{Pj Z?q "Hi@[!x#8jO)x~olqt^Rͷ |x ` ƐI(@ v_F  XRn` P fh Qnpr8tXvxR_k +>%fp_@xwhgEho0x@qv/Vk @Hr*@ ȋϠ @ X Ȍ @h- ހ ;XXx蘎긎؎b Ԩ0+ 7xu`8u?xjrِb|@ x`6h|a4ɷ|$p6_z ϰ `}Ń 0 OB@7:i ( ⠔축9ɕ^ٕ`bd9fYhy[i 0_`   zpnbx]ft ync p0|(w_|` (dJ6=P =A @{0?Ȱ i; ٍް09Yy虞I +Pd@pkHw^88U @ }0 4ȑ`W4襊 () _A 5  %p7 Y6zܘ) ;pVVzXZZV @p 4 H:`A`gxJa9uyڧWjA ~ڧy Yph 0 y* 0 K0 p Z %0 ? 0OP O ;ڪͺJӪzֺ  @V@z}kC z 0کA\j0ڭj` J; {| Cwꡋ& 6 z0mz9 0 =  0@ @@ZG`: J˴  рK8j۶lnp;r[t{v В  =#`}kC @sЏ'A@x[y[ #`{gй۶z{8; !l ɲqP 0hekx`  ;Š  % GS % KKbd; ` ;[{ _xଦ婞:${A! A ,|)pl i`]A͌P K0k Iɳ‘ښ8Ϙ:'ʩ9@,K &˪4Mp -$/3j(m9V2 4-OP=R]T}VXZ]ՠ_=`%# }pN |?1rm\R tIׂz ^MBͩ}$,}y- P_n<n . iI }کMp ƊP ڪڮ ܱܾ۠ ܲ͝]M̓~p`9 8_֐r x` ?z T=M#xUg}d)`ɮ@ Ҳ@r4 jPe'r,0!P'.ѓ-/N&5~>@B>D^F -]G>, TDAZ-~ 'vEc1x0t> l uu~yn {zք芾M*0> U Λ@. p (wvw]@3[p"Ƈg ^~N nϞѮ>׮^?N JT>~^N6T@gI }d)n v R "?$_&(*,.WW4 @Q4(OAA:!_=D ?l)NzPƻ'p Z?M546M5^iS[٥EFN)|RO[W?z|~~& V@ui? P @mojt?#x [?W6P ?uj I@_%/[_?_/" npB"W WA .d!C3o_5T2l=.qDLpE[ P@a\yMj Cx7FTҾJN0TrJ*DL"Kvq2 o˭@LrI8kR?C33@RƐZO_EG_jPhoM>D2NJD(;lON;?DЁrG_\ԥ\<3 !*UK$M=W@NԞ(P GLNHiݱlv[nNu({\tVռV62Me1Q4VjgӼ_8_^!&N)oڦ+1i{ffB\41(`O@H `)D0-`-bXm9`s 2_\e: b:n1c>1 $↑6| x0D<`?4b? u͉|7!Cfb )\ ؂ R~D1GO&R1Ӽ`2x$*Cُ<{0 f` $Q֛$#cIK&T>fh R24:[B!0b@ HV+ &b"ıx@59Mnap\ɹqf4D6MFiARa@ *TC3MbIh1C bi- T7HIpx*Ř-X.#h`ibPTPL@=d4&;  ^R5\DSQ@5Y_U bu1"e)Y2EuT2;:\+L "kA$I*2촎 ""F4pX6&焎'MB30c0δ (/_Nih(–\&fC{ޙ}o W~Kȡ6@B]4]7}H(T^hULS(RC h2y8c@ aضz*/@;+iar- hH/ʼn~33&dV(yq)i"<sL Ɂ\23dBY'fL094c-c, \d-}?b*ZO,V,P#s`&um)srmK)ZʌAV7Fxc81F'>{ϙ٦I $Eˬ}mlx;V x2b\ňZԙ L09Ȁ"CLc"IJtT!dUOƆ<`xKrbp$ mU5X #0@9^/2(Z ]p*\: ÍDZrV IhݩU 59d!X\~\2yͽ~sE2Ӷ G? '2!M@+;z r9^'|@3.e׹bҦAu9IHA"P[}dC_R/3Aп*fk 96(@$zVpUz·9&YViZ=µvE+Ei~IAXUXF ΋3]0ZQ8a>AzɈ z=4&@;;KNHk3q+I>@ӕ˰@z@h> E8D M3-IJAoAs ? .ȣ PX#``-tn˜:j>VV>hBӑ08ÿ )ҸH4qKJ7{3-:c*==$*Vȫ!XpX!+V<CH$C^ /K[`PN#b:=6h;,= D A ؀X /A]R[2؀x Ä^a'ke;c&+TBpJEq`ZX DҰ@*(l1,<9 @xLVP) ;P+C>#=s?q S <̃ի$>c=XxLXJh2vZc=p\ ظ.s٘Ia;MǬ?=X/ /Xd*E~P1p<0:,{Jѣٳ-l"2LNŸwE> @i )ћ(E B&D@7\ [Ba n\.Hٰb }81l I`;p~h.մN"#3Ϩ ՙ%(Ph%%1 d7~bv 1z3;3M%[0[ eS _9H1-d\5 gR;deΘ~D}IXwn auSc8F[Ȃ886Ll6%&Rgvx؄s@_0ePd((|0<RɛLO)Aw3i OhkgXB8f\ `<$=N, QdIUuj8n+ex% @ZϙϊQ]DޑkY8؂QAڧkX>2)giĐ!Į~I p 0Ҽd`j)Ύ=*~)i%>@.֔)(tqfI?uBCMTwo`Rʓ=`V`5Ѐs 8q̱Y'/RRuO' #h3IhE ؀!X[Q*'\lߋZ7EIp_'>R{5LhHchx`Kˮlp}кЂw@3)UXD;j/(P!c? Xo~&ZOsWa@Hu U DX 2Tv܏.mGgT$t!ryJXQOȁ"&8ZH:Gz'LLˬ >G@@#&f!%At>'*ɸ!Z_f@gTNP訄K 8 XhIXO֡rsqZW oȧ{Xg Bp@_\>p}?*I^@ p}x!,h BIfɠ![!X.7"q9*GPED(ОfҬi&Μ:w̹'A~9GPBi:ǨRR1ֆ @Uh†XVǒ-W 6ȒэU@nar A3Das5 ٔI*Y)'̚7thѣI)41dY12a L€ܺ M[}~}{XµF9B2.q- Yɔ+[I3= %jRNf8 }[?V\g*V "H+@@]E XIMFe穷";{Rix#9֛%hA8 C?d`^nA"H%J6^eT%3h5GP&V#)H}dOE!I3fA"xwY7fhf}Zzo'qtB3BeUzE 0'|`Z%C|u7wZ&19߫+.p\Ga(CmV r" ұQjd(mhz/f/uқ(hP*s͕?} WA A + RQ'Cr.XȻkMJ*|3S V6{P) +Gʔ R (hLF+-3ٝ^2G96B;3AlB{9).lp}Ah؋]62xfp{tcMGCaQLdVܬ׺V^/k_yb fSl:n;΀0a]2\Zn+?>>髟.86_JB??7"0a3Uuc;Ջ 3 rĠ(^abm9G DrEhAb5q`3K$LJ<;(%2N|" bgѾhvBK`*ư%>+A&49hb+ G$AQ<0< j&$ /JehsD~n>#AiU&r.b[7"o0J55#M&YUsy/!Td[@%)65⽭@rNp h?JV]ŸX%E_ Q?ZϊsRj1!0[j^4FvHĔ*~@B H$XN@~*l!\6C5Bd biIN]8Yw;zqAT9[EXY!)K @*Ed#*U%SX]eiBo) ۓE NS"ols*QO hArg>D{NDa**9KH)cq@( $Ҧ|7cB&iyhM RUB- ԓ ?t}T~oDy#Ę۱zBDX}}L.wÉ1̄ƷGs]h^ͷ-H b@3-d""_=<A@##VZf31N$0$(i:t_ɮ@?(Hf8soyUγ2@{n%:, ] <Ӳ,ъ}'gjF<6Xb!PwF|$RGo\P$LH ?9JA%qF1ڤ=mP\!t.A?QvBT` 3W%}54mѠC>iyy!1%?TL@4%^ÄAIFi !U0_iKV&Ὂ\ U-dmFQ.x֚B'h٠ NZFO *Z߫%i PAT]h!D! h ġ!aFlA !?\mm a'dD)AB$qx BU&H@D^ق(h/B0aeӼ"F!%)#B$xZ%BE8" D+L\T /Jz"j$!8#.u$I@/! G[MQdXBT3I'ZTco0hBF62 !b^G`q :R!r-۫`A95'aDMC}LG̀aJ'0BC.Cꂗ%" E>FGcB0F"d?0P1r@}^AHcA|/(\PP&+~RJz,C/EkVTXL̝ULGL] bAEN"GAS^Z$0 xA(1h\%ϰ z# XE"  Dª}F#+ kF\ʥm*Q `_挒ꖍZnDBb ڂ .#X)XZEFHhVXK&7FL0J`A1Amڦ( AeE 䐱*L)QAKAŐ  uPYElǔ.6jT?AB'g|D dfU]`狁?$ 1ɪNSǴLZ(E ]C kF< HjBeEBA`4@KYP)svu.[E+Eh\v辚j`F?tB\BD@IƬ.Z4?γE۴qD%hI˖gE$( eE&)6hivNEE@T1"Uڤ{&+6aA DAtPH$#ukȦ+ڈJ-tݤ!-D\}X&Uj&D'.rdpeV&vZ+A ޤ-^T FSZ|BE[J %Lc-.nU#p:MN 'TCMdNvfEA,Vf*EIF9B}b>? @ rd@A:Do rJn$V9XsYjF/-J4pfm0A( B. AVTf[-4((ZE)B/J_UO0ifuaT/<JnJa A HcD Q?L@F}%[PV# A%>.1GRvBop"!BpgUq،1|ÜsBtZ% W'Ѕk$'rvԍv<#_eA+D/>/R \nz\dAXGuTkEH'!jGoA$aN'Izؚƍ)+-BB 9k` k _!/.b~FGE;NZ ;%S'':4m+9Pk^sUX<4X/Bx5L?J͟u7~*B[īAKF35=S'>11Ъ2W+BdVmeUhZSKd'er9TN/T$8~l vbvT{JT*{1fS3dIs?PDEhffqUgO&[mjyhǯ?6wApQkDVaK5Vrx (RUFd#h5/=U,FIuj\fI\x.E ^AZRQliV95ܑ"cR,A<9)TnEf UBƁt899',?ʌwU<6DF4"-F,s9U`!F7y^jښ TPxNUxSj٦m -ny9%w} Y?Z sj{QWɳ/+Yxg06FEIqG._ 0aTxA"xIi_mR C^D5Ov :a +B (lܒE,jzYi,.fB6FEw9^W8_?kWG*ԫE4:,YDmˢժ8½H.TָK[k5lI/2{ϡmUֻZ1=&iF[j <+h³2&AXZÕ[ x`WćG>GOEQ$@D/-Y <^7wjx+˦WKuLVMY{rBF&W)zU_ nnUl.Y,ASizjt#U"//oV8iU1U[jtg|9*GPED(P~ v4!'N AcH-%h!VhfDHBВԆ NlA jߞ@PAy e?Lɖ5{Mgh n\sҰnGL()@L%cct_is.M*6'!؆#Nx1~~$A g&G)AR"8?ܱaU+ԪWnj%[:Vj̔af=m<Y#[~eJ "0@"N6p _B`(s͵4,[%:J+  ja}k &c l#1ʺ;\8Fd@%.mZ4ɲJp (8H H38?t EvǖZFZ bG--7[a|lk“Kdv&KX#,bhD $|-8 6!?!4=;eʗ~1T*:UUK\ȵYC($c>';5uSeN ̅|K%L1Ic45' 6&?(ގd :%hؤgO )n{:g\#&TP;Rf")4wTOʢ2eWȪ?5 /Bu8=~GH0Rdg@ %Nc#in!DM^HMTgqDzLC(V[d&Sr'e6ˏ,˿X$ j!6sAmuCqwхz# kB%+u ެ4bՙu!D ^LG?ˠsQ9 WX&g=H.`$HdG~a "ߙ˫bN ߮$4 σr׭2ogϣp l f1K$/_}3)7s$у'C0( vXAȶBU2YvfRWCU$fƹDGB%N.TâAJ }d`7p-Va YT G.DJW,iYYH(nhA%̒&Q.MHŏB0HT,H*ea0*ɼbk Z@GUdYHD4%ݑP -U |B$ T]=]XBP(7D˛_D@5UUM\'v3Ç% @ Z/0vg u`(vOk?kH8$e[O3JUKQ @*KdAl 8" Xi Ph+LA:GM3[$pQVnݑYxJ =okŹOa+o׽9X:cܾ#,D+ D}U| JCЮJ?,LL:T!$>X [Èe}.,޳*>{aJ´7XUƕ  `(Յk5Lx}C(@2D25{}׋@L$CCcmb˼*/|nD;$Af 0V "(W"!, .p;!00yϽ(a ZGm:?0A~B@NЂR~*"fz-f6 fp 7 m 'C0 pb&n#ͼ ('+NnD&.eVc$  /Ϧ ,%&`dD&ddbCCpNJ6^7 /r */ gln2@?b`IaadT?"2@6($7d\.pN1$և)~Q  \1f7rH2B1 Dn~O "D#xZ|*2ԏ%UE ;C`<8a4)VJ+I-r1V6@#/D8*8J 1]X%%q=$!dN^.d..bf ,$~(,q1Rc8Z (adODn%p>l,[2,,Ƀ.gN@4 ha8 Ҏ)l jkl(P* .R*dON$EC>B8s%" )s,s 73/%&w V#e(jPA6@Vjt2# +:/YH##7kNޑZN&t^19$1uf%3 J3wo.aʏ8N.#nl pD"'apF%TRlq C,r<&an{YvArт/ٗXTyfԈ؀UٚCKLٙ 3_(ݗ9Y9]z B,CzK,ٙ.)z x5.9E`!zOڣ3ӢvbsvmZX'4T9'z_}U 0B Oq^ v30 P2+Zɺzh[Z&o:1TەZwFچ;:Itu FD޼}W#0Udu0rG$OgSUڵr3v_y[ZG#Y;@da[P{J&ٹC{ۺ1=BR.ƻ{˼; Q:34}ľ˂˦Z2IؿdZ)e`-۴;+%5[}&Mw;%BW;ői[#z7q}jbKw\TNϜ ׽× Za(N!r-AJ]܏y;\OJAC\8LZArhs]w{؃]؇#@΀ؓ]ٗٛu ہݾK ZLk[@b}֗@#ٵ]߅ F# B]@ܣC}? !` PF?C^GKOS^O~ d Vc^gic< ^w^;Qa   +At<¥b!6A.>bAhQ^뷞^Ǟ˞j מ J(j^^`iAbY6!A陞̟>@&a\! 33]?{`Kگ= ^.A"Va>ң<&Fab[a Pr__[  _ǟ @@!`ՉByĈ(C$/⿉+Z1ƍ3 $!<|,dҀ%nq A"Ν<{ 4СD퉥R"`} 5ԩ<ň4:X`x 6lOlbnZ2)KaĎ|K$BuT9:5C/2%e38{LΤG&ըMk֢e>][iαuNUmعNm7]]9C#e֬\$|usm= iƏJ9n(i ݂J&0W]| y5`O#"a$ .*u"b'".l> mNKm^l -%B~ nFK*F KnڙxB<#pB~UI^xIk R%"'-JrJpR/{' 0uq$1!#1210s@ĶJEar3 s L2"tI-4zc9{餇:ꥫΉ>,.;쮋ꩋ{뼿nwP D#O}cOݯ-  }(ޱM?G2Ik-!q@E+N@@(p8@2d-XN0) B! 78B B 3(B3 i0p.9'aixKTbLJ Z8K8_,f"!W0jV!LaPUb'D&<:{#@~d!HB2|T$"yH@62t$Y(H$'ICR$%?H)vZ 6)R.R oSRD XBOn%&E>[zH&hR U%`Mp0Ep,9ωtsl; xsTn'!s'<8Te?ЄsE$p7-U~ܛ4USa~E7yRAyMiJӚԦ3)OwzSB)PS"uDiRTYTZ=Vԯ>53Bp ȩWա[R*VuD' bHFQM@C:&I F$lqELb}XE7Ma AV-iOԪvmk_ ؾ ,loܚVd`eVҰ w.hM>XX! eبd):~H& 6jVob|%V]!qfGyӁ.!DmG`Őa#^c;k"Ins<Wy0 |4ͷ34<%7yGsCyс~t{#o~Afv^075vC$~({}hgv}k{nw=q{w K &+~o"۹wg>{=/^{^G<uzYܚ/>؉o|#?g~|3_ɧѠQ_@hv|Wݟ~_?}:i/pc{'Yj{ {H q H`0~#H%X`4,hȂ-؁3uGu}77u;hGIKȄMOQȄ`WY8 _a(cTgc~Cugq(sHuhwy{Hy`u @  }}} ZX}n({߷(iJ}^0ߗ}@V (HhǸp(  x ~XHV 茌Ņ8+،h+0C I CP !)#yh Њ0xВH p0p(8 Dɑ$)SIUF&XC0Id! 0'pd)jP5}Qi{ɗ}~0^ ָ t٘-\  ɋrш٘8ٚuyBٙ)雿Pfi.Ɉ fɍeǜMI MJ 'Xx04 ypx٘霌 ܧ (JZ `u~𖏨H4xȠȠPJ>`)+J Y. 7İ=  0J8(O ɤ Jj& ZQʥ]L:ycJe:lCkʦ" l7's:m;jugglinglab-0.6.2+ds.1/html/new.gif000066400000000000000000000001571323754603300170020ustar00rootroot00000000000000GIF89a !, @kЩ$ Juggling Lab change notes

Release 0.6.2 (May 20, 2014)

New features

  • None

Bug fixes

  • Fixed bug in "exclude these expressions" part of siteswap generator.
  • Fixed performance issue in PatternList.

Other changes

  • Included Windows native executables (Juggling Lab.exe and j2.exe) in the Windows distribution.
  • Added more informative help message, and documentation, for command-line siteswap generator.
  • Distributing the source code as a simple directory instead of a jar file.
  • Added dialog explaining that saving animated GIF is only available in Simple view.

Release 0.6.1 (October 11, 2011)

New features

  • Added user interface support for right-to-left languages such as Hebrew and Arabic. User interface elements invert when the default system language is right-to-left. This behavior can be explicitly triggered by for example launching Juggling Lab with: java -Duser.language=he -jar JugglingLab.jar
  • Added support for UTF-8 encoded properties files, to make localization into non-Roman scripts easier.
  • Added locale setting to applet configuration, to override the system default languge.
  • Changed JML syntax to make it fully XML-compliant; new version is called JML 1.2.
  • Added Convert JML menu item to application, which converts JML files to version 1.2.

Bug fixes

  • Added better error-checking to prop color assignment parser (1362999).
  • Improved quality of error message on siteswap parsing errors (2878097).
  • Refactored UI messages and error messages to use templates, improving our ability to localize them.
  • Passing patterns now default to Simple view instead of Edit view, since the latter doesn't properly work with passing patterns (3160246).
  • Moved grip location of rings from geometrical center of the ring (the hole) to the edge, to appear more natural.
  • Fixed auto-scaling of the animation, so the props and jugglers are better sized and positioned within the view.
  • For patterns with more than 3 jugglers, increased the default spacing between jugglers to eliminate overlaps in the hands.
  • Fixed bugs in Save As HTML output.
  • Fixed internal error when animating siteswap patterns containing only 1s, along with a defined hand movement like half shower (1032779 -- bug logged in 2004!).
  • Fixed uncaught exception from parsing lexical errors due to unrecognized characters (2837873).

Other changes

  • Removed idx3d library and 3d rendering mode, making Juggling Lab fully open source.
  • Removed Jakarta regular expression library; using Java regular expression library instead.
  • Removed AElfred XML parser; using Java XML parser instead.
  • Removed Acme labs IntHashtable class; using Java Hashtable instead.
  • Removed support for legacy parameters mat_style, mat_HR, and mat_DR.
  • Added bookmarklet to home page.

Release 0.6 (March 25, 2010)

New features

  • None.

Bug fixes

  • Fixed bug under Windows XP: Application could not be quit using the traditional method of clicking the close icon ("red X") in the corner of the main window. (Herve Nicol)

Other changes

  • Changed siteswap.php to generate animations with ladder diagrams.
  • Removed support for Java 1.1.
  • Removed old_siteswap notation.
  • Removed experimental functionality to directly upload JML files to a wiki. The preferred approach is to use the <juggle> tag used by JuggleWiki.
  • Reorganized a lot of the documentation.

Release 0.5.3 (September 19, 2004)

New features

  • Complete rewrite of the siteswap parser, incorporating the following new features: (1) mixed asynch/synch notation, (2) sub-pattern repeats, and (3) simplified passing notation. See the updated siteswap notation documentation for more details. (For now, the old siteswap parser has been retained as "Siteswap_old", available from the Notation menu.)
  • Ability to select a prop type in the siteswap input panel. (Jason Haslam)

Bug fixes

  • None.

Other changes

  • Added zip-formatted distribution for Windows users.
  • Created source code documentation using Doxygen. (Johannes Waldmann)
  • Moved source code and source code documentation into a separate distribution file.

Release 0.5.2 (July 16, 2004)

New features

  • Preview of new ring prop type, accessible from the "Define prop..." popup menu item in the visual editor. Example in the demo area. (Jason Haslam)

Bug fixes

  • Fixed internal errors when doing regular expression filtering in siteswap generator, introduced in version 0.5.1 as result of code restructuring.
  • Fixed problem with animated GIF saving -- feature was inadvertently disabled.
  • Fixed internal errors caused by potential security restrictions when accessing remote images in the image prop.

Other changes

  • When running as an application, the siteswap generator now sends its output to a new window rather than the "Pattern List" tab. This restores the capability to save generator output as text or JML files. (Thanks to Sean Gandini for this catch.)

Release 0.5.1 (July 10, 2004)

New features

  • New "Image" prop type, which displays user-specified bitmapped image as a prop. Accessible from the "Define prop..." popup menu item in the visual editor. (Jason Haslam)
  • Added support for Ben Beever's '*' notation to repeat a synch pattern with switched hands. For example, (6x,4)* is now identical to (6x,4)(4,6x). (Rupert Millard)
  • Siteswap generator now allows period ranges to be entered, e.g. "1-5", "-5", "5-". An upper limit must be specified unless searching for prime patterns. Leave the "period" field empty to find all patterns, regardless of period. Also, you can now leave the "max. throw" field empty to turn off the max. throw restriction.
  • Siteswap generator now runs in the background, so that the user interface isn't blocked during long searches. (Jason Haslam)

Bug fixes

  • Fixed internal errors caused by bug in ladder diagram portion of visual editor. (Jason Haslam)
  • Fixed internal errors caused by specifying a negative "max throw" generator setting.
  • Fixed internal errors caused by out-of-range juggler and path numbers when reading JML files.

Other changes

  • Replaced Jack's lame bouncing-ball audio sample with a much better one from Vincent Bruel.
  • Added a "siteswap2" notation to the "Notation" menu, currently nonfunctional and for development purposes only.

Release 0.5 (April 2, 2004)

New features

  • Applet can upload a JML file to a server, enabling the Juggling Lab Wiki.
  • Applet can load and display pattern-type JML files, in addition to JML pattern lists.
  • Applet can launch an editing window that contains menus and nearly the full functionality of the standalone application.

Bug fixes

  • Fixed bug in siteswap generator code to find starting and ending sequences; bug was responsible for internal error messages.
  • Fixed bug in siteswap parser that caused some bounce throws to be read incorrectly.

Other changes

  • Added "side by side" body position to siteswap input panel.
  • Changed the applet calling parameters, and updated the applet documentation accordingly.

Release 0.4.1 (February 22, 2004)

New features

  • Created translations of GUI text for Spanish (Jason Haslam), Portuguese (Jason Haslam), and French (Xavier Verne); the software determines the language based on your system (typically OS) language settings.
  • Added antialiased drawing in the 2d renderer for Java installations that support it (Java 1.2 and higher).
  • Added regular expressions package to siteswap generator, allowing the user to specify more sophisticated exclusion/inclusion search criteria. This feature and the next three are discussed in the siteswap generator documentation.
  • Added siteswap generator option to generate only passing patterns that are connected.
  • Added siteswap generator option to generate only multiplexing patterns containing at least one true multiplex throw.
  • Siteswap generator by default now avoids generating duplicate passing patterns where the jugglers have simply been permuted, unless requested by the user.

Bug fixes

  • Fixed bug in siteswap generator that displayed rotations of composite passing siteswaps as distinct patterns.

Other changes

  • Used Java internationalization framework to isolate all language-specific user interface elements into external properties files (called GUIStrings.properties and ErrorStrings.properties for GUI text and error messages, respectively). (Jason Haslam)
  • Removed "exclude these passes" element from siteswap generator control panel; this functionality is now provided by the new improved exclusion/inclusion search capability.

Release 0.4 (January 10, 2004)

New features

  • Multiple simultaneous catches in the same hand are now staggered in time. Multiple catches occur in some multiplexed patterns; see this example.
  • The transitions in the visual editor ladder diagram are now colored the same as the balls they represent. (Jason Haslam)
  • Added optional sounds for catching and bouncing. By default, bounce sounds are on and catch sounds are off; these settings can be adjusted in the "Animation Preferences" dialog, or in an applet call via the catchsound and bouncesound animation variables. (Note: These sounds are not available within JugglingLabAWT.)
  • Rewrote siteswap generator code that finds start/end sequences for excited state patterns; the shortest possible sequences are now generated in all cases.
  • Added "manual settings" entry box on siteswap input panel, and updated documentation accordingly.
  • On Mac OS X application version, double-clicking JML files in the Finder now opens them in Juggling Lab (and starts the application, if it isn't running).

Bug fixes

  • Fixed the artifacts that sometimes appeared in the top border of the visual editor ladder diagram on throws to the same hand. (Jason Haslam)
  • Fixed bouncefrac setting bug with bounced siteswap patterns, which caused other bounce parameters (e.g., number of bounces) to be overridden.
  • Fixed physical placement of new events manually added to ladder diagram (using Edit View popup menu).
  • Fixed internal errors caused when user enters incorrectly-formatted text in siteswap generator control panel.

Other changes

  • Removed siteswap generator limitation that the max throw height could not be smaller than the number of balls, a reasonable situation when searching for multiplexed patterns.
  • The applet patternfile parameter used to specify a JML pattern file is now specified relative to the HTML page, not the JAR file.

Release 0.3.11 (December 27, 2003)

New features

  • Added support for "hyperlift" and "hyperforce" bouncing; see the siteswap notation documentation for an explanation of how to use these within siteswap patterns.
  • Added support for bounced throws with more than one bounce.
  • Added a PHP front end to Juggling Lab, and added a page of instructions.

Bug fixes

  • Fixed -n and -no flags in j2 command-line siteswap generator.
  • Fixed internal error in ladder diagram code when user deselects the pop-up menu (Jason Haslam).

Other changes

  • Made check for Java 1.2 in ballProp more efficient.

Release 0.3.10 (November 23, 2003)

New features

  • None.

Bug fixes

  • Fixed clipping of event location graphic (the green box) in the animator, when using the visual editor.

Other changes

  • Included MS-DOS/Unix scripts for running the siteswap generator from the command line; these are called j2 and are available in the bin directory.
  • Clarified the terms of the Juggling Lab license, most importantly the provision to make source code available.
  • Included build.xml for building Juggling Lab using the Apache Ant cross-platform Java build tool.
  • Included files to build the Mac OS X version of Juggling Lab into the Mac distribution.
  • Reorganized directory structure.

Release 0.3.9 (November 2, 2003)

New features

  • Balls now have transparent background, rather than square white background, when running on Java 1.2 or higher.
  • Added "highlight" parameter for balls, accessible from "mod" setting of JML <prop> tag, or in the visual editor under "Define Prop...".
  • Added menu option to save pattern lists as text (existing save option writes in JML format). This feature is probably most useful for saving lists of generated siteswaps.

Bug fixes

  • Fixed problem with JugglingLabAWTApplet in Internet Explorer when using Microsoft's VM. Problem caused by upgrade to JDK 1.4 compiler, which is not backward-compatible with Microsoft's VM unless compiler target setting is used properly.
  • Fixed bug when animating passing siteswap patterns -- '<' and '>' characters in pattern title were confusing the JML parser.
  • Made the generator "Run" button the default button when in the "Generator" panel. (The default button is the one activated by hitting the return key.)

Other changes

  • Added list of Juggling Lab contributors to main page.

Release 0.3.8 (September 23, 2003)

New features

  • None

Bug fixes

  • Fixed bug that affected multi-line patterns (i.e., those containing carriage returns or linefeeds); solution required slight adjustment to handling of output from the siteswap generator.

Other changes

  • None

Release 0.3.7 (September 19, 2003)

New features

  • Added stereo display mode, which shows a pair of images that give depth perception to the animation under "cross-eyed" viewing (i.e., cross your eyes slightly so that the images appear to merge). This feature is available in the Animation Preferences panel, or in the "animprefs" setting. See the examples.
  • Added support for more than 9 jugglers in siteswap patterns; notation is to use 'a' for juggler 10, 'b' for juggler 11, and so on, for a maximum of 35 jugglers.
  • Made file open/save dialogs default to the Juggling Lab directory on first use, and the last directory on subsequent uses.
  • Allow carriage returns and linefeeds in applet "pattern" parameter, so that text for hands, body, etc. settings can extend across multiple lines.

Bug fixes

  • Fixed major bug in siteswap "hands" setting when 't' and 'c' specifiers are used.
  • Fixed problem with legacy "mat_style" setting when used with synchronous patterns.
  • Added error check to ensure that throw/catch coordinates are specified in "hands" setting.
  • Turned off ladder diagram for passing patterns (ladder diagram does not currently support passing).
  • Fixed a startup problem that caused the Java 2 version of the applet (JugglingLab.class) to not initialize the animation correctly on some JVMs.
  • Fixed a problem when lists of passing siteswap patterns were saved and reloaded; required a change to the pattern list JML format (see below).

Other changes

  • Changed the pattern list JML format substantially. Added "animprefs" and "pattern" attributes to the "line" tag. This allows you to change the animation settings on a pattern-by-pattern basis, and also ensures that the patterns display identically under both the application and the applet. The applet "animprefs" parameter is now ignored when loading a patternlist.
  • Under Mac OS X, using java.awt.FileDialog class instead of javax.swing.JFileChooser in order to look more like a native application.
  • Adjusted default spacing between bodies in passing patterns with many jugglers, in order to reduce physical overlap.

Release 0.3.6 (August 21, 2003)

New features

  • Expanded format of "hands" setting in siteswap notation, to allow for multiple jugglers and increased time resolution. Updated documentation accordingly.
  • Created new "body" setting in siteswap notation, to set locations of jugglers in time. Updated documentation accordingly.
  • Added "Body movement" input box on siteswap notation control panel to make it easier to experiment with the "body" setting.
  • Eliminated creation of new objects while animating in 2d mode by using an object pool. Now causes fewer garbage collects under normal operation.

Bug fixes

  • Fixed bug in calculating the physical center of the pattern, which resulted in strange behavior during camera rotation.

Other changes

  • Changed format of "hands" setting to be more compact, readable, and consistent with the new "body" setting.
  • Made XYZ coordinate axes visible in camera-drag mode display only after mouse drag begins.
Known issues
  • Elbow positions are goofy for some hand positions, e.g., when a hand is behind the back
  • 3d display mode is relatively slow; likely an opportunity to optimize polygon count.
  • Juggler head vanishes or displays strangely when exactly edge-on.

Release 0.3.5 (August 5, 2003)

New features

  • Created the JugglingLabAWT applet class, requiring only Java 1.1 to run. This provides a simple viewer applet that doesn't require a download of the Java plug-in from Sun. Various updates to other classes, especially jugglinglab.core.Animator, to remove all Swing (Java 2) dependencies from the core animation code.
  • Created new documentation for the siteswap input panel and the applet calling convention.
  • Added back capability to pause/unpause animation. Click within the animation view to toggle (click+drag is interpreted as a change in camera angle; click+no drag pauses/unpauses the animator).
  • Made juggler bodies opaque in 2d rendering mode, using a "painter's sort" algorithm. Props also now display in correct z-sorted order relative to one another.
  • Added mechanism to define starting hands for asynch siteswap patterns, documented in the siteswap notation page.
  • Changed default camera angle for passing patterns.
  • Added support for JuggleAnim input parameters to the siteswap notation component.

Bug fixes

  • Added support for force-bounces back into siteswap notation component ('F' modifier).
  • Fixed "start paused" feature.
  • Fixed bug that caused interference between multiple applets on a single page, caused by global variables in the singleton mhnNotation class.

Other changes

  • Updated documentation for siteswap notation and the siteswap generator.
  • Made double-buffering on by default.
  • Changed coordinate format in siteswap hands setting from (x,y,z) to (x,z,y), to give shorter hands strings (y coordinate is front-to-back and is often 0).
Known issues
  • Elbow positions are goofy for some hand positions, e.g., when a hand is behind the back
  • 3d display mode is relatively slow; likely an opportunity to optimize polygon count.

Release 0.3.4 (July 17, 2003)

New features

  • Support for passing siteswap patterns: arbitrary number of jugglers, synch or asynch rhythm, and multiplexing
  • Full support for passing in siteswap generator
  • Option to disallow "clustered" throws (e.g., [33]) in siteswap generator
  • Ability to change camera angle in 2d rendering mode (hold down mouse button over animation and drag mouse to change view)
  • XYZ coordinate axes added to both 2d and 3d rendering modes, when camera angle is being changed
  • "Snap to grid" feature when camera angle is being changed

Bug fixes

  • Many improvements to GIF-writing code; now writes GIFs correctly in 3d rendering mode
  • Occasional pattern centering errors in the display, in 2d rendering mode
  • Internal errors caused by leaving "version" attribute out of <jml> tag
  • Internal errors associated with <position> tag
  • Disabled Edit View when there is more than one juggler (ladder diagram isn't working yet in this case)

Other changes

  • Removed "passing leader slot number" input to siteswap generator; passing leader is assumed to be juggler #1
Known issues
  • Elbow positions are goofy for some hand positions, e.g., when a hand is behind the back

Release 0.3.3 (June 21, 2003)

New features

  • Added 3d rendering capability using Peter Walser's idx3d III 3d library; option is accessible from Animation Preferences panel
  • Added ability to animate passing patterns; new <position> tag in JML defines juggler body positions and angles (Note: Juggling Lab does not yet have notation components for any of the common passing notations, so passing patterns require one to hand-code JML as of this release)

Bug fixes

  • None major

Other changes

  • Moved GIF-writing code into main distribution (the GIF patent expired in the USA on June 20, 2003)
  • Changed JML coordinate system to simplify 3d rendering: X coordinate is right/left, Y coordinate is in/out, Z coordinate is up/down

Release 0.3.2 (January 9, 2003)

New features

  • Added "find pattern rotations" option to siteswap generator
  • Added graphical indicator for "switch" symmetry type in visual editor

Bug fixes

  • Siteswaps with 0's/2's look funny because the hands swing too wide (siteswapNotation.java)
  • Siteswap generator prints cyclic rotations of some patterns in "all compositions" mode (siteswapGenerator.java)
  • Internal error caused by left/right click combination in visual editor (EditLadderDiagram.java)
  • Internal error caused by some invalid siteswaps (e.g., 46500) (siteswapNotation.java)
  • <holding> transitions missing from some siteswaps when converted to JML (e.g., [92]22) (siteswapNotation.java)
  • "Switch" symmetry type not working (EventImages.java)
  • Internal error caused by some JML parsing errors (JMLView.java)
  • Internal error caused by rescaling pattern timing (EditLadderDiagram.java)

Other changes

  • Changed default listing options in siteswap generator
  • Created page of change notes (this page)
jugglinglab-0.6.2+ds.1/html/phpinfo.html000077500000000000000000000156561323754603300200700ustar00rootroot00000000000000 Running Juggling Lab with a web link

Basics

The PHP front end to Juggling Lab allows you to quickly animate patterns by embedding all the animation instructions within a URL.

Try clicking on the following examples to get the idea. You can alternatively type this text directly into the browser address bar to pull up the animation. (Note: To see the animation you need a browser with Java available and enabled.)

The pattern information comes after the '?' in the URL. It can have two basic formats:

  1. A siteswap pattern only, in the generalized siteswap notation used by Juggling Lab.
  2. A series of variable assignments in the form "var1=a;var2=b;var3=c" and so on.

Variables recognized by Juggling Lab

When the second form above is used, Juggling Lab recognizes the following variables. Only the pattern variable is required; the others are optional.

  • pattern – siteswap pattern to animate, in generalized siteswap notation. No default.
  • bps – number of beats per second, a floating point value. Default is automatically calculated from the pattern.
  • dwell – number of beats a catch is made prior to the subsequent throw. Values are floating-point numbers between 0.0 and 2.0; default is 1.3.
  • hands – hand movement as a sequence of spatial coordinates for catches and throws and points in-between. This should be provided in the format used in the siteswap input panel.
  • body – body movement as a sequence of angles and spatial coordinates. This should be provided in the format used in the siteswap input panel.
  • colors – determines the coloring of the props. Each color is defined either by name or by its red/green/blue components on a 0-255 scale. Thus if this setting is equal to {red} or {255,0,0}, the animator will use red balls. If you define several colors, they will be assigned to the balls in a cyclical manner. For example, {255,0,0}{0,255,0} means that ball 1 is red, ball 2 is green, ball 3 is red, ball 4 is green, and so on. Recognized color names are: black, blue, cyan, gray, green, magenta, orange, pink, red, yellow. Using the value mixed (no braces) will apply a pre-defined mix of colors. Default is red balls.
  • propdiam – diameter of the props, in centimeters. Values are floating-point numbers greater than 0.0; default is 10.0.
  • prop – prop type to use. Recognized prop names are ball, image, and ring; default is ball.
  • gravity – acceleration of gravity, in cm/sec^2. Values are floating-point numbers; default is 980.0 (earth standard).
  • bouncefrac – fraction of a ball's energy retained after bouncing off the ground (how much of its dropped height does it return to?). Values are floating point numbers greater than 0.0; default is 0.9.
  • stereo – determines whether to display the pattern as a cross-eyed stereogram. Values are true/false; default value is false.
  • dbuffer – determines if the display will be double-buffered to minimize flicker. Values are true/false; default value is true.
  • startpaused – causes the animator to wait for a prompt from the user to begin animation. Values are true/false; default value is false.
  • fps – sets the number of frames per second to be drawn by the animator. Values are floating point numbers greater than 0.0; default value is 30.0.
  • slowdown – defines an overall time slowdown factor (e.g., slowdown=1.0 is actual speed, slowdown=2.0 is half actual speed). Values are floating point numbers greater than 0.0; default value is 2.0.
  • border – defines a border (in pixels) around the animation. Values are integers greater than or equal to 0; default value is 0.

The following variables are also supported for backward compatibility, but their continuing use is discouraged. Most are documented elsewhere:

  • tps – use bps instead.
  • dratio – defined as half of dwell. In the typical case where a given hand throws on every other beat, this equals the fraction of time the hand is filled with a ball. Values are floating-point numbers between 0.0 and 1.0; default is 0.65.
  • throwx – use hands instead .
  • rightthrowx – use hands instead.
  • leftthrowx – use hands instead.
  • catchx – use hands instead.
  • rightcatchx – use hands instead.
  • leftcatchx – use hands instead.
  • balldiam – use propdiam instead.
  • g – use gravity instead.
  • mat_style – use hands instead.
  • mat_HR – use tps instead.
  • mat_DR – use dratio instead.
jugglinglab-0.6.2+ds.1/html/regex.html000066400000000000000000000146111323754603300175220ustar00rootroot00000000000000 Juggling Lab siteswap generator

Regular expressions as siteswap generator filters

The Juggling Lab siteswap generator allows regular expressions to be used as output filters. This page is not intended to be a comprehensive discussion of regular expressions; for this read one of the several good tutorials available on the web.

Juggling Lab uses standard regular expression syntax, with some important differences.

Difference 1: Swapped metacharacters and literals

In standard regular expressions, the characters []()| act as metacharacters with special non-literal meaning. Doing a literal match of one of these characters requires a preceding backslash '\', for example the regex \[ matches the string [. In siteswap notation the characters []()| have special meaning, so relative to standard regular expressions we swap the roles of [ and \[. So within Juggling Lab the regex [ is a literal match for [, and \[ and \] are used to define character classes (see below).

Difference 2: When regular expression filters are applied

The "include" patterns are applied once, after a pattern is generated but before it is printed. Therefore the boundary matchers ^ and $ do what one expects, matching to the beginning or end of the pattern respectively. For example the include filter 4$ results in patterns ending with a 4 throw, since $ matches to the end of the pattern.

By contrast, for efficiency reasons the "exclude" filters are applied as the pattern is being built up, throw by throw. So the beginning matcher ^ always matches the beginning of the pattern, but the end matcher $ can match the end of any throw. (For this purpose, a "throw" is any set of events occurring simultaneously, e.g., (4,[2x2]) counts as a single throw.) So an exclude filter of 4$ excludes patterns containing 4 throws anywhere, not just at the end of the pattern.

Difference 3: Implied wildcard matching

If the beginning matcher ^ is not supplied in a given filter term, then a .* wildcard match is prepended to it. For include filters only, the same .* is appended to the pattern if no ending matcher $ is supplied. This is done for convenience, so that for example an include filter of 4 will match a 4 throw anywhere in the pattern (it is converted to .*4.* before the regex matching is done).

Note that .* is not automatically added to the end of exclude filters. Thus for example an exclude filter 33 will match two successive 3 throws anywhere in the pattern, but it will not match the siteswap throw [33]. One could exclude the latter with a filter pattern of [33] or 33].

Juggling Lab regular expression summary

Characters

   Char          Matches any identical character

Character Classes

   \[abc\]       Simple character class
   \[a-zA-Z\]    Character class with ranges
   \[^abc\]      Negated character class

Predefined Classes

   .             Matches any character other than newline
   \d            Matches a digit character
   \D            Matches a non-digit character

Boundary Matchers

   ^             Matches only at the beginning of a pattern
   $             Matches at the end of a pattern, or throw (see note above)

Greedy Closures

   A*            Matches A 0 or more times (greedy)
   A+            Matches A 1 or more times (greedy)
   A?            Matches A 1 or 0 times (greedy)
   A{n}          Matches A exactly n times (greedy)
   A{n,}         Matches A at least n times (greedy)
   A{n,m}        Matches A at least n but not more than m times (greedy)

Reluctant Closures

   A*?           Matches A 0 or more times (reluctant)
   A+?           Matches A 1 or more times (reluctant)
   A??           Matches A 0 or 1 times (reluctant)

Logical Operators

   AB            Matches A followed by B
   A\|B          Matches either A or B
   \(A\)         Used for subexpression grouping
   \(?:A\)       Used for subexpression clustering (just like grouping but no backrefs)

Backreferences

   \1            Backreference to 1st parenthesized subexpression
   \2            Backreference to 2nd parenthesized subexpression
   \3            Backreference to 3rd parenthesized subexpression
   \4            Backreference to 4th parenthesized subexpression
   \5            Backreference to 5th parenthesized subexpression
   \6            Backreference to 6th parenthesized subexpression
   \7            Backreference to 7th parenthesized subexpression
   \8            Backreference to 8th parenthesized subexpression
   \9            Backreference to 9th parenthesized subexpression

You can refer to the contents of a parenthesized expression within a regular expression itself. This is called a 'backreference'. The first backreference in a regular expression is denoted by \1, the second by \2 and so on. So the expression:

\(\[0-9\]+\)=\1

will match any string of the form n=n (like 0=0 or 2=2).

All closure operators (+, *, ?, {m,n}) are greedy by default, meaning that they match as many elements of the string as possible without causing the overall match to fail. If you want a closure to be reluctant (non-greedy), you can simply follow it with a '?'. A reluctant closure will match as few elements of the string as possible when finding matches. {m,n} closures don't currently support reluctancy.

jugglinglab-0.6.2+ds.1/html/ssgenerator.gif000066400000000000000000001110721323754603300205440ustar00rootroot00000000000000GIF89aj:XXX`)зggfŐĦ[̷طw<ƐNկS{ܝRȍ9Ҝk̠oYHʸuuutAySya3 RPGhmkŋ򿿿ШzῊ\]ʆY-||||;}N0_W3h⿜&')ҿrp,if+Wv>º@<i?]`)==x(d0~v褱quL߄  ʶHI@ZMQ,Ydnص+7QRfOX(*¬6>ߪڥK^Χ~v|t~`z·Ɓd{eܕ dDcο]μУKNسkνO@eډm).]^Wqr W~,"<_(_c-(x ᄃ@0 qF@ O$g'&:$4ay1r 0 aX#G<I=I< )lj( B@:&6cᬲ%%B)Lj Bޖk覫0!h{(7@Sl!˲p˟V{ +zRDmO14I.֛W:^28dtM C)^xY0la*8=p8r#-*SPB/1$|3(>35PPO^̍~@#0CGx)"*ܥl""3?!G.or {ro L'F"G5 La<;г8R3H ~ mO?A# H"p'2H :1P`)0x" R\" ?@ yPxuW̃ 0Y H"HL"9ƂQBNLp:0`JX@|^#CضvpQX  b7 {0> @k݃e*A\d#i֡,>h- -Glce tFA򕰌,gIK@Na X?!=z`x‚bf1l8f1!F t# b#G͆=,֣L:v%|x܄#!I|ӂ ' \!7 u={ Z$h=y9 N HGJҒt x ѫR=&M{`l(̰C 8&HaH`Vx_@SˠW}L&ͪV۩2yZHG")WbbY͊V`dAWFLSYWc.2FnMb9,si- wlf5";E1Ű&6%ZId5-HSH p{sP4x}` Ȝ ȥdrpPB P^UNE"HL &* 슁@6A|Ge/%5XS=&L d@gsڝp8`ֶ6}FqC4ڌ?(8αwpp9 1;% x(pkLj`7 JDV,`nv`E@8D!mxγ>e(RT91 84at_p-> ĬFl(x@S~~o{<+&lLӑ7&mkfͮ5]24Din>9ruF)[jE oO|7@'r K |ZF&(Qg1H GN\lXD8x4Z~|'׶ TPz˹ЇNH':m@:tE5b֟\`'E1k}o`%L\ d7Y0\~_q٠*P ϼ7{(RBGݠz0!^kb1ӿGpDch\O7 yo|[ؿsvlwٍu)IoۮO|oϿqx8Xx ؀nF~N5(~X؁ "8$X&x(*,؂.028#{KQSo[PB8DXFxHJL؄NPR8TXVxXZ@t>X&jl؆npr8tXvxxz|؇~q(lr`tbdxog(t(8xhlHw`aXchofj؊SX(艆t X(،Θ@7:^Pxؘڸ؍x! 긎؎8h!Ϙ((HXgX{B`hR1@R ّ "9$YI d0Yx8h:)B9DYFyHJB@*PR >T[tۼCz; }0esOEńG;W [P PK"J`0C 0/` p<0/` `k/k -{ 0ˉ:K-800' 22.*BHO*$բu % 5&`ArcHLg%J 0uP / *E `p[CE EPvP:u|xa{[r bpǁ\|v\fb ![[vp]uu /œ4¤\ 3C#uj* % ;2l-Qg6`2+s̔;Ō|:tp)B3p 6P"\A vAC6`Ά,9!]p , cpL+ mp`.ʛhښ)\N:P5 `b!p +l -h#(3}/4$ cp 0v+0S A0;yLA`!|0^ az+0`-j]S![TM*L3{ׯ/X1fӜP υp@Pٗ ib u ب)ٟڣ- p) P1e60v@+GpG ް=FfC`M֍\Azp>`+e Ap6m=<†M ";fp??>4;`#P"=(~f~?j>AdF~?PYԱp89=gvם8d #@=ֳ e0`=09~:>vp6@ߎnjXj0(ݠ @g aq {q 0G~^Na.`p@E A z:8n9-:nꨎ--J9^GW f^y_@R^~؞ھ~`D\>+P ~k 4٦ȾXU @Q/^Qvp- "?$_.Ppt0Rjǎi86" % ,pPQQKNPR?T_JP`Nn:x6kX؃X4x3u@?#,w_z|yPp߂pK.#8iE ?I?_ P0Qsp&,_? K?a_ȟʿ̿yy0_؟ڿ_?_ argnd?Ym$XA .dC%N|ܔ ,H@A ,PCAD, 0Ń>rpEtOA%ZQI.eSQJG"IDK2ia iծe[qΥ[]y_%kՏ!,y2ʖ/cΔ@֬5ogСE&]iԩUfkر>1]!L&w'^qɕ/gsѥO^u٩fh;⭎FKկg{ϧ_};ľcǾL:#pB +B 3pC;CCqDK4Dg3@o)AkFsqG{BkêtS Y#ODUtQF0-5KcML3tSN;/9cL&2=UuUV[u?7CmT9aDuW^{DHEuqR:et+ fuYhB UVZle_sV[puX/='+gxw^z`Mݭw_~(w`{X?PPJ3)X+b3g4XcCミXd/&dbURo=ǓS/& ukeOh< 5tMF;fQjѐlQOf[& ~#]X-R;l`,\s ^ʯ\?^VBGoOz!~_{מwUr3CGk ЏotbP C 7 Ã#P @@N^?0YbvT!1l[ OB oP`!  Qb LB LJ8~ATa!0 -4/B5! 7B"E$B]b G~b\ƥZNYNJ0c_sxq5(8a-dshl,^?vu#;@ S$YHiJT3!H "tC ^Wh"">$02pc@%ҡZZ9?.I~2؄#`l` y"Ա$ #G=0xӥ9 k FX فI@0skB@t1!J- Ҙvc0)J؂Pe*pFHOH-rfh)Wӽf"O`hR4Oхs[=*60Tb!] :/k`C3^ s(b~؋AF\-f_D{&lgXЙ] &>m!?ZSvc t9.`H K4V*Y JMC>poUFHp pP5B9eF8Z8 5 yP}U (Ǜ=Zw{0\>,yzPZ)68, Q'aͧ~_Ca}3~_Ǥ>o_We}'}I:+@<@?1D@|@D(@ @?@> A@:,/鑣@?q8cA@O@50AQ0 )꛿ L?*D1D#"&!Hx̯ $,ʣ=R$<> ?@neRXFµ˫B6-7{Z<2 BBnL¼HG<4K{k0Yt L8 M<9;c6840H/ ͱM f2N/@lN̐@S6/L1E O?~X>t{!/ OOO8 P5PD(@ІP1{Nc?jP! 8Ѽ8`)FHQ!PQmF`80wCHQMQQV؅EwзЂONXPn"R,R-R.RLhS1 S2SYX>3PS9=~9XS4jN m) =}SFmF]؅`$(MT~X"H:O8'Q`WyP!R\Kq#\U` |(Vc=Vd-"؆!?K5e;TD6P T9ho5* o3AomwR8nWiWyu W WqWvNY xVX:,0T0TXXNeV,`CH3(' "$x ADBcz-"$~C@#ND{Z(""#*9;"#/)RZiZ,DYZ1XAU, (-(!ԋV؁DTmM$T{Bk!B(4'YGEp'rJ%Ih-!2mڂŕ("ȳ0jxi2Pbl@-`]P*(H-x{A%ؕ]ڵ]%^'`N+-O|Ƭ2Ǿdy]&pG4\'u)t`&.u*"X@!|i`ha+=(19a B8\|Y# H=*nI*=x` -ʯ/131IF Zدq,bJPH>. q1٪cLS0<.7!Z%XMYŇ):Ld!ELdPePօX)(16Sb=0\hC(;X#X3VX\^;([LI;Z%L:3I7l 0>L(1 ckFjfkmCa[ )0K&zgh{qzg~g~e;,kE 耦B8(9h((i(OTB64?6PlJ H&!"X`Ȳ8Tx(ŝ:ȁ$_hOpPPP~pPw?orse B xxxx `[Q ݅|/S{hF|yyy?z|{(pS8mT:S(%> wz^K[NTPM6:տI U]Wwrg`jkPD]8 YWО|O7Ο,W2}> 'VT5YlM|gF$zh"r/J$oC@$Ph*)BZ'DTU#a~We(yyWi[\~ \X (iԇ;F 0&>c@jHM<Tfaeu$IA;9ǐ#k/ EDxa8ၖ&> fȒG(e :͘jײmOB H@A,XY@` |@!$l2̚7s4C\tWؘ '4F1p[DR9R{. 0fx(H<^^7yNJ,};aOQQoJ3\:Ϙʥk^|`b9SJ8!Zx!j!z Lvi)hl㏄˝67@(#:7&:Xsy8j?P?n!BCft#(0eW~[xf&\ϒM> L1^uݕ^}`bIй(:(.0A!vp ft `G!,#D!(b?yã=&¶I!(8嬭BXvD_Jr6++ [Q~Ylܙ| g"XcIF~.GP@1P:PA!+9Pp #WE]L)A̔/ŤnxW [K2d \0I F%1(P_s/p",oLͥ'}&h15]{s26eZZpD `4swwEpxjmݧAiiNwzSKk YCe܌i=Dw̵z Br{;u ?|)x2*ra) ?Cxʅx @O$q2qn"9qq|#*Xڹd(%+V8(UG RI!]0B!&3MrR:@ pAKDaJ9C0&`X  x6<BXU'0s-|2)GQ(B.2I@ ZTte,e XqC9(p%P#@-T:0;Z/4 }JlP[̚ҕ!>8O}ӇCGx@6%>ě$%zP<%!)0 2P )H2SbP9'I8x̏qyZa)TvZ@  /v!i0,̀ HJE BŐ6H ,[8="Zi@"< SE(C,NSҦfVC= Cଈ!skE5+x bewh@\i{=h z9C>Q $ӝP&s`wL2M+U<ofevؾ%61*7H@ e~f0 v# P0Dt'6l4pKiъDvvA)u A ^Ej (|`?fӢSxR [Xbh6t W\zNj ;c)Grm?б0@!&KÇn5/x: 8p`4-M* 3CT<*^1Lp1_e k0_o/ɞw ~j_=ksn3xL"0,sΖ!_0ڎAtB'A"K8¹ oGܢxA!A)LNe8F$/$.4\J:@A LI XI`8eVߕ,GPNO"%]~H.>Q#egC%A@  TBńׁ]MM?joC[U\]AfZ iYiVD^"g4 ,:B2TECҬAs$ĸٕfVii{Qgvvkj%kRRdEr2l <{&,C=ׄ(V QU?ȍd']. twZ?@#AH):e=RA:*V脰?bH"ZNRQ"X^-%LT@% T)|kTH/l)BO]Jʊ-$p/?-8#/5Y\D/1A6L$I]d).)?lc~.Aݥxyg@=(xA0iGw4Y Zk S8T#U;iJtWũɓMW@CyZU;}SEZΓXYN,jg=` _EB۵QI[mu{iG{G˹GKK]s@Dw+zx~J[~#x\9(TqKL$gYQf4p[V[pIWegQ,e X͛ ^|$b lAl`MբQ?@ x^xղ4WKHeyZъ˳K݊Ӣ,h˞.l1~ "LR+@Iir^C  PA&fD(A(AЭūiXp.֎gzg@80`0 4* aT?\}6|+ʍrk Fnt܄DZ,-x8@ >P-l `jPYz-,o/ofO.[6oRVx[C=Iy(fJPZPdЄ(Zpۙ߾N0\NjV3D]NdT}w1`t?bHerUbYEpZU[UhU]E<_A-r1"0 @``@L@ȧyŨ(g6hm0h9sjE$(8myՖVkyt6r-C=\4=\@=„ҍ13sw9 A{W[ @``{?Wz|bD#_rL@=T@=?;Zt^BeZBXc$tT&$Ao@^,Ȕpo qw3XZǔpsߘ0 1Iow]. iaQ^"|rȣ2]jZHX 0Agɧ)0[ p, SlBOx-Z-E=ݓx=ZYKZ)a1P!'af'%V$>@;~+EU۵e۶MtYhіU#I,l$=ulKxlKJԕۚzJICٛJ,wf6IZ@mZxrMT?uT,7@ 5yLc]S Lz\W:Rܹu!CqJcspi3Al]\kwlxDñ\j:yٍD@]woP:qZwAA/`(TBd3辣{"S-Pi?͞=~BC=?:"?1? 4xaB =i#NDbcF9vGpS&  $@ !Q B S$4ziRFT@JTRDkkRKLjJ iJ.aʤiN>a {p` 6|qbŃp0Ddub͛WDŽshуk%ZB ]r˘3k̹O vxpKRDtⷬH7_p1[;g@뵱҆{{nS.,Y2 '+t!#$H r z 1x@ zI 9pM<  )0Rz޲M܀\ɍ`" '*z+`Fɢ"1G 0cD8`~ 5|S;|p s *ij;ŸFD<D6 JJN:e;9 @*R2+B3N6 p3#c#zT6ܪ-.bƆBCib! aTr$71l@S)Y-tVi6#l0 xݘ &T1ۋ]<sctw_7(_UqEW] v s4)/o܏%<Ο1VktuH_uMXc>+†iL<3b/ 1\%DŽl&<{" jٟ'p ۉF R; ^> @!찂# h <;b]7uk{_'",<C#/*C^^D y74bhx?N( }(&v3P^iW)ү曤G9@"cBk^ؖFPpXȖ8A  \ r5 IJZrpJ F &7!%( ^'/N`# I-, 0@RC&rtdE0:KOIq69PA'0EE79e2*µsR?'(ppQ;G%!&O&h!_ԩQw$iHya1Eꐂ.9iR. -J  jΐT Fċ:Xh!&*G `TլY@ అ,Ќ)"+$y%aE"^A5$0 brKuV c[]^mۖNp(Ix[^^0q ۺV|\Nvn6_Ĺ\gUූ5` _ No lYl7!Iwf#K\b,݉i;״t13A谠n> c:{"'+l6W*nx7Ua \'Epssď0 ı;k!9'< :mfc<?&ݗ0/%ͿmH00N{G"ְ? /isim/(ubHNX7~/xmt1ՙPv5M )&F#k4PPڣjd/V՛m~`/P8ˮbC.0n]娏N"Awk̂#7&1e^tۜa3" z)_\%AuI_o N!E|v4Oz!X?e>8P[΄͓źzİ@8^^-@@I6y PW(zo'^|=+gf]`d1]e pׯ UoToQUcwx͝qo*n<,J`8NÞ0hf6NkJn(p $G;8g&"`-ɷDq.!>0ZpG *rpfPm<6h<.̠c!2X[bi8+gPV) iIhPy0@"P :OL @ QgIq2 NGLn  l ^*PF qCL+ !  ΏE 0z d23Fzhd4J <cJd `F *BQϠ*NG ̥T'pOE n R[QIslm0|aZ/.0v </<!%P!#r0 r"B#=M!/`";k/Ł OX4R`ֈE `M&f%clvprI@(gQe’/`J+r Q*%Y3@ afAzK.SK./~r*,5-1!B a2A B"&"A1R/2(E$a 8382bN#)B**na)T l5a**q2h#831809`g!C37=b1 C2@@(28E: ;ӂ7218 ̠=١0үp&S1C29C\P?2äo1R Zl v@טpAc?@C8$CqlEGXv>J4YeJ@Z84S @R4iH< J@JJ@jP4SI zP>%Jc7mx< EY$>`ZAI3d$f HqMYYAZAJ.`PuPn''P TB8AHdO{JzXvg_M! р7 $aI! aHX![,IV!b ljDe.0NT hmlT?.\UXaЁ6aV*bÛIs&1U&w FtQrb%**a/ ӊu\tJyi6FGR0D.a!x]v/V \!DA toHJk }3Mb2$`! 1w+`P I a~Joѳ,r{%+Ku;BEc.Ox8*@@gk؆o t\طR*13?|~/7CbT؉X?`i XPŠ֘؍ajY/WXv  .@W`,Ik,XyX y |8Ǖ\ >B;r&n؍X0j97c7fnG!ڬTyW! `8>y@Ѵ85%b/f@eBFbbldJ#0fI `1 yFAJtkQGE¡E9l3,zEg<1A-0V.&Un; enݩLK ˭ ߼&XA8-@ڮڦ/ICDp-$g"t S. mf9c_:pUI 6" `<T`dVf]\&dCek2αa%0JdFx8dL&k]^@DXP0f@A_a FbZ]B^`n[v/bDe6H@ ~ g С|6#ᴗ3<' XQ!Ix  hO,/}QSuߑb Ovѫ0g5mG kkb|ZWn"o&Y č@rœ688`|~@&jBzlԋ'o|ЇpFHG'Ijdܸx 0t =D}a1ylOG|3yg= AhLA⎽|1 y&:@C? 6Gn *0ڡ5f|[k/?<}U=cբ ݾ]妶k4١3! !{[7%3.`fC./  E~*n-OF Xyٸ`ID[fem![=I`~䙾 m>^n [~mP3|Ga:,z ^CN7Oaf ջљ՗DwOH!eM1HFedu\!^*##ܥ49Avj8b`6c$%?=i *"`! < B"43b_\'[v‹Q xA :|1ĉ+Z":z2~d<2ʕ,[J׀A (> h q5  `($a 2{;z Ƒdv,6ڵl9͜;{ :ѤK0ܿ >|!Ō;~ 9ɓ,9͜;XѤK>-ܔ :iĩOBES$&Q`"̛;ԫ\ug㵽7wӧQ$@BE.L!6 !WQ\E[^yRO aa"H~]U^ V?x =pT5?@5,y bebC^erbཨo^|gDS>h9*pl7<-ԲX >! EJ! ?"$)]_Hw."8T 4-(`At LCw ]XTC:/W#DT *lӉV {Tß%Wm-i޵xxNj^JؒOB.4@`Dr0@4CEC+pD.tpC{C1ٓD*t2E$Bt\IמIJ,1Xn#oVRO( OM@Bl ET?QO]C؆^K"},c0_Q&Pe[}X[w5Հ+kY1a ,$a241"M /ڋ/~L3s>}I To3# Q^@ bK R)!9}hR)4!(]:q qI +g`p:r00;>H-R7!OC'x:4B^-xxd&Q>2 Qq a0@  lq $3+BˠH@K {be& Шpka K񸦛RY;!!;X]$NX% A f[(ȏ("B;˻+KK,Ʋ,--!- L {ȿ[1#1C"42-s'33`uX!! טj9W9"9):P=;:'h=\;;A<Sţ;7#㛿՛;Ó7:Ę=CAT5Y7VEd4F#Ey7]TEFZEOFp6b8}yb$690 ZfD8Fr#$Á8Y4NtDNNE *PET$W5PA~P ,QUQ %Pа@4t xcUEO9 aR(T5OBBf`3zK\XBYYL\\J妧0&%EuRqK2c` S7rYLLM[ZV_2Yaaab1jZcye0 ce cVdɦ_<a<4e69VcB6aCl2jXDX0{vjƩj6kS&nF;f,z3*l#K leh5C`j=i>]ed ^7kӦT`K-$l.s2Gs6s9IVv|w`xt=uuuuhhwbw PGзMr$SP6d]Wip#J TY{&WWqw}`%ݪqTBq`4}nJ۬t0pl(-ΚкR$S 񂍱D:P >"v z=8v'AՍʆn(rHv~š ^pAo(ڻ=舐(Ty Q ^` j@B>DG\޸Y~͙gZ?^o˚,wHuy~-{nn貸t>X}Z2{}n&ߥŞl韾fnӑߌ~-o[^빮.N:P N'16.Nn׎ٮ3젾1a#n.W] !aQS$#c 0 ` ~ _;w`b-Q{9Q) e 6"M-vdD1$Rݬ!@ P]@#9 0&>c@r͙f2̐!&HM0&͛o1~eɂ+X;9_Î%;/PD- Mk)vg9ި|y`*cphLVj֭]V-!\u$,PCAD, 0Ń>PAp`_W-0%i FB_|yG#_D̂ۃOz痜)ZkE jHg SP ~DP0ʟ8n` &$|" B qA i1ADMDq@OLQG~JqT0''n2,'E"qmđ,(siE Q\Q)3Ld6t7#8c9蔛` p3O=SO0Уb*2B&axiP eo$) CORI?)O0C~.uZ B#1x01لUR_1p]{~\Y^S-U`]`uX]Mvf k 1[ay WYs^{)&v+k9 B|sMSp,G3Oc>~8Og OnLÇCQĂnUX $\OUzGM@`OP V>޳s>7[@^k>vBO%vϳ;n=%ط3Vs6 3a褣:1_KpPD jRx~f (w r&Et=oq0t=}YT) FUR)),I VB f~BJ \Ɂ Ӂ,-p~UK?KvȠ>Ơd!(!o=a1!\D M[t8) pՑ`k wonq(T1E BB%s(L\v6UHa&2[e nb P,E (^XXRM@2jBBŬ[h$)j 7+V.21s!5țdd(EВ&`oBƂ:In*LR)hDV!r, 6 CRl i)]RK)TF,O >y/kb枺Iq. C5Uo3O-JN{S5 ⭓[(0OFV l"8T1x,t"T@1&ЇL0cb$fEiJUz[n/K~r2{e6^,|*ND-,T>jTKBSjVɚbPoߢSA AZպVխokZ Wuuk^Ӻhկl`;Uͦ_`D0SbAd%;YVֲlf5YvvihE;ZҖ& tNlJ+/ֶmnu[ַnp ָEnr;^0o N8 7nv]v׻ox;^~`Eozջ޿VhNMo~~p:8 baXޗp W.[ YqMZ~vM@a[ДU/O̊ϻưq]뉊z¨  Vk_z!@ބ^kY(V? m[Ƚ.unjI2HUYgpgl) ಅ4$e)BдȪe@ǃ+HŴ)@8(ޗ.0Q׊f4GyP|Ub6XC2&epsXMg@!|UyV7#ͭ.}p=L$^ I Q@+UqdyD?GP mi $Qkt#b Q/1AJ…$)߄w7 AG%+_25Y|XWjjݾtWTEHC%E'ZC֮yYoOgԯ$h!c]F;oĬV3c{']{DгsMhW2[>aw@>II@>i@8XkLڋMd)4X/t'ȁ6XZ P==z >ՓP͓]QlO"O OLǼK*l}NP͛ZPB 7mS`2+E$ ӛj |Q _q< k36uS`xXjhS TCM@Nxk DuS1US8S-S1RC>T@MSJ 1]8.U}+K0RbjG>\R&*< ""FmZTPX)jPx9[V^pX+ qȁj:=T u`Xvx`W.8j rOIj WԀXqRuPrUsVqWyeX0iVx(T ZRZHW|ןӇ=WxgfO{_(T.WTiV 2nj$З; VP%x*u$ !pPBVkڮdXXB%\O܍h,Tjg}T PeN(x@S%dKVpW m0jnXin ~nn0nVQd^H6mjmr ,&.lgdAէngy˩6(ɸJ^p]H4vp߆P G]^Iת>G JGfugpT gL!G$?"L'r,TȌ+q*UV/dr%0731j6ws}^}̜;<=s!MIgjQzr9G2G$/xtIIJtJKLOJ/ K"v0]pWwu8WYZu\u]u[YChĤq.dOt$|/,nklmnvn'h /STPY0NPxx/z{wzy|w|xwLCCt?IcLd'pa5'7p(>q%vL8z/PL0Y]t *t(ѢA N!B!I=/8[}(uKh2M)u>C?^p2sP`~`*2SNxqDH Lx1ƎC,y2ʖ/c)(֮_Îڟ[X4%V!&p8ڱt rB`;Qy"3RP@S6t1=`__zEG$faG$I&K.T ӝurء#5ӀGOH% ?cd p%#5 s!s&t*"Xl >\Xu @ug@>(ab]+7W}ѷy"1 IŽnPIDE v h&i^!rکz;ELÀ= * `#@`l0&d8`3/S&e ĜA߲44>ɕh#f/{C{$1D /p0?a 2ܰ6,hE)YAHڄDl#\'/0@)N0P3ll+s>#BVT36Aa2t,}+$ ZI)4s*[n̕?,,bC!{o܆f$)eqam"xe q9(ZQj'紀* 1{2p{yTQʳ ` a {?@ 'u*]6NWa磟_ (q~6+_|k"wQr *ŹXC+h ^ =T:0!Eol)A<.@(Ġ @T$#a j"$f0ī:H/xbQPaZ"Eءhd7z}* )>b7F} S ! iH z 3 Z"<7( \ Y\ @DPQ+p.H( -, 011f3XmbgBi(Q B Of9 dB z&9ɩEo(:V@MJsDF{3FYhׁp-U҉p$~7тAydЂQK ?:C><'7:Np]7xG8=k?7 |IȊ>o{@fҟ>CJ'kۃ?!qw_X??o??` `SSYM\=IB`JR`Zb`jr`z`` ?$i؃ L%``a a"a*2a:bCG J؃Q?[РJaaaaaa!E?ASTFL@đ ЌQb%Z%bb&j&rb'z'b(("'Ҍ?]M@E?4X70'04`AB=h@/(b00 c11c2"2*c323:c4B4Jc5R5Zc6b6jc7r7zc3/&;w$ UFwbZ >L8 ./?d@ @dAA"dB*B2dC:CBdDJD&dU9zԃ"nbt#mN a$h"?BKdLLdMMdNNdOO ePKZEF~:H.H8_[X#R}JJeWzWeXXeYYeZZe[[e\;9^@= TaF`*9H^,FI>".fJ]:cBfdJdRfeZebffjfrfgzgfhhdbcV% 4ep; hp! Z}^cJ.ogp pgqq"gr*r2gs:sBgtJtRgr#^.j`_Bnb`>H70KDnn&.f{{g||g}}g~~gh }bgV\б&4RS< &I^mZ~K\Vz臂h舒h艢h芲hhҨ!(F(hUŦHHxֽʅ"@8L\$A B)J)MiRZiVb)ji闊i阚i隞ii)> 8 DžHt<p_m瑖KNVBjJRjZbjjrjz꧂jꨒj*V\N ΐwxfIi1א 4fk k"k*2k:BkJRk*k8êꩼLݠiwYU<îkkkkl C J @sIIX*K؜!plzǂlȊȒlɚɢlʪʲl˺l̂l4<5RÚwJhIDb1R(40m:BmJRmZbmjrmzׂm؊Jβ~+F`NVlf̬mmn n"n*2nh],c=t­tA\UZEUOnnnnnQ\&iFFhn؄A["o*2o:BoJRoZbojV/D]vWmrRwuC^q.MU^ooo/NЕnnzא/^/e9CpKSp[cpksp{]10Z.~Ϫu%p p p ppq W p n3q;CqKSq[cqk'1JYqqqq1[YqqX@;jugglinglab-0.6.2+ds.1/html/ssgenerator.html000066400000000000000000000512241323754603300207450ustar00rootroot00000000000000 Juggling Lab siteswap generator

Using the siteswap generator

A siteswap generator is a program that finds juggling patterns in siteswap notation. You give the generator a list of parameters that define what kinds of patterns you want it to find, and it finds all patterns that fit the given constraints.

There are four sections in this discussion:

Running the generator for the first time

Juggling Lab's siteswap generator panel is shown in the graphic below. To run it for the first time, perform the following steps:

  1. Click the "Defaults" button.
  2. Click the "Run" button.

siteswap generator screenshot

The generator should produce the list of five-ball siteswap patterns shown below.

  55555
  64555
  64645
  66355
  66364
  66625
    .
    .
    .
  77461
  77722
  77731
* 66670 *
* 67273 *
* 67570 *
* 75670 *
* 77272 *
* 77470 *

This is an exhaustive list of patterns satisfying the parameters entered on the panel above. (These parameters were reset to their default values when you clicked the "Defaults" button.) Each line is a separate pattern.

Why do some patterns have a '*' before and after them? These patterns require some transition throws to get from the cascade (in this case, siteswap 5) into the pattern, and more transition throws to get from the pattern back into the cascade. The '*' is just a placeholder to indicate that these transition throws are required. Check the "transition throws" box on the input panel and re-run the generator; the explicit values of the transition throws will be filled in.

For example, let's say you wanted to do the pattern 66670 once from the middle of a cascade. Because 66670 has transition throws, you can't just switch into it immediately like this:

       ... 5555555 666706667066670 ...
                 ^     ^

because of the collision indicated. (The space is there to guide the eye; it doesn't correspond to a beat in time.) You need a transition throw, in this case a '6':

       ... 5555555 6 666706667066670 ...

Similarly, you need a transition throw to get back to the cascade, in this case a '4':

       ... 666706667066670 4 5555555 ...

It can be shown that when transition throws are required to get into a pattern, then transition throws will always be required to get back out (and vice versa).

Patterns that require these extra transition throws are called excited state patterns, and the others without transition throws are called ground state patterns. The transition throws for an excited state pattern are not unique; in the case above the sequence '662' could have been used to exit the pattern 66670. Juggling Lab finds the shortest transition sequences possible.

Siteswap generator parameters

Each element of the generator panel specifies a parameter that constrains the generator's search algorithm:

  • Balls. Specifies the number of objects the generated patterns are to have.
  • Max. throw. Specifies a maximum siteswap throw value in the patterns found. Enter large values as 10, 11, 12, ... rather than the conventional a, b, c, ... of siteswap notation.
  • Period. Specifies the period of time, in "beats", before the pattern repeats. For an asynchronous pattern there is 1 beat per throw. In a synchronous pattern there are 2 beats per throw pair (r,l), so the period must be a multiple of 2.
  • Jugglers. Specifies the number of jugglers in the pattern.
  • Rhythm. Selects either asynchronous or synchronous rhythm of throws, i.e., whether the hands alternate throws or throw at the same time.
  • Compositions. Sets option to filter out patterns that are combinations (compositions) of simpler patterns. See the section below for a more complete description.
  • Find. Sets options to generate ground- or excited-state patterns (or both) and options for displaying them. See the section below for a more complete description.
  • Multiplexing. Specifies whether the generator is to find multiplexing patterns, and if so, the maximum number of simultaneous throws to allow from any hand. There are also options to exclude patterns requiring simultaneous catches from different places (such catches are typically quite difficult), and to exclude patterns with "clustered" multiplex throws of the same value (for example [33]). These exclusions apply only to the pattern itself, not to the transition throws of excited-state patterns. "True multiplexing" requires that each pattern have at least one multiplex throw containing no held balls; for example [32] with 5 balls would be excluded.
  • Exclude these expressions. Items to exclude from the search, written as regular expressions and separated by spaces if more than one. A pattern will be excluded if it matches any of these expressions. These exclusions apply only to the pattern itself, not to the transition throws of excited-state patterns. See the section below for a more complete description.
  • Include these expressions. Requires that patterns match all of the listed regular expressions. See the section below for a more complete description.
  • Passing communications delay. Number of time beats jugglers 2, 3, ... are given to react to a trick thrown by juggler 1. See section below for a more complete description.
  • Defaults button. Click on this to reset all generator parameters to their defaults.
  • Run button. Click on this to start the generator searching for patterns.

Compositions options

This option is a bit complicated and requires a little deeper understanding of siteswap notation.

One general observation about siteswap patterns is that any two that share the same transition throws can be strung together to get another valid pattern. Thus the two ground state three ball patterns 441 and 3 are combined to get another valid pattern: 4413. In this case we say that 4413 is a composition of 441 and 3.

Another general observation is that you can cyclically rotate the throws in a pattern to get another valid one. Thus 441 can be rotated left to get 414. Note that 414 is not a ground state pattern, as written, since in the following throw sequence:

         ... 3333333 414414414 ...
                   ^  ^

causes the two indicated throws to collide.

The program generally doesn't list all the rotated versions of the patterns that it finds, since this clutters up the listings. So how does it decide which rotation to display? It displays the rotation that minimizes the length and throw values of the transition throws into the pattern. In the case of 441, this minimum number of transition throws is 0 if the pattern is displayed as 441 (not 414), so it's displayed that way.

Now the three "Compositions" choices break down in the following way:

  1. All compositions. Show all patterns, including any compositions.
  2. Non-obvious compositions. Do not show patterns that are compositions of other, listed, patterns.
  3. No compositions. Show only patterns that are not compositions of any shorter patterns. (These are called prime or simple patterns.)

As an example, consider the three patterns 6316131, 4413, and 51414. The first is not a composition at all, so it will appear regardless of the "Compositions" setting. The second is a composition of two patterns that the program does print, namely 441 and 3; therefore it will be listed only with the "all compositions" setting.

The last pattern, 51414, is a composition of two shorter patterns, 51 (the shower) and 414. When "no compositions" is selected, 51414 will not be displayed. In the "non-obvious compositions" setting, however, this pattern will be displayed because, although 51 is displayed as such by the generator, 414 will be displayed as its ground state rotation 441. If you were looking at a generator listing you would see 51 and 441 with different transition throws, and it wouldn't be obvious that you could rotate the latter and tack it onto the former. These kinds of compositions are called non-obvious.

The default setting is to show all compositions.

Find options

This tells the generator what class of patterns to find: Ground state patterns, excited state patterns, or both. The "transition throws" option causes transition throws to be printed for any excited state patterns found -- otherwise '*' is printed as a placeholder. The "pattern rotations" causes all rotations of a pattern to be printed, for example 441, 414, and 144 would each be printed separately.

The "juggler permutations" option applies when generating passing patterns. As a default, the generator will avoid displaying multiple patterns that are just the same pattern with the jugglers reordered (permuted). For example, the two passing siteswaps <3|4p><2p|3> and <4p|3><3|2p> are the same pattern with the jugglers swapped, so only one of them is shown by the generator. You can show all permutations as distinct patterns by selecting the "juggler permutations" option. (Note: The algorithm Juggling Lab uses to exclude juggler-permuted duplicates is not guaranteed to exclude all of them, although it does exclude the vast majority.)

"Connected patterns only" also applies only to passing patterns. Selecting this option filters out any passing patterns that are two or more patterns (each with fewer jugglers) done together. A simple example is <5|3><1|3>, which is two jugglers standing next to each other doing solo juggling tricks.

Exclude / include these expressions

Values entered here specify terms that filter the generator output. Exclude eliminates all patterns that match any of the supplied terms, and include eliminates all patterns that don't match at least one of the supplied terms. Multiple terms may be provided for each, separated by spaces. For example an exclude of 11 2 3 [54] filters out all patterns containing at least one of the following: The throw combination 11 (two 1s in a row), throws 2 or 3, or the multiplex throw [54].

Filters can match patterns as well as literal terms. The terms supplied can be any regular expressions, with a syntax adjusted to accomodate siteswap pattern notation. For example an exclude term of <3p|.*> excludes all passing patterns where the first juggler throws a 3p (the '.*' is a wildcard that matches against any string of characters). As another example, the "true multiplexing only" option is implemented for solo asynch patterns with the [\[^2\]*] include term.

Passing communication delay

This delay setting only has an effect when there is more than one juggler. If you are doing a standard ground state passing pattern (see definition below; an example is <3p|3p><3|3> for six objects), then by definition you and your partner can switch into any ground state pattern instantly with no transition throws. However, many siteswap patterns will require you both to start throwing differently at the same time.

An analagous situation with a single juggler is if I wanted to switch from the pattern (4,4) into (4x,4x). No transition throws would be required, but both of my hands would have to start throwing 4x's at exactly the same time. There is no issue with communication/synchronization when a single juggler is controlling the entire pattern, but it can be an issue in passing. Pattern transitions that require immediate change in throwing behavior from several jugglers typically require the jugglers to count down to the pattern transition in order to ensure synchronization.

It is nice to allow for a communication delay, though, so that person #2 has time to react when person #1 starts throwing a trick (many of the popular passing tricks have this property). This is what this setting determines. The number you input is the number of throws after the beginning of the trick before person #2 needs to throw something different from what he was while doing a standard ground state pattern (like <3p|3p><3|3>).

A few words need to be said about what constitutes a "standard ground state pattern". These are those patterns composed of ground state patterns of length 1. For 6 objects, for example, run the generator with the settings: (balls=6, max throw=4, period=1, jugglers=2, find=ground). You get two ground state patterns of length 1: <3|3> and <3p|3p>. Any combination of these stuck together qualifies as a "standard ground state pattern"; these include standard two-count passing <3p|3p><3|3>, ultimate passing <3p|3p>, and so on. The delay flag lists all patterns which provide the requested communication delay for at least one of these "standard passing patterns". Whew, this is complicated.

As an example, run the generator with settings: (balls=6, max throw=4, period=3, jugglers=2, find=ground, delay=2). (Note that the "excited state patterns" box must be unchecked for the communications delay field to become active.) The list includes the following two patterns; the juggler in the left slot is the one "leading" the tricks:

                  <4|3p><4p|3><3|1>
                        which assumes the people were doing the
                        standard <3p|3p><3|3> before the trick was
                        being done.  Note that person #1 has to begin
                        when his partner is throwing a pass.

                  <4p|3p><4p|3p><3|1>
                        which assumes the people were ultimate
                        passing before starting the trick.

Some of the patterns will require a 2-count passing pattern to get the requested communication delay, others a 3-count, and so on. When you use this feature just scan the list for the patterns relevant to your case.

As a final example, run the generator with settings: (balls=6, max throw=3, period=3, jugglers=2, find=ground, multiplexing=enabled, # allowed throws=2, delay=3). One of the patterns is the popular "left-hand single" multiplexing pattern: <2|3p><2p|3><[3p/2]|3p>. Note that the communication delay setting of 3 has vastly reduced the number of tricks found.

Tips on using the siteswap generator

In general the number of siteswap patterns is very large, larger than you can possibly sift through in a lifetime. To find interesting patterns, the challenge is to constrain your search as much as possible. If you give the generator parameters that are too broad, it will automatically stop rather than run indefinitely (the limits are 1000 patterns found or 15 seconds elapsed, whichever comes first).

Some general tips on constraining the search:

  1. Don't make the "max throw" value larger than it needs to be.
  2. Exclude as many throw values as possible for self-throws and passes. For example, I tend to avoid '3's in 5-ball patterns. I also might exclude the '1p' and '2p' fast-passes.
  3. When multiplexing, limit the number of simultaneous throws and use the "no simultaneous catches" and "no clustered throws" options if you can. Multiplexing makes the number of patterns grow enormously.
  4. Try using the "no compositions" option to find only prime patterns, especially in searches for long-period patterns. Most of the best siteswaps happen to be prime anyway.
  5. Start with a large "passing communication delay" value if you're looking for passing tricks.

Running it from the command line

The file distribution includes a command-line version of the siteswap generator, located at bin/j2. When run in this way the generator by default has no limits on time or pattern count, so this is a good option if you're doing something big or complex.

From the bin directory try the following command line input, which should show a help message:

    j2

All of the input parameters described above have corresponding options from the command line. For example you can experiment with these:

    j2 5 7 5
    j2 5 7 5 -g
    j2 5 7 5 -g -n
    j2 5 7 5 -g -no
    j2 5 7 5 -ng -se
    j2 5 7 5 -x 2 3
    j2 5 7 5 -x 23
    j2 5 7 18 -prime

Generating synchronous patterns:

    j2 4 6 6 -s -g

Multiplexing has a number of options designed to filter out less interesting patterns:

    j2 5 6 4 -m 2 -g
    j2 5 6 4 -m 2 -g -mt

Here are some examples involving more than one juggler:

    j2 6 4 1 -j 2
    j2 6 4 2 -j 2 -g -jp -m 2 -d 1 -l 1

Experiment and see what you can discover! The number of possible siteswap patterns is vast, so it's easy to find patterns that have never been tried or even seen before. If you give j2 a task that requires too much time to complete, you can always use Control-C to stop it.

jugglinglab-0.6.2+ds.1/html/ssnotation.html000066400000000000000000000723651323754603300206230ustar00rootroot00000000000000 Siteswap notation used in Juggling Lab

Siteswap notation

This page describes the pattern notation used by the siteswap notation component of Juggling Lab. There are two main sections:

Description of siteswap notation

A lot of freedom exists in choosing a notation to use for juggling. In particular, there are always tradeoffs between expressiveness (how many weird patterns like Mills Mess can you uniquely describe?) and compactness. Siteswap notation is a very "compact" method, which has two major benefits: (1) it makes the notation amenable to computer analysis, and (2) it is easy for a person to look at a pattern and figure out how to do it. There is a price for this compactness, however; siteswap notation ignores all information concerning throwing and catching positions and styles, as well as any characteristics about the objects being juggled (e.g., number of spins on clubs).

When an object is thrown, the only things siteswap notation tells you are which hand to throw to, and the number of time beats until the object is thrown again. You have complete freedom in choosing how to make this happen: Make a standard throw, throw behind the back, bounce off the floor, do a helicopter spin on your head, or whatever, so long as the object ends up in the correct hand at the correct time.

Viewed in this way, siteswap notation is a very minimalist approach to juggling notation. Its ignorance of throwing styles means that tricks like the 3 ball cascade and Mills Mess get lumped together. Despite the limitations, siteswap patterns are fun to perform and can be a great starting point for adding your own creative embellishments.

Solo juggler with asynchronous throwing rhythm (vanilla siteswap)

The simplest case is that of a single juggler throwing alternately with both hands in a R-L-R-L kind of way (called asynchronous juggling). This is what you do in the standard cascade pattern. Each throw in our notation can then be described by a single number, namely the number of throws in the future when the object is thrown again. In a 3 ball cascade each throw is a '3', for example.

Note that the notation doesn't need to specify the destination hand, since odd numbers always go to the opposite hand, even numbers to the same hand (a result of constraining ourselves to a R-L-R-L throwing rhythm). Another way of thinking about it is this: When you do a throw 'n' (n is the throw number), throw just as you would if you were doing a cascade or fountain with n objects, at the same handspeed. A 3 is a short toss across, a 4 is higher and into the same hand, and so on.

An asynchronous siteswap is just a sequence of these numbers: The first number describes the first throw made, the second number the second throw (opposite hand as the first), and so on. At the end of the pattern you loop back to the beginning and continue.

Sample three ball tricks include (click on the patterns to see animations):

3
Standard cascade
51
Shower (that's 5 and 1, not fifty-one)
42
Two in one hand, hold with the other (see the explanation of holds below)
441
An interesting box-like pattern
531
55500
A 3-high flash

The '0', '1', and '2' throws need some explanation. A '2' throw is thrown again two throws in the future, in other words the next throw out of the same hand. Since the hand does nothing before throwing the object again, we are free to interpret a '2' as just a hold in that hand for one count. A '1' is a fast zip across from hand to hand, as in the shower. Finally, a '0' is no throw at all; the hand is empty (the pattern 60 is three in one hand, the other hand empty).

Throws with values greater than '9' are by convention assigned the letters 'a' (10), 'b' (11), 'c' (12), and so on. In Juggling Lab these must be supplied in lower case to avoid conflicting with throw modifiers.

Are all strings of numbers jugglable patterns? No. Notice that if you average the throws in each of the above patterns you always get 3, the number of objects being juggled. This is one of the ways you can tell whether or not a string of throw numbers forms a valid pattern. '76' doesn't work, but '75' is a valid six ball pattern (commonly known as the six ball half-shower). It turns out that even this averaging criterion is not enough to determine which strings of numbers are valid juggling patterns; for a better description see the JIS siteswap help pages.

Multiplexing

So far in our discussion of siteswap, we have placed some serious restrictions on the pattern: There is only one juggler (solo juggling), the hands are throwing in a right-left alternating rhythm (asynchronous juggling), and only one throw is made at a time out of each hand. This simplest form of siteswap notation, sometimes called vanilla siteswap, was the first kind discovered, independently by three people in 1985: Bruce Tiemann (Caltech), Paul Klimek (Santa Cruz), and Mike Day (Cambridge, England).

What we'd like to do is expand the set of patterns we can describe, by relaxing these restrictions one by one. We start by allowing the juggler to make multiple throws out of the same hand at the same time; this is a popular juggling technique known as multiplexing.

The simplest way to notate multiplexing is to group together with brackets the throw numbers of the multiplexed throws. An example five ball multiplexed pattern is 24[54]. From the middle of a cascade, we first do a hold with our right hand, throw a shorter toss from the left hand to itself, and then simultaneously throw a 5 and 4 with the right (the hand had two balls in it, since it did the hold first). Then we can either switch back into the cascade, or repeat the trick starting with a left-handed hold -- recall that we switch hands each repetition since the pattern is of odd length. [This, by the way, is a trick that Anthony Gatto did in his act, except that he did it all while juggling over his head. He can also do 26[76] with seven balls.]

Solo synchronous juggler

Now we relax the restriction that the juggler throws in a right-left alternating rhythm. The simplest case is where both hands are throwing at the same time, called synchronous juggling.

Synchronous siteswap notation is very much like vanilla siteswap notation above, but with two differences: (1) we group together throws made simultaneously with parenthesis, and (2) we now need to specify a destination hand for each throw, so put an 'x' after any throw that crosses over into the other hand (a throw without the 'x' is assumed to be directed to the same hand that threw it). A '2' is still a hold, but a '2x' is similar to the '1' in the siteswap notation above: a short pass from hand to hand. A '0' is still no throw, and a '0x' is not allowed. All throw numbers must now be even.

Examples of synchronous patterns:

(4,4)
4 ball synchronous fountain
(4x,4x)
A common crossing version of the 4 ball fountain
(4x,2x)
3 ball shower with simultaneous throws
(4,2x)(2x,4)
The 3 ball "box" or "see-saw" pattern
(6,6)(6x,2x)
A 5 ball trick
(6x,6x)(2x,2x)
A 4 ball trick
(4,4)(4,0)
3 balls in 4 ball synchronous fountain (1 missing)

By convention the left slot in the parenthesis is taken to correspond to the left hand. Multiplexing can also be notated, exactly as above; for example the 4 ball pattern (4,2)(2x,[44x]) has a multiplexed '4' and '4x' thrown with the right hand.

More than one juggler (passing)

Imagine several people juggling, each person asynchronously, but synchronized with respect to each other (i.e., all jugglers throw with their right hands at the same time). This is the situation in 2-count 6 club passing, for example. Now our notation has to tell all people what to do, which might sound complicated but actually isn't too bad if we add a few things to what we defined above.

Divide a "throw" into several parts, the throwing instructions for each juggler. Continue to write a self-throw as a single number, exactly as we did for siteswap notation (a 2 is a hold, a 3 is a low toss to the other hand, etc.). So for example, <3|3|3|3> is a pattern that describes 4 jugglers each doing a 3-ball cascade.

What about passes? Append a 'p' to a number to represent a passed throw. To figure out which of your partner's hands to pass to, use this rule: If without the 'p' the throw would go to your left hand, throw at your partner's left, and so on. If there are more than two jugglers, put a number after the 'p' to indicate which juggler you're passing to, with the convention that the leftmost juggler in the <|> is juggler #1, the next is juggler #2, and so on. So for example, <3p|3p> and <3p2|3p1> each describes the same passing pattern, namely 6-object ultimate passing.

Some example passing patterns (note the average rule still applies):

<3p|3p><3|3>
Ordinary 2-count 6 object passing. Notice how the instructions for each person are sectioned off. Each person starts throwing with his right.
<3p|3p>
Ultimate passing, where all throws are passes.
<3|3>
Two people doing 3 ball cascades.
<4p|3><2|3p>
A left-handed double, if done once from the middle of a "cascade" (in this case <3p|3p><3|3> qualifies).
<2|3p><2p|3><[3p/2]|3p><3|3>
A multiplexed pattern, the left-handed single. Do the first hold with your right hand, since that is when your partner is doing a '3p'. The '2p' is from your left to his left, and then you resume. Note the use of '/' in the multiplexed throw, to separate the two throws '3p' and '2' (otherwise the animator would think the 2 was the target juggler for the 3p pass). This could also have been notated [3p22].
<(4x,4xp)|(4x,4xp)>
A synchronous pattern with 2 jugglers and 8 objects. Note that the 'p' comes after the 'x'. The 4xp is thrown to the other juggler's left hand, since a hypothetical 4x thrown as a self-throw from the right hand would go to the throwing juggler's left hand. Multiplexing can also be included in a synchronous pattern with multiple jugglers.
<(2p3,4x)|(2xp3,4p1)|(2xp2,4xp2)>
A synchronous pattern with 3 jugglers and 9 objects.

Juggling Lab extensions to siteswap notation

The previous section described basic siteswap notation, which is also what is produced by the Juggling Lab siteswap generator. The animator portion of Juggling Lab also recognizes several extensions to this notation, to provide convenience and greater flexibility.

Conveniences: Subpattern repeats, simplified passing notation, and the * suffix

When a pattern contains a subpattern that you'd like to repeat multiple times, Juggling Lab provides a simple way to indicate this without manually repeating the subpattern. For example, let's say you want to do 10 throws of the 3-ball cascade, followed by two iterations of 531. One way to achieve this would be to use the pattern 3333333333531531.

Using the subpattern repeat notation, you can also write this as (3^10)(531^2). In all cases the result is as though the subpattern had been written out manually the specified number of times.

Another convenience is simplified passing notation, which allows you to combine together multiple beats within a single <|>. For example, 2-count passing with 6 can be shortened to <3p 3|3p 3> from the version <3p|3p><3|3> discussed above. The only restriction is that the total number of beats within a <|> must be the same for all jugglers.

A final notational convenience was introduced by Ben Beever, who noted that many popular synch patterns are symmetrical in the sense that the pattern consists of a throwing sequence which is then repeated with the roles of the hands exchanged. One example is the see-saw or box pattern (4,2x)(2x,4). The convention is to write only the first half of the pattern, and attach a "*" to indicate the hands-exchanged repeat. In this way the box pattern can be written (4,2x)*.

Adding throw modifiers

Juggling Lab allows you to add instructions to each siteswap throw in order to change the way the juggling looks. Each modifier is a string of upper-case letters that comes after the throw it modifies, and the main action is determined by the first letter in the string:

  • B -- Bounce the throw off the floor. The format is to put as many B's as you want bounces, followed by the style of the bounce:
    • L for lift bouncing
    • F for force bouncing
    • HL for hyperlift bouncing (for a description of hyperforce/hyperlift bouncing, see this discussion on rec.juggling)
    • HF for hyperforce bouncing
    For example:
    • BL indicates regular lift bouncing with single bounces
    • BBF indicates force bouncing with double bounces
    • BBHL indicates hyperlift bouncing with double bounces
    Note that a given bounce style may not always be possible if the ball is spending too much or too little time in the air. For example, it is not possible to do a double-bounce with too little time in the air. (Likewise, it is not possible to do a single-bounce hyperforce throw with too much time in the air.) In situations where the specified throw is not possible, Juggling Lab will adjust the throw/catch styles (lift vs. forced) to find something physically possible; its last resort is to decrease the number of bounces.
  • F -- Force-bounce the throw off the floor, with a single bounce. (Note: this is included for compatibility reasons; use of the B modifier is preferred)
  • H -- Hold an object that would ordinarily be thrown (e.g., a '4').
  • T -- Throw an object that would ordinarily be held (e.g., a '2').

For example, 42T3 is the siteswap 423 where the '2' is thrown, rather than held. <(2p3,4xBL)|(2xp3,4p1BL)|(2xp2,4xp2BL)> is the three-juggler passing pattern mentioned above, only now all throws from the right hands are bounced off the floor.

Mixed asynch/synch notation

Juggling Lab also understands patterns in a combination of asynch and synch notations. A few examples:

41x(4x,3)
A 3-ball pattern that is pretty close to (2,4)(4x,2x) in appearance.
55556x56x1x(6x,4)(4,6x)(6x,4)(5x,7)(6x,4)
A pattern that switches between the 5-ball cascade and the synch pattern (6x,4)*. (This pattern could have been written (5^4)6x56x1x((6x,4)*^1)(6x,4)(5x,7)(6x,4) to better indicate the subpatterns involved.)

Several new things are going on here, for example odd throw values (7 and 5) in a synch pair, and throws like "1x" and "5x". These departures are required to generate the change in rhythm as we switch between asynch and synch throwing.

A few points of clarification:

  • The "x" suffix is generalized here to mean "throw to the opposite hand that you would in an asynch pattern". So a "4x" is a crossing 4 as in standard synch notation, and a "1x" is a non-crossing 1 (i.e., a short hold).
  • When there is a switch from a synch to an asynch section, Juggling Lab assumes that the hand to throw is the opposite of the last asynch throw made (prior to the synch section).
  • Juggling Lab always assumes a single beat of no throws after each (,) synch pair. So an asynch throw after a synch throw happens two beats after the synch throw is made.
  • The siteswap average rule still holds for patterns in mixed notation.

Unfortunately the appropriate transitions between asynch and synch patterns are not simple to figure out (the common method of last resort is to draw a ladder diagram on paper). Perhaps a future version of Juggling Lab will include features to aid in finding these transitions.

Specifying hands in asynchronous patterns

The basic passing notation assumes that when an asynchronous throwing rhythm is used, all jugglers are throwing with the same hands at the same time (as in 2-count 6 club passing). However many interesting juggling patterns break this rule, for example 2-count 7 club passing; in this case the right hand of juggler #1 throws at the same time as the left hand of juggler #2. We would like to write 2-count 7 club passing as something like <4xp|3><3|4xp>, where we identify the first juggler as starting with her right (a pass), and the second as starting with her left (a self).

Juggling Lab allows you to do this by using a hands specifier: put a L or R before any asynchronous throw to cause that throw to be made by the left or right hand, respectively. Subsequent asynch throws are made in an alternating manner from that starting point, as usual. For example:

<R|L><4xp|3><3|4xp>
The solution to the 2-count 7 club passing problem. Juggler #1 starts with the right hand, juggler #2 starts with the left.
L75
A 6-ball half shower, with the left throwing high.

A hands specifier may come at any point in the pattern; in particular there may be multiple hands specifiers, for example R3R3xL3L3x which is a pattern with an unusual RRLL throwing rhythm. If there isn't a hands specifier prior to the first asynch throw, Juggling Lab assumes the first asynch throw is made by the right hand.

jugglinglab-0.6.2+ds.1/html/sspanel.gif000066400000000000000000000657621323754603300176730ustar00rootroot00000000000000GIF89a㡡|||$$$111cccxن4?IÿvAAA Tl!Og^hhhLLLda35OhuuuAPPP]j勋臇+++%1䟟___$oooWWW,'{<<<877/CYαqqq_O蓻~zATkK{]XJbwnji.|*[ue4P{-4t{/}cyyyXfwx酾SŮq [ZZ'.EƕHCr4_VyI z룢EmSVCS댘ϧHp͜q&[Cg  7%7J`+:LuyNqv彯 "1?ǮZiʲD>gjJ&),jaӠCGGGUjww>^~c=?϶ o!,H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳ JѣH*]ʴӧPJJիXjJFA""ċT8P+LʝKݻx˷߿ LÈ 3B98PYaE KlZhXkْӨS^ͺװc˞M۸sͻݖ6F#!.@Yja LkνËOӫ_ϾĀ%mFlyr=it@ul 6F(Vhfv (b `d €)bL@B``A`=rÏL?܌(S Z\v!nBpTTgV#d :D(K.y-8A (Ct`TЁ5CZ̤&7IM"&c e!)MJUʠvp%`a2/x’FXd:f:Ќ459jT@`8@>%}H t0椟x;n.&: DH>>T@/"m х:D'JQs49S؀'L< RT3gJI P$pNԈT 4*JԢHMR{*_@ pՀ6` =vD X VӧO™b^mq1; <@Mb]j(4ҘBW)fvA:;a ]iR Vr;0b^P _4W!8 pK.vw   2/h1cxv;/ལ]UnH>[ (5J|~Eَ {K% &x$ GZ5N+ T@(~^(xXO(2:p X8 0@8αwG-'&3`VC ȍ!P27B8e! \-sx"8adAL:xγiv@&(E;( h(a%!%0<\@j!H% ܎ HLZָε<nXSbŽX4/}37 =Dz:_zձy, lbe`wv (XBq; gg J͆@I05O:G FAkp39!BR]c(:FNr#YA 0Ա$wܮK-3hX-(`HOҗ;}%X 4ȫ~?FhG(!@hOe1\&< B#ᮆOx$!80E;^Hh:AynF @xB|қOW_z~ؠx]{ٳ^O~,h lB|xwt;x` OOw*{HAï*2ϿGXx ؀}@w`MPAUI&ɶl@"(p:0Fy 8*H:`+-h3:<؃>@B8DXFxH"'ql]Pd!$\؅^`؅cfxhjl؆npr8tXvXL8m& RXlǦr#]pȈK8Xx؉0?}%@UƆUnXx؋8XxȘʸȋ@Fq]b07Ќ(8X|-0w 0`q pxٸ؏9Yi0  Yyy|(hņץY&y|0 Y0294Y6y8:`@@ @ GJLٔNPR9@ MMC\ٕdM i8֍븖X|`p  tYvyxz|ٗ~À eu٘9` _Ö `ّHxژy  9Yyð Z " PTpșʹٜ9P5ؙ)Yi9֐P 9Yy  s@`C@dZz ڠe6B:Y"Yx LPYP *,ڢ.02:4P @J)6DZFzHJ&&A0TZ:٥@PlP pfZjlڦnpr:jzɠg:SZڏVp6@^W߉ܸ]Pp8'کꩤ:Z6d 0`Zګ:ĺpdʨZ)S<0Эy:*Zzڮ 㪮00 z* O"֚٨Ѫ (Ph+ ~";$[&{(;{h:F SpW$P* 9~5+˰鰐zLpTQbB T[l_@`۵d[f{h_i۵еRKRU0Lcy^  +$ KO PV\ bb  0e|@ b UJ?0 Wmq whl<Ǽ J0ƥ0{<pvPo4O#pZ\P 2R&p,`Nɞ A 4D@i%R&BU֐C H;˙i<͍ B J ͼ Ҽ,΍B 0Bl< , @|΍@ ?,P @LUlv` ״66S 6O4[P 76R Ҵ CLkûkskҚcNĻ̎<ͼ IsϐqpQIJmըİ PJM ` JZsc]UJJӀ P gGiSw% 4qRB,,$*(a4+; » Q 8) L@1d SA >ݡOl*kO ۑ@ p_ȑ ۡ _ sۑս- ԭ   ۨ y;3oV00Z OROP $*V]nwP -V66QwP~J] SĴ=Jۇ ,nbP _0b +8; `@5PA&R6gPWp@5b5&5$N!`ϰuPnQ@^b ˠ  u 0~ &u0.u ˰꥾~n;~ _즾⧰x`O)jJ 9C&9@x.a,^7 (&P9pePÿՠNjTڝތD* "?$_#_Pj.0- 7ѐ0>?<-/ f`-onpONQXgQZZ__?_dRM M)pZVpO`5`|~OӪ=S?_€j0 OeQhFߊ)|?|ʏĻTE ` pȟʿ  `yPp>!O}U̹o8 7V Po$XA .dC&j4nG!Eɡ.3hdK1eΤYs9 0a ,Fh:%n$nWaŎ%C$=[qΥ[]>*D =&I&\ذ 4iQcȑ0C(O@5T)SPQAW+TfkرeϦ:Iao'^qɕ [$Bϧ_}O?Z4gd@ 4@TpAt5*B 3pCCd p 63ϳBcr 6x$FeFqGnGGH rI(I*dH+2F,K-R-$L/Ls4!.#Q:CF O@tPB 5PDUtQFuQH#tRJ+Fl= 3UVS]UWaVUeW[U\Y^QU`gb5Xdc6Zjj[nl[cS>EQI+w^z^|w_~_x` 6`> sCD;CUQb3xc;cCydK6dSVye[veM,u=ig{gzh6hVzivi)fN9$=k{l6lV{mvm{nnxę!5v3n|p 7p/ܛ]+Yj+r3|s7qumx;7tSW}u֥j׽y4 Pvs}w{q}twxW~y>oEךE&oz~{~%7|ww~k  ` x@&P d`@FPT`lS5{_䪧>V>@ MxBP+da ]BP3a bԱoX>B >8LxD$&QH4@ r]xŹ q[bE41wfaqu QF8@x`c; zH:s" 3$&G c@& &WÏdaMn9 h!'%(aK&7S 7ȈBP3D '[yMlv䕧a7=pP&` D'Ps]BS(@;fL $@D<0<DPQl $)6)srg,^Y8rrp/Z.5(hd(t &p7 7B9@S !4!TD@vYJV (i]Wy o[)wKI Nrb. a@C(EPT9yby`@#' jA#(* LAlkZPAkoMu3vk_k9 a $\ &0P!Aae@L0|7v@+Z @p)/&00D |!8"p;'\Q{)L5nbNl~ BxSj1@HâP'4"rl|016JWx*#XP p]Ve@ &1GJ0L(*ЅvqV&LrH*d@Ȋ3riiR.<4P l@0JBLf69!oZ E2r @ijim"99`Cщ֜R @'4xvNTJ;l( #Aa@ br&eCs&[ptAօQA'&}u /i7/̦φ(g\x=q\#'yM~r72+:\',l~s\;y}s]C'zy<-7cpG]g][]՛.\c'¼kg{ۃnZ~Jz~w_Kw~qz;=hK'^~H2^<o$]<޽;3'}?O\W^gAz^cw=3/^ >={Wp-#?{'|觏7}~OhK>D|MjG9~_8ߖ @tc#+@l@Q?;'  T: ! ?=D@-&{A,?dAld@#6z!)+lr8D)BqvP8:&3@sY4p(Ʋ#1&c Bۻ*t>\%$ ȧ(u*dz'K`~(xB IM4DOTO@ `R.0$ .@0hP|ʥ:4;l<÷Cc"xM * Ⲟp h 0 (ijT*r*FpGj/ @6k0(w*~,|@,CB3Bl)܃)(x hd(%@ 0Bȱ-ذȐ,* -H0p 'p!* j$ C'$Ç4=Y4#E s.Z t(RЂMP hܮ;K ˱,˵..' b.pI"50-CSFV*Fc<ܡéԥ$|K (D`.X/ȪLQ#L,͝.ؙ 2`* 1 ´Ædde\ڄI'-2x(kB,2`ưaN($X/Np-O0v+ P"3l1&L8ü2|J)+T# N#KO+h4JۧvlO3}P 5 PЮRP@0-* 0 2 (hP՝T֑ g6ij Mm(%,/ŝQ3$# 4A /L67ˑI%{<#\RS%N@ET8T#G)\[6>M3:O9cdETUTU>?JmUkR+tUY=XuTU[S\UUUaͽZ-a=ֻUMUf]<`]fVVcEVkպbmkVSSVp-gp ;-WVmVW׮kT}?EVj3؞AVBv]qUCERS՜$HӇwW,b9RɶQQe/LS)v@)0C׳"T# !x b3Z1I95 &ُ#x +%ZV Es,(ȼ؂C̉tKQDM DE4FGԙRDJ͎X phΓMUEʥ. &(' (Z肵؎,h6=u(j0h+(LPܐ+($xȅIگy!@2Mx),_]ɖ|IɐIJ013^P0(%[1ڊ}Zd  -2H2XN1횴|`Wx_Ԃ`]\ x&߶1[E[ @9,QK RaLK,ÝQM-0!(W}=#X\@Q HK(xj]#) ]]-p06~1()ˉ*L0 xC;W(+,6<ڕePi@!-'((NCࢤ4T^e PHөдPmJ@O[K  eѫE*thPA%2F =eq|B#䞙wfx-+gIYMWHTWv.ڀ{WnOT+h9hL{g{h6_qfihhV^in&i>i.P>Xr}i֜iVLdU>1iSEjλ-頮jNvjjkk.k>kjjx&%kkkkkkl.l>l†wPyiff&)8ʮl˾lllllоlHp.m>mGo=]rM~+ܦmmmnn.na^n~HMQh[[C.&H USn4/ZXno~dA؇u]K>W`aJfk/opg`SF;pp p p O qq׀~]fqrl `);#U +  :w1>r$GD@&or'r&<Ȃ;`q5rIۜ(~`޼8' 2hN% +CWD&s& DpǼ\.OE[]_Ԃ`ԉ[ z)YEOޜH`BDE[ ItKL[QD\F;u;`j+ρ*Iu2 .`؂IDu2t.h uZ2''} ~'q5s=(s!/wTP>@V (.wqkll)24Hॄ\H3EЁ0" πGH2iزb{4xWxwo~wBmG)6`#4Emfu1hvځ"0' xmJ@h7mfNd\#OO@JzEz/{/{VH@h{@rg(486h+Ɣa | :sJJ X' -F J$P1_|ʷ|411=y)6"Ģhk3}-ݯ ݷ}܏5k_)_ ^~h!x2|+(~/7_Y((W@Xu.թ>5-(o  Q d0ڋ/Nٯg9p gܒ@  h`:A q%Yq4Q xP9p@ox?)TD < 2| HI 8T}g$}IJRD0/r.|! c(C YP%js>!(!F}'@*ЁdA N,22b/9ƅR(F315%:')&=)JSҕ"406)Nsӕӑ1$AN2nF=*RԎԋ  ԩRVj˜B4N LKf=+ZӪֵn}+\*׹ҵl Qӭ:PXkI;=,b2},d#+R¹.үa*VC;=-jSR*geTJUu!iW򶷡lkEui%\u sTS7cG+̱cvx7rWv ]Ѻ oե#kg[?.k0L %ht",7q :p(la:bX0@, NKxp|K_an@ k{!# p޸ |W  XH~Єqg@P7ry_@G3Yl'1rx,9op/P>%2e7r G; z}@iKq d1chj8zAj:ִ8 G~xZ/ [w/M7ddW(01"xB+dj;ԧށr.#e}txwxelks6C8=g h3m t~A @E ".o8@x$F*<X +8x?k־.lH3F18zP BpB hBuC1͎7zm׷ԩnuku'x&=Ko:+4m š%5x# 1 pfdޛ{?їڍ3= 3;FW@*I.LZ% u]Q@]>>c5?o|RԷ~/ӝooñ IG' g(Q  D Y i b˜` f"( FLUb ՗zh%Hd[(Q ^PBݑ֑QZ*V(a!)p^l>&^V[ W !;-H-N"ADa]"&f!W % i)"**"++",Ƣ,b+V"T5a" 0#11#2&2.#363>#4#>.:6n#7Z#2Z$"99#$_r;# }#=a6#@@?.c<&B.̣AԳ1DN$E2'"$Gv$@5 Fz$IddFB$BV$K9:dHc$MdJ?$O䐡da$QeUe)LdNS:TFTN%UVU^%VfVnTƋS;dP*e;2%KI%[[%\ƥ\%]֥]^%_%XE^NP%F1A8 c>&dFfA#Te^&f:$|C6l>"e8*Q!EY؁4&kk& l#Ԧmfm&$@&1D7:X,&t20ϯ4ԂtB-PuVtB%@2 H@X> 0d%pApCp(Fe $Ԩ( ApBip=r4hȆv(EMTgbьV"\FP"dtc`Dr `q('N( `hAFxPRpA8 HAD Ύ'4@XtA4FtğNj^: 2XHKR@5$'j\* T@@@RA$\~A<`|^*(r&!FNh$.e0@ 7s+:N0AԀ4XwTCD@@H@k+H@@AC+++*,ބ ؀5 N L@@ AS / ʆ A ʶl̪'@DJ% A4@-&.-6-B4kED- l8 &^VHy@5@ `4ALh ڶm BPB @ C)@-- y0B.PJҀSHPB"&xMn? @..,4ko9Ρ5hZT\@.C]-\D0L`t/op@O͸oM\ZH0S@T2C0AD0`<0YD0\`Y@ ,0 cXdP sB6'R'Z/;ԙ@ǥGvlGgxzNDH%zqڇFG$qPFPE^ȏ8 Q9AI7X;ghpID $˳  A@4|qGNG s s鿂JXG$G'r(P䇨|RJ8A( 2 2GlC r-2HX hXK32'sK4Ktm9:FXL:8dp4XCH`7H˼ @ ATL:<3|ʜ\L   M(AؐM B{Csހؤl4Gwt0X af(0Z%-ԀƋN :0QWS&T!Ip綖` d9PZ5[7u$RsrXtPI`6a!% Ãq2W-ij=%|&n6 hQ!R"Vd[se/Ѐ4g+6+ `uV+ ^%J9A2)S6-7s7s76u7#^JwJ4@5@|7xx7yy7zzxC@5(V7Kj7~JkN7 Jr+v}$87-%P7O8dKW ]u8^o;]8y:xIV X8Ǹ8da-ޗNp%m8-"!.ː97)VH& Yxni]4Wx Q0Aw9^ g-`؇E Aџ Q8#:z z٥'\d?b^繞cRYő%XAaѭۙZY< {ٙz:mћř=A9x-[ _q4TCiA ;Axy;ݵѽѱQ_C)<{5i87{1Yۘ@P|f  [ =<̣QQQ|{mX;AۜWcp븬Ϻ%=̙ʩ@,p"̅ ]H t p[לؓ} ګQ9B\y:usy=ܕ@H ]]CPB;Klܥ؝[藾9ݚ ,w>KS~?w<,^iyaˑ͑@ Qa?m!D6]}ӡd48dT1)VxcF9vPbFIZD0R2&x2yS@JT%-WDĜiQ8`ˤPN-YI< -iإ&ܸ)H+\J-CH QA,Z@8`@X A Hɓ)W|sf͛9w7xL.&L(Q„)kP6Yh/-@ "@0;ạ:6Nڶq~n`BZ)%х Fo }2303 Jh! Ï|FJR JAJp& 5,UBjPCM"$7CE4 =l9 q)l|k=ӏ+찁 \lh.0AФX |T1X3+3ĩM4՜Ӥ7,I=}K̏+ pJT A(H%RL5ݔN=EҌIdLȔ|XeD\uݕ^}`bՀf͌ 5U@* dsulV3Qpr=t]v}\|Xf|6hUKG  >8Q /DSQ-!E-)VԆQv]ޒM>U^YI{;FECnldlYuޙg\fieWb.5>餕^c>Uh~#~h묵.RajE>!Z՞ޙC~[l'`;왋&$~[5߼=M?ue\cg+|/?x&_}k8j&%K&_?|9_Շ'YuO` 8 X@p@:`-qDZ g; !HXB)T S8G1!$ {z0غmPA<2HAg(&* *XE*^H(э VlVX]x+f4; Aj Fl _cPgko(ahLR|~,'0mR   P aept ǐ K 3uא GJ  Lj2  PQgQ' PQ'`3QMw 7C1V:q O%S_Q.VPkn{3r7B+/QvQC Q}IPaQQq0kQQA1pjC rq#r y$#C"?Vm2f``222V$ `YH@c&#'%#T vΏ`"`&C@$)3)*E$@"bjj$+Jڡ""0hD*HJ( 8,R"h0@@$-R.6gE(!hh2\ln` $ *373*,# *֪ @7\3AS4 ȠDJ2bs6k'%9U"0 & 0s2 z Ӓ-P nR;{*#M2ċ+K25 3  ƪԳ9ɏ%R$ "S"\=М$ \ RA"fJA `ĄjǞ)7m0 Ħ$CAt12 qR $".-8tBB3 HE9"ʠ"P8&t'F'J-F1%@3Ơf k^3$ NO2~$ PL`G2|8[&VML@,D@+K\u隕ﺓo" 0 [Oڦ:vEn$Сz(A7pW35(۲:rK i:c P@ 0@ Wo+`$" ]WygwCF @yU A<;^@YxNFoWvC ?d7I{ PB[}Da$VBbwI r$t [SdP C|qPৗ`z;P@Mr X|8 bKMz n8yK\ąȹxǓ:d0M }h$ 6PG"r'\*e=QeZM B&6=Wo M ,'@;9G\EVEg]O07p ww`7$ONWpżRv+Vkos]w{Xe`d^؏ٓ]ٗٛE^sN7end=v`ۿ=deuQұϝF޵F&7f޽i] iu[Rނ>1+`3=}!XKC9q/c5_C_[^ks>B]{޷ݣIg}&S^Y1j=賞ս^m^対۞.^"22폗څ~Nn "?!_'+._3-;?EnN6C_c_@(v{_?'!a Z(A _ <0#ja@@hA__T ;5fn gl)gi&c -0R6{!WCa6b'> i"?lRBYJ]:dEL ] eB"_<{T\lhб K18;H"+'2Y2ks><A01/6dمP`*ذLl@vTrN"_|Aj6 wrOvlH[-I3 荒.x@ ED暧 Қy7`AN,4_ӏH9"l(;YFsbxC1Ɍ%qvryr$-iROL%1Ә´s2 !H ; `jL)@ B `ZuwC)l l@aѢ ty' ׸rx'xV^|sB_կD`Jz Q ٵC iH$2HdtE܋}l E@  S,Llnjɬ ,Lll̾@@ͦ|, -` ` пt ! 0J<\# O -Mm  -<[0@ܿ w 9s\}M -p,`9;=? A-CMEmGIKM Juggling Lab siteswap input panel

Using the pattern entry panel

The pattern entry panel is where you type in a pattern to juggle, and then optionally adjust the pattern timing and movement of the hands. Its appearance is shown below.

siteswap panel screenshot

Description of each part:

  • Pattern. Box where you enter a pattern to juggle, using siteswap notation.
  • Beats per second. A number greater than 0.0 that specifies how many beats there are each second. There is typically an average of one throw per beat. Leaving this blank causes Juggling Lab to calculate a default value based on the pattern. Typical values are between 3.0 and 5.5 beats per second.
  • Dwell beats. A number between 0.0 and 2.0 that specifies the number of beats a catch is made prior to the subsequent throw. Default value is 1.3.
  • Hand movement. Specifies hand movement using a text string in a format described below. The pulldown list allows you to select from a number of built-in hand movement strings. As a default, Juggling Lab determines hand movement based on the pattern.
  • Body movement. Specifies movement for the jugglers using a text string in a format described below. The pulldown list allows you to select from a number of built-in body movement strings. As a default, Juggling Lab determines body positions based on the number of jugglers.
  • Prop type. The pulldown list selects the prop to use.
  • Manual settings. Manual settings to configure the pattern; see the description below.
  • Defaults button. Click this to restore default values.
  • Juggle button. Click this to juggle the pattern.

Hand movement format

The text string representing hand movement allows you to specify the spatial location of the hands at the times of each throw and catch, as well as at points in time in between. Juggling Lab uses a spline interpolation algorithm to calculate hand locations at all times from the coordinates specified at these discrete points in time. The format is flexible enough to allow you to define hand movements of arbitrary complexity.

Imagine that you are the juggler, and define a coordinate system with the x axis going from left to right in front of you (positive direction is to your right), the y axis going in and out (positive is out), and the z axis going up and down (positive is up). The point (x, y, z) = (0,0,0) lies at the midline of your body, in the "usual" plane of juggling in front of you, and at a height that places your forearms roughly parallel with the ground. We will specify hand movement in terms of coordinates in this system.

The simplest case is a single juggler, with only throw and catch positions defined. In this case, the text string consists of a series of coordinate pairs in the form "(throwx,throwz,throwy)(catchx,catchz,catchy).", where each pair is assigned, in order, to a throw in the siteswap pattern. All dimensions are in centimeters. Note in particular that the y and z coordinates have been interchanged; this is for convenience since leaving out components at the end will default them to 0, e.g., (30,10) is shorthand for (x=30,z=10,y=0). Other facts:

  • If a coordinate pair is assigned to a left-handed throw or catch, the throwx and catchx values are automatically negated.
  • The number of pairs specified need not equal the number of throws in the siteswap -- it just loops back to the beginning when it gets to the end of the pairs. Alternatively, the hand style can have more beats than the pattern.
  • When applied to a synchronous siteswap, the coordinates are assigned to the throws in the order the throws are written. For example, for the pattern (4x,6x), the first hand coordinate is assigned to the left-handed '4x', the next to the right-handed '6x', and so on.

As an example, the standard style for inside throws is "(10)(32.5).", which means to throw at 10 cm from the centerline (at no elevation) and make the next catch at 32.5 cm from the centerline (also at no elevation). The standard style for Mills Mess is "(-30)(2.5).(30)(-2.5).(-30)(0)." if you care to puzzle that one out.

The '.' separators in the examples above correspond to beats in the siteswap pattern. For example, at 5 throws per second in an asynch pattern the throws are typically made at times 0.0 seconds, 0.2 seconds, 0.4 seconds, and so on. Catch times are determined based on the dwell ratio setting. (The only throws not made exactly on-beat are '1' throws, which are thrown slightly early and caught slightly late.)

Hand locations at other times (besides the throw and catch points) can also be defined, by adding additional coordinates for each beat. For example, the style "t(10)c(32.5)(0,45,-25)." is an "eating the apple on every beat" hand style that keeps the throw and catch positions of inside throws, but also defines the hand to be at location (0,45,-25) at a time exactly halfway between each catch and subsequent throw. Note the use of 't' and 'c' to indicate which coordinates correspond to throw and catch positions. A few rules:

  • The 't' and 'c' specifiers are optional; if unspecified, the first coordinate is assumed to be the throw, and the last coordinate is assumed to be the catch.
  • The 't' specifier must attach to the first coordinate, if specified.
  • If multiple additional (i.e., other than throw/catch) positions are specified, they are assigned at uniform time intervals between the throws and catches. Imagine the coordinate timeline drawn on a rubber sheet, and imagine stretching the sheet in time to match the pattern at the known throw and catch times; the other coordinates then fall uniformly in between these defined times.
  • You can specify '-' in place of a coordinate if you wish to occupy a point in time but not define a hand coordinate. For example, consider the hand style "t(10)(0)-(50)c(32.5).", where the pattern timing is such that the first throw and catch are made at t=0.00 and t=0.20 seconds, respectively. Then in this case, the hand is defined to be at location (0) at t=0.05 and (50) at t=0.15, but the hand location at t=0.10 is left unspecified.
  • Throw and catch positions cannot be assigned the value '-', i.e., these positions must always be explicitly defined.

Lastly, when there are multiple jugglers, by default the hand style is applied to each of them equally. To define different hand styles for each juggler, the format is "<(style for juggler 1)|(style for juggler 2)| ... >". For example, using the style "<t(10)c(32.5)(0,45,-25).|(-30)(2.5).(30)(-2.5).(-30)(0).>" with the pattern <3|5> gives two jugglers, one "eating apples" and the other juggling a 5 ball Mills Mess.

Body movement format

The text string defining body movement allows you to define angles and locations for each juggler's body, as a function of time. Its format is similar to the hand movement format above, with some differences:

  • The coordinate format is different: (angle, bodyx, bodyy, bodyz), where "angle" is the rotation angle around the z axis. The other coordinates "bodyx", "bodyy", and "bodyz" are in a global coordinate system, unlike the hand coordinates which are defined in a local coordinate system centered on each juggler. Default coordinates for a single juggler are (angle,bodyx,bodyy,bodyz)=(0,0,0,100). bodyz=0 is floor height.
  • Coordinates are not attached explicitly to throws and catches, but are laid out uniformly in time within each beat of the pattern. The 't' and 'c' specifiers are not used.
  • Coordinates need not be defined on each beat. For example, the body style "(0)....(90)....(180)....(270)...." defines a juggler slowly rotating at a fixed position, with a total period of 16 beats.
  • The same body style cannot be applied to more than one juggler. When passing, separate body styles for each juggler must be explicitly indicated using the same '<|>' format as the hand movement setting. (If the number of jugglers in the body style is greater than the number in the pattern, the extra jugglers in the body style are ignored.)

Examples body styles:

  • "<(90).|(270,-125).|(90,125).|(270,-250).|(90,250).|(270,-375).>" = a line passing formation for up to 6 jugglers.
  • "(0,75,0)...(90,0,75)...(180,-75,0)...(270,0,-75)..." = a single juggler slowly walking in circles, with a total period of 12 beats.
  • "(0)(90)(180)(270)." = a silly example defining a single juggler doing a counter-clockwise pirouette on every beat. (Note that, like the hand movement setting, multiple coordinates can be defined within a single beat. The '-' spacer can also be used.)
  • "(0).(0).(0).(0).(0).(0,0,0,150)." = a single juggler jumping up and down.

Manual settings to configure the pattern

This entry method provides a way to manually control the siteswap pattern. Everything that can be set in the other portions of the siteswap input panel can be manually entered in this box as well. Manual settings override settings made in other parts of the panel.

The format of the entry is a text string comprised of semicolon-separated assignment settings, for example "pattern=(4x,4x);bps=6.0;hands=(32.5)(10).". Variables are:

  • pattern – pattern to animate, in siteswap notation. No default.
  • bps – number of beats per second, a floating point value. Default is automatically calculated from the pattern.
  • dwell – number of beats a catch is made prior to the subsequent throw. Values are floating-point numbers between 0.0 and 2.0; default is 1.3.
  • hands – hand movement as a sequence of spatial coordinates, using the format described above.
  • body – body movement as a sequence of angles and spatial coordinates, using the format described above.
  • colors – determines the coloring of the props. Each color is defined either by name or by its red/green/blue components on a 0-255 scale. Thus if this setting is equal to {red} or {255,0,0}, the animator will use red balls. If you define several colors, they will be assigned to the balls in a cyclical manner. For example, {255,0,0}{0,255,0} means that ball 1 is red, ball 2 is green, ball 3 is red, ball 4 is green, and so on. Recognized color names are: black, blue, cyan, gray, green, magenta, orange, pink, red, yellow. Using the value mixed (no braces) will apply a pre-defined mix of colors. Default is red balls.
  • propdiam – diameter of the props, in centimeters. Values are floating-point numbers greater than 0.0; default is 10.0.
  • prop – prop type to use. Recognized prop names are ball, image, and ring; default is ball.
  • gravity – acceleration of gravity, in cm/sec^2. Values are floating-point numbers; default is 980.0 (earth standard).
  • bouncefrac – fraction of a ball's energy retained after bouncing off the ground (how much of its dropped height does it return to?). Values are floating point numbers greater than 0.0; default is 0.9.

The following variables are also supported for backward compatibility, but their continuing use is discouraged. Most are documented elsewhere:

  • tps – use bps instead.
  • dratio – defined as half of dwell. In the typical case where a given hand throws on every other beat, this equals the fraction of time the hand is filled with a ball. Values are floating-point numbers between 0.0 and 1.0; default is 0.65.
  • throwx – use hands instead .
  • rightthrowx – use hands instead.
  • leftthrowx – use hands instead.
  • catchx – use hands instead.
  • rightcatchx – use hands instead.
  • leftcatchx – use hands instead.
  • balldiam – use propdiam instead.
  • g – use gravity instead.
jugglinglab-0.6.2+ds.1/html/title.gif000066400000000000000000000421141323754603300173310ustar00rootroot00000000000000GIF89a8|||Թ : :,,,cccAAA444&&&öhhhLqqqPPP;;___LLLWWW;;; i.l)333333p`pmgf)&< 4~~~44/AJ2Q-yyyx98<< ڰjvummmOF􄖖ZZZppL/1Tt*uuu_XppgPQQ"ʘ,^)WIqqVN+p%>P;Ln3=v2dl$}}~|6 ""ڈZivmݲH жeeee e\ eb[i+ A ++ =7#5  GGG=23vvֶ~m ݪ5g>TPߢK\<>TXZX8ȵK=̉!,8H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ Jt (]ʴӧPJJիXjʵׯ`Êe(1x4 #Tł ?d˷߿ LÈ+^̸ǐ#K,G('<*6Alyä#^(l۸sͻ Nȓ+_μymIs)x9ɛϡG트szAT2ҫ_Ͼ˟OϿ@( ^YgFiPZnG[(a^ ($h(,0(4h# H(` g6iI[rI@ATR #b0W! `3 h9eWyhifp)'OVD @w n'a[  X c)CB '=uqI`% aW gЀ tPY0(@'ol'|1dX/`AHA`P%!jJH"HL| r@hCEsh0b_!r"W&a" {(!B !>`tIBL!@ 0>uG1NX[ Cѹ΁=B eH Oء r3dC)bM@DEhJ Hm`8$"_;c 'fA,ȗ#c'!!2P`@0K.2 FqW@  A<xE5f sa-cGAjB3@X ">π0r0α0e #XҖF .DL[:JG*LVJHL}t"3fm,l"Mbئރ9J́+Lb0h<1wΚ,:knw ,!a5C v >$:,; G<~N @<`F3N?@ / p6q ϸ'aa8 %#y==Pj[C H͇NHOAp<00+@Bn{DX jx3CxAD~W2zoAd0xb;kl4`iL?ޱ h P MxX(>02S8VY.4`xhjl؆npr8pvxxz|tg)`p$ LXi4X vX x ؉ȉ艠9 ؊8XxHuwwGpVFPGЌ8Xxؘڸ؍8XHpX'q ' P؏9Yy ِi}( w|WX0$Y&y(*,ْ.0294Y6y8:<)`w5@  =PR9TYVyX?~@ wvIMjlٖnpr9tYvyxz|ٗ~w]~`)@JL)j9Yyٙ9YyiI^y5٘#IAٛ9Yyșʹٜ@iaeɘgY@E1`0@9׉i߹ٟyٟ59yܙD)1A`jYZ=Aj.ўIiI *z8,y)yjI<0'/3jiN+ZjP.1ʠ4jXڥhJ\" :2ZNilz!xnrJVgzzZ~ ڠhyqj ʨD5Zѧ*:jڡ JG:ʪ q:cZZR*ڝjڤк*"J*ڭqqz: 説J꨷ʮꮨꨝ**)oozTJzz( [0S@#H0``;  _`P Vۥ h`6kh (kna" [PpJkPlYPK>;B Z#ʰʰK _[`6! Yn#@!Za{e J NۥP%0;Px?̺ʭPL ^dR!@,p;0 6];jZ_pZ``%{n r w˵ }[Vfk/n{p|0QW@J[ [{kK1$WP=4[=@-zF0J+ `ʶ/,H Q$A0 #nKjEz(l@,wPP pg+UջʫPY: W;vu\0 ‘䪭mнOlV -1 / r<{ 1 |ƄI|K,Ⱥ, a8:=^?c=En&ZxK7"Nu[0}C-,1|Lp0o.} {ྠ q. bk_^|܌@MZ C\|h!xM]N dQ"p1` n>`=s^²>(p`ana>~J;>> 388( 2aK~`.P w1Ga`Y.ϣY !1 WQB`a='N-; P%{ 1WA oQjO籞MPR>pM)p B?(N%;i0>Bt'_}Nzϸ.p~@/`!<@+@+ Ȍ?(`*}/A (0WoWW/Cq0P wPWv@>/-y,I]mG0$ !  $XA{.dxP@Ç L\88tȠa (`H$ @ :p89uOA%Z` #&`ĈB!!!+2 1(RBϺNI'TE(k$`R>7 -!n5 5n{ZA¿p#Q=O31CK5U67-`=WVҔQ݀C?E L$[#Tb-*U\꠷#fJbh{ ^4R3wܠŶQ[l! 8O#%_2^ࣄx#'H`bV(zkS^6Q xdcʉ ^8l`#F ၝD!b2cB2 "A^T&5j (@ VA P(h=УZbA'LZT3mi$$ DB vZ ^Fa+^uٯvSU:Zn@e$fHbuQA[Lte%0[޹rW y =Y+\"8|+{x`D~@/p.9\0`K\("q-gQ\}!\!V^?*2D!X8VQ|@ G5\^fx cSDH >aAi/Iَ-\3^O/(l@ǂL +J0KF  ̗)Y7KƱ_&80YƖ@.bU& AP,bHla S؂/ AeZ-^9O SL  ZnpkVCj4tZA8&#si"g12ym +p̃(}C/ Ѓ hCHDсd/'`MX ',#{ "E20` `æ6B8=gW}F'Tq _EI a{z^G5Z%`p`t="0ևNaWDE֏NMJ4Ph,(QKSI0 lp\,C%KYsӘ~w- 8HL#_#'ټ ^elXkkjÁh$/S‘Is.LP%l.T36 pC;^ >"5)|+ԻjfKdrb\Զs' JCt}* D4n,.({_f|̣_ݿWЋln ^k8IH2)kbщEA}"c>L"IS`GY900ZLX.G:^(.#4C)3lP9*(% @(8hܥZوe`xEN -qla &pBpR,̦+z|^$! v5iuY݋ǐp+[uqo 0گ7%y!; 0?hjw&{݅^Q jk`z r`gA+uҭ$•@./=mzޒv/Ia3~$5O4};9oI ˩-s*^<߯Rz'Lf6ٍ`36Ex_nB5zQL :л -}/_{: hiW%_ke;FERڴ B=!ť+U>SN%1~sStĀvI jD7?QрA~]ǿs 3wwc%?ճ13?7 \G k B2YMЄs2X'@n);C8J.3Zk>[{  =\c""m?b#0TA'6 &# c' ;"A03;K @ c>. J++yB=@&6ઠx \cЄ=AM,, 12C)b>5ø/ 6KL,M-!EU S$\E+-7 Ńʉ<"ڮ0PĠRAӣCbl?j@ !x;B.Y_F|+GLEkCs(wɉqF@mԆ)G8ȯɩRd[ʳ Љ )%K82E|" ɂ$%9Q0)Cx!0X&4]^F-' ;dC:$ Pˠ`cjI[@}O,"M7q٢l& ȉ;A?˭G 8 BJZ˜`3 cM!? =|5,2 2 BF(#<6*ɞ!O|#O2jHd\OlO:|$OOOpO˄<;<@!A AMNa!e$+"\/#&܉+H`q̔HTQ!!ȉ$\ !HNI7NR-U,J2^ ܉hRP_RR:]ѡdAJg I H1OK}SS :]T;ȯ;" H: :DEF69G$Cp*TDͲ,T:uUZU[U\U]ՇSr9U'dxgp'@1O]DH'sֽԿ#V'qWq}*@;J78SV(!hJ֜ JhIQؘ<_U6N-/DqO^W㝍PRi0@;EP oZ 0 !݋]EE5pÛ5Ĝ(-_E"EKALArŘ+hH`5IdN;-_qE +2LQƩ NX?GZذ^_E&i: 8[ 5 nՋi#<^&f@:(:`a)NE`ZE Խ Ǭ^Wm%yjm %^}<">?dA΋c`-@dۮq;*~Yeb9M0cxJT6$=9<([W5Wt54a[aZ[?AeIMcm]c%qБ VcEVee>@`B W ݼx@zMd-H!( ~0E%Z_Ii\ǾSN%4uf ʀ1; qej&% cf @ @IcI7ЃCz)ld$WPӑ!VovTJJ~p@4knVi7n:Kmw[KY(==`l@/]|\e6nkyc~gmG ɔ<ˉJ !h^?;V]Y T2`>r'+6ϖqqqS/(+ s0;y{foy۾X4fY$5As~_"?rk&m Tjf~&p|Qr 8&¯rP,(h B^\ }nPG56r\0 pA $PP*(H@…2t0' -j(ҡB$4)ԨR>  ZNa$ X{XpEZ$o0Ċq0Ydʕ-_ƜYfΝ=2f1a(Rm 02I4^%;kI=@#ۢA!s1(Ut S&M8u02ڍUpM⇾DW[vF}\ ^ψK,^q$mA DI)\cAF]Oex{R":PH†{i&Q+xL\qDfG @A\b1cIPB]ߑڍ`4)ވ߉Yemیi#qa sIYuM8hvR@柩UZB%*[Q`3xo\1Jho^}`tF8ҝ^ 0bv$CBZ"8W<3x e*hG2Z[`We^kAoQ|qڛPBJeFA/,n #p䩴r>8ݲ;U 0dN O9!2W -(lPL+%Bk;(dE<lBWC53]'T1 bPx*GGI*HQD~7~`-ž{DZ\9bGq@(W Z !Fݥvna mԢ7{qǽAz'1xx"f;oNT3܍muŒ3mn;L6!=lP{B󚐎+jq)C$J$+5qJ +A`I!pP'P Jxq?]jq U49 =@0B(D~MUfjr?J%Hp B ~pthg#EP}Tp!I=, bT+cx)m8H7Ah@a7g$ vx,ѓuC .&mкRi7!YrTB=0(\𼨸oY9D]LG+9n²@lᆸP:Y-@Q\E:cD1m1lީɳ @±<6E` ?m(U{W R@$HBsRœ.C r 6IWO%֔! x!0AN`@;=!KsU'4n`0tR*4)ʳC!|` Cq pxPrKc! W%ZL6?4M-::2SJWPbي&;kpڨJ!UXqG(gDPx``]EaQ ̥3jj]H;9  L9%׾H9t &`.fᱦ:8b~gH4xڃ`V6 AD5 т8QԂd[RVg i.b a@X@oKȧt?$Kg4 "pޑV)jm8duQN@t[.^Azd29AB3 03S@k Pь,@}f 7VoThpȎ}f2%-AI$5Zi@%\ոtHxApMq - \A@g"G]FÿI[LYV̑atN2A t@ f0=dS)n|`Ŀ2}7Z\dI-9@QA H$A#p$ah@"N<Q4QsŹNM^7U*ry vI\A{X A1W ")La CVB+(0) ۣi3<&9iK @.<`؅_ tv6zjn$j_5p΁U%-~{f$_L}f>dcn&V|QeMfF B.0(0-(FcjghPhbni>f|NfZghQ^WH}eRڨԨQzRH lr'"Ea%*̂ڧNiI)(r̂*D% X d@nxg瘆){))f L4M@TBfikgl醚RiFDV2*BGeRfJꤊ)ZQ`j%h*$@"ꨶ hi f`ja:#*Q4,ΪXتB&*znH4= )]xfj&Rkj&(bhSk*⪴뮶Fg22hĽ2諹*뺒^k&h@8BlꡲbiAR@ȪrBΕi2(t,*|6u,-6>-FN-V^-fn-v~-؂-,-%+ `(@4֭---..&.nª+tٖ-@(` +Mm#x!P.붮.Ʈ.֮...F. !x#rnALx+HBv~//J/v,!!xB FoLЀH*@@ 00'&lB@ @*HЀ0$.<@ 8 8̀ 0 ǰ 0 װ 00011 .@ $ <.LpK@oB+jN@"@ 0 1DZ1ױ111  2!A7hA  X)h *Bς 1 ;+2,Dz,2-ײ-2..2//20031"/0r(8.op*A&w|.+op$. ہ*:3;;3<dz<3=׳=3>>3??3@=sA,s3{Z# ̄+doCB8r93 4II4JJ4KK4LǴL4M״M4NN D hABC*E/NtEW$ |>`GAx 29;X5YY5ZZ5[[5\ǵ\5]׵]5^[G25(x$`<@N \>B @wl\B@* (|Wi6jj6kk6lǶl6m׶m6nn6lv <!d(oRD7llrTDxf(gςgWy7zz7{{7|Ƿ|7}׷}7~~7|g{ t@ `@r/@ X5DŽt0do Bxw7!@̂888Ǹ8׸8縎8,p$w(@ x\q0s3\s hdB`#<t8@ (t@ 9ǹ9׹9繞99:*({8Cylk\tW8(@$+d\,@`@:Ǻ:׺:纮::;{z`+9 8HB>'/>ܻ@T< )\{W@_Ux#@= PԾ>>>??'/?A>@@ ƿk{ؓ d9T>) +>=?׿?? 4xaB 6tbD)V8@ Xh%GR 䍑'<*P F 1_>rboT!i@#ARK6ujTSVzkV[vl֣EE  $J*Y)s&6oٳOI@(+p` 6|qbŋ7vrdɓ)Wدg=f!-_Ƅ7˹qgٳi׶}wnݻyxpÉ7~IC&]:&MIDۍt׉|xɗ7}zٷw~|׷?w۳l:{X|% - 5ܐ==TPAT-@\Bemuܑ)} "stQED@#|(*2F&. ;jugglinglab-0.6.2+ds.1/patterns/000077500000000000000000000000001323754603300164135ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/patterns/JuggleMaster.jml000066400000000000000000001604621323754603300215210ustar00rootroot00000000000000 JuggleMaster Patterns 1 Ball out of a 3-Cascade Throw Twice 2 Balls out of a 3-Cascade Throw 3 Times pattern=3;dratio=0.5;tps=3.572;hands=(10)(32.5). Slower 3-Cascade pattern=40;dratio=0.5;tps=4.331 pattern=(4,4);dratio=0.5;tps=4.331;hands=(10)(32.5). pattern=4;dratio=0.5;tps=4.331;hands=(10)(32.5). 2 Balls out of a 5-Cascade 3 Balls out of a 5-Cascade Chase Flash Throw 4 out of 5 4 Balls out of a 5-Cascade 552 pattern=5551 pattern=5;dratio=0.5;tps=4.98;hands=(10)(32.5). 3-ball Flash pattern=(4x,2)(2,4x);dratio=0.5;tps=5.591;hands=(-25,-15)(25,30).(17.5,45)(10,45).(17.5,45)(10,45).(-25,-15)(25,30). Eating an apple pattern=3;dratio=0.5;tps=4.611;hands=(45,20)(52.5,45). pattern=3;dratio=0.5;tps=3.572;hands=(10)(35,15).(10)(20).(35,15)(20). pattern=3;dratio=0.5;tps=3.572;hands=(7.5,95)(30,95). pattern=3;dratio=0.5;tps=3.572;hands=(32.5)(10). pattern=3;dratio=0.5;tps=3.572;hands=(30)(-20). pattern=3;dratio=0.5;tps=4.124;hands=(10)(32.5).(10)(32.5).(10)(32.5).(32.5)(25).(10)(-32.5,25).(20,-10)(32.5,-15).(0,10)(32.5).(10)(32.5). Reachover (alternate) pattern=3;dratio=0.5;tps=4.124;hands=(10)(32.5).(10)(32.5).(10)(32.5).(32.5)(25,20).(10,-15)(-40,-15).(10,20)(32.5,15).(0)(32.5).(10)(32.5). pattern=3;dratio=0.5;tps=4.124;hands=(7.5,20)(32.5,15).(32.5)(25,20).(10)(-32.5,-25). pattern=3;dratio=0.5;tps=3.572;hands=(-30)(-10). 1Up-2Up A (Columns) 1Up-2Up B 1Up-2Up C 1Up-2Up D pattern=(4,4)(4,0);dratio=0.5;tps=5.176;hands=(10)(32.5).(10)(10).(-32.5)(10).(10)(10). 1Up-2Up F Yo-Yo Oy-Oy Around The Yo-Yo Yo-Yo (Columns Fake A) Yo-Yo (Columns Fake B) Yo-Yo (Columns Fake C) Yo-Yo (Traverse) pattern=3;dratio=0.5;tps=4.43;hands=(50,50)(37.5,25).(25)(50,50).(37.5,25)(25).(50,50)(37.5,25).(25)(50,50).(37.5,25)(25). 2-in-1-Hand Tennis pattern=3;dratio=0.5;tps=4.611;hands=(30,20)(7.5).(22.5,95)(25,100). pattern=3;dratio=0.5;tps=4.269;hands=(30)(7.5,20).(22.5,95)(25,85). pattern=(2x,4x);dratio=0.5;tps=5.591;hands=(30,50)(0,-25).(35)(25). pattern=(2x,4)(4,2x);dratio=0.5;tps=5.001;hands=(35,50)(25,-15).(15)(25).(15)(25).(35,50)(25,-15). pattern=441;dratio=0.5;tps=6.125;hands=(12.5,-10)(37.5,20).(15)(12,5,-10).(22.5,50)(15). pattern=(2x,4x)(4x,2)(4x,2x)(2,4x);dratio=0.5;tps=6.125;hands=(30,50)(25).(25)(15).(10)(25).(15)(15).(25)(15).(30,50)(25).(15)(15).(10)(25). pattern=242334;dratio=0.5;tps=5.001;hands=(25,-15)(25,-15).(25)(0).(25,65)(25,65).(0)(15).(-25,65)(12.5,20).(15)(25). pattern=2334;dratio=0.5;tps=5.371;hands=(25,55)(0,60).(0)(25).(-25,60)(0,55).(0)(25). pattern=3;dratio=0.5;tps=5.051;hands= (-17.5,60)(17.5,60).(-17.5)(17.5). pattern=423;dratio=0.5;tps=6.125;hands=(-25,20)(0,20).(25,50)(-25,50).(0,10)(25,-15). pattern=(4,4);dratio=0.5;tps=4.331;hands=(32.5)(10). pattern=4;dratio=0.5;tps=4.331;hands=(32.5)(10). pattern=(4x,4x)(4,4);dratio=0.5;tps=4.331;hands=(30,10)(10).(30)(10).(10)(30).(10)(30,10). pattern=(4x,4x);dratio=0.5;tps=4.331;hands=(17.5,15)(32.5).(17.5)(32.5,15). pattern=(4x,4x);dratio=0.5;tps=4.331;hands=(17.5,15)(32.5,15).(17.5)(32.5).(17.5)(32.5).(17.5,15)(32.5,15). pattern=444447333;dratio=0.5;tps=4.964;hands=(10)(32.5). pattern=44453;dratio=0.5;tps=4.98;hands=(10)(0).(10)(37.5,15).(10)(22.5).(37.5,15)(22.5).(10)(22.5). 4-ball Burkes Barrage Danceys Devilment pattern=5;dratio=0.5;tps=4.98;hands=(32.5)(10). pattern=[32][32][32][32][32][32][52][52][52]555555522;dratio=0.5;tps=4.98;hands=(10)(32.5). pattern=555555744;dratio=0.5;tps=4.964;hands=(10)(32.5). 5-ball Burkes Barrage pattern=51 3-Half Shower A pattern=3;dratio=0.5;tps=3.572;hands=(37.5,40)(20).(20)(37.5,40). pattern=71;dratio=0.5;tps=6.08;hands=(25)(12.5).(12.5)(25). pattern=53;dratio=0.5;tps=4.98;hands=(25)(12.5).(12.5)(25). pattern=5;dratio=0.5;tps=4.98;hands=(37.5,40)(20).(20)(37.5,40). pattern=73;dratio=0.5;tps=6.08;hands=(25)(12.5).(12.5)(25). pattern=(4x,6x);dratio=0.5;tps=5.556;hands=(12.5)(25).(25)(12.5). pattern=75;dratio=0.5;tps=6.08;hands=(25)(12.5).(12.5)(25). pattern=(2x,4x);dratio=0.5;tps=4.331;hands=(12.5)(25).(25)(12.5). pattern=(2x,6x);dratio=0.5;tps=5.556;hands=(12.5)(25).(25)(12.5). pattern=7131;dratio=0.5;tps=6.08;hands=(25)(12.5).(12.5)(25). pattern=(2x,6x)(2x,2x);dratio=0.5;tps=6.416;hands=(15)(30,15).(30,15)(15).(15)(15,15).(15,15)(15). pattern=315171;dratio=0.5;tps=6.08;hands=(25)(12.5).(12.5)(25). pattern=9151;dratio=0.5;tps=7.012;hands=(25)(12.5).(12.5)(25). pattern=(2x,4x);dratio=0.5;tps=4.331;hands=(-7.5,20)(7.5,20).(-25)(12.5). pattern=(2x,4x);dratio=0.5;tps=4.331;hands=(0,20)(12.5,20).(25)(7.5).(0,20)(12.5,20).(-25)(7.5). pattern=35;dratio=0.5;tps=4.98;hands=(37.5,40)(20).(20)(37.5,40). pattern=3;dratio=0.5;tps=4.611;hands=(-17.5,35)(17.5,35).(-32.5)(32.5). pattern=[97]121;dratio=0.5;tps=7.012;hands=(25)(12.5).(12.5)(25). pattern=3;dratio=0.5;tps=3.572;hands=(-25,-10)(25).(25,10)(-25,20). pattern=330;dratio=0.5;tps=4.0;hands=(-30)(2.5).(30)(-2.5).(-30)(0). pattern=3;dratio=0.5;tps=4.0;hands=(-30)(2.5).(30)(-2.5).(-30)(0). pattern=423;dratio=0.5;tps=4.331;hands=(-30)(2.5).(30)(-2.5).(-30)(0). pattern=414;dratio=0.5;tps=4.331;hands=(-30)(2.5).(30)(-2.5).(-30)(0). pattern=315;dratio=0.5;tps=4.98;hands=(-30)(2.5).(30)(-2.5).(-30)(0). pattern=612;dratio=0.5;tps=5.556;hands=(-30)(2.5).(30)(-2.5).(-30)(0). pattern=4;dratio=0.5;tps=5.371;hands=(-30)(2.5).(30)(-2.5).(-30)(0). pattern=534;dratio=0.5;tps=4.98;hands=(-30)(2.5).(30)(-2.5).(-30)(0). pattern=552;dratio=0.5;tps=4.98;hands=(-30)(2.5).(30)(-2.5).(-30)(0). pattern=642;dratio=0.5;tps=5.556;hands=(-30)(2.5).(30)(-2.5).(-30)(0). pattern=5;dratio=0.5;tps=4.98;hands=(-30)(2.5).(30)(-2.5).(-30)(0). pattern=6;dratio=0.5;tps=5.556;hands=(-30)(2.5).(30)(-2.5).(-30)(0). pattern=864;dratio=0.5;tps=6.562;hands=(-30)(2.5).(30)(-2.5).(-30)(0). pattern=[34]23;dratio=0.5;tps=4.331;hands=(-30)(2.5).(30)(-2.5).(-30)(0). pattern=3;dratio=0.5;tps=5.648;hands=(-30,5)(-5,10).(30,10)(-5,5).(-15,-20)(15,-15). pattern=3;dratio=0.5;tps=4.43;hands=(30)(0,10).(-30,-15)(0,-15).(-30,10)(30).(-15)(0). pattern=3;dratio=0.5;tps=4.43;hands=(-2.5)(-30).(0)(-30).(2.5)(30). pattern=44133;dratio=0.5;tps=5.371;hands=(-30,25)(0,10).(30)(25).(-7.5)(17.5,-10).(25,10)(-5).(-25,-15)(5,-10). pattern=(4x,4x)(0,0);dratio=0.75;tps=7.342;hands=(-25,10)(-10).(-25,-5)(-10,-15).(30,40)(15,50).(30,40)(15,50).(-25,-5)(-10,-15).(-25,10)(-10).(30,40)(15,50).(30,40)(15,50). pattern=(4x,4x)(0,4x)(4x,4x)(4x,0);dratio=0.75;tps=7.342;hands=(-25,10)(-10).(-25,-5)(-10,-15).(30,40)(15,50).(30,40)(15,50).(-25,-5)(-10,-15).(-25,10)(-10).(30,40)(15,50).(30,40)(15,50). pattern=(4x,4x);dratio=0.75;tps=7.342;hands=(-25,10)(-10).(-25,-5)(-10,-15).(30,40)(15,50).(30,40)(15,50).(-25,-5)(-10,-15).(-25,10)(-10).(30,40)(15,50).(30,40)(15,50). pattern=(2x,4)(0,2x);dratio=0.5;tps=5.591;hands=(5)(25).(25)(25).(25)(25).(5)(25). pattern=(2x,4)(4,2x);dratio=0.5;tps=5.591;hands=(5)(25).(25)(25).(25)(25).(5)(25). pattern=(2x,4x)(2x,4)(4x,2x)(4,2x);dratio=0.5;tps=5.839;hands=(17.5)(35).(0)(0).(0)(0).(35)(35).(0)(0).(17.5)(35).(35)(35).(0)(0). Advanced Box pattern=633;dratio=0.5;tps=5.556;hands=(25)(17.5).(0)(25).(0)(17.5). pattern=(8,2x)(4,2x)(2x,8)(2x,4);dratio=0.5;tps=6.562;hands=(25)(25).(7.5)(25).(25)(25).(7.5)(25).(7.5)(25).(25)(25).(7.5)(25).(25)(25). pattern=(6,2x)(6,2x)(2x,6)(2x,6);dratio=0.5;tps=5.556;hands=(10)(32.5). pattern=(6,4x)(4x,6);dratio=0.5;tps=5.556;hands=(10)(32.5). pattern=3;dratio=0.5;tps=3.572;hands=(25,-10)(0,-10).(25,15)(-25,15).(0,-10)(-25,-10).(-25,15)(0,15).(-25,-10)(25,-10).(0,15)(25,15). pattern=3;dratio=0.5;tps=3.572;hands=(25,-10)(0,-10).(25,15)(-25,15).(0,-10)(-25,-10).(-25,15)(0,15).(-25,-10)(25,-10).(0,15)(25,-10).(25,15)(0,15).(25,-10)(-25,-10).(0,15)(-25,15).(-25,-10)(0,-10).(-25,15)(25,15).(0,-10)(25,15). pattern=4;dratio=0.5;tps=4.331;hands=(30)(10).(10)(30).(10)(30).(30)(10). pattern=(4,4);dratio=0.5;tps=4.331;hands=(30)(10).(10)(30).(10)(30).(30)(10). pattern=(4,4);dratio=0.5;tps=4.331;hands=(30)(10).(30)(10).(10)(30).(10)(30). pattern=(4,4);dratio=0.5;tps=4.331;hands=(30)(-10).(-10)(30).(-10)(30).(30)(-10). pattern=(6,6)(6,6)(0,6);dratio=0.5;tps=5.556;hands=(30)(15).(30)(15).(15)(15).(15)(0).(15)(30).(0)(30). pattern=5;dratio=0.5;tps=4.98;hands=(-30)(0).(-15)(15).(0)(30).(15)(30).(30)(15).(30)(0).(15)(-15).(0)(-30).(-15)(-30).(-30)(-15). pattern=5;dratio=0.5;tps=4.98;hands=(30)(15).(15)(30).(15)(0).(30)(-30).(0)(-15).(-30)(-15).(-15)(-30).(-15)(0).(-30)(30).(0)(15). pattern=5;dratio=0.5;tps=4.98;hands=(30,15)(0,15).(-15)(15).(0,15)(-30,15).(15)(-30).(-30,15)(15,15).(-30)(0).(15,15)(-15,15).(0)(30).(-15,15)(30,15).(30)(-15). pattern=(6,6);dratio=0.5;tps=5.556;hands=(37.5)(22.5).(37.5)(22.5).(22.5)(7.5).(22.5)(7.5).(7.5)(37.5).(7.5)(37.5). pattern=([46],[46])(0,6)(2,2);dratio=0.5;tps=5.556;hands=(32.5)(32.5).(32.5)(0).(32.5)(32.5).(0)(32.5).(32.5)(32.5).(32.5)(32.5). pattern=40;dratio=0.5;tps=4.331;hands=(0)(25).(32.5)(32.5).(25)(0).(32.5)(32.5). pattern=60;dratio=0.5;tps=5.556 3-Multiplex in One Hand pattern=8040;dratio=0.5;tps=6.562 pattern=60;dratio=0.5;tps=5.556;hands=(-5)(15).(32.5)(32.5).(15)(35).(32.5)(32.5).(35)(-5).(32.5)(32.5). pattern=60;dratio=0.5;tps=5.556;hands=(5)(45).(32.5)(32.5).(25)(-15).(32.5)(32.5). pattern=[34]1;dratio=0.5;tps=4.331;hands=(10)(32.5). pattern=4[43]1;dratio=0.5;tps=4.331;hands=(10)(32.5). Martin 5-ball Multiplex A 5-ball Multiplex B 25[75]51 7-ball Splits A 7-ball Splits B 26[76] pattern=[234]57;dratio=0.5;tps=6.08;hands=(10)(32.5). pattern=[54];dratio=0.5;tps=4.98;hands=(10)(32.5). pattern=91;dratio=0.5;tps=7.012;hands=(25)(12.5).(12.5)(25). pattern=b1;dratio=0.5;tps=7.835;hands=(25)(12.5).(12.5)(25). pattern=d1;dratio=0.5;tps=8.58;hands=(25)(12.5).(12.5)(25). pattern=6;dratio=0.5;tps=5.556;hands=(10)(32.5). pattern=7;dratio=0.5;tps=6.08;hands=(10)(32.5). pattern=8;dratio=0.5;tps=6.562;hands=(10)(32.5). pattern=9;dratio=0.5;tps=7.012;hands=(10)(32.5). jugglinglab-0.6.2+ds.1/patterns/bounce.jml000066400000000000000000000037321323754603300203770ustar00rootroot00000000000000 Demo bounce patterns pattern=3BHL;tps=1.2;hands=(15)(20,15)c(25)(20,-15). pattern=3BL;tps=1.6;hands=(20)(23,15)c(25)(23,-15). pattern=3BF;tps=1.8;;hands=(25)(20). pattern=3BHF;tps=3.5;hands=(25)(10). pattern=7BHL;tps=3.5 pattern=5BBF;tps=2 pattern=9BBBHL1;tps=2.1 pattern=19BBBHL;tps=2.1;hands=(20)(20,15)c(20)(20,-15).;body=(0,75,0)..(72,23,71)..(144,-61,44)..(216,-61,-44)..(288,23,-71).. Bounced yo-yo jugglinglab-0.6.2+ds.1/patterns/common.jml000066400000000000000000000340051323754603300204110ustar00rootroot00000000000000 Juggling Lab Patterns Around the pair Burkes Barrage 42T3 24[54] Multiplex Rubensteins Revenge Tornado Weave Shakespeare Shuffle pattern=(8B,2x)(4,2x)(2x,8B)(2x,4);hands=(40)(20).(7.5)(20).(20)(20).(7.5)(40).(7.5)(20).(40)(20).(7.5)(40).(20)(20). pattern=7B44 441 Mills Mess (4,4) Clawed box jugglinglab-0.6.2+ds.1/patterns/demo.jml000066400000000000000000000231721323754603300200500ustar00rootroot00000000000000 Demo patterns 3 7 Demo of Ball with Transparent Background pattern=3 pattern=7 pattern=<R|L><4xp|3><3|4xp> 5 turning 5 walking 5 ball half-pirouettes jugglinglab-0.6.2+ds.1/patterns/siteswaps.jml000066400000000000000000000406251323754603300211500ustar00rootroot00000000000000 Siteswap Patterns pattern=3 pattern=42 pattern=423 pattern=441 pattern=531 pattern=73131 pattern=9313131 pattern=5241 pattern=46131 pattern=63141 pattern=52512 pattern=55500 pattern=471231 pattern=723141 pattern=731241 pattern=6316131 pattern=51;tps=5.0;hands=(25)(12.5).(12.5)(25). pattern=7131;tps=5.0;hands=(25)(12.5).(12.5)(25). pattern=913131;tps=5.0;hands=(25)(12.5).(12.5)(25). pattern=55050 pattern=60 pattern=8040 pattern=801 pattern=71701701 pattern=(4,2x)(2x,4);tps=4.0;hands=(25)(25).(5)(25).(5)(25).(25)(25). pattern=4 pattern=53;hands=(32.5)(17.5).(17.5)(32.5). pattern=534 pattern=552 pattern=5551 pattern=55550 pattern=633 pattern=5641 pattern=6451 pattern=6631 pattern=7333 pattern=7441 pattern=7531 pattern=63551 pattern=63641 pattern=64613 pattern=73451 pattern=67313 pattern=73631 pattern=566151 pattern=575151 pattern=577131 pattern=733551 pattern=62 pattern=561 pattern=723 pattern=741 pattern=5713 pattern=8413 pattern=8512 pattern=66161 pattern=6716161 pattern=714 pattern=8134 pattern=71;hands=(25)(12.5).(12.5)(25). pattern=9151;hands=(25)(12.5).(12.5)(25). pattern=9124 pattern=831 pattern=9313 pattern=912 pattern=(4,4) pattern=(4x,4x) pattern=(4,6x)(2x,4) pattern=(4,6x)(4x,2) pattern=(4x,6x)(4x,2x) pattern=(4x,6)(4,2x) pattern=(6,4x)(4x,2) pattern=(6x,6x)(2x,2x) pattern=(2x,6x);hands=(12.5)(25).(25)(12.5). pattern=(6x,2)(2x,6)(2,6x)(6,2x) pattern=(8,2x)(4,2x)(2x,8)(2x,4);hands=(25)(25).(7.5)(25).(25)(25).(7.5)(25).(7.5)(25).(25)(25).(7.5)(25).(25)(25). pattern=(2x,8)(4,2)(8,2)(4,2x) pattern=(8,2)(2x,4x) pattern=(2x,8)(4,2x) pattern=(2x,6x)(6x,2x) pattern=5 pattern=64 pattern=645 pattern=663 pattern=744 pattern=753 pattern=6662 pattern=6734 pattern=7463 pattern=7733 pattern=8444 pattern=8534 pattern=8552 pattern=8642 pattern=66661 pattern=67363 pattern=67741 pattern=75751;hands=(45)(25).(25)(45).(45)(25).(25)(25).(17.5)(45). pattern=77731 pattern=88441 pattern=94444 pattern=95551 pattern=97531 pattern=747741 pattern=774714 pattern=a55550 pattern=9494414 pattern=73;hands=(37.5)(20).(20)(37.5). pattern=672 pattern=834 pattern=852 pattern=6671 pattern=6851 pattern=7571;hands=(45)(25).(25)(45). pattern=7841 pattern=9353 pattern=9551 pattern=9515 pattern=9155 pattern=777171 pattern=771 pattern=825 pattern=861 pattern=82 pattern=96181 pattern=915 pattern=91951 pattern=91;hands=(37.5)(17.5).(17.5)(37.5). pattern=24[54] pattern=25[53] pattern=26[43] pattern=22[43][54] pattern=22[53][53] pattern=24[64]4 pattern=24[65]3 pattern=25[65]2 pattern=26[64]2 pattern=27[43]4 pattern=27[53]3 pattern=27[54]2 pattern=623[54] pattern=723[53] pattern=22[52][65][21] pattern=22[72][54][21] pattern=22[43][64]4 pattern=22[43][65]3 pattern=22[53][65]2 pattern=22[54][65]1 pattern=22[64][64]1 pattern=22[75][53]1 pattern=22[76][43]1 pattern=24[65]62 pattern=24[76]33 pattern=24[76]42 pattern=25[65]61 pattern=25[75]51 pattern=25[76]23 pattern=25[76]41 pattern=26[64]61 pattern=26[76]31 pattern=27[43]63 pattern=27[54]61 pattern=27[75]31 pattern=622[42][54] pattern=622[62][43] pattern=623[64]4 pattern=623[65]3 pattern=625[65]1 pattern=626[64]1 pattern=627[54]1 pattern=6622[54] pattern=722[65][21] pattern=723[65]2 pattern=724[65]1 pattern=7423[54] pattern=23[64] pattern=25[62] pattern=27[42] pattern=25[75]1 pattern=24[72] pattern=(4x,6x);hands=(17.5)(37.5).(37.5)(17.5). pattern=(6,4) pattern=(4x,6)(4,6x) pattern=(4x,6)(6,4x) pattern=(6x,4)(4,6x) pattern=(6x,4)(6,4x) pattern=(6x,6x)(2x,6x) pattern=(6x,8x)(2x,4x) pattern=(8,6x)(2x,4) pattern=(6,6)(2x,6)(6,4x) pattern=(6x,4)(6x,6x)(2,6x) pattern=(2x,8)(8,2x) pattern=(8,2x)(6x,4) pattern=6 pattern=75;hands=(45)(25).(25)(45). pattern=756 pattern=774 pattern=855 pattern=864 pattern=7773 pattern=8844 pattern=77772 pattern=777771 pattern=786861 pattern=868671 pattern=945 pattern=77781 pattern=78681 pattern=86781 pattern=88581 pattern=7881 pattern=891 pattern=(6,6) pattern=(6x,6x) jugglinglab-0.6.2+ds.1/source/000077500000000000000000000000001323754603300160535ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/source/JugglingLab.java000077500000000000000000000222221323754603300211060ustar00rootroot00000000000000// JugglingLab.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ import java.applet.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.io.*; import java.net.*; import javax.swing.*; import org.xml.sax.*; import jugglinglab.core.*; import jugglinglab.jml.*; import jugglinglab.util.*; import jugglinglab.notation.*; import jugglinglab.view.*; public class JugglingLab extends JApplet { static ResourceBundle guistrings; static ResourceBundle errorstrings; protected Animator ja = null; protected JugglingLabPanel jlp = null; protected AnimatorPrefs jc = null; public JugglingLab() { initAudioClips(); initDefaultPropImages(); } protected void configure_applet() { String config = getParameter("config"); String prefs = getParameter("animprefs"); String jmldir = getParameter("jmldir"); String jmlfile = getParameter("jmlfile"); // default values int entry_type = Notation.NOTATION_SITESWAP; int view_type = View.VIEW_SIMPLE; if (config != null) { ParameterList param = new ParameterList(config); String entry = param.getParameter("entry"); if (entry != null) { if (entry.equalsIgnoreCase("none")) entry_type = Notation.NOTATION_NONE; else if (entry.equalsIgnoreCase("siteswap")) entry_type = Notation.NOTATION_SITESWAP; } String view = param.getParameter("view"); if (view != null) { if (view.equalsIgnoreCase("none")) view_type = View.VIEW_NONE; else if (view.equalsIgnoreCase("simple")) view_type = View.VIEW_SIMPLE; else if (view.equalsIgnoreCase("edit")) view_type = View.VIEW_EDIT; else if (view.equalsIgnoreCase("selection")) view_type = View.VIEW_SELECTION; else if (view.equalsIgnoreCase("jml")) view_type = View.VIEW_JML; } String loc = param.getParameter("locale"); if (loc != null) { // want to get to this before the resource bundles are needed // by this or any other objects String[] locarray = loc.split("_", 5); System.out.println("locarray = " + locarray); Locale newloc = null; if (locarray.length == 1) newloc = new Locale(locarray[0]); else if (locarray.length == 2) newloc = new Locale(locarray[0], locarray[1]); else if (locarray.length > 2) newloc = new Locale(locarray[0], locarray[1], locarray[2]); JLLocale.setLocale(newloc); } } JugglingLab.guistrings = JLLocale.getBundle("GUIStrings"); JugglingLab.errorstrings = JLLocale.getBundle("ErrorStrings"); try { jc = new AnimatorPrefs(); if (prefs != null) jc.parseInput(prefs); JMLPattern pat = null; PatternList pl = null; boolean readerror = false; if (jmlfile != null) { if (!jmlfile.endsWith(".jml")) throw new JuggleExceptionUser(errorstrings.getString("Error_JML_extension")); if (jmlfile.indexOf(".") != (jmlfile.length()-4)) throw new JuggleExceptionUser(errorstrings.getString("Error_JML_filename")); try { URL jmlfileURL = null; if (jmldir != null) jmlfileURL = new URL(new URL(jmldir), jmlfile); else jmlfileURL = new URL(getDocumentBase(), jmlfile); JMLParser parse = new JMLParser(); parse.parse(new InputStreamReader(jmlfileURL.openStream())); if (parse.getFileType() == JMLParser.JML_PATTERN) pat = new JMLPattern(parse.getTree()); else { pl = new PatternList(); pl.readJML(parse.getTree()); } } catch (MalformedURLException mue) { throw new JuggleExceptionUser(errorstrings.getString("Error_URL_syntax")+" '"+jmldir+"'"); } catch (IOException ioe) { readerror = true; // System.out.println(ioe.getMessage()); // throw new JuggleExceptionUser(errorstrings.getString("Error_reading_pattern")); } catch (SAXException se) { throw new JuggleExceptionUser(errorstrings.getString("Error_parsing_pattern")); } } if (pat == null) { String notation = getParameter("notation"); String pattern = getParameter("pattern"); if ((notation != null) && (pattern != null)) { Notation not = null; if (notation.equalsIgnoreCase("jml")) { try { pat = new JMLPattern(new StringReader(pattern)); } catch (IOException ioe) { throw new JuggleExceptionUser(errorstrings.getString("Error_reading_JML")); } catch (SAXException se) { throw new JuggleExceptionUser(errorstrings.getString("Error_parsing_JML")); } } else { not = Notation.getNotation(notation); pat = not.getJMLPattern(pattern); } } } if (readerror) throw new JuggleExceptionUser(errorstrings.getString("Error_reading_pattern")); JugglingLabPanel jlp = new JugglingLabPanel(null, entry_type, pl, view_type); jlp.setDoubleBuffered(true); this.setBackground(new Color(0.9f, 0.9f, 0.9f)); setContentPane(jlp); Locale loc = JLLocale.getLocale(); this.applyComponentOrientation(ComponentOrientation.getOrientation(loc)); validate(); // NOTE: animprefs will only be applied when some kind of pattern is defined if (pat != null) jlp.getView().restartView(pat, jc); } catch (Exception e) { String message = ""; if (e instanceof JuggleExceptionUser) message = e.getMessage(); else { if (e instanceof JuggleExceptionInternal) message = "Internal error"; else message = e.getClass().getName(); if (e.getMessage() != null) message = message + ": " + e.getMessage(); } JPanel p = new JPanel(); p.setBackground(Color.white); GridBagLayout gb = new GridBagLayout(); p.setLayout(gb); JLabel lab = new JLabel(message); lab.setHorizontalAlignment(SwingConstants.CENTER); p.add(lab); GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = GridBagConstraints.CENTER; gbc.fill = GridBagConstraints.BOTH; gbc.gridwidth = gbc.gridheight = 1; gbc.gridx = 0; gbc.gridy = 0; gbc.insets = new Insets(0,0,0,0); gbc.weightx = 1.0; gbc.weighty = 1.0; gb.setConstraints(lab, gbc); setContentPane(p); validate(); if (e instanceof JuggleExceptionInternal) ErrorDialog.handleException(e); else if (!(e instanceof JuggleExceptionUser)) e.printStackTrace(); } } // applet version starts here public void init() { // do it this way, so that calls to Swing methods happen on the event dispatch thread SwingUtilities.invokeLater(new Runnable() { public void run() { configure_applet(); } }); } public void start() { if ((jlp != null) && (jlp.getView() != null) && !jc.mousePause) jlp.getView().setPaused(false); if ((ja != null) && (ja.message == null) && !jc.mousePause) ja.setPaused(false); } public void stop() { if ((jlp != null) && (jlp.getView() != null) && !jc.mousePause) jlp.getView().setPaused(true); if ((ja != null) && (ja.message == null) && !jc.mousePause) ja.setPaused(true); } public void destroy() { if ((jlp != null) && (jlp.getView() != null)) jlp.getView().dispose(); if (ja != null) ja.dispose(); } // It's easiest to load the audioclips here and pass them along to Animator. // For some reason AudioClip is part of the Applet package. protected void initAudioClips() { AudioClip[] clips = new AudioClip[2]; URL catchurl = this.getClass().getResource("/resources/catch.au"); if (catchurl != null) clips[0] = newAudioClip(catchurl); URL bounceurl = this.getClass().getResource("/resources/bounce.au"); if (bounceurl != null) clips[1] = newAudioClip(bounceurl); Animator.setAudioClips(clips); } // The class loader delegation model makes it difficult to find resources from // within the VersionSpecific class. There must be a better way to do it but I // give it up already. protected void initDefaultPropImages() { URL[] images = new URL[2]; images[0] = this.getClass().getResource("/resources/ball.gif"); images[1] = this.getClass().getResource("/resources/ball.png"); VersionSpecific.setDefaultPropImages(images); } // application version starts here public static void main(String[] args) { try { new JugglingLab(); // to load audio clips new ApplicationWindow("Juggling Lab"); } catch (JuggleExceptionUser jeu) { new ErrorDialog(null, jeu.getMessage()); } catch (JuggleExceptionInternal jei) { ErrorDialog.handleException(jei); } } } jugglinglab-0.6.2+ds.1/source/gifwriter/000077500000000000000000000000001323754603300200555ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/source/gifwriter/GIFAnimWriter.java000077500000000000000000000134711323754603300233400ustar00rootroot00000000000000// GIFAnimWriter.java // // Copyright 2003 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package gifwriter; import java.util.Hashtable; import java.util.Vector; import java.io.*; import java.awt.*; public class GIFAnimWriter { int iterations; int maxwidth, maxheight; Vector frames, delays; boolean colormap_valid = false; Hashtable colormap; int defaultcolorkey; // The iterations parameter specifies the number of repetitions for the // animation, from 1 to 65535. Using 0 loops infinitely. public GIFAnimWriter(int iterations) { this.iterations = iterations; colormap = null; colormap_valid = false; } public GIFAnimWriter() { this(0); } // This version allows us to manually add to the colormap public void doColorMap(Color color, boolean defaultcolor) throws IOException { if (colormap == null) colormap = new Hashtable(); int index = colormap.size(); int rgb = color.getRGB(); GIFEncoderHashitem item = (GIFEncoderHashitem)colormap.get(Integer.valueOf(rgb)); if (item == null) { if (index >= 256) throw new IOException( "Too many colors for a GIF" ); item = new GIFEncoderHashitem(rgb, color, 1, index); ++index; colormap.put(Integer.valueOf(rgb), item); } else ++item.count; if (defaultcolor) this.defaultcolorkey = rgb; } // This version constructs a colormap by looking at the contents of an image. public void doColorMap(Image img) throws IOException { GIFWriter gw = new GIFWriter(); gw.setImage(img); if (!colormap_valid) { // Create new color table maxwidth = gw.getWidth(); maxheight = gw.getHeight(); gw.loadData(); gw.doColorMap(); colormap = gw.getColorMap(); colormap_valid = true; } else { // Add to existing one int temp; if ((temp = gw.getWidth()) > maxwidth) maxwidth = temp; if ((temp = gw.getHeight()) > maxheight) maxheight = temp; gw.loadData(); gw.setColorMap(colormap, defaultcolorkey); gw.doColorMap(); } gw.flushPixels(); } /* public void doColorMap(Color[] colorarray) throws IOException { for (int i = 0; i < colorarray.length; i++) doColorMap(colorarray[i], false); } public void doColorMap(Color color) throws IOException { doColorMap(color, false); } */ public Hashtable getColorMap() { return this.colormap; } public void writeHeader(OutputStream out) throws IOException { // write out the header. Use the allocated GIFWriter to do this. // note that it contains the proper colormap info. GIFWriter.writeHeader(colormap, maxwidth, maxheight, out); // write Netscape looping extension. GIFWriter.Putbyte((byte)0x21, out); GIFWriter.Putbyte((byte)0xff, out); GIFWriter.Putbyte((byte)0x0b, out); GIFWriter.Putbyte((byte)'N', out); GIFWriter.Putbyte((byte)'E', out); GIFWriter.Putbyte((byte)'T', out); GIFWriter.Putbyte((byte)'S', out); GIFWriter.Putbyte((byte)'C', out); GIFWriter.Putbyte((byte)'A', out); GIFWriter.Putbyte((byte)'P', out); GIFWriter.Putbyte((byte)'E', out); GIFWriter.Putbyte((byte)'2', out); GIFWriter.Putbyte((byte)'.', out); GIFWriter.Putbyte((byte)'0', out); GIFWriter.Putbyte((byte)0x03, out); GIFWriter.Putbyte((byte)0x01, out); GIFWriter.Putword(iterations, out); GIFWriter.Putbyte((byte)0x00, out); } public void writeDelay(int delay, OutputStream out) throws IOException { // write out the delay graphic control extension GIFWriter.Putbyte((byte)0x21, out); GIFWriter.Putbyte((byte)0xf9, out); GIFWriter.Putbyte((byte)0x04, out); GIFWriter.Putbyte((byte)0x00, out); GIFWriter.Putword(delay, out); GIFWriter.Putbyte((byte)0x00, out); GIFWriter.Putbyte((byte)0x00, out); } public void writeGIF(Image img, OutputStream out) throws IOException { GIFWriter gw = new GIFWriter(); gw.setImage(img); // write out the actual image data gw.loadData(); gw.setColorMap(colormap, defaultcolorkey); gw.writeBody(out); gw.flushPixels(); } public void writeTrailer(OutputStream out) throws IOException { GIFWriter.writeTrailer(out); } // Add a frame to the movie. /* public void addFrame(Image img, int delay) throws IOException { frames.addElement(img); delays.addElement(new Integer(delay)); colormap_valid = false; } // Write out the movie. public void writeGIFAnim(OutputStream out) throws IOException { int i, temp; int numframes = frames.size(); // We want to do the work in two passes through the image frames. // On the first pass we build the global colormap. // Keep this colormap around in the future, in case we want to // write out again. // The second pass actually encodes and writes the data. Image[] img = new Image[numframes]; for (i = 0; i < numframes; i++) img[i] = (Image)frames.elementAt(i); if (!colormap_valid) { // Build up the color table for (i = 0; i < numframes; i++) doColorMap(img[i]); } writeHeader(out); // write out the individual frames for (i = 0; i < numframes; i++) { writeDelay(((Integer)delays.elementAt(i)).intValue(), out); writeGIF(img[i], out); } writeTrailer(out); }*/ } jugglinglab-0.6.2+ds.1/source/gifwriter/GIFEncoderHashitem.java000077500000000000000000000022601323754603300243130ustar00rootroot00000000000000// GIFEncoderHashitem.java // // Copyright 2003 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package gifwriter; import java.awt.*; public class GIFEncoderHashitem { public int rgb; public int count; public int index; public Color color; public GIFEncoderHashitem(int rgb, Color color, int count, int index) { this.rgb = rgb; this.count = count; this.index = index; this.color = color; } } jugglinglab-0.6.2+ds.1/source/gifwriter/GIFWriter.java000077500000000000000000000422061323754603300225310ustar00rootroot00000000000000// GIFWriter.java // // Copyright 2003 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package gifwriter; import java.util.Enumeration; import java.util.Hashtable; import java.io.*; import java.awt.*; import java.awt.image.*; public class GIFWriter implements ImageObserver { private Image img; private int width; private int height; private boolean loadingdata; // we need these flags since loading is private boolean loadingstarted; // done from another thread private IOException iox; private Hashtable colorHash; private int defaultcolorkey; private int[] rgbPixels; private boolean gotwidthheight; private boolean gotcolormap; private boolean gotdata; public GIFWriter() { } public void setImage(Image img) { this.img = img; gotwidthheight = gotcolormap = gotdata = false; height = img.getHeight(this); width = img.getWidth(this); if (height != -1 && width != -1) gotwidthheight = true; } // If we want to know these before the image is in memory, then // we'll have to block. public synchronized int getWidth() throws IOException { while ( !gotwidthheight ) try { wait(); } catch ( InterruptedException e ) {} if ( iox != null ) throw iox; return width; } public synchronized int getHeight() throws IOException { while ( !gotwidthheight ) try { wait(); } catch ( InterruptedException e ) {} if ( iox != null ) throw iox; return height; } /// Write a single GIF to the output. This blocks until the writing // is done, and does not close the output stream. // @param img The image to encode. // @param out The stream to write the GIF to. public void writeGIF(OutputStream out) throws IOException { if (!gotdata) // skip if we already have loadData(); /* if (!gotcolormap) { // skip if we already have setColorMap(null); // shouldn't be necessary doColorMap(); }*/ writeHeader(out); writeBody(out); writeTrailer(out); // stop(); } public synchronized void loadData() throws IOException { gotdata = false; if (!gotwidthheight) getWidth(); // waits until dimensions available rgbPixels = null; rgbPixels = new int[width * height]; PixelGrabber pg = new PixelGrabber(img, 0, 0, width, height, rgbPixels, 0, width); try { if (!pg.grabPixels()) throw new IOException("grabPixels() unsuccessful"); } catch (InterruptedException e) { throw new IOException("grabPixels() interrupted"); } gotdata = true; img.getSource().removeConsumer(pg); } public void flushPixels() throws IOException { rgbPixels = null; gotdata = false; img.flush(); // flushes data cached by Image class } public void doColorMap() throws IOException { if (!gotdata) throw new IOException("Don't have image data"); // Put all the pixels into a hash table. if (colorHash == null) colorHash = new Hashtable(); int index = colorHash.size(); for ( int row = 0; row < height; ++row ) { int rowOffset = row * width; for ( int col = 0; col < width; ++col ) { int rgb = rgbPixels[rowOffset + col] & 0xffffff; GIFEncoderHashitem item = (GIFEncoderHashitem) colorHash.get(Integer.valueOf(rgb)); if ( item == null ) { if ( index < 256 ) { item = new GIFEncoderHashitem(rgb, null, 1, index); /* int red = (rgb >> 16) & 0xff; int green = (rgb >> 8) & 0xff; int blue = (rgb) & 0xff; System.out.println("adding color "+index+" at (x="+col+",y="+row+"): r="+red+", g="+green+", b="+blue); */ ++index; colorHash.put(Integer.valueOf(rgb), item); } /* else throw new IOException( "Too many colors for a GIF" );*/ } else ++item.count; } } gotcolormap = true; } public Hashtable getColorMap() { return colorHash; } public void setColorMap(Hashtable chash, int defaultcolorkey) { colorHash = chash; this.defaultcolorkey = defaultcolorkey; gotcolormap = (chash != null); } public void writeHeader(OutputStream outs) throws IOException { writeHeader(colorHash, width, height, outs); } public static void writeHeader(Hashtable colormap, int mywidth, int myheight, OutputStream outs) throws IOException { byte B; int i; // Figure out how many bits to use. int logColors; int index = colormap.size(); if ( index <= 2 ) logColors = 1; else if ( index <= 4 ) logColors = 2; else if ( index <= 16 ) logColors = 4; else logColors = 8; // Turn colors into colormap entries. int mapSize = 1 << logColors; byte[] reds = new byte[mapSize]; byte[] grns = new byte[mapSize]; byte[] blus = new byte[mapSize]; for ( Enumeration e = colormap.elements(); e.hasMoreElements(); ) { GIFEncoderHashitem item = (GIFEncoderHashitem) e.nextElement(); reds[item.index] = (byte) ( ( item.rgb >> 16 ) & 0xff ); grns[item.index] = (byte) ( ( item.rgb >> 8 ) & 0xff ); blus[item.index] = (byte) ( item.rgb & 0xff ); } // Write the Magic header Putbyte( (byte)'G', outs ); Putbyte( (byte)'I', outs ); Putbyte( (byte)'F', outs ); Putbyte( (byte)'8', outs ); Putbyte( (byte)'9', outs ); Putbyte( (byte)'a', outs ); //writeString( outs, "GIF89a" ); // Write out the screen width and height Putword( mywidth, outs ); Putword( myheight, outs ); // Indicate that there is a global colour map B = (byte) 0x80; // Yes, there is a color map // OR in the resolution B |= (byte) ( ( 8 - 1 ) << 4 ); // Not sorted // OR in the Bits per Pixel B |= (byte) ( ( logColors - 1 ) ); // Write it out Putbyte( B, outs ); // Write out the Background colour Putbyte( (byte)0, outs ); // Pixel aspect ratio - 1:1. //Putbyte( (byte) 49, outs ); // Java's GIF reader currently has a bug, if the aspect ratio byte is // not zero it throws an ImageFormatException. It doesn't know that // 49 means a 1:1 aspect ratio. Well, whatever, zero works with all // the other decoders I've tried so it probably doesn't hurt. Putbyte( (byte) 0, outs ); // Write out the Global Colour Map for ( i = 0; i < mapSize; i++ ) { Putbyte( reds[i], outs ); Putbyte( grns[i], outs ); Putbyte( blus[i], outs ); } } public void writeBody(OutputStream outs) throws IOException { if (!gotdata) throw new IOException("Don't have image data"); if (!gotcolormap) throw new IOException("Don't have a colormap"); int logColors; int index = colorHash.size(); int InitCodeSize; if ( index <= 2 ) logColors = 1; else if ( index <= 4 ) logColors = 2; else if ( index <= 16 ) logColors = 4; else logColors = 8; // Calculate number of bits we are expecting if (!gotwidthheight) getWidth(); // waits until dimensions are known CountDown = width * height; // The initial code size if ( logColors <= 1 ) InitCodeSize = 2; else InitCodeSize = logColors; // Write an Image separator Putbyte( (byte) ',', outs ); // Write the Image header Putword( 0, outs ); Putword( 0, outs ); Putword( this.width, outs ); Putword( this.height, outs ); Putbyte( (byte) 0x00, outs ); // Write out the initial code size Putbyte( (byte) InitCodeSize, outs ); // Set up the current x and y position curx = 0; cury = 0; // Go and actually compress the data compress( InitCodeSize+1, outs ); // Write out a Zero-length packet (to end the series) Putbyte( (byte) 0, outs ); } public static void writeTrailer(OutputStream outs) throws IOException { // Write the GIF file terminator Putbyte( (byte) ';', outs ); } // Get width and height info asynchronously as they become // available. This is from ImageObserver. public synchronized boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { boolean needmore = false; if ((infoflags & ImageObserver.ABORT) != 0) { iox = new IOException("Image aborted"); gotwidthheight = true; return false; } if ((infoflags & ImageObserver.WIDTH) != 0) this.width = width; else needmore = true; if ((infoflags & ImageObserver.HEIGHT) != 0) this.height = height; else needmore = true; gotwidthheight = !needmore; if (gotwidthheight) notifyAll(); return needmore; } byte GetPixel( int x, int y ) throws IOException { GIFEncoderHashitem item = (GIFEncoderHashitem) colorHash.get( rgbPixels[y*width+x] & 0xffffff ); if ( item == null ) { // System.out.println("Could not get color at (x="+x+",y="+y+")"); item = (GIFEncoderHashitem) colorHash.get( defaultcolorkey ); } return (byte) item.index; } /* public static void writeString( OutputStream out, String str ) throws IOException { int len = str.length(); byte[] buf = new byte[len]; str.getBytes( 0, len, buf, 0 ); out.write( buf ); }*/ int curx, cury; int CountDown; static final int EOF = -1; // Return the next pixel from the image int GIFNextPixel() throws IOException { byte r; if ( CountDown == 0 ) return EOF; --CountDown; r = GetPixel( curx, cury ); if ( ++curx == this.width ) { curx = 0; ++cury; } return r & 0xff; } // Write out a word to the GIF file public static void Putword( int w, OutputStream outs ) throws IOException { Putbyte( (byte) ( w & 0xff ), outs ); Putbyte( (byte) ( ( w >> 8 ) & 0xff ), outs ); } // Write out a byte to the GIF file public static void Putbyte( byte b, OutputStream outs ) throws IOException { outs.write( b ); } // GIFCOMPR.C - GIF Image compression routines // // Lempel-Ziv compression based on 'compress'. GIF modifications by // David Rowley (mgardi@watdcsu.waterloo.edu) // General DEFINEs static final int BITS = 12; static final int HSIZE = 5003; // 80% occupancy // GIF Image compression - modified 'compress' // // Based on: compress.c - File compression ala IEEE Computer, June 1984. // // By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) // Jim McKie (decvax!mcvax!jim) // Steve Davies (decvax!vax135!petsd!peora!srd) // Ken Turkowski (decvax!decwrl!turtlevax!ken) // James A. Woods (decvax!ihnp4!ames!jaw) // Joe Orost (decvax!vax135!petsd!joe) int n_bits; // number of bits/code int maxbits = BITS; // user settable max # bits/code int maxcode; // maximum code, given n_bits int maxmaxcode = 1 << BITS; // should NEVER generate this code final int MAXCODE( int n_bits ) { return ( 1 << n_bits ) - 1; } int[] htab = new int[HSIZE]; int[] codetab = new int[HSIZE]; int hsize = HSIZE; // for dynamic table sizing int free_ent = 0; // first unused entry // block compression parameters -- after all codes are used up, // and compression rate changes, start over. boolean clear_flg = false; // Algorithm: use open addressing double hashing (no chaining) on the // prefix code / next character combination. We do a variant of Knuth's // algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime // secondary probe. Here, the modular division first probe is gives way // to a faster exclusive-or manipulation. Also do block compression with // an adaptive reset, whereby the code table is cleared when the compression // ratio decreases, but after the table fills. The variable-length output // codes are re-sized at this point, and a special CLEAR code is generated // for the decompressor. Late addition: construct the table according to // file size for noticeable speed improvement on small files. Please direct // questions about this implementation to ames!jaw. int g_init_bits; int ClearCode; int EOFCode; void compress( int init_bits, OutputStream outs ) throws IOException { int fcode; int i; int c; int ent; int disp; int hsize_reg; int hshift; // Set up the globals: g_init_bits - initial number of bits g_init_bits = init_bits; // Set up the necessary values clear_flg = false; n_bits = g_init_bits; maxcode = MAXCODE( n_bits ); ClearCode = 1 << ( init_bits - 1 ); EOFCode = ClearCode + 1; free_ent = ClearCode + 2; char_init(); ent = GIFNextPixel(); hshift = 0; for ( fcode = hsize; fcode < 65536; fcode *= 2 ) ++hshift; hshift = 8 - hshift; // set hash code range bound hsize_reg = hsize; cl_hash( hsize_reg ); // clear hash table output( ClearCode, outs ); outer_loop: while ( (c = GIFNextPixel()) != EOF ) { fcode = ( c << maxbits ) + ent; i = ( c << hshift ) ^ ent; // xor hashing if ( htab[i] == fcode ) { ent = codetab[i]; continue; } else if ( htab[i] >= 0 ) { // non-empty slot disp = hsize_reg - i; // secondary hash (after G. Knott) if ( i == 0 ) disp = 1; do { if ( (i -= disp) < 0 ) i += hsize_reg; if ( htab[i] == fcode ) { ent = codetab[i]; continue outer_loop; } } while ( htab[i] >= 0 ); } output( ent, outs ); ent = c; if ( free_ent < maxmaxcode ) { codetab[i] = free_ent++; // code -> hashtable htab[i] = fcode; } else cl_block( outs ); } // Put out the final code. output( ent, outs ); output( EOFCode, outs ); } // output // // Output the given code. // Inputs: // code: A n_bits-bit integer. If == -1, then EOF. This assumes // that n_bits =< wordsize - 1. // Outputs: // Outputs code to the file. // Assumptions: // Chars are 8 bits long. // Algorithm: // Maintain a BITS character long buffer (so that 8 codes will // fit in it exactly). Use the VAX insv instruction to insert each // code in turn. When the buffer fills up empty it and start over. int cur_accum = 0; int cur_bits = 0; int masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; void output( int code, OutputStream outs ) throws IOException { cur_accum &= masks[cur_bits]; if ( cur_bits > 0 ) cur_accum |= ( code << cur_bits ); else cur_accum = code; cur_bits += n_bits; while ( cur_bits >= 8 ) { char_out( (byte) ( cur_accum & 0xff ), outs ); cur_accum >>= 8; cur_bits -= 8; } // If the next entry is going to be too big for the code size, // then increase it, if possible. if ( free_ent > maxcode || clear_flg ) { if ( clear_flg ) { maxcode = MAXCODE(n_bits = g_init_bits); clear_flg = false; } else { ++n_bits; if ( n_bits == maxbits ) maxcode = maxmaxcode; else maxcode = MAXCODE(n_bits); } } if ( code == EOFCode ) { // At EOF, write the rest of the buffer. while ( cur_bits > 0 ) { char_out( (byte) ( cur_accum & 0xff ), outs ); cur_accum >>= 8; cur_bits -= 8; } flush_char( outs ); } } // Clear out the hash table // table clear for block compress void cl_block( OutputStream outs ) throws IOException { cl_hash( hsize ); free_ent = ClearCode + 2; clear_flg = true; output( ClearCode, outs ); } // reset code table void cl_hash( int hsize ) { for ( int i = 0; i < hsize; ++i ) htab[i] = -1; } // GIF Specific routines // Number of characters so far in this 'packet' int a_count; // Set up the 'byte output' routine void char_init() { a_count = 0; } // Define the storage for the packet accumulator byte[] accum = new byte[256]; // Add a character to the end of the current packet, and if it is 254 // characters, flush the packet to disk. void char_out( byte c, OutputStream outs ) throws IOException { accum[a_count++] = c; if ( a_count >= 254 ) flush_char( outs ); } // Flush the packet to disk, and reset the accumulator void flush_char( OutputStream outs ) throws IOException { if ( a_count > 0 ) { outs.write( a_count ); outs.write( accum, 0, a_count ); a_count = 0; } } } jugglinglab-0.6.2+ds.1/source/jugglinglab/000077500000000000000000000000001323754603300203405ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/source/jugglinglab/MacOS/000077500000000000000000000000001323754603300213025ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/source/jugglinglab/MacOS/PlatformSpecificMacOS.java000077500000000000000000000112521323754603300262660ustar00rootroot00000000000000// PlatformSpecificMacOS.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.MacOS; import jugglinglab.core.*; import jugglinglab.notation.*; import jugglinglab.util.*; import javax.swing.*; import java.awt.*; import java.io.*; import com.apple.eawt.*; public class PlatformSpecificMacOS extends jugglinglab.core.PlatformSpecific { public FileDialog fd = null; public Application app = null; public boolean isMacOS() { return true; } public void setupPlatform() { // Apple provides some hooks to make the application look more like // a native OS X application app = com.apple.eawt.Application.getApplication(); app.addApplicationListener(new ApplicationAdapter() { public void handleAbout(ApplicationEvent event) { SwingUtilities.invokeLater(new Runnable() { public void run() { jlw.getNotationGUI().doMenuCommand(NotationGUI.HELP_ABOUT); } }); event.setHandled(true); } public void handleQuit(ApplicationEvent event) { SwingUtilities.invokeLater(new Runnable() { public void run() { try { jlw.doMenuCommand(ApplicationWindow.FILE_EXIT); } catch (JuggleExceptionInternal jei) { ErrorDialog.handleException(jei); } } }); event.setHandled(true); } public void handleOpenFile(ApplicationEvent event) { final File toopen = new File(event.getFilename()); SwingUtilities.invokeLater(new Runnable() { public void run() { // System.out.println("trying to open file "+filename); try { jlw.showJMLWindow(toopen); } catch (JuggleExceptionUser je) { new ErrorDialog(jlw, je.getMessage()); } catch (JuggleExceptionInternal jei) { ErrorDialog.handleException(jei); } } }); event.setHandled(true); } }); } public int showOpenDialog(Component c) { // return super.showOpenDialog(c); return showOpenDialog(c, null); } public int showOpenDialog(Component c, javax.swing.filechooser.FileFilter ff) { FilenameFilter filter = null; if (ff != null) { final javax.swing.filechooser.FileFilter fff = ff; filter = new FilenameFilter() { public boolean accept(File dir, String name) { return fff.accept(new File(dir, name)); } }; } if (fd == null) { Frame f = (Frame)jlw; if (c instanceof Frame) f = (Frame)c; fd = new FileDialog(f); fd.setDirectory(System.getProperty("user.dir")); } fd.setFilenameFilter(filter); // filter == null => no filter fd.setMode(FileDialog.LOAD); fd.setVisible(true); // fd.show(); if (fd.getFile() == null) return JFileChooser.CANCEL_OPTION; return JFileChooser.APPROVE_OPTION; } public int showSaveDialog(Component c) { // return super.showSaveDialog(c); if (fd == null) { Frame f = (Frame)jlw; if (c instanceof Frame) f = (Frame)c; fd = new FileDialog(f); fd.setDirectory(System.getProperty("user.dir")); } fd.setMode(FileDialog.SAVE); fd.setVisible(true); // fd.show(); if (fd.getFile() == null) return JFileChooser.CANCEL_OPTION; return JFileChooser.APPROVE_OPTION; } public File getSelectedFile() { // return super.getSelectedFile(); if (fd == null) return null; return new File(fd.getDirectory(), fd.getFile()); } }jugglinglab-0.6.2+ds.1/source/jugglinglab/core/000077500000000000000000000000001323754603300212705ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/source/jugglinglab/core/Animator.java000066400000000000000000000633371323754603300237210ustar00rootroot00000000000000// Animator.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.core; import java.applet.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; import java.io.*; import java.util.*; import java.net.*; import java.lang.reflect.*; import javax.swing.*; import jugglinglab.jml.*; import jugglinglab.renderer.*; import jugglinglab.util.*; public class Animator extends JPanel implements Runnable { static ResourceBundle guistrings; // static ResourceBundle errorstrings; static { guistrings = JLLocale.getBundle("GUIStrings"); // errorstrings = JLLocale.getBundle("ErrorStrings"); } protected Thread engine; protected boolean engineStarted = false;; protected boolean enginePaused = false; protected boolean engineRunning = false; public boolean writingGIF = false; public JuggleException exception; public String message; protected JMLPattern pat; protected AnimatorPrefs jc; protected jugglinglab.renderer.Renderer ren1 = null, ren2 = null; protected Coordinate overallmax = null, overallmin = null; protected int[] animpropnum = null, temppropnum = null; protected Permutation invpathperm = null; protected int num_frames; protected double sim_time; protected double sim_interval_secs; protected long real_interval_millis; protected static AudioClip catchclip = null, bounceclip = null; protected boolean waspaused; // for pause on mouse away // protected boolean waspaused_valid = false; protected boolean outside; protected boolean outside_valid; protected boolean cameradrag; protected int startx, starty, lastx, lasty; protected double[] camangle; protected double[] actualcamangle; protected double[] actualcamangle1; protected double[] actualcamangle2; protected static final double snapangle = JLMath.toRad(15.0); protected Dimension prefsize; public Animator() { cameradrag = false; initHandlers(); camangle = new double[2]; camangle[0] = JLMath.toRad(0.0); camangle[1] = JLMath.toRad(90.0); actualcamangle1 = new double[2]; actualcamangle2 = new double[2]; jc = new AnimatorPrefs(); outside = true; waspaused = outside_valid = false; this.setOpaque(true); } public void setJAPreferredSize(Dimension d) { prefsize = d; } // override methods in java.awt.Component public Dimension getPreferredSize() { if (prefsize != null) return new Dimension(prefsize); return getMinimumSize(); } public Dimension getMinimumSize() { return new Dimension(100,100); } public static void setAudioClips(AudioClip[] clips) { Animator.catchclip = clips[0]; Animator.bounceclip = clips[1]; } protected void initHandlers() { this.addMouseListener(new MouseAdapter() { long lastpress = 0L; long lastenter = 1L; public void mousePressed(MouseEvent me) { lastpress = me.getWhen(); // The following (and the equivalent in mouseReleased()) is a hack to swallow // a mouseclick when the browser stops reporting enter/exit events because the // user has clicked on something else. The system reports simultaneous enter/press // events when the user mouses down in the component; we want to swallow this as a // click, and just use it to get focus back. if (jc.mousePause && (lastpress == lastenter)) return; if (exception != null) return; if (!engineStarted) return; Animator.this.startx = me.getX(); Animator.this.starty = me.getY(); } public void mouseReleased(MouseEvent me) { if (jc.mousePause && (lastpress == lastenter)) return; if (exception != null) return; Animator.this.cameradrag = false; if (!engineStarted && (engine != null) && engine.isAlive()) { setPaused(!enginePaused); return; } if ((me.getX() == startx) && (me.getY() == starty) && (engine != null) && engine.isAlive()) { setPaused(!enginePaused); // Animator.this.getParent().dispatchEvent(me); } if (Animator.this.getPaused()) repaint(); } public void mouseEntered(MouseEvent me) { lastenter = me.getWhen(); if (jc.mousePause /*&& waspaused_valid*/) setPaused(waspaused); outside = false; outside_valid = true; } public void mouseExited(MouseEvent me) { if (jc.mousePause) { waspaused = getPaused(); // waspaused_valid = true; setPaused(true); } outside = true; outside_valid = true; } }); this.addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged(MouseEvent me) { if (exception != null) return; if (!engineStarted) return; if (!cameradrag) { // return; Animator.this.cameradrag = true; Animator.this.lastx = Animator.this.startx; Animator.this.lasty = Animator.this.starty; Animator.this.camangle = Animator.this.ren1.getCameraAngle(); } int xdelta = me.getX() - Animator.this.lastx; int ydelta = me.getY() - Animator.this.lasty; Animator.this.lastx = me.getX(); Animator.this.lasty = me.getY(); double[] camangle = Animator.this.camangle; camangle[0] += (double)(xdelta) * 0.02; camangle[1] -= (double)(ydelta) * 0.02; if (camangle[1] < 0.000001) camangle[1] = 0.000001; if (camangle[1] > JLMath.toRad(90.0)) camangle[1] = JLMath.toRad(90.0); while (camangle[0] < 0.0) camangle[0] += JLMath.toRad(360.0); while (camangle[0] >= JLMath.toRad(360.0)) camangle[0] -= JLMath.toRad(360.0); Animator.this.setCameraAngle(camangle); if (Animator.this.getPaused()) repaint(); } }); this.addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent e) { if (exception != null) return; if (!engineStarted) return; syncRenderer(); repaint(); } }); } protected double[] snapCamera(double[] ca) { double[] result = new double[2]; result[0] = ca[0]; result[1] = ca[1]; if (result[1] < snapangle) result[1] = 0.000001; if ((result[1] > (JLMath.toRad(90.0) - snapangle)) /*&& (result[1] < (JLMath.toRad(90.0) + snapangle)) */) result[1] = JLMath.toRad(90.0); // if (result[1] > (JLMath.toRad(180.0) - snapangle)) // result[1] = JLMath.toRad(179.99999); return result; } protected void setCameraAngle(double[] camangle) { actualcamangle = snapCamera(camangle); while (actualcamangle[0] < 0.0) actualcamangle[0] += JLMath.toRad(360.0); while (actualcamangle[0] >= JLMath.toRad(360.0)) actualcamangle[0] -= JLMath.toRad(360.0); if (jc.stereo) { actualcamangle1[0] = actualcamangle[0] - 0.05; actualcamangle1[1] = actualcamangle[1]; ren1.setCameraAngle(actualcamangle1); actualcamangle2[0] = actualcamangle[0] + 0.05; actualcamangle2[1] = actualcamangle[1]; ren2.setCameraAngle(actualcamangle2); } else ren1.setCameraAngle(actualcamangle); } public void restartJuggle(JMLPattern pat, AnimatorPrefs newjc) throws JuggleExceptionUser, JuggleExceptionInternal { // try to lay out new pattern first so that if there's an error we won't stop the current animation if ((pat != null) && !pat.isLaidout()) pat.layoutPattern(); // stop the current animation thread, if one is running killAnimationThread(); if (pat != null) this.pat = pat; if (newjc != null) this.jc = newjc; if (this.pat == null) return; ren1 = new Renderer2D(); if (this.jc.stereo) ren2 = new Renderer2D(); ren1.setPattern(this.pat); if (this.jc.stereo) ren2.setPattern(this.pat); if (this.pat.getNumberOfJugglers() == 1) { this.camangle[0] = JLMath.toRad(0.0); this.camangle[1] = JLMath.toRad(90.0); } else { this.camangle[0] = JLMath.toRad(340.0); this.camangle[1] = JLMath.toRad(70.0); } setCameraAngle(camangle); this.setBackground(ren1.getBackground()); syncToPattern(); if (jugglinglab.core.Constants.DEBUG_LAYOUT) System.out.println(this.pat); engine = new Thread(this); engine.start(); } public void restartJuggle() throws JuggleExceptionUser, JuggleExceptionInternal { restartJuggle(null, null); } public void run() { // Called when this object becomes a thread long real_time_start, real_time_wait; Thread.currentThread().setPriority(Thread.MIN_PRIORITY); engineStarted = false; if (jc.mousePause) { waspaused = jc.startPause; // waspaused_valid = outside_valid; } try { engineRunning = true; // ok to start rendering if (jc.startPause) { message = guistrings.getString("Message_click_to_start"); repaint(); enginePaused = true; while (enginePaused && engineRunning) { synchronized (this) { try { wait(); } catch (InterruptedException ie) { } } } } message = null; // setCameraAngle(camangle); real_time_start = System.currentTimeMillis(); double oldtime, newtime; if (jc.mousePause) { if (outside_valid) setPaused(outside); else setPaused(true); // assume mouse is outside animator, if not known waspaused = false; // waspaused_valid = true; } while (engineRunning) { setTime(pat.getLoopStartTime()); engineStarted = true; for (int i = 0; engineRunning && (getTime() < (pat.getLoopEndTime() - 0.5*sim_interval_secs)); i++) { repaint(); try { real_time_wait = real_interval_millis - (System.currentTimeMillis() - real_time_start); if (real_time_wait > 0) Thread.sleep(real_time_wait); real_time_start = System.currentTimeMillis(); } catch (InterruptedException ie) { // What should we do here? throw new JuggleExceptionInternal("Animator was interrupted"); } while (enginePaused && engineRunning) { synchronized (this) { try { wait(); } catch (InterruptedException ie) { } } } oldtime = getTime(); setTime(getTime() + sim_interval_secs); newtime = getTime(); if (jc.catchSound && (catchclip != null)) { for (int path = 1; path <= pat.getNumberOfPaths(); path++) { if (pat.getPathCatchVolume(path, oldtime, newtime) > 0.0) { // System.out.println("Caught path "+path); catchclip.play(); } } } if (jc.bounceSound && (bounceclip != null)) { for (int path = 1; path <= pat.getNumberOfPaths(); path++) { if (pat.getPathBounceVolume(path, oldtime, newtime) > 0.0) { // System.out.println("Caught path "+path); bounceclip.play(); } } } } advanceProps(animpropnum); } } catch (JuggleException je) { exception = je; repaint(); } finally { engineStarted = engineRunning = enginePaused = false; engine = null; // this is critical as it signals restartJuggle() that exit is occurring } synchronized (this) { notify(); // tell possible thread wait()ing in restartJuggle() that animator thread is exiting } } // stop the current animation thread, if one is running protected synchronized void killAnimationThread() { while ((engine != null) && engine.isAlive()) { setPaused(false); // get thread out of pause so it can exit engineRunning = false; try { wait(); // wait for notify() from exiting run() method } catch (InterruptedException ie) { } } engine = null; // just in case animator doesn't initialize these engineStarted = false; enginePaused = false; engineRunning = false; exception = null; message = null; } public boolean getPaused() { return enginePaused; } public synchronized void setPaused(boolean wanttopause) { if ((enginePaused == true) && (wanttopause == false)) { notify(); // wake up wait() in run() method } enginePaused = wanttopause; } public double getTime() { return sim_time; }; public void setTime(double time) { /* while (time < pat.getLoopStartTime()) time += (pat.getLoopEndTime() - pat.getLoopStartTime()); while (time > pat.getLoopEndTime()) time -= (pat.getLoopEndTime() - pat.getLoopStartTime()); */ sim_time = time; } public void paintComponent(Graphics g) { if (exception != null) drawString(exception.getMessage(), g); else if (message != null) drawString(message, g); else if (engineRunning && !writingGIF) { try { drawFrame(getTime(), animpropnum, g); } catch (JuggleExceptionInternal jei) { this.killAnimationThread(); System.out.println(jei.getMessage()); System.exit(0); // ErrorDialog.handleException(jei); } } } protected void drawFrame(double sim_time, int[] pnum, Graphics g) throws JuggleExceptionInternal { if (this.jc.stereo) { Dimension d = this.getSize(); this.ren1.drawFrame(sim_time, pnum, g.create(0,0,d.width/2,d.height), Animator.this); this.ren2.drawFrame(sim_time, pnum, g.create(d.width/2,0,d.width/2,d.height), Animator.this); } else { this.ren1.drawFrame(sim_time, pnum, g, Animator.this); } if (!this.cameradrag) return; // try to turn on antialiased rendering VersionSpecific.getVersionSpecific().setAntialias(g); { double[] ca = ren1.getCameraAngle(); double theta = ca[0]; double phi = ca[1]; double xya = 30.0; double xyb = xya * Math.sin(90.0*0.0174532925194 - phi); double zlen = xya * Math.cos(90.0*0.0174532925194 - phi); int cx = 38; int cy = 45; int xx = cx + (int)(0.5 - xya * Math.cos(theta)); int xy = cy + (int)(0.5 + xyb * Math.sin(theta)); int yx = cx + (int)(0.5 - xya * Math.cos(theta + 90.0*0.0174532925194)); int yy = cy + (int)(0.5 + xyb * Math.sin(theta + 90.0*0.0174532925194)); int zx = cx; int zy = cy - (int)(0.5 + zlen); g.setColor(Color.green); g.drawLine(cx, cy, xx, xy); g.drawLine(cx, cy, yx, yy); g.drawLine(cx, cy, zx, zy); g.fillOval(xx-2, xy-2, 5, 5); g.fillOval(yx-2, yy-2, 5, 5); g.fillOval(zx-2, zy-2, 5, 5); g.drawString("x", xx-2, xy-4); g.drawString("y", yx-2, yy-4); g.drawString("z", zx-2, zy-4); } if (this.jc.stereo) { double[] ca = ren2.getCameraAngle(); double theta = ca[0]; double phi = ca[1]; double xya = 30.0; double xyb = xya * Math.sin(90.0*0.0174532925194 - phi); double zlen = xya * Math.cos(90.0*0.0174532925194 - phi); int cx = 38 + this.getSize().width/2; int cy = 45; int xx = cx + (int)(0.5 - xya * Math.cos(theta)); int xy = cy + (int)(0.5 + xyb * Math.sin(theta)); int yx = cx + (int)(0.5 - xya * Math.cos(theta + 90.0*0.0174532925194)); int yy = cy + (int)(0.5 + xyb * Math.sin(theta + 90.0*0.0174532925194)); int zx = cx; int zy = cy - (int)(0.5 + zlen); g.setColor(Color.green); g.drawLine(cx, cy, xx, xy); g.drawLine(cx, cy, yx, yy); g.drawLine(cx, cy, zx, zy); g.fillOval(xx-2, xy-2, 5, 5); g.fillOval(yx-2, yy-2, 5, 5); g.fillOval(zx-2, zy-2, 5, 5); g.drawString("x", xx-2, xy-4); g.drawString("y", yx-2, yy-4); g.drawString("z", zx-2, zy-4); } } protected void drawString(String message, Graphics g) { int x, y, width; Dimension appdim = this.getSize(); int appWidth = appdim.width; int appHeight = appdim.height; FontMetrics fm = g.getFontMetrics(); width = fm.stringWidth(message); x = (appWidth > width) ? (appWidth-width)/2 : 0; y = (appHeight + fm.getHeight()) / 2; g.setColor(Color.white); g.fillRect(0, 0, appWidth, appHeight); g.setColor(Color.black); g.drawString(message, x, y); } protected void advanceProps(int[] pnum) { for (int i = 0; i < pat.getNumberOfPaths(); i++) temppropnum[invpathperm.getMapping(i+1)-1] = pnum[i]; for (int i = 0; i < pat.getNumberOfPaths(); i++) pnum[i] = temppropnum[i]; } public void syncToPattern() { findMaxMin(); syncRenderer(); // figure out timing constants; adjust fps to get integer number of frames in loop num_frames = (int)(0.5 + (pat.getLoopEndTime() - pat.getLoopStartTime()) * jc.slowdown * jc.fps); sim_interval_secs = (pat.getLoopEndTime()-pat.getLoopStartTime()) / num_frames; real_interval_millis = (long)(1000.0 * sim_interval_secs * jc.slowdown); animpropnum = new int[pat.getNumberOfPaths()]; for (int i = 1; i <= pat.getNumberOfPaths(); i++) animpropnum[i-1] = pat.getPropAssignment(i); temppropnum = new int[pat.getNumberOfPaths()]; invpathperm = pat.getPathPermutation().getInverse(); } protected void findMaxMin() { // the algorithm here could be improved to take into account which props are // on which paths. We may also want to leave room for the rest of the juggler. int i; Coordinate patternmax = null, patternmin = null; Coordinate handmax = null, handmin = null; Coordinate propmax = null, propmin = null; for (i = 1; i <= pat.getNumberOfPaths(); i++) { patternmax = Coordinate.max(patternmax, pat.getPathMax(i)); patternmin = Coordinate.min(patternmin, pat.getPathMin(i)); if (jugglinglab.core.Constants.DEBUG_LAYOUT) System.out.println("Pattern max "+i+" = "+patternmax); } // make sure all hands are visible for (i = 1; i <= pat.getNumberOfJugglers(); i++) { handmax = Coordinate.max(handmax, pat.getHandMax(i, HandLink.LEFT_HAND)); handmin = Coordinate.min(handmin, pat.getHandMin(i, HandLink.LEFT_HAND)); handmax = Coordinate.max(handmax, pat.getHandMax(i, HandLink.RIGHT_HAND)); handmin = Coordinate.min(handmin, pat.getHandMin(i, HandLink.RIGHT_HAND)); } for (i = 1; i <= pat.getNumberOfProps(); i++) { propmax = Coordinate.max(propmax, pat.getProp(i).getMax()); propmin = Coordinate.min(propmin, pat.getProp(i).getMin()); } // make sure props are entirely visible along all paths patternmax = Coordinate.add(patternmax, propmax); patternmin = Coordinate.add(patternmin, propmin); // make sure hands are entirely visible handmax = Coordinate.add(handmax, ren1.getHandWindowMax()); handmin = Coordinate.add(handmin, ren1.getHandWindowMin()); // make sure jugglers' bodies are visible this.overallmax = Coordinate.max(handmax, ren1.getJugglerWindowMax()); this.overallmax = Coordinate.max(overallmax, patternmax); this.overallmin = Coordinate.min(handmin, ren1.getJugglerWindowMin()); this.overallmin = Coordinate.min(overallmin, patternmin); // we want to ensure everything stays visible as we rotate the camera // viewpoint. the following is simple and seems to work ok. if (pat.getNumberOfJugglers() == 1) { overallmin.z -= 0.3 * Math.max(Math.abs(overallmin.y), Math.abs(overallmax.y)); overallmax.z += 5.0; // keeps objects from rubbing against top of window } else { double tempx = Math.max(Math.abs(overallmin.x), Math.abs(overallmax.x)); double tempy = Math.max(Math.abs(overallmin.y), Math.abs(overallmax.y)); overallmin.z -= 0.4 * Math.max(tempx, tempy); overallmax.z += 0.4 * Math.max(tempx, tempy); } // make the x-coordinate origin at the center of the view double maxabsx = Math.max(Math.abs(this.overallmin.x), Math.abs(this.overallmax.x)); this.overallmin.x = -maxabsx; this.overallmax.x = maxabsx; if (jugglinglab.core.Constants.DEBUG_LAYOUT) { System.out.println("Hand max = "+handmax); System.out.println("Hand min = "+handmin); System.out.println("Prop max = "+propmax); System.out.println("Prop min = "+propmin); System.out.println("Pattern max = "+patternmax); System.out.println("Pattern min = "+patternmin); System.out.println("Overall max = "+this.overallmax); System.out.println("Overall min = "+this.overallmin); this.overallmax = new Coordinate(100.0,0.0,500.0); this.overallmin = new Coordinate(-100.0,0.0,-100.0); } } protected void syncRenderer() { Dimension d = this.getSize(); if (this.jc.stereo) { d.width /= 2; this.ren1.initDisplay(d, jc.border, this.overallmax, this.overallmin); this.ren2.initDisplay(d, jc.border, this.overallmax, this.overallmin); } else this.ren1.initDisplay(d, jc.border, this.overallmax, this.overallmin); } public boolean isAnimInited() { return engineStarted; } public JMLPattern getPattern() { return pat; } public AnimatorPrefs getAnimatorPrefs() { return jc; } public int[] getAnimPropNum() { return animpropnum; } public void dispose() { killAnimationThread(); } public void writeGIFAnim() { try { Class jagw = Class.forName("jugglinglab.core.AnimatorGIFWriter"); Method setup = jagw.getMethod("setup", new Class[] {Animator.class, jugglinglab.renderer.Renderer.class, jugglinglab.renderer.Renderer.class, Integer.TYPE, Double.TYPE, Long.TYPE}); Object gw = jagw.newInstance(); setup.invoke(gw, new Object[] {this, ren1, ren2, new Integer(num_frames), new Double(sim_interval_secs), new Long(real_interval_millis)}); writingGIF = true; Thread worker = (Thread)gw; worker.start(); } catch (ClassNotFoundException cnfe) { return; } catch (NoSuchMethodException nsme) { return; } catch (SecurityException se) { return; } catch (IllegalAccessException iae) { return; } catch (InstantiationException ie) { return; } catch (InvocationTargetException ite) { return; } } } jugglinglab-0.6.2+ds.1/source/jugglinglab/core/AnimatorEdit.java000066400000000000000000000317451323754603300245250ustar00rootroot00000000000000// AnimatorEdit.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.core; import java.awt.*; import java.awt.event.*; import jugglinglab.util.*; import jugglinglab.jml.*; public class AnimatorEdit extends Animator { protected LadderDiagram ladder = null; protected boolean event_active = false; protected JMLEvent event; protected int xlow1, xhigh1, ylow1, yhigh1; protected int xlow2, xhigh2, ylow2, yhigh2; protected boolean dragging = false; protected boolean dragging_left = false; protected int xstart, ystart, xdelta, ydelta; public AnimatorEdit() { super(); } protected void initHandlers() { final JMLPattern fpat = pat; this.addMouseListener(new MouseAdapter() { long lastpress = 0L; long lastenter = 1L; public void mousePressed(MouseEvent me) { lastpress = me.getWhen(); // The following (and the equivalent in mouseReleased()) is a hack to swallow // a mouseclick when the browser stops reporting enter/exit events because the // user has clicked on something else. The system reports simultaneous enter/press // events when the user mouses down in the component; we want to swallow this as a // click, and just use it to get focus back. if (jc.mousePause && (lastpress == lastenter)) return; if (exception != null) return; if (!engineStarted) return; if (event_active) { int mx = me.getX(); int my = me.getY(); if ((mx >= xlow1) && (mx <= xhigh1) && (my >= ylow1) && (my <= yhigh1)) { dragging = true; dragging_left = true; xstart = mx; ystart = my; xdelta = ydelta = 0; return; } int t = AnimatorEdit.this.getSize().width / 2; if ((mx >= (xlow2+t)) && (mx <= (xhigh2+t)) && (my >= ylow2) && (my <= yhigh2)) { dragging = true; dragging_left = false; xstart = mx; ystart = my; xdelta = ydelta = 0; return; } } // if we get here, start a reposition of the camera AnimatorEdit.this.startx = me.getX(); AnimatorEdit.this.starty = me.getY(); } public void mouseReleased(MouseEvent me) { if (jc.mousePause && (lastpress == lastenter)) return; if (exception != null) return; if (!engineStarted && (engine != null) && engine.isAlive()) { setPaused(!enginePaused); return; } if (event_active && dragging) { JMLEvent master = (event.isMaster() ? event : event.getMaster()); boolean flipx = (event.getHand() != master.getHand()); Coordinate newgc = ren1.getScreenTranslatedCoordinate( event.getGlobalCoordinate(), xdelta, ydelta ); if (AnimatorEdit.this.jc.stereo) { Coordinate newgc2 = ren2.getScreenTranslatedCoordinate( event.getGlobalCoordinate(), xdelta, ydelta ); newgc = Coordinate.add(newgc, newgc2); newgc.setCoordinate(0.5*newgc.x, 0.5*newgc.y, 0.5*newgc.z); } Coordinate newlc = pat.convertGlobalToLocal(newgc, event.getJuggler(), event.getT()); Coordinate deltalc = Coordinate.sub(newlc, event.getLocalCoordinate()); if (flipx) deltalc.x = -deltalc.x; Coordinate orig = master.getLocalCoordinate(); master.setLocalCoordinate(Coordinate.add(orig, deltalc)); xdelta = ydelta = 0; EditLadderDiagram eld = (EditLadderDiagram)ladder; eld.activeEventMoved(); } AnimatorEdit.this.cameradrag = false; dragging = false; if ((me.getX() == startx) && (me.getY() == starty) && (engine != null) && engine.isAlive()) setPaused(!enginePaused); if (AnimatorEdit.this.getPaused()) repaint(); } public void mouseEntered(MouseEvent me) { lastenter = me.getWhen(); if (jc.mousePause /*&& waspaused_valid*/) setPaused(waspaused); outside = false; outside_valid = true; } public void mouseExited(MouseEvent me) { if (jc.mousePause) { waspaused = getPaused(); // waspaused_valid = true; setPaused(true); } outside = true; outside_valid = true; } }); this.addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged(MouseEvent me) { if (exception != null) return; if (!engineStarted) return; if (dragging) { int mx = me.getX(); int my = me.getY(); xdelta = mx - xstart; ydelta = my - ystart; repaint(); } else if (!cameradrag) { AnimatorEdit.this.cameradrag = true; AnimatorEdit.this.lastx = AnimatorEdit.this.startx; AnimatorEdit.this.lasty = AnimatorEdit.this.starty; AnimatorEdit.this.camangle = AnimatorEdit.this.ren1.getCameraAngle(); } if (!cameradrag) return; int xdelta = me.getX() - AnimatorEdit.this.lastx; int ydelta = me.getY() - AnimatorEdit.this.lasty; AnimatorEdit.this.lastx = me.getX(); AnimatorEdit.this.lasty = me.getY(); double[] camangle = AnimatorEdit.this.camangle; camangle[0] += (double)(xdelta) * 0.02; camangle[1] -= (double)(ydelta) * 0.02; if (camangle[1] < 0.0001) camangle[1] = 0.0001; if (camangle[1] > JLMath.toRad(90.0)) camangle[1] = JLMath.toRad(90.0); while (camangle[0] < 0.0) camangle[0] += JLMath.toRad(360.0); while (camangle[0] >= JLMath.toRad(360.0)) camangle[0] -= JLMath.toRad(360.0); AnimatorEdit.this.setCameraAngle(camangle); if (event_active) createEventView(); if (AnimatorEdit.this.getPaused()) repaint(); } }); this.addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent e) { if (exception != null) return; if (!engineStarted) return; syncRenderer(); repaint(); } }); } protected double[] snapCamera(double[] ca) { double[] result = super.snapCamera(ca); if (event_active) { double a = JLMath.toRad(pat.getJugglerAngle(event.getJuggler(), event.getT())); if (anglediff(a - result[0]) < snapangle) result[0] = a; else if (anglediff(a + 90.0*0.0174532925194 - result[0]) < snapangle) result[0] = a + 90.0*0.0174532925194; else if (anglediff(a + 180.0*0.0174532925194 - result[0]) < snapangle) result[0] = a + 180.0*0.0174532925194; else if (anglediff(a + 270.0*0.0174532925194 - result[0]) < snapangle) result[0] = a + 270.0*0.0174532925194; } return result; } protected double anglediff(double delta) { while (delta > JLMath.toRad(180.0)) delta -= JLMath.toRad(360.0); while (delta <= JLMath.toRad(-180.0)) delta += JLMath.toRad(360.0); return Math.abs(delta); } public void setLadderDiagram(LadderDiagram ladder) { this.ladder = ladder; } // set position of tracker bar in ladder diagram as we animate public void setTime(double time) { super.setTime(time); if (ladder != null) ladder.setTime(time); } public void activateEvent(JMLEvent ev) { if ((ladder != null) && !(ladder instanceof EditLadderDiagram)) return; event = ev; event_active = true; createEventView(); } public void deactivateEvent() { event_active = false; } protected void createEventView() { if (event_active) { // translate by one pixel and see how far it was in juggler space { Coordinate c = event.getGlobalCoordinate(); Coordinate c2 = ren1.getScreenTranslatedCoordinate(c, 1, 0); Coordinate dc = Coordinate.sub(c, c2); double dl = Math.sqrt(dc.x*dc.x + dc.y*dc.y + dc.z*dc.z); int boxhw = (int)(0.5 + 5.0 / dl); // pixels corresponding to 5cm in juggler space int[] center = ren1.getXY(c); xlow1 = center[0] - boxhw; ylow1 = center[1] - boxhw; xhigh1 = center[0] + boxhw; yhigh1 = center[1] + boxhw; } if (this.jc.stereo) { Coordinate c = event.getGlobalCoordinate(); Coordinate c2 = ren2.getScreenTranslatedCoordinate(c, 1, 0); Coordinate dc = Coordinate.sub(c, c2); double dl = Math.sqrt(dc.x*dc.x + dc.y*dc.y + dc.z*dc.z); int boxhw = (int)(0.5 + 5.0 / dl); // pixels corresponding to 5cm in juggler space int[] center = ren2.getXY(c); xlow2 = center[0] - boxhw; ylow2 = center[1] - boxhw; xhigh2 = center[0] + boxhw; yhigh2 = center[1] + boxhw; } } } protected void syncRenderer() { super.syncRenderer(); if (event_active) createEventView(); } protected void drawFrame(double sim_time, int[] pnum, Graphics g) throws JuggleExceptionInternal { super.drawFrame(sim_time, pnum, g); if (!event_active) return; Dimension d = this.getSize(); Graphics g2 = g; if (this.jc.stereo) g2 = g.create(0,0,d.width/2,d.height); if (g2 instanceof Graphics2D) { Graphics2D g22 = (Graphics2D)g2; g22.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); } g2.setColor(Color.green); g2.drawLine(xlow1+xdelta, ylow1+ydelta, xhigh1+xdelta, ylow1+ydelta); g2.drawLine(xhigh1+xdelta, ylow1+ydelta, xhigh1+xdelta, yhigh1+ydelta); g2.drawLine(xhigh1+xdelta, yhigh1+ydelta, xlow1+xdelta, yhigh1+ydelta); g2.drawLine(xlow1+xdelta, yhigh1+ydelta, xlow1+xdelta, ylow1+ydelta); if (this.jc.stereo) { g2 = g.create(d.width/2,0,d.width/2,d.height); if (g2 instanceof Graphics2D) { Graphics2D g22 = (Graphics2D)g2; g22.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); } g2.setColor(Color.green); g2.drawLine(xlow2+xdelta, ylow2+ydelta, xhigh2+xdelta, ylow2+ydelta); g2.drawLine(xhigh2+xdelta, ylow2+ydelta, xhigh2+xdelta, yhigh2+ydelta); g2.drawLine(xhigh2+xdelta, yhigh2+ydelta, xlow2+xdelta, yhigh2+ydelta); g2.drawLine(xlow2+xdelta, yhigh2+ydelta, xlow2+xdelta, ylow2+ydelta); } } } jugglinglab-0.6.2+ds.1/source/jugglinglab/core/AnimatorGIFWriter.java000066400000000000000000000262761323754603300254450ustar00rootroot00000000000000// AnimatorGIFWriter.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.core; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; import java.io.*; import java.util.*; import java.net.*; // import java.lang.reflect.*; import jugglinglab.jml.*; import jugglinglab.renderer.*; import jugglinglab.util.*; import gifwriter.*; public class AnimatorGIFWriter extends Thread { static ResourceBundle guistrings; // static ResourceBundle errorstrings; static { guistrings = JLLocale.getBundle("GUIStrings"); // errorstrings = JLLocale.getBundle("ErrorStrings"); } Animator ja = null; JMLPattern pat = null; jugglinglab.renderer.Renderer ren1 = null, ren2 = null; int num_frames; double sim_interval_secs; long real_interval_millis; OutputStream out = null; public AnimatorGIFWriter() { this.setPriority(Thread.MIN_PRIORITY); } public void setup(Animator ja, jugglinglab.renderer.Renderer ren1, jugglinglab.renderer.Renderer ren2, int num_frames, double sim_interval_secs, long real_interval_millis) { this.ja = ja; this.pat = ja.getPattern(); this.ren1 = ren1; this.ren2 = ren2; this.num_frames = num_frames; this.sim_interval_secs = sim_interval_secs; this.real_interval_millis = real_interval_millis; } public void run() { if (!jugglinglab.core.Constants.INCLUDE_GIF_SAVE) return; try { /* Class gawclass = null; try { gawclass = Class.forName("gifwriter.GIFAnimWriter"); } catch (ClassNotFoundException cnfe) { try { URL[] jarurl = new URL[] {new URL("file:GIFAnimWriter.jar")}; URLClassLoader loader = new URLClassLoader(jarurl); gawclass = Class.forName("gifwriter.GIFAnimWriter", true, loader); } catch (ClassNotFoundException cnfe2) { new ErrorDialog(parent, "Required file GIFAnimWriter.jar not found"); return; } catch (MalformedURLException ex) { throw new JuggleExceptionInternal("Malformed URL"); } } Method docolormap1 = null; // public void doColorMap(Color color, boolean defaultcolor) throws IOException; Method writeheader = null; // public void writeHeader(OutputStream out) throws IOException; Method writedelay = null; // public void writeDelay(int delay, OutputStream out) throws IOException; Method writegif = null; // public void writeGIF(Image img, OutputStream out) throws IOException; Method writetrailer = null; // public void writeTrailer(OutputStream out) throws IOException; try { docolormap1 = gawclass.getMethod("doColorMap", new Class[] {Color.class, Boolean.TYPE}); writeheader = gawclass.getMethod("writeHeader", new Class[] {OutputStream.class}); writedelay = gawclass.getMethod("writeDelay", new Class[] {Integer.TYPE, OutputStream.class}); writegif = gawclass.getMethod("writeGIF", new Class[] {Image.class, OutputStream.class}); writetrailer = gawclass.getMethod("writeTrailer", new Class[] {OutputStream.class}); } catch (NoSuchMethodException nsme) { throw new JuggleExceptionInternal("Could not find method: "+nsme.getMessage()); } catch (SecurityException se) { throw new JuggleExceptionInternal("Method not accessible (security): "+se.getMessage()); } */ boolean origpause = ja.getPaused(); ja.setPaused(true); try { FileOutputStream out = null; ProgressMonitor pm = null; int option = PlatformSpecific.getPlatformSpecific().showSaveDialog(ja); if (option == JFileChooser.APPROVE_OPTION) { if (PlatformSpecific.getPlatformSpecific().getSelectedFile() != null) { ja.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); File file = PlatformSpecific.getPlatformSpecific().getSelectedFile(); out = new FileOutputStream(file); // Create the object that will actually do the writing /* Object gaw = null; try { gaw = gawclass.newInstance(); } catch (IllegalAccessException iae) { throw new JuggleExceptionInternal("Cannot access gifwriter.GIFAnimWriter class (security)"); } catch (InstantiationException ie) { throw new JuggleExceptionInternal("Could not instantiate gifwriter.GIFAnimWriter object"); }*/ GIFAnimWriter gaw = new GIFAnimWriter(); // set black as default drawing color // docolormap1.invoke(gaw, new Object[] {Color.black, new Boolean(true)}); // gaw.doColorMap(Color.black, true); Dimension dim = ja.getSize(); int appWidth = dim.width; int appHeight = dim.height; Image tempoffscreen = ja.createImage(appWidth, appHeight); Graphics tempoffg = tempoffscreen.getGraphics(); // writeheader.invoke(gaw, new Object[] {out}); // gaw.writeHeader(out); int[] gifpropnum = new int[pat.getNumberOfPaths()]; for (int i = 0; i < pat.getNumberOfPaths(); i++) gifpropnum[i] = pat.getPropAssignment(i+1); int patperiod = pat.getPeriod(); int totalframes = patperiod * num_frames * 2; int framecount = 0; pm = new ProgressMonitor(ja, guistrings.getString("Saving_animated_GIF"), "", 0, totalframes); boolean canceled = false; // loop through the individual frames twice, first to build the // color map and the second to write the GIF frames for (int pass = 0; pass < 2; pass++) { if (pass == 1) gaw.writeHeader(out); for (int i = 0; i < patperiod; i++) { double time = pat.getLoopStartTime(); for (int j = 0; j < num_frames; j++) { if (pass == 1) gaw.writeDelay((int)(real_interval_millis/10), out); if (ren2 != null) { this.ren1.drawFrame(time, gifpropnum, tempoffg.create(0,0,dim.width/2,dim.height), ja); this.ren2.drawFrame(time, gifpropnum, tempoffg.create(dim.width/2,0,dim.width/2,dim.height), ja); } else { this.ren1.drawFrame(time, gifpropnum, tempoffg, ja); } // ren.drawFrame(time, gifpropnum, tempoffg, ja); if (pass == 0) gaw.doColorMap(tempoffscreen); else gaw.writeGIF(tempoffscreen, out); if (pm != null) { framecount++; String note = (pass==0 ? guistrings.getString("Message_GIFsave_color_map") : guistrings.getString("Message_GIFsave_writing_frame")+" "+(framecount-num_frames)+"/"+num_frames); SwingUtilities.invokeLater(new PBUpdater(pm,framecount,note)); if (pm.isCanceled()) return; } time += sim_interval_secs; } ja.advanceProps(gifpropnum); } } // writetrailer.invoke(gaw, new Object[] {out}); gaw.writeTrailer(out); tempoffg.dispose(); } } } catch (FileNotFoundException fnfe) { throw new JuggleExceptionInternal("AnimGIFSave file not found: "+fnfe.getMessage()); } catch (IOException ioe) { throw new JuggleExceptionInternal("AnimGIFSave IOException: "+ioe.getMessage()); } /* catch (IllegalAccessException iae) { throw new JuggleExceptionInternal("AnimGIFSave IllegalAccessException: "+iae.getMessage()); } catch (InvocationTargetException ite) { throw new JuggleExceptionInternal("AnimGIFSave InvocationTargetException: "+ite.getMessage()); } */ catch (IllegalArgumentException iae) { throw new JuggleExceptionInternal("AnimGIFSave IllegalArgumentException: "+iae.getMessage()); } finally { if (out != null) { try { out.close(); } catch (IOException ioe) {} } ja.setCursor(Cursor.getDefaultCursor()); ja.setPaused(origpause); } } catch (Exception e) { jugglinglab.util.ErrorDialog.handleException(e); } ja.writingGIF = false; } } class PBUpdater implements Runnable { ProgressMonitor pro = null; int setting; String note; public PBUpdater(ProgressMonitor pro, int setting, String note) { this.pro = pro; this.setting = setting; this.note = note; } public void run() { pro.setProgress(setting); pro.setNote(note); } } jugglinglab-0.6.2+ds.1/source/jugglinglab/core/AnimatorPrefs.java000066400000000000000000000130001323754603300246770ustar00rootroot00000000000000// AnimatorPrefs.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.core; import java.util.*; import java.text.MessageFormat; import jugglinglab.util.*; import jugglinglab.jml.*; public class AnimatorPrefs { // static ResourceBundle guistrings; static ResourceBundle errorstrings; static { // guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } public static final boolean stereo_def = false; public static final boolean startPause_def = false; public static final boolean mousePause_def = false; public static final boolean catchSound_def = false; public static final boolean bounceSound_def = true; public static final double fps_def = 30.0; public static final double slowdown_def = 2.0; public static final int border_def = 0; public boolean stereo = stereo_def; public boolean startPause = startPause_def; public boolean mousePause = mousePause_def; public boolean catchSound = catchSound_def; public boolean bounceSound = bounceSound_def; public double fps = fps_def; public double slowdown = slowdown_def; public int border = border_def; public AnimatorPrefs() { super(); } public AnimatorPrefs(AnimatorPrefs jc) { if (jc.slowdown >= 0.0) this.slowdown = jc.slowdown; if (jc.fps >= 0.0) this.fps = jc.fps; if (jc.border >= 0) this.border = jc.border; this.startPause = jc.startPause; this.mousePause = jc.mousePause; this.stereo = jc.stereo; this.catchSound = jc.catchSound; this.bounceSound = jc.bounceSound; } public void parseInput(String input) throws JuggleExceptionUser { int tempint; double tempdouble; String value = null; ParameterList pl = new ParameterList(input); if ((value = pl.getParameter("stereo")) != null) this.stereo = Boolean.valueOf(value).booleanValue(); if ((value = pl.getParameter("startpaused")) != null) this.startPause = Boolean.valueOf(value).booleanValue(); if ((value = pl.getParameter("mousepause")) != null) this.mousePause = Boolean.valueOf(value).booleanValue(); if ((value = pl.getParameter("catchsound")) != null) this.catchSound = Boolean.valueOf(value).booleanValue(); if ((value = pl.getParameter("bouncesound")) != null) this.bounceSound = Boolean.valueOf(value).booleanValue(); if ((value = pl.getParameter("fps")) != null) { try { tempdouble = Double.valueOf(value).doubleValue(); this.fps = tempdouble; } catch (NumberFormatException e) { String template = errorstrings.getString("Error_number_format"); Object[] arguments = { "fps" }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } } if ((value = pl.getParameter("slowdown")) != null) { try { tempdouble = Double.valueOf(value).doubleValue(); this.slowdown = tempdouble; } catch (NumberFormatException e) { String template = errorstrings.getString("Error_number_format"); Object[] arguments = { "slowdown" }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } } if ((value = pl.getParameter("border")) != null) { try { tempint = Integer.parseInt(value); this.border = tempint; } catch (NumberFormatException e) { String template = errorstrings.getString("Error_number_format"); Object[] arguments = { "border" }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } } } public String toString() { String result = ""; if (stereo != stereo_def) result += "stereo="+this.stereo+";"; if (startPause != startPause_def) result += "startpaused="+this.startPause+";"; if (mousePause != mousePause_def) result += "mousepause="+this.mousePause+";"; if (catchSound != catchSound_def) result += "catchsound="+this.catchSound+";"; if (bounceSound != bounceSound_def) result += "bouncesound="+this.bounceSound+";"; if (fps != fps_def) result += "fps="+JMLPattern.toStringTruncated(this.fps,2)+";"; if (slowdown != slowdown_def) result += "slowdown="+JMLPattern.toStringTruncated(this.slowdown,2)+";"; if (border != border_def) result += "border="+this.border+";"; if (result.length() != 0) result = result.substring(0, result.length()-1); return result; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/core/AnimatorPrefsDialog.java000066400000000000000000000214011323754603300260230ustar00rootroot00000000000000// AnimatorPrefsDialog.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.core; import java.awt.*; import java.awt.event.*; import java.text.MessageFormat; import javax.swing.*; import java.util.*; import jugglinglab.util.*; public class AnimatorPrefsDialog extends JDialog { static ResourceBundle guistrings; static ResourceBundle errorstrings; static { guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } protected JTextField tf1, tf2, tf3; protected JCheckBox cb2, cb3, cb4, cb5, cb6; protected JButton but1, but2; protected AnimatorPrefs newjc; // protected boolean finished = false; protected final static int border = 10; public AnimatorPrefsDialog(JFrame parent) { // set up dialog super(parent, guistrings.getString("Animation_Preferences"), true); GridBagLayout gb = new GridBagLayout(); this.getContentPane().setLayout(gb); JPanel p1 = new JPanel(); // to hold text boxes p1.setLayout(gb); JLabel lab1 = new JLabel(guistrings.getString("Frames_per_second")); p1.add(lab1); gb.setConstraints(lab1, make_constraints(GridBagConstraints.LINE_START,1,0, new Insets(0,3,0,0))); tf1 = new JTextField(4); p1.add(tf1); gb.setConstraints(tf1, make_constraints(GridBagConstraints.LINE_START,0,0, new Insets(0,0,0,0))); JLabel lab2 = new JLabel(guistrings.getString("Slowdown_factor")); p1.add(lab2); gb.setConstraints(lab2, make_constraints(GridBagConstraints.LINE_START,1,1, new Insets(0,3,0,0))); tf2 = new JTextField(4); p1.add(tf2); gb.setConstraints(tf2, make_constraints(GridBagConstraints.LINE_START,0,1, new Insets(0,0,0,0))); JLabel lab3 = new JLabel(guistrings.getString("Border_(pixels)")); p1.add(lab3); gb.setConstraints(lab3, make_constraints(GridBagConstraints.LINE_START,1,2, new Insets(0,3,0,0))); tf3 = new JTextField(4); p1.add(tf3); gb.setConstraints(tf3, make_constraints(GridBagConstraints.LINE_START,0,2, new Insets(0,0,0,0))); cb2 = new JCheckBox(guistrings.getString("Start_paused")); cb6 = new JCheckBox(guistrings.getString("Pause_on_mouse_away")); cb3 = new JCheckBox(guistrings.getString("Stereo_display")); cb4 = new JCheckBox(guistrings.getString("Catch_sounds")); cb5 = new JCheckBox(guistrings.getString("Bounce_sounds")); JPanel p2 = new JPanel(); // buttons at bottom p2.setLayout(gb); but1 = new JButton(guistrings.getString("Cancel")); but1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { setVisible(false); } }); p2.add(but1); gb.setConstraints(but1, make_constraints(GridBagConstraints.LINE_END,0,0, new Insets(0,0,0,0))); but2 = new JButton(guistrings.getString("OK")); but2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { int tempint; double tempdouble; setVisible(false); // read out prefs newjc = new AnimatorPrefs(newjc); // clone old controls try { tempdouble = Double.valueOf(tf1.getText()).doubleValue(); if (tempdouble > 0.0) newjc.fps = tempdouble; } catch (NumberFormatException e) { String template = errorstrings.getString("Error_number_format"); Object[] arguments = { "fps" }; new ErrorDialog(AnimatorPrefsDialog.this, MessageFormat.format(template, arguments)); } try { tempdouble = Double.valueOf(tf2.getText()).doubleValue(); if (tempdouble > 0.0) newjc.slowdown = tempdouble; } catch (NumberFormatException e) { String template = errorstrings.getString("Error_number_format"); Object[] arguments = { "slowdown" }; new ErrorDialog(AnimatorPrefsDialog.this, MessageFormat.format(template, arguments)); } try { tempint = Integer.parseInt(tf3.getText()); if (tempint >= 0) newjc.border = tempint; } catch (NumberFormatException e) { String template = errorstrings.getString("Error_number_format"); Object[] arguments = { "border" }; new ErrorDialog(AnimatorPrefsDialog.this, MessageFormat.format(template, arguments)); } newjc.startPause = cb2.isSelected(); newjc.mousePause = cb6.isSelected(); newjc.stereo = cb3.isSelected(); newjc.catchSound = cb4.isSelected(); newjc.bounceSound = cb5.isSelected(); } }); p2.add(but2); gb.setConstraints(but2, make_constraints(GridBagConstraints.LINE_END,1,0, new Insets(0,10,0,0))); this.getContentPane().add(cb3); gb.setConstraints(cb3, make_constraints(GridBagConstraints.LINE_START,0,0, new Insets(0,border,0,border))); this.getContentPane().add(cb2); gb.setConstraints(cb2, make_constraints(GridBagConstraints.LINE_START,0,1, new Insets(0,border,0,border))); this.getContentPane().add(cb6); gb.setConstraints(cb6, make_constraints(GridBagConstraints.LINE_START,0,2, new Insets(0,border,0,border))); this.getContentPane().add(cb4); gb.setConstraints(cb4, make_constraints(GridBagConstraints.LINE_START,0,3, new Insets(0,border,0,border))); this.getContentPane().add(cb5); gb.setConstraints(cb5, make_constraints(GridBagConstraints.LINE_START,0,4, new Insets(0,border,3,border))); this.getContentPane().add(p1); // now make the whole window gb.setConstraints(p1, make_constraints(GridBagConstraints.LINE_START,0,5, new Insets(3,border,border,border))); this.getContentPane().add(p2); gb.setConstraints(p2, make_constraints(GridBagConstraints.LINE_END,0,6, new Insets(0,border,border,border))); this.getRootPane().setDefaultButton(but2); // OK button is default Locale loc = JLLocale.getLocale(); this.applyComponentOrientation(ComponentOrientation.getOrientation(loc)); this.pack(); this.setResizable(false); } protected static GridBagConstraints make_constraints(int location, int gridx, int gridy, Insets ins) { GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = location; gbc.fill = GridBagConstraints.NONE; gbc.gridheight = gbc.gridwidth = 1; gbc.gridx = gridx; gbc.gridy = gridy; gbc.insets = ins; gbc.weightx = gbc.weighty = 0.0; return gbc; } public AnimatorPrefs getPrefs(AnimatorPrefs oldjc) { newjc = oldjc; tf1.setText(Double.toString(oldjc.fps)); tf2.setText(Double.toString(oldjc.slowdown)); tf3.setText(Integer.toString(oldjc.border)); cb2.setSelected(oldjc.startPause); cb6.setSelected(oldjc.mousePause); cb3.setSelected(oldjc.stereo); cb4.setSelected(oldjc.catchSound); cb5.setSelected(oldjc.bounceSound); this.setVisible(true); return newjc; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/core/ApplicationWindow.java000077500000000000000000000422311323754603300255730ustar00rootroot00000000000000// ApplicationWindow.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.core; import java.awt.*; import java.awt.event.*; import java.io.*; import javax.swing.*; import org.xml.sax.*; import java.util.*; import java.util.regex.*; import java.text.MessageFormat; import jugglinglab.jml.*; import jugglinglab.notation.*; import jugglinglab.util.*; public class ApplicationWindow extends JFrame implements ActionListener, WindowListener { static ResourceBundle guistrings; static ResourceBundle errorstrings; static { guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } protected NotationGUI ng = null; protected boolean macos = false; public ApplicationWindow(String title) throws JuggleExceptionUser, JuggleExceptionInternal { super(title); ng = new NotationGUI(this); macos = PlatformSpecific.getPlatformSpecific().isMacOS(); JMenuBar mb = new JMenuBar(); JMenu filemenu = createFileMenu(); mb.add(filemenu); JMenu notationmenu = ng.createNotationMenu(); mb.add(notationmenu); JMenu helpmenu = ng.createHelpMenu(!macos); if (helpmenu != null) mb.add(helpmenu); setJMenuBar(mb); PlatformSpecific.getPlatformSpecific().registerParent(this); PlatformSpecific.getPlatformSpecific().setupPlatform(); setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); ng.setDoubleBuffered(true); this.setBackground(new Color(0.9f, 0.9f, 0.9f)); setContentPane(ng); ng.setNotation(Notation.NOTATION_SITESWAP); Locale loc = JLLocale.getLocale(); this.applyComponentOrientation(ComponentOrientation.getOrientation(loc)); notationmenu.getItem(Notation.NOTATION_SITESWAP-1).setSelected(true); pack(); setResizable(false); setVisible(true); addWindowListener(this); } protected static final String[] fileItems = new String[] { "Open JML...", "Convert JML...", null, "Quit" }; protected static final String[] fileCommands = new String[] { "open", "convert", null, "exit" }; protected static final char[] fileShortcuts = { 'O', ' ', ' ', 'Q' }; protected JMenu createFileMenu() { JMenu filemenu = new JMenu(guistrings.getString("File")); for (int i = 0; i < (macos ? fileItems.length-2 : fileItems.length); i++) { if (fileItems[i] == null) filemenu.addSeparator(); else { JMenuItem fileitem = new JMenuItem(guistrings.getString(fileItems[i].replace(' ', '_'))); if (fileShortcuts[i] != ' ') fileitem.setAccelerator(KeyStroke.getKeyStroke(fileShortcuts[i], Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); fileitem.setActionCommand(fileCommands[i]); fileitem.addActionListener(this); filemenu.add(fileitem); } } return filemenu; } public void actionPerformed(ActionEvent ae) { String command = ae.getActionCommand(); try { if (command.equals("open")) doMenuCommand(FILE_OPEN); /*else if (command.equals("newpat")) doFileMenuCommand(FILE_NEWPAT); else if (command.equals("newlist")) doFileMenuCommand(FILE_NEWLIST); else if (command.equals("juggleanim")) doMenuCommand(FILE_CONVERT);*/ else if (command.equals("convert")) doMenuCommand(FILE_CONVERT); else if (command.equals("exit")) doMenuCommand(FILE_EXIT); } catch (Exception e) { ErrorDialog.handleException(e); } } public static final int FILE_NONE = 0; // public static final int FILE_NEWPAT = 1; // public static final int FILE_NEWLIST = 2; public static final int FILE_OPEN = 3; // public static final int FILE_JUGGLEANIM = 4; public static final int FILE_CONVERT = 5; public static final int FILE_EXIT = 6; public void doMenuCommand(int action) throws JuggleExceptionInternal { switch (action) { case FILE_NONE: break; /* case FILE_NEWPAT: { PatternWindow jaw2 = null; try { siteswapNotation sn = new siteswapNotation(); JMLPattern pat = sn.getJMLPattern("pattern=5"); jaw2 = new PatternWindow(pat.getTitle(), pat, new AnimatorPrefs()); } catch (JuggleExceptionUser je) { if (jaw2 != null) jaw2.dispose(); new ErrorDialog(this, je.getMessage()); } catch (JuggleException je) { if (jaw2 != null) jaw2.dispose(); throw new JuggleExceptionInternal(je.getMessage()); } } break; case FILE_NEWLIST: new PatternListWindow(guistrings.getString("Pattern_List")); break; */ case FILE_OPEN: { javax.swing.filechooser.FileFilter filter = new javax.swing.filechooser.FileFilter() { public boolean accept(File f) { StringTokenizer st = new StringTokenizer(f.getName(), "."); String ext = ""; while (st.hasMoreTokens()) ext = st.nextToken(); return (ext.equals("jml") || f.isDirectory()); } public String getDescription() { return "JML Files"; } }; try { if (PlatformSpecific.getPlatformSpecific().showOpenDialog(this, filter) == JFileChooser.APPROVE_OPTION) { if (PlatformSpecific.getPlatformSpecific().getSelectedFile() != null) showJMLWindow(PlatformSpecific.getPlatformSpecific().getSelectedFile()); } } catch (JuggleExceptionUser je) { new ErrorDialog(this, je.getMessage()); } break; } /* case FILE_JUGGLEANIM: { PatternListWindow pw = null; try { try { int option = PlatformSpecific.getPlatformSpecific().showOpenDialog(this); if (option == JFileChooser.APPROVE_OPTION) { if (PlatformSpecific.getPlatformSpecific().getSelectedFile() != null) { pw = new PatternListWindow(guistrings.getString("Patterns")); readJuggleAnimPatternfile(pw, new FileReader(PlatformSpecific.getPlatformSpecific().getSelectedFile())); } } } catch (FileNotFoundException fnfe) { throw new JuggleExceptionUser(errorstrings.getString("Error_file_not_found")+ ": "+fnfe.getMessage()); } catch (IOException ioe) { throw new JuggleExceptionUser(errorstrings.getString("Error_IO")+": "+ioe.getMessage()); } } catch (JuggleExceptionUser jeu) { if (pw != null) pw.dispose(); new ErrorDialog(this, jeu.getMessage()); } catch (JuggleExceptionInternal jei) { if (pw != null) pw.dispose(); ErrorDialog.handleException(jei); } break; } */ case FILE_CONVERT: { javax.swing.filechooser.FileFilter filter = new javax.swing.filechooser.FileFilter() { public boolean accept(File f) { StringTokenizer st = new StringTokenizer(f.getName(), "."); String ext = ""; while (st.hasMoreTokens()) ext = st.nextToken(); return (ext.equals("jml") || f.isDirectory()); } public String getDescription() { return "JML Files"; } }; try { if (PlatformSpecific.getPlatformSpecific().showOpenDialog(this, filter) == JFileChooser.APPROVE_OPTION) { if (PlatformSpecific.getPlatformSpecific().getSelectedFile() != null) convertJML(PlatformSpecific.getPlatformSpecific().getSelectedFile()); } } catch (JuggleExceptionUser je) { new ErrorDialog(this, je.getMessage()); } break; } case FILE_EXIT: System.exit(0); break; } } public void showJMLWindow(File jmlf) throws JuggleExceptionUser, JuggleExceptionInternal { JFrame frame = null; PatternListWindow pw = null; try { try { JMLParser parser = new JMLParser(); parser.parse(new FileReader(jmlf)); switch (parser.getFileType()) { case JMLParser.JML_PATTERN: { JMLNode root = parser.getTree(); JMLPattern pat = new JMLPattern(root); frame = new PatternWindow(pat.getTitle(), pat, new AnimatorPrefs()); break; } case JMLParser.JML_LIST: { JMLNode root = parser.getTree(); pw = new PatternListWindow(root); PatternList pl = pw.getPatternList(); break; } default: { throw new JuggleExceptionUser(errorstrings.getString("Error_invalid_JML")); } } } catch (FileNotFoundException fnfe) { throw new JuggleExceptionUser(errorstrings.getString("Error_file_not_found")+": "+fnfe.getMessage()); } catch (IOException ioe) { throw new JuggleExceptionUser(errorstrings.getString("Error_IO")+": "+ioe.getMessage()); } catch (SAXParseException spe) { String template = errorstrings.getString("Error_parsing"); Object[] arguments = { new Integer(spe.getLineNumber()) }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } catch (SAXException se) { throw new JuggleExceptionUser(se.getMessage()); } } catch (JuggleExceptionUser jeu) { if (frame != null) frame.dispose(); if (pw != null) pw.dispose(); throw jeu; } catch (JuggleExceptionInternal jei) { if (frame != null) frame.dispose(); if (pw != null) pw.dispose(); throw jei; } } public void convertJML(File jmlf) throws JuggleExceptionUser { String in = null, out = null; try { int len = (int)jmlf.length(); FileReader fr = new FileReader(jmlf); char[] ch = new char[len]; fr.read(ch, 0, len); in = new String(ch); } catch (IOException ioe) { String template = errorstrings.getString("Error_reading_file"); Object[] arguments = { jmlf.getName() }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } // check to see if input file is already JML version 1.2 // check if we should be loading as JML version 1.0 (switch y and z coordinates in events) boolean switchyz = false; Matcher m = Pattern.compile("]*version[\\s]*=[\\s]*['\"]([^'\"]*)['\"]").matcher(in); if (m.find()) { if (m.group(1).equals("1.0")) switchyz = true; else if (m.group(1).equals("1.2")) throw new JuggleExceptionUser(errorstrings.getString("Error_already_12")); } else if (JMLDefs.default_JML_on_load.equals("1.0")) switchyz = true; // ---> m = Pattern.compile("]*>").matcher(in); out = m.replaceAll(""); // (...1) ---> XMLc(...1) StringBuffer sb = new StringBuffer(); m = Pattern.compile("(.*?)").matcher(out); while (m.find()) { String g = "" + JMLNode.xmlescape(m.group(1)).trim() + ""; m.appendReplacement(sb, g); } m.appendTail(sb); out = sb.toString(); // display="(...1)" ---> display="XMLc(...1)" sb = new StringBuffer(); m = Pattern.compile("display[\\s]*=[\\s]*\"([^\"]*)\"").matcher(out); while (m.find()) { String g = "display=\"" + JMLNode.xmlescape(m.group(1)).trim() + "\""; m.appendReplacement(sb, g); } m.appendTail(sb); out = sb.toString(); // animprefs="(...1)" ---> animprefs="XMLc(...1)" sb = new StringBuffer(); m = Pattern.compile("animprefs[\\s]*=[\\s]*\"([^\"]*)\"").matcher(out); while (m.find()) { String g = "animprefs=\"" + JMLNode.xmlescape(m.group(1)).trim() + "\""; m.appendReplacement(sb, g); } m.appendTail(sb); out = sb.toString(); // ---> (...2) sb = new StringBuffer(); m = Pattern.compile("(]*notation[\\s]*=[\\s]*\"jml\"[^>]*?)[\\s]+pattern[\\s]*=[\\s]*['\"]([^']*)['\"]([^>]*)/>").matcher(out); while (m.find()) { String g = m.group(1) + m.group(3) + ">" + m.group(2) + ""; m.appendReplacement(sb, g); } m.appendTail(sb); out = sb.toString(); // ---> (...2) sb = new StringBuffer(); m = Pattern.compile("(]*?)[\\s]+pattern[\\s]*=[\\s]*['\"]([^']*)['\"]([^>]*notation[\\s]*=[\\s]*\"jml\"[^>]*?)[\\s]*/>").matcher(out); while (m.find()) { String g = m.group(1) + m.group(3) + ">" + m.group(2) + ""; m.appendReplacement(sb, g); } m.appendTail(sb); out = sb.toString(); // all of the JML patterns are taken care of above; any remaining lines with // 'pattern=' are in other notations // ---> XMLc(...2) sb = new StringBuffer(); m = Pattern.compile("(]*?)[\\s]+pattern[\\s]*=[\\s]*['\"]([^'\"]*)['\"]([^>]*?)[\\s]*/>").matcher(out); while (m.find()) { String g = m.group(1) + m.group(3) + ">\n" + JMLNode.xmlescape(m.group(2)).trim() + "\n"; m.appendReplacement(sb, g); } m.appendTail(sb); out = sb.toString(); if (switchyz) { // ]*)[\\s]+([yz])[\\s]*=[\\s]*\"([^\"]*)\"([^>]*)[\\s]+([yz])[\\s]*=[\\s]*\"([^\"]*)\"").matcher(out); while (m.find()) { String g = m.group(1) + " " + m.group(2) + "=\"" + m.group(6) + "\"" + m.group(4) + " " + m.group(5) + "=\"" + m.group(3) + "\""; m.appendReplacement(sb, g); } m.appendTail(sb); out = sb.toString(); } String outname = jmlf.getName(); m = Pattern.compile("^(.*)(\\.[^\\.]*)$").matcher(outname); if (m.find()) outname = m.group(1) + "_converted" + m.group(2); // insert before filename extension else outname = outname + "_converted"; if (Constants.DEBUG_PARSING) { System.out.println("------------------- input file: -------------------"); System.out.println(in); System.out.println("------------------- output file: -------------------"); System.out.println(out); System.out.println("output filename = " + outname); } try { File outfile = new File(jmlf.getParent(), outname); if (outfile.exists()) { String template = errorstrings.getString("Error_already_exists"); Object[] arguments = { outname }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(outfile), "UTF-8"); osw.write(out, 0, out.length()); osw.flush(); osw.close(); } catch (IOException ioe) { String template = errorstrings.getString("Error_writing_file"); Object[] arguments = { outname }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } } public NotationGUI getNotationGUI() { return ng; } public void windowOpened(WindowEvent e) { } public void windowClosing(WindowEvent e) { try { doMenuCommand(FILE_EXIT); } catch (Exception ex) { System.exit(0); } } public void windowClosed(WindowEvent e) { } public void windowIconified(WindowEvent e) { } public void windowDeiconified(WindowEvent e) { } public void windowActivated(WindowEvent e) { } public void windowDeactivated(WindowEvent e) { } } jugglinglab-0.6.2+ds.1/source/jugglinglab/core/Constants.java000077500000000000000000000025221323754603300241130ustar00rootroot00000000000000// Constants.java // // Copyright 2003 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.core; public class Constants { public static final String version = "0.6.2"; public static final String year = "2014"; public static final boolean DEBUG_LAYOUT = false; public static final boolean DEBUG_PARSING = false; public static final boolean INCLUDE_GIF_SAVE = true; public static final int ANGLE_LAYOUT_METHOD = jugglinglab.curve.Curve.lineCurve; public static final int SPLINE_LAYOUT_METHOD = jugglinglab.curve.splineCurve.rmsaccel; }jugglinglab-0.6.2+ds.1/source/jugglinglab/core/EditLadderDiagram.java000066400000000000000000002122221323754603300254220ustar00rootroot00000000000000// EditLadderDiagram.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.core; import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; import javax.swing.event.*; import javax.swing.filechooser.*; import java.io.File; import java.net.*; import java.text.MessageFormat; import jugglinglab.util.*; import jugglinglab.jml.*; import jugglinglab.path.*; import jugglinglab.prop.*; public class EditLadderDiagram extends LadderDiagram implements ActionListener { static ResourceBundle guistrings; static ResourceBundle errorstrings; static { guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } static final protected double min_throw_time = 0.05; static final protected double min_hold_time = 0.05; protected AnimatorEdit animator = null; protected JFrame parent = null; static final private int STATE_INACTIVE = 0; static final private int STATE_EVENT_SELECTED = 1; static final private int STATE_MOVING_EVENT = 2; static final private int STATE_MOVING_TRACKER = 3; static final private int STATE_POPUP = 4; protected int gui_state; // one of STATE_x values above protected LadderEventItem active_eventitem = null; protected int start_y; protected int delta_y, delta_y_min, delta_y_max; protected LadderItem popupitem = null; protected int popup_y; protected JPopupMenu popup = null; protected JMenuItem[] popupmenuitems = null; protected Vector dialog_controls = null; protected ParameterDescriptor[] dialog_pd = null; public EditLadderDiagram(JMLPattern pat, JFrame parent) { super(pat); this.parent = parent; active_eventitem = null; setupPopup(); final JMLPattern fpat = pat; this.gui_state = STATE_INACTIVE; if (pat.getNumberOfJugglers() > 1) return; this.addMouseListener(new MouseAdapter() { public void mousePressed(final MouseEvent me) { int my = me.getY(); if (my < border_top) my = border_top; else if (my > (height-border_top)) my = height - border_top; if (me.isPopupTrigger()) { gui_state = STATE_POPUP; active_eventitem = getSelectedLadderEvent(me.getX(), me.getY()); if (active_eventitem != null) popupitem = active_eventitem; else popupitem = getSelectedLadderPath(me.getX(), me.getY(), path_slop); popup_y = me.getY(); if (animator != null) { double scale = (fpat.getLoopEndTime() - fpat.getLoopStartTime()) / (double)(height - 2*border_top); double newtime = (double)(my - border_top) * scale; anim_paused = animator.getPaused(); animator.setPaused(true); animator.setTime(newtime); animator.deactivateEvent(); if (active_eventitem != null) animator.activateEvent(active_eventitem.event); animator.repaint(); } adjustPopup(popupitem); popup.show(EditLadderDiagram.this, me.getX(), me.getY()); } else { switch (gui_state) { case STATE_INACTIVE: case STATE_EVENT_SELECTED: active_eventitem = getSelectedLadderEvent(me.getX(), me.getY()); if (active_eventitem == null) { gui_state = STATE_MOVING_TRACKER; tracker_y = my; repaint(); if (animator != null) { double scale = (fpat.getLoopEndTime() - fpat.getLoopStartTime()) / (double)(height - 2*border_top); double newtime = (double)(my - border_top) * scale; anim_paused = animator.getPaused(); animator.setPaused(true); animator.setTime(newtime); animator.deactivateEvent(); animator.repaint(); } } else { gui_state = STATE_MOVING_EVENT; start_y = me.getY(); findEventLimits(active_eventitem); repaint(); if (animator != null) { animator.activateEvent(active_eventitem.event); animator.repaint(); } } break; case STATE_MOVING_EVENT: // ErrorDialog.handleException(new JuggleExceptionInternal("mouse pressed in MOVING_EVENT state")); break; case STATE_MOVING_TRACKER: // ErrorDialog.handleException(new JuggleExceptionInternal("mouse pressed in MOVING_TRACKER state")); break; case STATE_POPUP: gui_state = (active_eventitem == null) ? STATE_INACTIVE : STATE_EVENT_SELECTED; if (animator != null) animator.setPaused(anim_paused); break; } } } public void mouseReleased(final MouseEvent me) { if (me.isPopupTrigger()) { switch (gui_state) { case STATE_INACTIVE: case STATE_EVENT_SELECTED: case STATE_MOVING_EVENT: // skip this code for MOVING_TRACKER state, since already // executed in mousePressed() above if (animator != null) { int my = me.getY(); if (my < border_top) my = border_top; else if (my > (height-border_top)) my = height - border_top; double scale = (fpat.getLoopEndTime() - fpat.getLoopStartTime()) / (double)(height - 2*border_top); double newtime = (double)(my - border_top) * scale; anim_paused = animator.getPaused(); animator.setPaused(true); animator.setTime(newtime); animator.deactivateEvent(); if (active_eventitem != null) animator.activateEvent(active_eventitem.event); animator.repaint(); } case STATE_MOVING_TRACKER: gui_state = STATE_POPUP; if (delta_y != 0) { delta_y = 0; repaint(); } popup_y = me.getY(); popupitem = active_eventitem; if (popupitem == null) { popupitem = getSelectedLadderEvent(me.getX(), me.getY()); if (popupitem == null) popupitem = getSelectedLadderPath(me.getX(), me.getY(), path_slop); } adjustPopup(popupitem); popup.show(EditLadderDiagram.this, me.getX(), me.getY()); break; case STATE_POPUP: ErrorDialog.handleException(new JuggleExceptionInternal("tried to enter POPUP state while already in it")); break; } } else { switch (gui_state) { case STATE_INACTIVE: // should only get here if user cancelled popup menu or deselected event break; case STATE_EVENT_SELECTED: // should only get here if user cancelled popup menu break; case STATE_MOVING_EVENT: gui_state = STATE_EVENT_SELECTED; if (delta_y != 0) { moveEvent(active_eventitem.eventitem); for (int i = 0; i < laddereventitems.size(); i++) { LadderEventItem item = (LadderEventItem)laddereventitems.elementAt(i); if (item.eventitem == active_eventitem.eventitem) { item.ylow += delta_y; item.yhigh += delta_y; } } delta_y = 0; activeEventMoved(); /* layoutPattern(); createView(); active_eventitem = null; if (animator != null) animator.deactivateEvent(); */ repaint(); } break; case STATE_MOVING_TRACKER: gui_state = STATE_INACTIVE; if (animator != null) animator.setPaused(anim_paused); break; case STATE_POPUP: break; } } } }); this.addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged(MouseEvent me) { int my = me.getY(); if (my < border_top) my = border_top; else if (my > (height-border_top)) my = height - border_top; switch (gui_state) { case STATE_INACTIVE: // This exception was being generated on popup cancelation when it could have been ignored. // See bug report 861856. //ErrorDialog.handleException(new JuggleExceptionInternal("mouse dragged in INACTIVE state")); break; case STATE_EVENT_SELECTED: ErrorDialog.handleException(new JuggleExceptionInternal("mouse dragged in EVENT_SELECTED state")); break; case STATE_MOVING_EVENT: int old_delta_y = delta_y; delta_y = me.getY() - start_y; if (delta_y < delta_y_min) delta_y = delta_y_min; if (delta_y > delta_y_max) delta_y = delta_y_max; if (delta_y != old_delta_y) EditLadderDiagram.this.repaint(); break; case STATE_MOVING_TRACKER: tracker_y = my; EditLadderDiagram.this.repaint(); if (animator != null) { double scale = (fpat.getLoopEndTime() - fpat.getLoopStartTime()) / (double)(height - 2*border_top); double newtime = (double)(my - border_top) * scale; animator.setTime(newtime); animator.repaint(); } break; case STATE_POPUP: break; } } }); } protected void findEventLimits(LadderEventItem item) { double tmin = pat.getLoopStartTime(); double tmax = pat.getLoopEndTime(); double scale = (pat.getLoopEndTime() - pat.getLoopStartTime()) / (double)(height - 2*border_top); for (int j = 0; j < item.event.getNumberOfTransitions(); j++) { JMLTransition tr = item.event.getTransition(j); switch (tr.getType()) { case JMLTransition.TRANS_THROW: { // Find out when the ball being thrown was last caught JMLEvent ev = item.event.getPrevious(); while (ev != null) { if ((ev.getPathTransition(tr.getPath(), JMLTransition.TRANS_CATCH) != null) || (ev.getPathTransition(tr.getPath(), JMLTransition.TRANS_SOFTCATCH) != null)) break; ev = ev.getPrevious(); } if (ev == null) ErrorDialog.handleException(new JuggleExceptionInternal("Null event 1 in mousePressed()")); double tlim = ev.getT() + min_hold_time; if (tlim > tmin) tmin = tlim; // next catch is easy to find ev = tr.getOutgoingPathLink().getEndEvent(); if (!sameMaster(ev, item.event)) { tlim = ev.getT() - min_throw_time; if (tlim < tmax) tmax = tlim; } } break; case JMLTransition.TRANS_CATCH: case JMLTransition.TRANS_SOFTCATCH: { // previous throw is easy to find JMLEvent ev = tr.getIncomingPathLink().getStartEvent(); if (!sameMaster(ev, item.event)) { double tlim = ev.getT() + min_throw_time; if (tlim > tmin) tmin = tlim; } // Find out when the ball being caught is next thrown ev = item.event.getNext(); while (ev != null) { if (ev.getPathTransition(tr.getPath(), JMLTransition.TRANS_THROW) != null) break; ev = ev.getNext(); } if (ev == null) ErrorDialog.handleException(new JuggleExceptionInternal("Null event 2 in mousePressed()")); double tlim = ev.getT() - min_hold_time; if (tlim < tmax) tmax = tlim; } break; } } delta_y_min = (int)((tmin - item.event.getT()) / scale); delta_y_max = (int)((tmax - item.event.getT()) / scale); } private boolean sameMaster(JMLEvent ev1, JMLEvent ev2) { JMLEvent ev1m = ev1.isMaster() ? ev1 : ev1.getMaster(); JMLEvent ev2m = ev2.isMaster() ? ev2 : ev2.getMaster(); return (ev1m == ev2m); } protected void moveEvent(LadderEventItem item) { JMLEvent ev = item.event; double scale = (pat.getLoopEndTime() - pat.getLoopStartTime()) / (double)(height - 2*border_top); double shift = delta_y * scale; double newt = ev.getT() + shift; if (newt < pat.getLoopStartTime()) { shift = pat.getLoopStartTime() - ev.getT(); newt = pat.getLoopStartTime(); } else if (newt >= pat.getLoopEndTime()) { shift = pat.getLoopEndTime() - 0.0001 - ev.getT(); newt = pat.getLoopEndTime() - 0.0001; } boolean throwpath[] = new boolean[pat.getNumberOfPaths()]; boolean catchpath[] = new boolean[pat.getNumberOfPaths()]; boolean holdpathorig[] = new boolean[pat.getNumberOfPaths()]; boolean holdpathnew[] = new boolean[pat.getNumberOfPaths()]; for (int j = 0; j < ev.getNumberOfTransitions(); j++) { JMLTransition tr = ev.getTransition(j); switch (tr.getType()) { case JMLTransition.TRANS_THROW: throwpath[tr.getPath()-1] = true; break; case JMLTransition.TRANS_CATCH: case JMLTransition.TRANS_SOFTCATCH: catchpath[tr.getPath()-1] = true; break; case JMLTransition.TRANS_HOLDING: holdpathnew[tr.getPath()-1] = holdpathorig[tr.getPath()-1] = true; break; } } if (delta_y < 0) { // moving to earlier time ev = ev.getPrevious(); while ((ev != null) && (ev.getT() > newt)) { if (!sameMaster(ev, item.event) && (ev.getJuggler() == item.event.getJuggler()) && (ev.getHand() == item.event.getHand())) { for (int j = 0; j < ev.getNumberOfTransitions(); j++) { JMLTransition tr = ev.getTransition(j); switch (tr.getType()) { case JMLTransition.TRANS_THROW: holdpathnew[tr.getPath()-1] = true; break; case JMLTransition.TRANS_CATCH: case JMLTransition.TRANS_SOFTCATCH: holdpathnew[tr.getPath()-1] = false; break; case JMLTransition.TRANS_HOLDING: if (throwpath[tr.getPath()-1]) { ev.removeTransition(j); if (!ev.isMaster()) ev.getMaster().removeTransition(j); j--; // next trans moved into slot } break; } } for (int j = 0; j < pat.getNumberOfPaths(); j++) { if (catchpath[j]) { JMLTransition tr = new JMLTransition(JMLTransition.TRANS_HOLDING, (j+1), null, null); ev.addTransition(tr); if (!ev.isMaster()) { Permutation pp = ev.getPathPermFromMaster().getInverse(); tr = new JMLTransition(JMLTransition.TRANS_HOLDING, pp.getMapping(j+1), null, null); ev.getMaster().addTransition(tr); } } } } ev = ev.getPrevious(); } } else if (delta_y > 0) { // moving to later time ev = ev.getNext(); while ((ev != null) && (ev.getT() < newt)) { if (!sameMaster(ev, item.event) && (ev.getJuggler() == item.event.getJuggler()) && (ev.getHand() == item.event.getHand())) { for (int j = 0; j < ev.getNumberOfTransitions(); j++) { JMLTransition tr = ev.getTransition(j); switch (tr.getType()) { case JMLTransition.TRANS_THROW: holdpathnew[tr.getPath()-1] = false; break; case JMLTransition.TRANS_CATCH: case JMLTransition.TRANS_SOFTCATCH: holdpathnew[tr.getPath()-1] = true; break; case JMLTransition.TRANS_HOLDING: if (catchpath[tr.getPath()-1]) { ev.removeTransition(j); if (!ev.isMaster()) ev.getMaster().removeTransition(j); j--; } break; } } for (int j = 0; j < pat.getNumberOfPaths(); j++) { if (throwpath[j]) { JMLTransition tr = new JMLTransition(JMLTransition.TRANS_HOLDING, (j+1), null, null); ev.addTransition(tr); if (!ev.isMaster()) { Permutation pp = ev.getPathPermFromMaster().getInverse(); tr = new JMLTransition(JMLTransition.TRANS_HOLDING, pp.getMapping(j+1), null, null); ev.getMaster().addTransition(tr); } } } } ev = ev.getNext(); } } ev = item.event; Permutation pp = ev.getPathPermFromMaster().getInverse(); if (!ev.isMaster()) ev = ev.getMaster(); for (int j = 0; j < pat.getNumberOfPaths(); j++) { if (holdpathnew[j] != holdpathorig[j]) { if (holdpathnew[j]) { JMLTransition tr = new JMLTransition(JMLTransition.TRANS_HOLDING, pp.getMapping(j+1), null, null); ev.addTransition(tr); } else { JMLTransition tr = ev.getPathTransition(pp.getMapping(j+1), JMLTransition.TRANS_HOLDING); if (tr == null) ErrorDialog.handleException(new JuggleExceptionInternal("Null transition in removing hold")); ev.removeTransition(tr); } } } pat.removeEvent(ev); ev.setT(ev.getT() + shift); // change time of master pat.addEvent(ev); // remove/add cycle keeps events sorted } private static String popupItems[] = { "Change title...", "Change overall timing...", "Add event to L hand", "Add event to R hand", null, "Remove event", null, "Define prop...", "Make last in event", "Define throw...", "Change to catch", "Change to softcatch" }; protected void setupPopup() { popup = new JPopupMenu(); popupmenuitems = new JMenuItem[popupItems.length]; JMenuItem item; for (int i = 0; i < popupItems.length; i++) { String name = popupItems[i]; if (name != null) { item = new JMenuItem(guistrings.getString(name.replace(' ', '_'))); item.addActionListener(this); popup.add(item); popupmenuitems[i] = item; } else popup.addSeparator(); } popup.setBorder(new BevelBorder(BevelBorder.RAISED)); popup.addPopupMenuListener(new PopupMenuListener() { public void popupMenuCanceled(PopupMenuEvent e) {} public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { // System.out.println("popup becoming invisible"); if (gui_state == STATE_POPUP) { gui_state = (active_eventitem == null) ? STATE_INACTIVE : STATE_EVENT_SELECTED; if (animator != null) animator.setPaused(anim_paused); } } public void popupMenuWillBecomeVisible(PopupMenuEvent e) {} }); } protected void adjustPopup(LadderItem item) { for (int i = 0; i < popupmenuitems.length; i++) { if (popupmenuitems[i] != null) popupmenuitems[i].setEnabled(true); } if (item == null) { for (int i = 5; i < popupmenuitems.length; i++) if (popupmenuitems[i] != null) popupmenuitems[i].setEnabled(false); return; } switch (item.type) { case LadderEventItem.TYPE_EVENT: { LadderEventItem evitem = (LadderEventItem)item; for (int i = 0; i < 4; i++) if (popupmenuitems[i] != null) popupmenuitems[i].setEnabled(false); for (int i = 7; i < popupmenuitems.length; i++) if (popupmenuitems[i] != null) popupmenuitems[i].setEnabled(false); for (int i = 0; i < evitem.event.getNumberOfTransitions(); i++) { JMLTransition tr = evitem.event.getTransition(i); if (tr.getType() != JMLTransition.TRANS_HOLDING) { popupmenuitems[5].setEnabled(false); break; } } // check to make sure we're not allowing the user to delete // an event if it's the last one in that hand. // do this by finding the next event in the same hand; if it // has the same master, it's the only one if (popupmenuitems[5].isEnabled()) { int hand = evitem.event.getHand(); int juggler = evitem.event.getJuggler(); JMLEvent evm1 = evitem.event.isMaster() ? evitem.event : evitem.event.getMaster(); JMLEvent ev = evitem.event.getNext(); while (ev != null) { if ((ev.getHand() == hand) && (ev.getJuggler() == juggler)) { JMLEvent evm2 = ev.isMaster() ? ev : ev.getMaster(); if (evm1 == evm2) popupmenuitems[5].setEnabled(false); break; } ev = ev.getNext(); } } } break; case LadderEventItem.TYPE_TRANSITION: { LadderEventItem evitem = (LadderEventItem)item; JMLTransition tr = evitem.event.getTransition(evitem.transnum); for (int i = 0; i < 6; i++) if (popupmenuitems[i] != null) popupmenuitems[i].setEnabled(false); if (evitem.transnum == (evitem.event.getNumberOfTransitions()-1)) popupmenuitems[8].setEnabled(false); if (tr.getType() != JMLTransition.TRANS_THROW) popupmenuitems[9].setEnabled(false); if (tr.getType() != JMLTransition.TRANS_SOFTCATCH) popupmenuitems[10].setEnabled(false); if (tr.getType() != JMLTransition.TRANS_CATCH) popupmenuitems[11].setEnabled(false); } break; default: // LadderPathItem popupmenuitems[5].setEnabled(false); for (int i = 8; i < popupmenuitems.length; i++) if (popupmenuitems[i] != null) popupmenuitems[i].setEnabled(false); break; } } public void actionPerformed(ActionEvent event) { String name = event.getActionCommand(); if (name == null) return; int itemnum = 0; for (int i = 0; i < popupItems.length; i++) { if (popupItems[i] != null && name.equals(guistrings.getString(popupItems[i].replace(' ', '_')))) { itemnum = i; break; } } switch (itemnum) { case 0: // Change title... changeTitle(); break; case 1: // Change overall timing... changeTiming(); break; case 2: // Add event to L hand { JMLEvent ev = addEventToHand(HandLink.LEFT_HAND); active_eventitem = null; if (animator != null) animator.deactivateEvent(); layoutPattern(); createView(); repaint(); } break; case 3: // Add event to R hand { JMLEvent ev = addEventToHand(HandLink.RIGHT_HAND); active_eventitem = null; if (animator != null) animator.deactivateEvent(); layoutPattern(); createView(); repaint(); } break; case 4: break; case 5: // Remove event { // adjustPopup() ensures that the event only has hold transitions if (!(popupitem instanceof LadderEventItem)) { ErrorDialog.handleException(new JuggleExceptionInternal("LadderDiagram remove event class format")); return; } JMLEvent ev = ((LadderEventItem)popupitem).event; if (!ev.isMaster()) ev = ev.getMaster(); pat.removeEvent(ev); active_eventitem = null; if (animator != null) animator.deactivateEvent(); layoutPattern(); createView(); repaint(); } break; case 6: break; case 7: // Define prop... defineProp(); break; case 8: // Make last in event { if (popupitem == null) { ErrorDialog.handleException(new JuggleExceptionInternal("No popupitem in case 8")); return; } if (!(popupitem instanceof LadderEventItem)) { ErrorDialog.handleException(new JuggleExceptionInternal("LadderDiagram make last transition class format")); return; } JMLEvent ev = ((LadderEventItem)popupitem).event; if (!ev.isMaster()) ev = ev.getMaster(); JMLTransition tr = ev.getTransition(((LadderEventItem)popupitem).transnum); ev.removeTransition(tr); ev.addTransition(tr); // will add at end active_eventitem = null; if (animator != null) animator.deactivateEvent(); layoutPattern(); createView(); repaint(); } break; case 9: // Define throw... defineThrow(); break; case 10: // Change to catch { if (popupitem == null) { ErrorDialog.handleException(new JuggleExceptionInternal("No popupitem in case 10")); return; } if (!(popupitem instanceof LadderEventItem)) { ErrorDialog.handleException(new JuggleExceptionInternal("LadderDiagram change to catch class format")); return; } JMLEvent ev = ((LadderEventItem)popupitem).event; if (!ev.isMaster()) ev = ev.getMaster(); int transnum = ((LadderEventItem)popupitem).transnum; JMLTransition tr = ev.getTransition(((LadderEventItem)popupitem).transnum); tr.setType(JMLTransition.TRANS_CATCH); active_eventitem = null; if (animator != null) animator.deactivateEvent(); layoutPattern(); createView(); repaint(); } break; case 11: // Change to softcatch { if (popupitem == null) { ErrorDialog.handleException(new JuggleExceptionInternal("No popupitem in case 11")); return; } if (!(popupitem instanceof LadderEventItem)) { ErrorDialog.handleException(new JuggleExceptionInternal("LadderDiagram change to softcatch class format")); return; } JMLEvent ev = ((LadderEventItem)popupitem).event; if (!ev.isMaster()) ev = ev.getMaster(); int transnum = ((LadderEventItem)popupitem).transnum; JMLTransition tr = ev.getTransition(((LadderEventItem)popupitem).transnum); tr.setType(JMLTransition.TRANS_SOFTCATCH); active_eventitem = null; if (animator != null) animator.deactivateEvent(); layoutPattern(); createView(); repaint(); } break; } popupitem = null; // System.out.println("action performed"); if (gui_state == STATE_POPUP) { gui_state = (active_eventitem == null) ? STATE_INACTIVE : STATE_EVENT_SELECTED; if (animator != null) animator.setPaused(anim_paused); } } protected void changeTitle() { final JDialog jd = new JDialog(parent, guistrings.getString("Change_title"), true); GridBagLayout gb = new GridBagLayout(); jd.getContentPane().setLayout(gb); final JTextField tf = new JTextField(20); tf.setText(pat.getTitle()); JButton okbutton = new JButton(guistrings.getString("OK")); okbutton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String newtitle = tf.getText(); pat.setTitle(newtitle); jd.dispose(); } }); jd.getContentPane().add(tf); gb.setConstraints(tf, make_constraints(GridBagConstraints.LINE_START,0,0, new Insets(10,10,0,10))); jd.getContentPane().add(okbutton); gb.setConstraints(okbutton, make_constraints(GridBagConstraints.LINE_END,0,1, new Insets(10,10,10,10))); jd.getRootPane().setDefaultButton(okbutton);// OK button is default jd.pack(); jd.setResizable(false); jd.setVisible(true); parent.setTitle(pat.getTitle()); } protected void changeTiming() { final JDialog jd = new JDialog(parent, guistrings.getString("Change_timing"), true); GridBagLayout gb = new GridBagLayout(); jd.getContentPane().setLayout(gb); JPanel p1 = new JPanel(); p1.setLayout(gb); JLabel lab = new JLabel(guistrings.getString("Rescale_percentage")); p1.add(lab); gb.setConstraints(lab, make_constraints(GridBagConstraints.LINE_END,0,0, new Insets(0,0,0,0))); final JTextField tf = new JTextField(7); p1.add(tf); gb.setConstraints(tf, make_constraints(GridBagConstraints.LINE_START,1,0, new Insets(0,5,0,0))); JButton okbutton = new JButton(guistrings.getString("OK")); okbutton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { jd.dispose(); } }); jd.getContentPane().add(p1); gb.setConstraints(p1, make_constraints(GridBagConstraints.LINE_START,0,0, new Insets(10,10,0,10))); jd.getContentPane().add(okbutton); gb.setConstraints(okbutton, make_constraints(GridBagConstraints.LINE_END,0,1, new Insets(10,10,10,10))); jd.getRootPane().setDefaultButton(okbutton);// OK button is default jd.pack(); jd.setVisible(true); double scale; try { scale = Double.valueOf(tf.getText()).doubleValue() / 100.0; } catch (NumberFormatException e) { new ErrorDialog(this, "Number format error in rescale percentage"); return; } if (scale > 0.0) { JMLEvent ev = pat.getEventList(); while (ev != null) { if (ev.isMaster()) ev.setT(ev.getT() * scale); ev = ev.getNext(); } JMLPosition pos = pat.getPositionList(); while (pos != null) { pos.setT(pos.getT() * scale); pos = pos.getNext(); } for (int i = 0; i < pat.getNumberOfSymmetries(); i++) { JMLSymmetry sym = pat.getSymmetry(i); double delay = sym.getDelay(); if (delay > 0.0) { sym.setDelay(delay * scale); if ((delay * scale) < animator.getTime()) { animator.setTime(0.0); } } } layoutPattern(); createView(); } } protected JMLEvent addEventToHand(int hand) { int juggler = 1; // assumes single juggler double scale = (pat.getLoopEndTime() - pat.getLoopStartTime()) / (double)(height - 2*border_top); double evtime = (double)(popup_y - border_top) * scale; Coordinate evpos = new Coordinate(); try { pat.getHandCoordinate(juggler, hand, evtime, evpos); } catch (JuggleExceptionInternal jei) { ErrorDialog.handleException(jei); } JMLEvent ev = new JMLEvent(); ev.setLocalCoordinate(pat.convertGlobalToLocal(evpos, juggler, evtime)); ev.setT(evtime); ev.setHand(juggler, hand); pat.addEvent(ev); for (int i = 0; i < pat.getNumberOfPaths(); i++) { boolean holding = false; JMLEvent evt = ev.getPrevious(); while (evt != null) { JMLTransition tr = evt.getPathTransition(i+1, JMLTransition.TRANS_ANY); if (tr != null) { if ((evt.getJuggler() != ev.getJuggler()) || (evt.getHand() != ev.getHand())) { holding = false; break; } if (tr.getType() == JMLTransition.TRANS_THROW) { holding = false; break; } holding = true; break; } evt = evt.getPrevious(); } if (holding) { JMLTransition tr = new JMLTransition(JMLTransition.TRANS_HOLDING, (i+1), null, null); ev.addTransition(tr); } } return ev; } protected void defineProp() { if (popupitem == null) { ErrorDialog.handleException(new JuggleExceptionInternal("defineProp() null popupitem")); return; } // figure out which path number the user selected int pn = 0; if (popupitem instanceof LadderEventItem) { if (popupitem.type != LadderItem.TYPE_TRANSITION) { ErrorDialog.handleException(new JuggleExceptionInternal("defineProp() bad LadderItem type")); return; } JMLEvent ev = ((LadderEventItem)popupitem).event; int transnum = ((LadderEventItem)popupitem).transnum; JMLTransition tr = ev.getTransition(transnum); pn = tr.getPath(); } else { pn = ((LadderPathItem)popupitem).pathnum; } final int pathnum = pn; final int[] animpropnum = animator.getAnimPropNum(); final int propnum = animpropnum[pathnum - 1]; //final int propnum = pat.getPropAssignment(pathnum); // System.out.println("pathnum = " + pathnum + ", propnum = " + propnum); final Prop startprop = pat.getProp(propnum); final boolean paused = animator.getPaused(); animator.setPaused(true); String[] prtypes = Prop.builtinProps; final JDialog jd = new JDialog(parent, guistrings.getString("Define_prop"), true); GridBagLayout gb = new GridBagLayout(); jd.getContentPane().setLayout(gb); JPanel p1 = new JPanel(); p1.setLayout(gb); JLabel lab = new JLabel(guistrings.getString("Prop_type")); p1.add(lab); gb.setConstraints(lab, make_constraints(GridBagConstraints.LINE_END,0,0, new Insets(0,0,0,0))); final JPanel p2 = new JPanel(); p2.setLayout(gb); final JComboBox cb1 = new JComboBox(prtypes); p1.add(cb1); gb.setConstraints(cb1, make_constraints(GridBagConstraints.LINE_START,1,0, new Insets(0,10,0,0))); cb1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { String type = (String)cb1.getItemAt(cb1.getSelectedIndex()); // System.out.println("Got an action item: "+type); try { Prop pt; if (type.equalsIgnoreCase(startprop.getName())) pt = startprop; else pt = Prop.getProp(type); makeParametersPanel(p2, pt.getParameterDescriptors()); } catch (JuggleExceptionUser jeu) { new ErrorDialog(jd, jeu.getMessage()); return; } jd.pack(); } }); String[] bp = Prop.builtinProps; for (int i = 0; i < bp.length; i++) { if (bp[i].equalsIgnoreCase(startprop.getName())) { cb1.setSelectedIndex(i); break; } } final JPanel p3 = new JPanel(); p3.setLayout(gb); JButton cancelbutton = new JButton(guistrings.getString("Cancel")); p3.add(cancelbutton); gb.setConstraints(cancelbutton, make_constraints(GridBagConstraints.LINE_END,0,0,new Insets(0,0,0,0))); cancelbutton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { jd.dispose(); animator.setPaused(paused); } }); JButton okbutton = new JButton(guistrings.getString("OK")); p3.add(okbutton); gb.setConstraints(okbutton, make_constraints(GridBagConstraints.LINE_END,1,0,new Insets(0,10,0,0))); okbutton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String type = (String)cb1.getItemAt(cb1.getSelectedIndex()); String mod = null; try { mod = getParameterList(); } catch (JuggleExceptionUser jeu) { new ErrorDialog(parent, jeu.getMessage()); return; } // System.out.println("type = "+type+", mod = "+mod); // Sync paths with current prop list for (int i = 0; i < pat.getNumberOfPaths(); i++) { pat.setPropAssignment(i+1, animpropnum[i]); } // check to see if any other paths are using this prop definition boolean killprop = true; for (int i = 0; i < pat.getNumberOfPaths(); i++) { if (i != pathnum - 1) { if (animpropnum[i] == propnum) { killprop = false; break; } } } if (killprop) { pat.removeProp(propnum); } // check to see if a prop like this one has already been defined boolean gotmatch = false; int matchingprop = 0; for (int i = 1; i <= pat.getNumberOfProps(); i++) { PropDef pdef = pat.getPropDef(i); if (type.equalsIgnoreCase(pdef.getType())) { if (((mod == null) && (pdef.getMod() == null)) || ((mod != null) && mod.equalsIgnoreCase(pdef.getMod()))) { gotmatch = true; matchingprop = i; break; } } } if (gotmatch) { // new prop is identical to pre-existing one pat.setPropAssignment(pathnum, matchingprop); } else { // new prop is different PropDef newprop = new PropDef(type.toLowerCase(), mod); pat.addProp(newprop); pat.setPropAssignment(pathnum, pat.getNumberOfProps()); } layoutPattern(); jd.dispose(); animator.setPaused(paused); } }); jd.getContentPane().add(p1); gb.setConstraints(p1, make_constraints(GridBagConstraints.LINE_START,0,0,new Insets(10,10,0,10))); jd.getContentPane().add(p2); gb.setConstraints(p2, make_constraints(GridBagConstraints.LINE_START,0,1,new Insets(0,0,0,0))); jd.getContentPane().add(p3); gb.setConstraints(p3, make_constraints(GridBagConstraints.LINE_END,0,2,new Insets(10,10,10,10))); jd.getRootPane().setDefaultButton(okbutton);// OK button is default Locale loc = JLLocale.getLocale(); jd.applyComponentOrientation(ComponentOrientation.getOrientation(loc)); jd.pack(); jd.setResizable(false); jd.setVisible(true); // blocks until dispose() above dialog_controls = null; } protected void defineThrow() { if (!(popupitem instanceof LadderEventItem)) { ErrorDialog.handleException(new JuggleExceptionInternal("defineThrow() class format")); return; } JMLEvent ev = ((LadderEventItem)popupitem).event; if (!ev.isMaster()) ev = ev.getMaster(); final JMLTransition tr = ev.getTransition(((LadderEventItem)popupitem).transnum); String[] pptypes = Path.builtinPaths; final JDialog jd = new JDialog(parent, guistrings.getString("Define_throw"), true); GridBagLayout gb = new GridBagLayout(); jd.getContentPane().setLayout(gb); JPanel p1 = new JPanel(); p1.setLayout(gb); JLabel lab = new JLabel(guistrings.getString("Throw_type")); p1.add(lab); gb.setConstraints(lab, make_constraints(GridBagConstraints.LINE_END,0,0,new Insets(0,0,0,0))); final JPanel p2 = new JPanel(); p2.setLayout(gb); final JComboBox cb1 = new JComboBox(pptypes); p1.add(cb1); gb.setConstraints(cb1, make_constraints(GridBagConstraints.LINE_START,1,0, new Insets(0,10,0,0))); cb1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { String type = (String)cb1.getItemAt(cb1.getSelectedIndex()); // System.out.println("Got an action item: "+type); try { Path ppt; if (type.equalsIgnoreCase(tr.getThrowType())) ppt = tr.getOutgoingPathLink().getPath(); else ppt = Path.getPath(type); makeParametersPanel(p2, ppt.getParameterDescriptors()); } catch (JuggleExceptionUser jeu) { new ErrorDialog(jd, jeu.getMessage()); return; } jd.pack(); } }); String[] bpp = Path.builtinPaths; for (int i = 0; i < bpp.length; i++) { if (bpp[i].equalsIgnoreCase(tr.getThrowType())) { cb1.setSelectedIndex(i); break; } } final JPanel p3 = new JPanel(); p3.setLayout(gb); JButton cancelbutton = new JButton(guistrings.getString("Cancel")); p3.add(cancelbutton); gb.setConstraints(cancelbutton, make_constraints(GridBagConstraints.LINE_END,0,0,new Insets(0,0,0,0))); cancelbutton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { jd.dispose(); } }); JButton okbutton = new JButton(guistrings.getString("OK")); p3.add(okbutton); gb.setConstraints(okbutton, make_constraints(GridBagConstraints.LINE_END,1,0, new Insets(0,10,0,0))); okbutton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String type = (String)cb1.getItemAt(cb1.getSelectedIndex()); tr.setThrowType(type.toLowerCase()); String mod = null; try { mod = getParameterList(); } catch (JuggleExceptionUser jeu) { new ErrorDialog(parent, jeu.getMessage()); return; } tr.setMod(mod); layoutPattern(); jd.dispose(); } }); jd.getContentPane().add(p1); gb.setConstraints(p1, make_constraints(GridBagConstraints.LINE_START,0,0,new Insets(10,10,0,10))); jd.getContentPane().add(p2); gb.setConstraints(p2, make_constraints(GridBagConstraints.LINE_START,0,1,new Insets(0,0,0,0))); jd.getContentPane().add(p3); gb.setConstraints(p3, make_constraints(GridBagConstraints.LINE_END,0,2,new Insets(10,10,10,10))); jd.getRootPane().setDefaultButton(okbutton);// OK button is default jd.pack(); jd.setResizable(false); jd.setVisible(true); // blocks until dispose() above dialog_controls = null; } private static final String[] booleanList = { "True", "False" }; protected void makeParametersPanel(JPanel jp, ParameterDescriptor[] pd) { jp.removeAll(); GridBagLayout gb = new GridBagLayout(); jp.setLayout(gb); dialog_controls = new Vector(); dialog_pd = pd; if (pd.length != 0) { /* JLabel lab1 = new JLabel("Properties"); jp.add(lab1); gb.setConstraints(lab1, make_constraints(GridBagConstraints.LINE_START,0,0, new Insets(10,10,0,10))); */ JPanel pdp = new JPanel(); pdp.setLayout(gb); for (int i = 0; i < pd.length; i++) { JLabel lab = new JLabel(pd[i].name); pdp.add(lab); gb.setConstraints(lab, make_constraints(GridBagConstraints.LINE_START,0,i,new Insets(0,0,0,0))); if (pd[i].type == ParameterDescriptor.TYPE_BOOLEAN) { //JComboBox jcb = new JComboBox(booleanList); JCheckBox jcb = new JCheckBox(); pdp.add(jcb); gb.setConstraints(jcb, make_constraints(GridBagConstraints.LINE_START,1,i,new Insets(2,5,2,0))); dialog_controls.add(jcb); boolean def = ((Boolean)(pd[i].value)).booleanValue(); //jcb.setSelectedIndex(def ? 0 : 1); jcb.setSelected(def); } else if (pd[i].type == ParameterDescriptor.TYPE_FLOAT) { JTextField tf = new JTextField(7); pdp.add(tf); gb.setConstraints(tf, make_constraints(GridBagConstraints.LINE_START,1,i,new Insets(0,5,0,0))); dialog_controls.add(tf); Double def = (Double)(pd[i].value); tf.setText(def.toString()); } else if (pd[i].type == ParameterDescriptor.TYPE_CHOICE) { String[] choices = new String[pd[i].range.size()]; pd[i].range.copyInto(choices); JComboBox jcb = new JComboBox(choices); pdp.add(jcb); gb.setConstraints(jcb, make_constraints(GridBagConstraints.LINE_START,1,i,new Insets(0,5,0,0))); dialog_controls.add(jcb); String val = (String)(pd[i].value); for (int j = 0; j < choices.length; j++) { if (val.equalsIgnoreCase(choices[j])) { jcb.setSelectedIndex(j); break; } } } else if (pd[i].type == ParameterDescriptor.TYPE_INT) { JTextField tf = new JTextField(4); pdp.add(tf); gb.setConstraints(tf, make_constraints(GridBagConstraints.LINE_START,1,i,new Insets(0,5,0,0))); dialog_controls.add(tf); Integer def = (Integer)(pd[i].value); tf.setText(def.toString()); tf.addCaretListener(new CaretListener() { public void caretUpdate(CaretEvent e) { //System.out.println("Caret Update"); } }); } else if (pd[i].type == ParameterDescriptor.TYPE_ICON) { final ParameterDescriptor fpd = pd[i]; final ParameterDescriptor[] fpds = pd; final JPanel fjp = jp; URL filename = (URL)fpd.value; ImageIcon icon = new ImageIcon(filename, filename.toString()); // Scale the image down if it's too big final float MAX_HEIGHT = 100; if (icon.getIconHeight() > MAX_HEIGHT) { float scaleFactor = MAX_HEIGHT/icon.getIconHeight(); int height = (int)(scaleFactor*icon.getIconHeight()); int width = (int)(scaleFactor*icon.getIconWidth()); icon.setImage(icon.getImage().getScaledInstance(width, height, Image.SCALE_SMOOTH)); } JLabel label = new JLabel(icon); // Clicking on the icon launches a file chooser for getting a new image label.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { FileFilter filter = new FileFilter() { public boolean accept(File f) { StringTokenizer st = new StringTokenizer(f.getName(), "."); String ext = ""; while (st.hasMoreTokens()) ext = st.nextToken(); return (ext.equals("jpg") || ext.equals("gif") || ext.equals("png") || f.isDirectory()); } public String getDescription() { return "Image Files"; } }; PlatformSpecific ps = PlatformSpecific.getPlatformSpecific(); int result = ps.showOpenDialog(EditLadderDiagram.this, filter); if (result == JFileChooser.APPROVE_OPTION) { try { URL source = ps.getSelectedFile().toURI().toURL(); // We have to load the image to get the correct dimensions ImageIcon icon = new ImageIcon(source, source.toString()); // Rebuild the paramter descriptions fpds[0].value = source; //fpds[1].value = new Integer(icon.getIconWidth()); //fpds[2].value = new Integer(icon.getIconHeight()); //fpds[1].default_value = fpds[1].value; //fpds[2].default_value = fpds[2].value; // Remake the parameter panal with new default values. makeParametersPanel(fjp, fpds); ((JDialog)(fjp.getTopLevelAncestor())).pack(); } catch (MalformedURLException ex) { // This should never happen ErrorDialog.handleException(new JuggleExceptionUser(errorstrings.getString("Error_malformed_URL."))); } } } }); // Add the icon to the panel pdp.add(label); gb.setConstraints(label, make_constraints(GridBagConstraints.LINE_START,1,i,new Insets(0,5,5,0))); dialog_controls.add(label); } } jp.add(pdp); gb.setConstraints(pdp, make_constraints(GridBagConstraints.LINE_START,0,1,new Insets(10,10,0,10))); } } protected String getParameterList() throws JuggleExceptionUser { String result = null; for (int i = 0; i < dialog_pd.length; i++) { String term = null; Object control = dialog_controls.get(i); if (dialog_pd[i].type == ParameterDescriptor.TYPE_BOOLEAN) { //JComboBox jcb = (JComboBox)control; //boolean val = ((jcb.getSelectedIndex() == 0) ? true : false); JCheckBox jcb = (JCheckBox)control; boolean val = jcb.isSelected(); boolean def_val = ((Boolean)(dialog_pd[i].default_value)).booleanValue(); if (val != def_val) term = (new Boolean(val)).toString(); } else if (dialog_pd[i].type == ParameterDescriptor.TYPE_FLOAT) { JTextField tf = (JTextField)control; try { double val = Double.valueOf(tf.getText()).doubleValue(); double def_val = ((Double)(dialog_pd[i].default_value)).doubleValue(); if (val != def_val) term = tf.getText().trim(); } catch (NumberFormatException nfe) { String template = errorstrings.getString("Error_number_format"); Object[] arguments = { dialog_pd[i].name }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } } else if (dialog_pd[i].type == ParameterDescriptor.TYPE_CHOICE) { JComboBox jcb = (JComboBox)control; int ind = jcb.getSelectedIndex(); String val = (String)(dialog_pd[i].range.elementAt(ind)); String def_val = (String)(dialog_pd[i].default_value); if (!val.equalsIgnoreCase(def_val)) term = val; } else if (dialog_pd[i].type == ParameterDescriptor.TYPE_INT) { JTextField tf = (JTextField)control; try { int val = Integer.valueOf(tf.getText()).intValue(); int def_val = ((Integer)(dialog_pd[i].default_value)).intValue(); if (val != def_val) term = tf.getText().trim(); } catch (NumberFormatException nfe) { String template = errorstrings.getString("Error_number_format"); Object[] arguments = { dialog_pd[i].name }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } } else if (dialog_pd[i].type == ParameterDescriptor.TYPE_ICON) { JLabel label = (JLabel)control; ImageIcon icon = (ImageIcon)label.getIcon(); String def = ((URL)(dialog_pd[i].default_value)).toString(); if (!icon.getDescription().equals(def)) term = icon.getDescription(); // This contains the URL string } if (term != null) { term = dialog_pd[i].name + "=" + term; if (result == null) result = term; else result = result + ";" + term; } } return result; } // public void popupMenuCanceled(PopupMenuEvent e) { popupitem = null; } // public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {} // public void popupMenuWillBecomeVisible(PopupMenuEvent e) {} protected static GridBagConstraints make_constraints(int location, int gridx, int gridy, Insets ins) { GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = location; gbc.fill = GridBagConstraints.NONE; gbc.gridheight = gbc.gridwidth = 1; gbc.gridx = gridx; gbc.gridy = gridy; gbc.insets = ins; gbc.weightx = gbc.weighty = 0.0; return gbc; } public void setAnimator(AnimatorEdit anim) { this.animator = anim; } public void setTime(double time) { if (gui_state == STATE_MOVING_TRACKER) return; super.setTime(time); } public void activeEventMoved() { if ((active_eventitem == null) || (animator == null)) return; // find the screen coordinates of the event that moved int x = (active_eventitem.xlow + active_eventitem.xhigh) / 2; int y = (active_eventitem.ylow + active_eventitem.yhigh) / 2; layoutPattern(); // rebuild pattern event list createView(); // rebuild ladder diagram // reactivate the moved event with AnimatorEdit active_eventitem = getSelectedLadderEvent(x, y); animator.activateEvent(active_eventitem.event); } protected void layoutPattern() { try { pat.layoutPattern(); if (animator != null) { animator.syncToPattern(); animator.repaint(); } } catch (JuggleExceptionUser jeu) { ErrorDialog.handleException(new JuggleExceptionInternal(jeu.getMessage())); } catch (JuggleExceptionInternal jei) { ErrorDialog.handleException(jei); } } protected void paintComponent(Graphics gr) { // try to turn on antialiased rendering VersionSpecific.getVersionSpecific().setAntialias(gr); if (pat.getNumberOfJugglers() > 1) { int x, y, width; Dimension cdim = this.getSize(); int cWidth = cdim.width; int cHeight = cdim.height; FontMetrics fm = gr.getFontMetrics(); width = fm.stringWidth("Not available"); x = (cWidth > width) ? (cWidth-width)/2 : 0; y = (cHeight + fm.getHeight()) / 2; gr.setColor(Color.white); gr.fillRect(0, 0, cWidth, cHeight); gr.setColor(Color.black); gr.drawString("Not available", x, y); return; } paintBackground(gr); // Could probably get this permutation from the pattern instead of the animator. int[] animpropnum = animator.getAnimPropNum(); // draw events gr.setColor(Color.black); for (int i = 0; i < laddereventitems.size(); i++) { LadderEventItem item = (LadderEventItem)laddereventitems.elementAt(i); int yoffset = ((gui_state == STATE_MOVING_EVENT) && (active_eventitem.eventitem == item.eventitem)) ? delta_y : 0; if (item.type == item.TYPE_EVENT) gr.fillOval(item.xlow, item.ylow + yoffset, (item.xhigh-item.xlow), (item.yhigh-item.ylow)); else { // This condition could probably be applied to all event drawing. if (item.ylow + yoffset >= border_top || item.yhigh + yoffset <= height + border_top) { // Color ball representation with the prop's color. JMLTransition tr = item.event.getTransition(item.transnum); int pathnum = tr.getPath(); int propnum = animpropnum[pathnum - 1]; gr.setColor(pat.getProp(propnum).getEditorColor()); gr.fillOval(item.xlow, item.ylow + yoffset, (item.xhigh-item.xlow), (item.yhigh-item.ylow)); gr.setColor(Color.black); gr.drawOval(item.xlow, item.ylow + yoffset, (item.xhigh-item.xlow), (item.yhigh-item.ylow)); } } } // draw the box around the selected event if (active_eventitem != null) { int yoffset = (gui_state == STATE_MOVING_EVENT) ? delta_y : 0; gr.setColor(Color.green); gr.drawLine(active_eventitem.xlow-1, active_eventitem.ylow+yoffset-1, active_eventitem.xhigh+1, active_eventitem.ylow+yoffset-1); gr.drawLine(active_eventitem.xhigh+1, active_eventitem.ylow+yoffset-1, active_eventitem.xhigh+1, active_eventitem.yhigh+yoffset+1); gr.drawLine(active_eventitem.xhigh+1, active_eventitem.yhigh+yoffset+1, active_eventitem.xlow, active_eventitem.yhigh+yoffset+1); gr.drawLine(active_eventitem.xlow-1, active_eventitem.yhigh+yoffset+1, active_eventitem.xlow-1, active_eventitem.ylow+yoffset-1); } // draw the tracker line showing the time gr.setColor(Color.red); gr.drawLine(0, tracker_y, width, tracker_y); } /* private int orbits[][] = null; private Color orbitColor[] = null; public void restartView(JMLPattern pat, AnimatorPrefs jc) throws JuggleExceptionUser, JuggleExceptionInternal { if (pat != null) this.pat = pat; if (jc != null) this.jc = jc; if (pat != null) { OrbitLadderDiagram new_ladder = new OrbitLadderDiagram(pat, parent); new_ladder.setAnimator(jae); jae.setLadderDiagram(new_ladder); jae.deactivateEvent(); new_ladder.setPreferredSize(new Dimension(ladder_width, 1)); new_ladder.setMinimumSize(new Dimension(ladder_min_width, 1)); this.ladder.removeAll(); this.ladder.add(new_ladder, BorderLayout.CENTER); this.ladder.validate(); findOrbits(); // Color the paths of the ladder diagram for (int i = 0; i < orbits.length; i++) { for (int j = 0; j < orbits[i].length; j++) { new_ladder.setPathColor(orbits[i][j]+1, orbitColor[i]); } } } jae.restartJuggle(pat, jc); } private void findOrbits() { if (this.pat == null) return; int pathorb[] = new int[this.pat.getNumberOfPaths()]; int orbids[] = new int[this.pat.getNumberOfPaths()]; int orbitCount = 0; for (int i = 0; i < pathorb.length ; i++) { pathorb[i] = -1; } // Go through all the symetries and work out which path belongs // to which orbit. for (int i = 0; i < this.pat.getNumberOfSymmetries(); i++) { Permutation perm = this.pat.getSymmetry(i).getPathPerm(); for (int j = 0; j < perm.getSize(); j++) { int elem = perm.getMapping(j+1)-1; // Not zero based ! if (pathorb[elem] == -1) { if (pathorb[j] == -1) { pathorb[j] = orbitCount; orbids[orbitCount] = orbitCount; orbitCount++; } pathorb[elem] = pathorb[j]; } else { if (pathorb[j] == -1) { pathorb[j] = pathorb[elem]; } else if (pathorb[j] != pathorb[elem]) { // These were separate orbits, now should be merged orbids[pathorb[elem]] = orbids[pathorb[j]]; } } } } // Clean up to have a sequential list int oc = 0; for (int i = 0; i < orbitCount; i++) { if (orbids[i]>=oc) { int v = orbids[i]; for (int j = i; j < orbitCount; j++) if (orbids[j] == v) orbids[j] = oc; oc++; } } // Now store which orbit is made out of which paths this.orbits = new int[oc][]; for (int i = 0; i < oc; i++) { int ocp = 0; for (int j = 0; j < 2; j++) { for (int k = 0; k < pathorb.length; k++) { if (orbids[pathorb[k]] == i) { if (j == 1) this.orbits[i][ocp] = k; ocp++; } } if (j == 0) this.orbits[i] = new int[ocp]; ocp = 0; } } // Now create the colors. We will never need more colors // than orbits. We want to exclude gray colors, as that // will be used for 'deselected'. this.orbitColor = new Color[oc]; int cols[] = {255,0,0}; int phase = 0; for (int i = 0; i < oc; i++) { this.orbitColor[i] = new Color(cols[0], cols[1], cols[2]); if ((phase == 0 && cols[2] < 255) || (phase == 1 && cols[2] == 255)) { int d = cols[0]; cols[0] = cols[2]; cols[2] = cols[1]; cols[1] = d; } else if (phase == 0) { cols[1] = 255; phase++; } else if (phase == 1) { if (cols[2]>0) cols[1] = cols[2]/2; else cols[1] = cols[1]/2; cols[2] = cols[1]; phase = 0; } } */ /* System.out.println("there are " + oc + " orbits"); String blabel = ""; for (int j = 0; j < this.orbits.length; j++) { blabel += "("; for (int k = 0; k < this.orbits[j].length; k++) { blabel += (this.orbits[j][k]+1); if (k < this.orbits[j].length-1) blabel += ","; } blabel += ")"; } System.out.println("orbit decomposition : " + blabel); */ /* } */ } jugglinglab-0.6.2+ds.1/source/jugglinglab/core/JugglingLabPanel.java000077500000000000000000000053121323754603300253040ustar00rootroot00000000000000// JugglingLabPanel.java // // Copyright 2003 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.core; import java.awt.*; import java.net.*; import java.util.*; import javax.swing.*; import jugglinglab.notation.*; import jugglinglab.util.*; import jugglinglab.view.*; public class JugglingLabPanel extends JPanel { /* static ResourceBundle guistrings; static ResourceBundle errorstrings; static { guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } */ protected NotationGUI ng = null; protected View view = null; public JugglingLabPanel(JFrame parent, int entry_type, PatternList pl, int view_type) throws JuggleExceptionUser, JuggleExceptionInternal { GridBagLayout gb = new GridBagLayout(); setLayout(gb); if (view_type != View.VIEW_NONE) { view = new View(parent, new Dimension(200,300)); view.setViewMode(view_type); add(view); GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = GridBagConstraints.LINE_START; gbc.fill = GridBagConstraints.BOTH; gbc.gridwidth = gbc.gridheight = 1; gbc.gridx = 1; gbc.gridy = 0; gbc.insets = new Insets(0,0,0,0); gbc.weightx = 1.0; gbc.weighty = 1.0; gb.setConstraints(view, gbc); } if (pl != null) pl.setTargetView(view); if ((entry_type != Notation.NOTATION_NONE) || (pl != null)) { ng = new NotationGUI(parent, view, pl, true); ng.setNotation(entry_type); // select the first notation in the menu list add(ng); GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = GridBagConstraints.LINE_START; gbc.fill = GridBagConstraints.VERTICAL; gbc.gridheight = gbc.gridwidth = 1; gbc.gridx = 0; gbc.gridy = 0; gbc.insets = new Insets(0,0,0,0); gbc.weightx = 0.0; gbc.weighty = 1.0; gb.setConstraints(ng, gbc); } } public NotationGUI getNotationGUI() { return ng; } public View getView() { return view; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/core/LadderDiagram.java000066400000000000000000000415251323754603300246220ustar00rootroot00000000000000// LadderDiagram.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.core; import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; import javax.swing.event.*; import jugglinglab.util.*; import jugglinglab.jml.*; import jugglinglab.path.*; import jugglinglab.prop.*; public class LadderDiagram extends JPanel { static final protected Color background = Color.white; static final protected int border_top = 25; static final protected double border_sides = 0.15; static final protected int transition_radius = 5; static final protected double selfthrow_width = 0.25; static final protected int path_slop = 5; static final protected int cacheframes = 5; static final protected double passing_border_sides = 0.2; protected JMLPattern pat = null; protected double sim_time = 0.0; protected int width, height; protected int right_x, left_x; protected int passing_first_x, passing_offset_x; protected int tracker_y = border_top; private boolean has_switch_symmetry; private boolean has_switchdelay_symmetry; protected Vector laddereventitems = null; protected Vector ladderpathitems = null; protected Image laddercache = null; protected boolean laddercachedirty; protected int cacheframesleft; protected boolean anim_paused; public LadderDiagram(JMLPattern pat) { this.setBackground(background); this.setOpaque(false); this.pat = pat; createView(); } protected LadderEventItem getSelectedLadderEvent(int x, int y) { for (int i = 0; i < laddereventitems.size(); i++) { LadderEventItem item = (LadderEventItem)laddereventitems.elementAt(i); if ((x >= item.xlow) && (x <= item.xhigh) && (y >= item.ylow) && (y <= item.yhigh)) return item; } return null; } protected LadderPathItem getSelectedLadderPath(int x, int y, int slop) { LadderPathItem result = null; double dmin = 0.0; if ((y < (border_top - slop)) || (y > (height - border_top + slop))) return null; for (int i = 0; i < ladderpathitems.size(); i++) { LadderPathItem item = (LadderPathItem)ladderpathitems.elementAt(i); double d; if (item.type == LadderPathItem.TYPE_SELF) { if ((y < (item.ystart - slop)) || (y > (item.yend + slop))) continue; d = (x - item.xcenter)*(x - item.xcenter) + (y - item.ycenter)*(y - item.ycenter); d = Math.abs(Math.sqrt(d) - item.radius); } else { int xmin = ((item.xstart < item.xend) ? item.xstart : item.xend); int xmax = ((item.xstart < item.xend) ? item.xend : item.xstart); if ((x < (xmin - slop)) || (x > (xmax + slop))) continue; if ((y < (item.ystart - slop)) || (y > (item.yend + slop))) continue; d = (item.xend - item.xstart)*(y - item.ystart) - (x - item.xstart)*(item.yend - item.ystart); d = Math.abs(d) / Math.sqrt((item.xend - item.xstart)*(item.xend - item.xstart) + (item.yend - item.ystart)*(item.yend - item.ystart)); } if ((int)d < slop) { if ((result == null) || (d < dmin)) { result = item; dmin = d; } } } return result; } public void setPathColor(int path, Color color) { for (int i = 0; i < ladderpathitems.size(); i++) { LadderPathItem item = (LadderPathItem)ladderpathitems.elementAt(i); if (item.pathnum == path) item.color = color; } } public void setTime(double time) { if (this.sim_time == time) return; this.sim_time = time; double loop_start = pat.getLoopStartTime(); double loop_end = pat.getLoopEndTime(); tracker_y = (int)(0.5 + (double)(height-2*border_top) * (sim_time-loop_start) / (loop_end - loop_start)) + border_top; repaint(); } protected void createView() { has_switch_symmetry = has_switchdelay_symmetry = false; for (int i = 0; i < pat.getNumberOfSymmetries(); i++) { JMLSymmetry sym = pat.getSymmetry(i); switch (sym.getType()) { case JMLSymmetry.TYPE_SWITCH: has_switch_symmetry = true; break; case JMLSymmetry.TYPE_SWITCHDELAY: has_switchdelay_symmetry = true; break; } } // first create events (little circles) this.laddereventitems = new Vector(); double loop_start = pat.getLoopStartTime(); double loop_end = pat.getLoopEndTime(); JMLEvent eventlist = pat.getEventList(); JMLEvent current = eventlist; while (current.getT() < loop_start) current = current.getNext(); while (current.getT() < loop_end) { LadderEventItem item = new LadderEventItem(); item.type = LadderEventItem.TYPE_EVENT; item.eventitem = item; item.event = current; laddereventitems.add(item); for (int i = 0; i < current.getNumberOfTransitions(); i++) { LadderEventItem item2 = new LadderEventItem(); item2.type = LadderEventItem.TYPE_TRANSITION; item2.eventitem = item; item2.event = current; item2.transnum = i; laddereventitems.add(item2); } current = current.getNext(); } // create paths (lines and arcs) this.ladderpathitems = new Vector(); if (pat.getNumberOfJugglers() == 1) { current = eventlist; while (current.getT() <= loop_end) { for (int i = 0; i < current.getNumberOfTransitions(); i++) { JMLTransition tr = current.getTransition(i); PathLink opl = tr.getOutgoingPathLink(); if (opl != null) { LadderPathItem item = new LadderPathItem(); item.transnum_start = i; item.startevent = opl.getStartEvent(); item.endevent = opl.getEndEvent(); if (opl.isInHand()) item.type = LadderPathItem.TYPE_HOLD; else item.type = (item.startevent.getHand()==item.endevent.getHand()) ? LadderPathItem.TYPE_SELF : LadderPathItem.TYPE_CROSS; item.pathnum = opl.getPathNum(); item.color = Color.black; ladderpathitems.add(item); } } current = current.getNext(); } } updateView(); } protected void updateView() { Dimension dim = this.getSize(); this.width = dim.width; this.height = dim.height; this.left_x = (int)((double)width/2.0 * border_sides); this.right_x = width - left_x; if (pat.getNumberOfJugglers() > 1) { this.passing_first_x = (int)((double)width/2.0 * passing_border_sides); this.passing_offset_x = (int)((double)(width - 2 * passing_first_x) / (double)(pat.getNumberOfJugglers() - 1)); } this.laddercachedirty = true; this.laddercache = null; this.cacheframesleft = cacheframes; double loop_start = pat.getLoopStartTime(); double loop_end = pat.getLoopEndTime(); // set locations of events and transitions for (int i = 0; i < laddereventitems.size(); i++) { LadderEventItem item = (LadderEventItem)laddereventitems.elementAt(i); JMLEvent current = item.event; int event_x = (current.getHand() == HandLink.LEFT_HAND ? left_x : right_x) - transition_radius; int event_y = (int)(0.5 + (double)(height-2*border_top) * (current.getT()-loop_start) / (loop_end - loop_start)) + border_top - transition_radius; if (item.type == LadderEventItem.TYPE_EVENT) { item.xlow = event_x; item.xhigh = event_x + 2 * transition_radius; item.ylow = event_y; item.yhigh = event_y + 2 * transition_radius; } else { if (current.getHand() == HandLink.LEFT_HAND) event_x += 2 * transition_radius * (item.transnum+1); else event_x -= 2 * transition_radius * (item.transnum+1); item.xlow = event_x; item.xhigh = event_x + 2 * transition_radius; item.ylow = event_y; item.yhigh = event_y + 2 * transition_radius; } } // set locations of paths (lines and arcs) for (int i = 0; i < ladderpathitems.size(); i++) { LadderPathItem item = (LadderPathItem)ladderpathitems.elementAt(i); item.xstart = (item.startevent.getHand() == HandLink.LEFT_HAND ? (left_x + (item.transnum_start+1)*2*transition_radius) : (right_x - (item.transnum_start+1)*2*transition_radius)); item.ystart = (int)(0.5 + (double)(height-2*border_top) * (item.startevent.getT()-loop_start) / (loop_end - loop_start)) + border_top; item.yend = (int)(0.5 + (double)(height-2*border_top) * (item.endevent.getT()-loop_start) / (loop_end - loop_start)) + border_top; int slot = 0; for (int j = 0; j < item.endevent.getNumberOfTransitions(); j++) { JMLTransition temp = item.endevent.getTransition(j); if (temp.getPath() == item.pathnum) { slot = j; break; } } item.xend = (item.endevent.getHand() == HandLink.LEFT_HAND ? (left_x + (slot+1)*2*transition_radius) : (right_x - (slot+1)*2*transition_radius)); if (item.type == LadderPathItem.TYPE_SELF) { double a = 0.5 * Math.sqrt((double)((item.xstart-item.xend)*(item.xstart-item.xend)) + (double)((item.ystart-item.yend)*(item.ystart-item.yend))); double xt = 0.5 * (double)(item.xstart + item.xend); double yt = 0.5 * (double)(item.ystart + item.yend); double b = selfthrow_width * (double)width; double d = 0.5 * (a*a / b - b); if (d < (0.5*b)) d = 0.5 * b; double mult = (item.endevent.getHand()==HandLink.LEFT_HAND) ? -1.0 : 1.0; double xc = xt + mult * d * (yt - (double)item.ystart) / a; double yc = yt + mult * d * ((double)item.xstart - xt) / a; double rad = Math.sqrt(((double)item.xstart-xc)*((double)item.xstart-xc) + ((double)item.ystart-yc)*((double)item.ystart-yc)); item.xcenter = (int)(0.5 + xc); item.ycenter = (int)(0.5 + yc); item.radius = (int)(0.5 + rad); } } } protected void paintBackground(Graphics gr) { // check if ladder was resized Dimension dim = this.getSize(); if ((dim.width != width) || (dim.height != height)) { updateView(); //active_eventitem = null; //if (animator != null) // animator.deactivateEvent(); } if (laddercachedirty) { Graphics g = gr; if (cacheframesleft == 0) { laddercache = this.createImage(width, height); g = laddercache.getGraphics(); // try to turn on antialiased rendering VersionSpecific.getVersionSpecific().setAntialias(g); laddercachedirty = false; } else { cacheframesleft--; } // first erase the background g.setColor(this.getBackground()); g.fillRect(0, 0, width, height); if (pat.getNumberOfJugglers() == 1) { // draw the lines signifying symmetries g.setColor(Color.lightGray); g.drawLine(0, border_top, width, border_top); g.drawLine(0, height-border_top, width, height-border_top); if (has_switch_symmetry) { g.drawLine(left_x, height-border_top/2, right_x, height-border_top/2); g.drawLine(left_x, height-border_top/2, left_x+left_x, height-border_top*3/4); g.drawLine(left_x, height-border_top/2, left_x+left_x, height-border_top/4); g.drawLine(right_x, height-border_top/2, right_x-left_x, height-border_top*3/4); g.drawLine(right_x, height-border_top/2, right_x-left_x, height-border_top/4); } if (has_switchdelay_symmetry) g.drawLine(0, height/2, width, height/2); // draw the lines representing the hands g.setColor(Color.black); for (int i = -1; i < 2; i++) { g.drawLine(left_x+i, border_top, left_x+i, height-border_top); g.drawLine(right_x+i, border_top, right_x+i, height-border_top); } // draw paths Shape clip = g.getClip(); for (int i = 0; i < ladderpathitems.size(); i++) { LadderPathItem item = (LadderPathItem)ladderpathitems.elementAt(i); g.setColor(item.color); g.clipRect(left_x, border_top, (right_x-left_x), height-2*border_top); if (item.type == LadderPathItem.TYPE_CROSS) g.drawLine(item.xstart, item.ystart, item.xend, item.yend); else if (item.type == LadderPathItem.TYPE_HOLD) g.drawLine(item.xstart, item.ystart, item.xend, item.yend); else { if (!(item.yend < border_top)) { g.clipRect(left_x, item.ystart, (right_x-left_x), (item.yend-item.ystart)); g.drawOval(item.xcenter-item.radius, item.ycenter-item.radius, 2*item.radius, 2*item.radius); } } g.setClip(clip); } } else { // draw the lines representing the jugglers g.setColor(Color.black); for (int j = 0; j < pat.getNumberOfJugglers(); j++) { for (int i = -1; i < 2; i++) { int px = passing_first_x + j * passing_offset_x; g.drawLine(px+i, border_top, px+i, height-border_top); } } } } if (!laddercachedirty) gr.drawImage(laddercache, 0, 0, this); } protected void paintComponent(Graphics gr) { // try to turn on antialiased rendering VersionSpecific.getVersionSpecific().setAntialias(gr); paintBackground(gr); // draw events gr.setColor(Color.black); for (int i = 0; i < laddereventitems.size(); i++) { LadderEventItem item = (LadderEventItem)laddereventitems.elementAt(i); if (item.type == item.TYPE_EVENT) gr.fillOval(item.xlow, item.ylow, (item.xhigh-item.xlow), (item.yhigh-item.ylow)); else { gr.setColor(this.getBackground()); gr.fillOval(item.xlow, item.ylow, (item.xhigh-item.xlow), (item.yhigh-item.ylow)); gr.setColor(Color.black); gr.drawOval(item.xlow, item.ylow, (item.xhigh-item.xlow), (item.yhigh-item.ylow)); } } // draw the tracker line showing the time gr.setColor(Color.red); gr.drawLine(0, tracker_y, width, tracker_y); } } class LadderItem { static final public int TYPE_EVENT = 1; static final public int TYPE_TRANSITION = 2; static final public int TYPE_SELF = 3; static final public int TYPE_CROSS = 4; static final public int TYPE_HOLD = 5; public int type; } class LadderEventItem extends LadderItem { public int xlow, xhigh, ylow, yhigh; public LadderEventItem eventitem = null; public JMLEvent event = null; public int transnum = 0; } class LadderPathItem extends LadderItem { public int xstart, ystart, xend, yend; public int xcenter, ycenter, radius; // for type SELF public Color color; public JMLEvent startevent = null; public JMLEvent endevent = null; public int transnum_start = 0; public int pathnum; } jugglinglab-0.6.2+ds.1/source/jugglinglab/core/PatternList.java000066400000000000000000000245751323754603300244210ustar00rootroot00000000000000// PatternList.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.core; import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*; import java.text.MessageFormat; import jugglinglab.jml.*; import jugglinglab.notation.*; import jugglinglab.util.*; import jugglinglab.view.*; public class PatternList extends JPanel { static ResourceBundle guistrings; static ResourceBundle errorstrings; static { guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } final static Font font_nopattern = new Font("SanSerif", Font.BOLD | Font.ITALIC, 14); final static Font font_pattern = new Font("Monospaced", Font.PLAIN, 14); View animtarget = null; String title = null; JList list = null; DefaultListModel model = null; // JLabel status = null; public PatternList() { makePanel(); this.setOpaque(false); } public PatternList(View target) { makePanel(); this.setOpaque(false); setTargetView(target); } protected void makePanel() { model = new DefaultListModel(); list = new JList(model); list.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); list.setCellRenderer(new PatternCellRenderer()); list.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent lse) { PatternWindow jaw2 = null; try { if (lse.getValueIsAdjusting()) { PatternRecord rec = (PatternRecord)model.elementAt(list.getSelectedIndex()); JMLPattern pat = null; if (rec.notation != null && rec.notation.equalsIgnoreCase("JML") && rec.pattern != null) { pat = new JMLPattern(rec.pattern, PatternList.this.loadingversion); } else if (rec.notation != null && rec.anim != null) { Notation not = Notation.getNotation(rec.notation); pat = not.getJMLPattern(rec.anim); } else return; if (pat != null) { pat.setTitle(rec.display); AnimatorPrefs ap = new AnimatorPrefs(); if (rec.animprefs != null) ap.parseInput(rec.animprefs); if (animtarget != null) animtarget.restartView(pat, ap); else jaw2 = new PatternWindow(pat.getTitle(), pat, ap); } } } catch (JuggleExceptionUser je) { if (jaw2 != null) jaw2.dispose(); new ErrorDialog(PatternList.this, je.getMessage()); } catch (Exception e) { if (jaw2 != null) jaw2.dispose(); jugglinglab.util.ErrorDialog.handleException(e); } } }); JScrollPane pane = new JScrollPane(list); this.setLayout(new BorderLayout()); this.add(pane, BorderLayout.CENTER); } public void setTargetView(View target) { animtarget = target; } public void addPattern(String display, String animprefs, String notation, String anim, JMLNode pat) { // display = display.trim(); if (notation != null) notation = notation.trim(); if (animprefs != null) animprefs = animprefs.trim(); if (anim != null) anim = anim.trim(); PatternRecord rec = new PatternRecord(display, animprefs, notation, anim, pat); model.addElement(rec); } public void clearList() { model.clear(); } public void setTitle(String title) { this.title = title; } public String getTitle() { return this.title; } String loadingversion = null; public void readJML(JMLNode root) throws JuggleExceptionUser { if (!root.getNodeType().equalsIgnoreCase("jml")) throw new JuggleExceptionUser(errorstrings.getString("Error_missing_JML_tag")); loadingversion = root.getAttributes().getAttribute("version"); if (loadingversion == null) loadingversion = "1.0"; JMLNode listnode = root.getChildNode(0); if (!listnode.getNodeType().equalsIgnoreCase("patternlist")) throw new JuggleExceptionUser(errorstrings.getString("Error_missing_patternlist_tag")); int linenumber = 0; for (int i = 0; i < listnode.getNumberOfChildren(); i++) { JMLNode child = listnode.getChildNode(i); if (child.getNodeType().equalsIgnoreCase("title")) { title = child.getNodeValue().trim(); } else if (child.getNodeType().equalsIgnoreCase("line")) { linenumber++; JMLAttributes attr = child.getAttributes(); String display = attr.getAttribute("display"); if ((display==null) || display.equals("")) display = " "; // JList won't display empty strings String animprefs = attr.getAttribute("animprefs"); String notation = attr.getAttribute("notation"); String anim = null; JMLNode pattern = null; if (notation != null) { if (notation.equalsIgnoreCase("JML")) { for (int j = 0; j < child.getNumberOfChildren(); j++) { JMLNode subchild = child.getChildNode(j); if (subchild.getNodeType().equalsIgnoreCase("pattern")) { pattern = subchild; break; } } if (pattern == null) { String template = errorstrings.getString("Error_missing_pattern"); Object[] arguments = { Integer.valueOf(linenumber) }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } } else { anim = child.getNodeValue().trim(); } } addPattern(display, animprefs, notation, anim, pattern); } else throw new JuggleExceptionUser(errorstrings.getString("Error_illegal_tag")); } } public void writeJML(Writer wr) throws IOException { PrintWriter write = new PrintWriter(wr); for (int i = 0; i < JMLDefs.jmlprefix.length; i++) write.println(JMLDefs.jmlprefix[i]); String vers = this.loadingversion; if (vers == null) vers = JMLDefs.default_JML_on_save; write.println(""); write.println(""); write.println("" + JMLNode.xmlescape(this.title) + ""); for (int i = 0; i < model.size(); i++) { PatternRecord rec = (PatternRecord)model.elementAt(i); String line = ""); } write.println(""); write.println(""); for (int i = 0; i < JMLDefs.jmlsuffix.length; i++) write.println(JMLDefs.jmlsuffix[i]); write.flush(); // write.close(); } public void writeText(Writer wr) throws IOException { PrintWriter write = new PrintWriter(wr); for (int i = 0; i < model.size(); i++) { PatternRecord rec = (PatternRecord)model.elementAt(i); write.println(rec.display); } write.flush(); // write.close(); } class PatternRecord { public String display; public String animprefs; public String notation; public String anim; public JMLNode pattern; // if the pattern is in JML notation public PatternRecord(String dis, String ap, String not, String ani, JMLNode pat) { this.display = dis; this.animprefs = ap; this.notation = not; this.anim = ani; this.pattern = pat; } } class PatternCellRenderer extends JLabel implements ListCellRenderer { public Component getListCellRendererComponent( JList list, // the list Object value, // value to display int index, // cell index boolean isSelected, // is the cell selected boolean cellHasFocus) // does the cell have focus { PatternRecord rec = (PatternRecord)value; setFont((rec.anim == null && rec.pattern == null) ? font_nopattern : font_pattern); setText(rec.display); if (isSelected) { setBackground(list.getSelectionBackground()); setForeground(list.getSelectionForeground()); } else { setBackground(list.getBackground()); setForeground(list.getForeground()); } setEnabled(list.isEnabled()); setOpaque(true); return this; } } } jugglinglab-0.6.2+ds.1/source/jugglinglab/core/PatternListWindow.java000077500000000000000000000161701323754603300256040ustar00rootroot00000000000000// PatternListWindow.java // // Copyright 2002 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.core; import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*; import jugglinglab.jml.*; import jugglinglab.notation.*; import jugglinglab.util.*; public class PatternListWindow extends JFrame implements ActionListener { static ResourceBundle guistrings; // static ResourceBundle errorstrings; static { guistrings = JLLocale.getBundle("GUIStrings"); // errorstrings = JLLocale.getBundle("ErrorStrings"); } String title = null; PatternList pl = null; protected JMenuItem[] fileitems = null; public PatternListWindow(String title) { super(title); this.title = title; makeWindow(); pl.setTitle(title); this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); } public PatternListWindow(JMLNode root) throws JuggleExceptionUser { super(); makeWindow(); pl.readJML(root); if (pl.getTitle() != null) title = pl.getTitle(); else title = ResourceBundle.getBundle("JugglingLabStrings").getString("Patterns"); setTitle(title); this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); } protected void makeWindow() { this.pl = new PatternList(null); pl.setDoubleBuffered(true); this.setBackground(Color.white); this.setContentPane(pl); this.setSize(300,450); createMenuBar(); Locale loc = JLLocale.getLocale(); this.applyComponentOrientation(ComponentOrientation.getOrientation(loc)); // list contents are always left-to-right -- DISABLE FOR NOW // this.getContentPane().applyComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); this.setVisible(true); } public PatternList getPatternList() { return pl; } protected String[] fileItems = new String[] { "Close", null, "Save JML As...", "Save Text As..." }; protected String[] fileCommands = new String[] { "close", null, "saveas", "savetext" }; protected char[] fileShortcuts = { 'W', ' ', 'S', 'T' }; protected void createMenuBar() { JMenuBar mb = new JMenuBar(); JMenu filemenu = new JMenu(guistrings.getString("File")); this.fileitems = new JMenuItem[fileItems.length]; for (int i = 0; i < fileItems.length; i++) { if (fileItems[i] == null) filemenu.addSeparator(); else { fileitems[i] = new JMenuItem(guistrings.getString(fileItems[i].replace(' ', '_'))); if (fileShortcuts[i] != ' ') fileitems[i].setAccelerator(KeyStroke.getKeyStroke(fileShortcuts[i], Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); fileitems[i].setActionCommand(fileCommands[i]); fileitems[i].addActionListener(this); filemenu.add(fileitems[i]); } } mb.add(filemenu); setJMenuBar(mb); } public static final int FILE_NONE = 0; public static final int FILE_CLOSE = 1; public static final int FILE_SAVE = 2; public static final int FILE_SAVETEXT = 3; // Implements ActionListener to wait for MenuItem events public void actionPerformed(ActionEvent ae) { String command = ae.getActionCommand(); try { if (command.equals("close")) doFileMenuCommand(FILE_CLOSE); else if (command.equals("saveas")) doFileMenuCommand(FILE_SAVE); else if (command.equals("savetext")) doFileMenuCommand(FILE_SAVETEXT); } catch (Exception e) { jugglinglab.util.ErrorDialog.handleException(e); } } public void doFileMenuCommand(int action) throws JuggleExceptionInternal { switch (action) { case FILE_NONE: break; case FILE_CLOSE: dispose(); break; case FILE_SAVE: try { int option = PlatformSpecific.getPlatformSpecific().showSaveDialog(this); if (option == JFileChooser.APPROVE_OPTION) { if (PlatformSpecific.getPlatformSpecific().getSelectedFile() != null) { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); FileWriter fw = new FileWriter(PlatformSpecific.getPlatformSpecific().getSelectedFile()); pl.writeJML(fw); fw.close(); } } } catch (FileNotFoundException fnfe) { throw new JuggleExceptionInternal("File not found on save: " + fnfe.getMessage()); } catch (IOException ioe) { throw new JuggleExceptionInternal("IOException on save: " + ioe.getMessage()); } finally { setCursor(Cursor.getDefaultCursor()); } break; case FILE_SAVETEXT: try { int option = PlatformSpecific.getPlatformSpecific().showSaveDialog(this); if (option == JFileChooser.APPROVE_OPTION) { if (PlatformSpecific.getPlatformSpecific().getSelectedFile() != null) { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); FileWriter fw = new FileWriter(PlatformSpecific.getPlatformSpecific().getSelectedFile()); pl.writeText(fw); fw.close(); } } } catch (FileNotFoundException fnfe) { throw new JuggleExceptionInternal("File not found on save: " + fnfe.getMessage()); } catch (IOException ioe) { throw new JuggleExceptionInternal("IOException on save: " + ioe.getMessage()); } finally { setCursor(Cursor.getDefaultCursor()); } break; } } public void addPattern(String display, String animprefs, String notation, String anim, JMLNode pattern) { pl.addPattern(display, animprefs, notation, anim, pattern); } } jugglinglab-0.6.2+ds.1/source/jugglinglab/core/PatternWindow.java000077500000000000000000000102771323754603300247520ustar00rootroot00000000000000// PatternWindow.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.core; import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import jugglinglab.jml.*; import jugglinglab.util.*; import jugglinglab.view.*; public class PatternWindow extends JFrame implements ActionListener { /* static ResourceBundle guistrings; static ResourceBundle errorstrings; static { guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } */ protected View view = null; protected JMenu filemenu = null; protected JMenu viewmenu = null; public PatternWindow(String name, JMLPattern pat, AnimatorPrefs jc) throws JuggleExceptionUser, JuggleExceptionInternal { this(name, pat, jc, new Dimension(400, 450)); } public PatternWindow(String name, JMLPattern pat, AnimatorPrefs jc, Dimension dim) throws JuggleExceptionUser, JuggleExceptionInternal { super(name); view = new View(this, dim); JMenuBar mb = new JMenuBar(); filemenu = view.createFileMenu(); mb.add(filemenu); viewmenu = view.createViewMenu(); for (int i = 0; i < viewmenu.getItemCount(); i++) { JMenuItem jmi = viewmenu.getItem(i); if (jmi == null) break; // hit the first separator, end of the list of views jmi.addActionListener(this); // so we can enable/disable GIFsave depending on view mode } mb.add(viewmenu); setJMenuBar(mb); if (pat.getNumberOfJugglers() > 1) { view.setViewMode(View.VIEW_SIMPLE); viewmenu.getItem(0).setSelected(true); } else { view.setViewMode(View.VIEW_EDIT); viewmenu.getItem(1).setSelected(true); } /* 5/18/2014 Turned this off; UI was too confusing for (int i = 0; i < filemenu.getItemCount(); i++) { JMenuItem jmi = filemenu.getItem(i); if (jmi != null && jmi.getActionCommand().equals("savegifanim")) jmi.setEnabled(false); } */ setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); view.setDoubleBuffered(true); this.setBackground(Color.white); setContentPane(view); Locale loc = JLLocale.getLocale(); this.applyComponentOrientation(ComponentOrientation.getOrientation(loc)); pack(); view.restartView(pat, jc); setVisible(true); } protected void restartJuggle(String name, JMLPattern pat, AnimatorPrefs jc) throws JuggleException { this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); if (name != null) this.setTitle(name); view.restartView(pat, jc); this.setCursor(Cursor.getDefaultCursor()); } // Implements ActionListener to enable/disable GIFsave as view mode changes public void actionPerformed(ActionEvent ae) { /* 5/18/2014 Turned this off; UI was too confusing boolean gifenabled = false; if (ae.getActionCommand().equals("simple")) gifenabled = jugglinglab.core.Constants.INCLUDE_GIF_SAVE; */ boolean gifenabled = jugglinglab.core.Constants.INCLUDE_GIF_SAVE; for (int i = 0; i < filemenu.getItemCount(); i++) { JMenuItem jmi = filemenu.getItem(i); if ((jmi != null) && jmi.getActionCommand().equals("savegifanim")) { jmi.setEnabled(gifenabled); return; } } } public synchronized void dispose() { super.dispose(); if (view != null) { view.dispose(); view = null; } } } jugglinglab-0.6.2+ds.1/source/jugglinglab/core/PlatformSpecific.java000077500000000000000000000054301323754603300253720ustar00rootroot00000000000000// PlatformSpecific.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.core; import javax.swing.*; import java.awt.*; import java.io.*; public class PlatformSpecific { protected static PlatformSpecific ps = null; protected ApplicationWindow jlw = null; protected JFileChooser jfc = null; public static PlatformSpecific getPlatformSpecific() { if (ps == null) { if (System.getProperty("jugglinglab.macosxapp") != null) { try { Object obj = Class.forName("jugglinglab.MacOS.PlatformSpecificMacOS").newInstance(); ps = (PlatformSpecific)obj; } catch (ClassNotFoundException cnfe) { ps = null; // revert to 100% pure stub } catch (IllegalAccessException iae) { ps = null; } catch (InstantiationException ie) { ps = null; } } } if (ps == null) ps = new PlatformSpecific(); return ps; } public void registerParent(ApplicationWindow jlw) { this.jlw = jlw; } // Now the platform-specific methods: public boolean isMacOS() { return false; } public void setupPlatform() {} public int showOpenDialog(Component c) { return showOpenDialog(c, null); } public int showOpenDialog(Component c, javax.swing.filechooser.FileFilter ff) { if (jfc == null) { jfc = new JFileChooser(System.getProperty("user.dir")); } jfc.setFileFilter(ff); // ff == null => no filter return jfc.showOpenDialog(c); } public int showSaveDialog(Component c) { if (jfc == null) jfc = new JFileChooser(System.getProperty("user.dir")); return jfc.showSaveDialog(c); } public File getSelectedFile() { if (jfc == null) return null; return jfc.getSelectedFile(); } }jugglinglab-0.6.2+ds.1/source/jugglinglab/core/VersionSpecific.java000077500000000000000000000053031323754603300252320ustar00rootroot00000000000000// VersionSpecific.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.core; import java.awt.*; import java.net.*; public class VersionSpecific { protected static VersionSpecific vs = null; protected static URL[] images = null; public static VersionSpecific getVersionSpecific() { if (vs == null) { if (getJavaVersion() >= 2) { // use the reflection API so that validating classloaders don't // try to load VersionSpecific2 try { Object vso = Class.forName("jugglinglab.core.VersionSpecific2").newInstance(); vs = (VersionSpecific)vso; } catch (ClassNotFoundException e) { vs = null; } catch (SecurityException e) { vs = null; } catch (IllegalAccessException e) { vs = null; } catch (InstantiationException e) { vs = null; } } } if (vs == null) vs = new VersionSpecific(); return vs; } public static int getJavaVersion() { String version = System.getProperty("java.version"); char ch = version.charAt(2); return Character.digit(ch, 10); } public static void setDefaultPropImages(URL[] is) { images = is; } // Now the version-specific methods: public void setAntialias(Graphics g) { } public void setColorTransparent(Graphics g) { g.setColor(Color.white); } public Image makeImage(Component comp, int width, int height) { Image image = comp.createImage(width, height); Graphics tempg = image.getGraphics(); tempg.setColor(comp.getBackground()); tempg.fillRect(0, 0, width, height); return image; } public URL getDefaultPropImage() { return images[0]; } }jugglinglab-0.6.2+ds.1/source/jugglinglab/core/VersionSpecific2.java000077500000000000000000000034431323754603300253170ustar00rootroot00000000000000// VersionSpecific2.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.core; import java.awt.*; import java.awt.image.*; import java.net.*; public class VersionSpecific2 extends VersionSpecific { public void setAntialias(Graphics g) { if (g instanceof Graphics2D) { Graphics2D g2 = (Graphics2D)g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); } } public void setColorTransparent(Graphics g) { if (g instanceof Graphics2D) { Graphics2D g2 = (Graphics2D)g; g2.setComposite(AlphaComposite.Src); // Change for VersionSpecific g2.setColor(new Color(1f, 1f, 1f, 0f)); } } public Image makeImage(Component comp, int width, int height) { Image im = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE); if (im == null) im = super.makeImage(comp, width, height); return im; } public URL getDefaultPropImage() { return images[1]; } }jugglinglab-0.6.2+ds.1/source/jugglinglab/curve/000077500000000000000000000000001323754603300214645ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/source/jugglinglab/curve/Curve.java000066400000000000000000000062401323754603300234150ustar00rootroot00000000000000// Curve.java // // Copyright 2002 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.curve; import jugglinglab.util.*; public abstract class Curve { public static final int splineCurve = 1; // implemented types public static final int lineCurve = 2; protected int numpoints; protected Coordinate[] positions = null; protected double[] times = null; protected Coordinate start_velocity = null, end_velocity = null; public abstract void initCurve(String st) throws JuggleExceptionUser; public void setCurve(Coordinate[] positions, double[] times, Coordinate start_velocity, Coordinate end_velocity) throws JuggleExceptionInternal { this.positions = positions; this.times = times; this.start_velocity = start_velocity; this.end_velocity = end_velocity; this.numpoints = positions.length; if (numpoints != times.length) throw new JuggleExceptionInternal("Path error 1"); } public void setCurve(Coordinate[] positions, double[] times) throws JuggleExceptionInternal { this.setCurve(positions, times, null, null); } public abstract void calcCurve() throws JuggleExceptionInternal; public double getStartTime() { return times[0]; } public double getEndTime() { return times[numpoints-1]; } public double getDuration() { return (times[numpoints-1]-times[0]); } public void translateTime(double deltat) { for (int i = 0; i < numpoints; i++) times[i] += deltat; } public abstract void getCoordinate(double time, Coordinate newPosition); // for screen layout purposes public Coordinate getMax() { return getMax2(times[0], times[numpoints-1]); } public Coordinate getMin() { return getMin2(times[0], times[numpoints-1]); } public Coordinate getMax(double begin, double end) { if ((end < getStartTime()) || (begin > getEndTime())) return null; return getMax2(begin, end); } public Coordinate getMin(double begin, double end) { if ((end < getStartTime()) || (begin > getEndTime())) return null; return getMin2(begin, end); } protected abstract Coordinate getMax2(double begin, double end); protected abstract Coordinate getMin2(double begin, double end); // utility for getMax2/getMin2 protected Coordinate check(Coordinate result, double t, boolean findmax) { Coordinate loc = new Coordinate(); this.getCoordinate(t, loc); if (findmax) result = Coordinate.max(result, loc); else result = Coordinate.min(result, loc); return result; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/curve/lineCurve.java000066400000000000000000000104771323754603300242740ustar00rootroot00000000000000// lineCurve.java // // Copyright 2003 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.curve; import jugglinglab.util.*; public class lineCurve extends Curve { protected int n; // number of line segments protected double[][] a, b; // line coefficients protected double[] durations; // durations of segments public void initCurve(String st) { } public void calcCurve() throws JuggleExceptionInternal { this.n = numpoints - 1; if (n < 1) throw new JuggleExceptionInternal("lineCurve error 1"); this.a = new double[n][3]; this.b = new double[n][3]; this.durations = new double[n]; for (int i = 0; i < n; i++) { durations[i] = times[i+1] - times[i]; if (durations[i] < 0.0) throw new JuggleExceptionInternal("lineCurve error 2"); } double[] x = new double[n+1]; for (int i = 0; i < 3; i++) { for (int j = 0; j < (n+1); j++) x[j] = positions[j].getIndex(i); // now solve for line coefficients for (int j = 0; j < n; j++) { a[j][i] = x[j]; b[j][i] = (x[j+1] - x[j]) / durations[j]; } } } public void getCoordinate(double time, Coordinate newPosition) { if ((time < times[0]) || (time > times[n])) return; int i; for (i = 0; i < n; i++) if (time <= times[i+1]) break; if (i == n) i = n - 1; time -= times[i]; newPosition.setCoordinate( a[i][0] + time * b[i][0], a[i][1] + time * b[i][1], a[i][2] + time * b[i][2] ); } protected Coordinate getMax2(double begin, double end) { if ((end < times[0]) || (begin > times[n])) return null; Coordinate result = null; double tlow = Math.max(times[0], begin); double thigh = Math.min(times[n], end); result = check(result, tlow, true); result = check(result, thigh, true); for (int i = 0; i <= n; i++) { if ((tlow <= times[i]) && (times[i] <= thigh)) result = check(result, times[i], true); if (i != n) { double tlowtemp = Math.max(tlow, times[i]); double thightemp = Math.min(thigh, times[i+1]); if (tlowtemp < thightemp) { result = check(result, tlowtemp, true); result = check(result, thightemp, true); } } } return result; } protected Coordinate getMin2(double begin, double end) { if ((end < times[0]) || (begin > times[n])) return null; Coordinate result = null; double tlow = Math.max(times[0], begin); double thigh = Math.min(times[n], end); result = check(result, tlow, false); result = check(result, thigh, false); for (int i = 0; i <= n; i++) { if ((tlow <= times[i]) && (times[i] <= thigh)) result = check(result, times[i], false); if (i != n) { double tlowtemp = Math.max(tlow, times[i]); double thightemp = Math.min(thigh, times[i+1]); if (tlowtemp < thightemp) { result = check(result, tlowtemp, false); result = check(result, thightemp, false); } } } return result; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/curve/splineCurve.java000066400000000000000000000366141323754603300246400ustar00rootroot00000000000000// splineCurve.java // // Copyright 2003 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.curve; import jugglinglab.util.*; public class splineCurve extends Curve { protected int n; // number of spline segments protected double[][] a, b, c, d; // spline coefficients protected double[] durations; // durations of segments public void initCurve(String st) { } // Calculate the coefficients a, b, c, d for each portion of the spline path. // To solve for these four unknowns, we need four boundary conditions: the // path position at each endpoint (2), and the hand velocity at each endpoint (2). // hand the hand is making a throw or softcatch, the velocities are known and // given by the velocity of the object being thrown/caught. The other velocities // are not known and must be assigned -- we assign them according to one of three // minimization techniques. public void calcCurve() throws JuggleExceptionInternal { int i, j; boolean edgeVelocitiesKnown = ((start_velocity != null) && (end_velocity != null)); this.n = numpoints - 1; if (n < 1) throw new JuggleExceptionInternal("splineCurve error 1"); this.a = new double[n][3]; this.b = new double[n][3]; this.c = new double[n][3]; this.d = new double[n][3]; this.durations = new double[n]; for (i = 0; i < n; i++) { durations[i] = times[i+1] - times[i]; if (durations[i] < 0.0) throw new JuggleExceptionInternal("splineCurve error 2"); } double[] x = new double[n+1]; double[] v = new double[n+1]; double t; for (i = 0; i < 3; i++) { for (j = 0; j < (n+1); j++) x[j] = positions[j].getIndex(i); if (edgeVelocitiesKnown) { v[0] = start_velocity.getIndex(i); v[n] = end_velocity.getIndex(i); // find velocities by minimizing rms acceleration findvels_edges_known(v, x, durations, n, jugglinglab.core.Constants.SPLINE_LAYOUT_METHOD); } else { findvels_edges_unknown(v, x, durations, n, jugglinglab.core.Constants.SPLINE_LAYOUT_METHOD); } //System.out.println("index = "+i+", v[1] = "+v[1]+"\n"); // now that we have velocities, solve for spline coefficients for (j = 0; j < n; j++) { a[j][i] = x[j]; b[j][i] = v[j]; t = durations[j]; c[j][i] = (3.0*(x[j+1]-x[j])-(v[j+1]+2.0*v[j])*t)/(t*t); d[j][i] = (-2.0*(x[j+1]-x[j])+(v[j+1]+v[j])*t)/(t*t*t); //System.out.println("a="+a[j][i]+", b="+b[j][i]+", c="+c[j][i]+", d="+d[j][i]+"\n"); } } } // These are the three minimization techniques to assign velocities: // "rmsaccel" minimizes the rms acceleration of the hand // "continaccel" makes the hand acceleration a continuous function // "rmsvel" minimizes the rms velocity of the hand public static final int rmsaccel = 0; public static final int continaccel = 1; public static final int rmsvel = 2; // This method assigns the unknown velocities at the intermediate times // from the known velocities at the endpoints (and positions at all // times). n is the number of sections -- (n-1) is the number of // unknown velocities. v and x have dimension (n+1), t has dimension // n. v[0] and v[n] are assumed to be initialized to known endpoints. // // In each minimization technique, the calculus problem reduces to // solving a system of linear equations of the form A.v = b, where v // is a column vector of the velocities. In this case, the matrix A is // in tridiagonal form, which is solved efficiently in O(N) time. A is // also a symmetric matrix, so the sub- and super-diagonals are equal. static protected void findvels_edges_known(double[] v, double[] x, double[] t, int n, int method) throws JuggleExceptionInternal { if (n < 2) return; double[] Adiag = new double[n-1]; double[] Aoffd = new double[n-1]; // A is symmetric double[] b = new double[n-1]; for (int i = 0; i < n-1; i++) { switch (method) { case rmsaccel: case continaccel: // cases end up being identical Adiag[i] = 2.0/t[i+1] + 2.0/t[i]; Aoffd[i] = 1.0/t[i+1]; b[i] = 3.0*(x[i+2]-x[i+1])/(t[i+1]*t[i+1]) + 3.0*(x[i+1]-x[i])/(t[i]*t[i]); if (i == 0) b[0] -= v[0]/t[0]; if (i == (n-2)) b[n-2] -= v[n]/t[n-1]; break; case rmsvel: Adiag[i] = 4.0*(t[i] + t[i+1]); Aoffd[i] = -t[i+1]; b[i] = 3.0*(x[i+2]-x[i]); if (i == 0) b[0] += v[0]*t[0]; if (i == (n-2)) b[n-2] += v[n]*t[n-1]; break; } } double[] vtemp = new double[n-1]; // n-1 unknown velocities tridag(Aoffd, Adiag, Aoffd, b, vtemp, n-1); // solve for (int i = 0; i < n-1; i++) v[i+1] = vtemp[i]; } // This method assigns the unknown velocities at the intermediate times. // Unlike the case above, here none of the velocities are known. They are // all assigned via minimization, with the constraint that v[n]=v[0]. // // Also unlike the case above, here the calculus does not reduce to a pure // tridiagonal system. The matrix A is tridiagonal, except for nonzero // elements in the upper-right and lower-left corners. Since A is close // to tridiagonal, we can use the Woodbury formula, which allows us to // solve a few auxiliary tridiagonal problems and then combine the results // to solve the full problem. See pg. 77 from Numerical Recipes in C, first // edition. static protected void findvels_edges_unknown(double[] v, double[] x, double[] t, int n, int method) throws JuggleExceptionInternal { if (n < 2) return; double[] Adiag = new double[n]; double[] Aoffd = new double[n]; // A is symmetric double Acorner = 0.0; // nonzero element in UR/LL corners of A double[] b = new double[n]; for (int i = 0; i < n; i++) { switch (method) { case rmsaccel: case continaccel: if (i == 0) { Adiag[0] = 2.0/t[n-1] + 2.0/t[0]; Acorner = 1.0/t[n-1]; b[0] = 3.0*(x[1]-x[0])/(t[0]*t[0]) + 3.0*(x[n]-x[n-1])/(t[n-1]*t[n-1]); } else { Adiag[i] = 2.0/t[i-1] + 2.0/t[i]; b[i] = 3.0*(x[i+1]-x[i])/(t[i]*t[i]) + 3.0*(x[i]-x[i-1])/(t[i-1]*t[i-1]); } Aoffd[i] = 1.0/t[i]; // not used for i=n-1 break; case rmsvel: if (i == 0) { Adiag[0] = 4.0*(t[n-1] + t[0]); Acorner = -t[n-1]; b[0] = 3.0*(x[n]-x[n-1]+x[1]-x[0]); } else { Adiag[i] = 4.0*(t[i-1] + t[i]); b[i] = 3.0*(x[i+1]-x[i-1]); } Aoffd[i] = -t[i]; break; } } /* System.out.println("\nBeginning solution. RHS:"); for (int i = 0; i < n; i++) System.out.println(" b["+i+"] = "+b[i]); */ // Woodbury's formula: solve the problem ignoring A's nonzero corners tridag(Aoffd, Adiag, Aoffd, b, v, n); if (n > 2) { // need to deal with nonzero corners? // solve a few auxiliary problems: double[] z1 = new double[n]; b[0] = Acorner; for (int i = 1; i < n; i++) b[i] = 0.0; tridag(Aoffd, Adiag, Aoffd, b, z1, n); double[] z2 = new double[n]; b[n-1] = Acorner; for (int i = 0; i < n-1; i++) b[i] = 0.0; tridag(Aoffd, Adiag, Aoffd, b, z2, n); // now we need to calculate a 2x2 matrix H: double H00, H01, H10, H11; H00 = 1.0 + z2[0]; H01 = -z2[n-1]; H10 = -z1[0]; H11 = 1.0 + z1[n-1]; double det = H00 * H11 - H01 * H10; H00 /= det; H01 /= det; H10 /= det; H11 /= det; // finally, use the formula to adjust the velocities: double m0 = H00 * v[n-1] + H01 * v[0]; double m1 = H10 * v[n-1] + H11 * v[0]; for (int i = 0; i < n; i++) v[i] -= (z1[i] * m0 + z2[i] * m1); } v[n] = v[0]; /* // do the matrix multiply to check the answer System.out.println("Final result RHS:"); for (int i = 0; i < n; i++) { double res = v[i] * Adiag[i]; if (i != (n-1)) res += v[i+1] * Aoffd[i]; if (i > 0) res += v[i-1] * Aoffd[i-1]; if ((i == 0) && (n > 2)) res += Acorner * v[n-1]; if ((i == (n-1)) && (n > 2)) res += Acorner * v[0]; System.out.println(" rhs["+i+"] = "+res); }*/ } // The following method is adapted from Numerical Recipes. It solves // the linear system A.u = r where A is tridiagonal. a[] is the // subdiagonal, b[] the diagonal, c[] the superdiagonal. a, b, c, r, and // u are indexed from 0. Only the array u[] is changed. static protected void tridag(double[] a, double[] b, double[] c, double[] r, double[] u, int n) throws JuggleExceptionInternal { int j; double bet; double[] gam = new double[n]; if (b[0] == 0.0) throw new JuggleExceptionInternal("Error 1 in TRIDAG"); bet = b[0]; u[0] = r[0] / bet; for (j = 1; j < n; j++) { gam[j] = c[j-1] / bet; bet = b[j] - a[j-1]*gam[j]; if (bet == 0.0) throw new JuggleExceptionInternal("Error 2 in TRIDAG"); u[j] = (r[j] - a[j-1]*u[j-1]) / bet; } for (j = (n-1); j > 0; j--) u[j-1] -= gam[j]*u[j]; } public void getCoordinate(double time, Coordinate newPosition) { if ((time < times[0]) || (time > times[n])) return; int i; for (i = 0; i < n; i++) if (time <= times[i+1]) break; if (i == n) i = n-1; time -= times[i]; newPosition.setCoordinate( a[i][0]+time*(b[i][0]+time*(c[i][0]+time*d[i][0])), a[i][1]+time*(b[i][1]+time*(c[i][1]+time*d[i][1])), a[i][2]+time*(b[i][2]+time*(c[i][2]+time*d[i][2])) ); } protected Coordinate getMax2(double begin, double end) { if ((end < times[0]) || (begin > times[n])) return null; Coordinate result = null; double tlow = Math.max(times[0], begin); double thigh = Math.min(times[n], end); result = check(result, tlow, true); result = check(result, thigh, true); for (int i = 0; i <= n; i++) { if ((tlow <= times[i]) && (times[i] <= thigh)) result = check(result, times[i], true); if (i != n) { double tlowtemp = Math.max(tlow, times[i]); double thightemp = Math.min(thigh, times[i+1]); if (tlowtemp < thightemp) { result = check(result, tlowtemp, true); result = check(result, thightemp, true); for (int index = 0; index < 3; index++) { if (Math.abs(d[i][index]) > 1.0e-6) { double k = c[i][index]*c[i][index] - 3.0*b[i][index]*d[i][index]; if (k > 0.0) { double te = times[i] + (-c[i][index]-Math.sqrt(k))/(3*d[i][index]); if ((tlowtemp < te) && (te < thightemp)) result = check(result, te, true); } } else if (c[i][index] < 0.0) { double te = -b[i][index]/(2.0*c[i][index]); te += times[i]; if ((tlowtemp < te) && (te < thightemp)) result = check(result, te, true); } } } } } return result; } protected Coordinate getMin2(double begin, double end) { if ((end < times[0]) || (begin > times[n])) return null; Coordinate result = null; double tlow = Math.max(times[0], begin); double thigh = Math.min(times[n], end); result = check(result, tlow, false); result = check(result, thigh, false); for (int i = 0; i <= n; i++) { if ((tlow <= times[i]) && (times[i] <= thigh)) result = check(result, times[i], false); if (i != n) { double tlowtemp = Math.max(tlow, times[i]); double thightemp = Math.min(thigh, times[i+1]); if (tlowtemp < thightemp) { result = check(result, tlowtemp, false); result = check(result, thightemp, false); for (int index = 0; index < 3; index++) { if (Math.abs(d[i][index]) > 1.0e-6) { double k = c[i][index]*c[i][index] - 3.0*b[i][index]*d[i][index]; if (k > 0.0) { double te = times[i] + (-c[i][index]+Math.sqrt(k))/(3*d[i][index]); if ((tlowtemp < te) && (te < thightemp)) result = check(result, te, false); } } else if (c[i][index] > 0.0) { double te = -b[i][index]/(2.0*c[i][index]); te += times[i]; if ((tlowtemp < te) && (te < thightemp)) result = check(result, te, false); } } } } } return result; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/generator/000077500000000000000000000000001323754603300223265ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/source/jugglinglab/generator/Generator.java000077500000000000000000000071161323754603300251270ustar00rootroot00000000000000// Generator.java // // Copyright 2003 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.generator; import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.util.*; import java.io.*; import java.net.*; import jugglinglab.util.*; // This class defines a general object that is capable of generating tricks // and converting them into commands that the animator understands. public abstract class Generator { static ResourceBundle guistrings; static ResourceBundle errorstrings; static { guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } // The built-in generators public static final String[] builtinGenerators = { "siteswap" }; // This is a factory to create Generators from names. Note the // naming convention. public static Generator getGenerator(String name) { try { Object obj = Class.forName("jugglinglab.generator."+ name.toLowerCase()+"Generator").newInstance(); if (!(obj instanceof Generator)) { return null; // throw new JuggleExceptionUser("Generator type '"+name+"' doesn't work"); } return (Generator)obj; } catch (ClassNotFoundException cnfe) { return null; // throw new JuggleExceptionUser("Generator type '"+name+"' not found"); } catch (IllegalAccessException iae) { return null; // throw new JuggleExceptionUser("Cannot access '"+name+"' generator file (security)"); } catch (InstantiationException ie) { return null; // throw new JuggleExceptionUser("Couldn't create '"+name+"' generator"); } } public abstract String getStartupMessage(); public abstract JPanel getGeneratorControls(); public abstract void resetGeneratorControls(); // use parameters from controller frame public abstract void initGenerator() throws JuggleExceptionUser; // use command line args public abstract void initGenerator(String[] args) throws JuggleExceptionUser; public void initGenerator(String arg) throws JuggleExceptionUser { int i, numargs; StringTokenizer st = new StringTokenizer(arg, " \n"); numargs = st.countTokens(); String args[] = new String[numargs]; for (i = 0; i < numargs; i++) args[i] = st.nextToken(); this.initGenerator(args); } public abstract int runGenerator(GeneratorTarget t); // The following is identical to the above, but imposes // bounds in space and time public abstract int runGenerator(GeneratorTarget t, int max_num, double secs) throws JuggleExceptionUser; } jugglinglab-0.6.2+ds.1/source/jugglinglab/generator/GeneratorTarget.java000066400000000000000000000040171323754603300262700ustar00rootroot00000000000000// GeneratorTarget.java // // Copyright 2003 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.generator; import java.io.*; import javax.swing.*; import jugglinglab.core.*; // This is used as an adapter to handle the generator output public class GeneratorTarget { PatternList ltarget = null; PrintStream ptarget = null; public GeneratorTarget(PatternListWindow target) { this.ltarget = target.getPatternList(); } public GeneratorTarget(PatternList target) { this.ltarget = target; } public GeneratorTarget(PrintStream ps) { this.ptarget = ps; } public void writePattern(final String display, final String notation, final String anim) { if (ltarget != null) { // This method isn't necessarily being called from the event dispatch // thread, so do it this way to ensure the displayed list is only // updated from the event dispatch thread. SwingUtilities.invokeLater(new Runnable() { public void run() { ltarget.addPattern(display, null, notation, anim, null); } }); } if (ptarget != null) ptarget.println(display); } public void setStatus(String display) { if (ptarget != null) ptarget.println(display); } }jugglinglab-0.6.2+ds.1/source/jugglinglab/generator/siteswapGenerator.java000077500000000000000000001774771323754603300267310ustar00rootroot00000000000000// siteswapGenerator.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.generator; import javax.swing.*; import java.util.*; import java.util.regex.*; import java.text.MessageFormat; import jugglinglab.util.*; import jugglinglab.core.*; // This class is a port of the J2 siteswap pattern generator to Java. // For now the "custom" mode has been commented out, although at some // point it might be interesting to have a graphical rhythm editor. /************************************************************************/ /* J version 2.3 by Jack Boyce 12/91 */ /* jboyce@tybalt.caltech.edu */ /* */ /* This program finds all juggling siteswap patterns for a given */ /* number of balls, maximum throw value, and pattern length. */ /* A state graph approach is used in order to speed up computation. */ /* */ /* It is a complete rewrite of an earlier program written in 11/90 */ /* which handled only non-multiplexed asynchronous solo siteswaps. */ /* This version can generate multiplexed and nonmultiplexed tricks */ /* for an arbitrary number of people, number of hands, and throwing */ /* rhythm. The built-in modes are asynchronous and synchronous solo */ /* juggling, and two person asynchronous passing. */ /* */ /* Include flag modified and the -simple flag added on 2/92 */ /* Extra check (for speed) added to gen_loops() on 01/19/98 */ /* Bug fix to find_start_end() on 02/18/99 */ /************************************************************************/ public class siteswapGenerator extends Generator { // Different types of siteswaps protected final static int ASYNCH = 0; /* different types of modes */ protected final static int SYNCH = 1; // protected final static int CUSTOM = 2; // Types of multiplexing filter slots private final static int MP_EMPTY = 0; private final static int MP_THROW = 1; private final static int MP_LOWER_BOUND = 2; private final static int TYPE = 0; private final static int FROM = 1; private final static int VALUE = 2; // max. # of chars. printed per throw private final static int CHARS_PER_THROW = 50; protected final static int asynch_rhythm_repunit[][] = { { 1 } }; protected final static int synch_rhythm_repunit[][] = { { 1, 0 }, { 1, 0 } }; // Instance variables protected int pattern_rhythm[][][], pattern_state[][][]; protected int pattern_throwcount[][], pattern_holes[][][]; protected int pattern_throw_to[][][], pattern_throw_value[][][]; protected int pattern_filter[][][][]; protected boolean pattern_printx; protected int hands, max_occupancy, leader_person; protected int rhythm_repunit[][], rhythm_period; protected int holdthrow[], person_number[], scratch1[], scratch2[]; protected int ground_state[][]; protected int ground_state_length; protected int n, ht, l, llow, lhigh; protected Vector exclude, include; protected char[] output; protected int outputpos; protected int numflag, groundflag; protected int rotflag; // added 12/15/02 protected int fullflag, mp_filter, delaytime; protected boolean mp_clustered; protected boolean lameflag, sequenceflag; protected boolean connected_patterns; protected boolean[] connections; protected boolean juggler_permutations; protected boolean[] perm_scratch1, perm_scratch2; protected int mode, jugglers, slot_size; protected char[] starting_seq, ending_seq; protected int starting_seq_length, ending_seq_length; protected GeneratorTarget target; protected int max_num; // maximum number of patterns to print protected double max_time; // maximum number of seconds protected long max_time_millis; // maximum number of milliseconds protected long start_time_millis; // start time of run, in milliseconds protected int loop_counter; // gen_loop() counter for checking timeout protected final static int loop_counter_max = 20000; protected siteswapGeneratorControl control; // contains controls for generator // The public methods public String getStartupMessage() { return "Welcome to the J2 Siteswap Generator"; } public JPanel getGeneratorControls() { if (control == null) control = new siteswapGeneratorControl(); return control; } public void resetGeneratorControls() { if (control != null) control.resetControl(); } public void initGenerator() throws JuggleExceptionUser { if (control == null) initGenerator("5 7 5"); // default settings else initGenerator(control.getParams()); } public void initGenerator(String[] args) throws JuggleExceptionUser { int i, j, k, multiplex = 1; boolean true_multiplex = false; if (args.length < 3) throw new JuggleExceptionUser(errorstrings.getString("Error_generator_insufficient_input")); max_occupancy = 0; leader_person = 1; numflag = 0; groundflag = 0; rotflag = 0; fullflag = mp_filter = 1; mp_clustered = true; delaytime = 0; lameflag = false; connected_patterns = false; juggler_permutations = false; sequenceflag = true; mode = ASYNCH; /* default mode */ jugglers = 1; target = null; exclude = new Vector(); include = new Vector(); for (i = 3; i < args.length; i++) { if (args[i].equals("-n")) numflag = 1; else if (args[i].equals("-no")) numflag = 2; else if (args[i].equals("-g")) groundflag = 1; else if (args[i].equals("-ng")) groundflag = 2; else if (args[i].equals("-f")) fullflag = 0; else if (args[i].equals("-prime")) fullflag = 2; else if (args[i].equals("-rot")) rotflag = 1; else if (args[i].equals("-jp")) juggler_permutations = true; else if (args[i].equals("-lame")) lameflag = true; else if (args[i].equals("-se")) sequenceflag = false; else if (args[i].equals("-s")) mode = SYNCH; /* else if (!strcmp(argv[i], "-c")) { mode = CUSTOM; if (i != (argc - 1)) custom_initialize(argv[++i]); else { printf("No custom rhythm file given\n"); exit(0); } }*/ else if (args[i].equals("-cp")) connected_patterns = true; else if (args[i].equals("-mf")) mp_filter = 0; else if (args[i].equals("-mc")) mp_clustered = false; else if (args[i].equals("-mt")) true_multiplex = true; else if (args[i].equals("-m")) { if ((i < (args.length - 1)) && (args[i + 1].charAt(0) != '-')) { try { multiplex = Integer.parseInt(args[i + 1]); } catch (NumberFormatException nfe) { String template = errorstrings.getString("Error_number_format"); String str = guistrings.getString("simultaneous_throws"); Object[] arguments = { str }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } i++; } } else if (args[i].equals("-j")) { if ((i < (args.length - 1)) && (args[i + 1].charAt(0) != '-')) { try { jugglers = Integer.parseInt(args[i + 1]); } catch (NumberFormatException nfe) { String template = errorstrings.getString("Error_number_format"); String str = guistrings.getString("Jugglers"); Object[] arguments = { str }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } i++; } } else if (args[i].equals("-d")) { if ((i < (args.length - 1)) && (args[i + 1].charAt(0) != '-')) { try { delaytime = Integer.parseInt(args[i + 1]); } catch (NumberFormatException nfe) { String template = errorstrings.getString("Error_number_format"); String str = guistrings.getString("Passing_communication_delay"); Object[] arguments = { str }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } groundflag = 1; // find only ground state tricks i++; } } else if (args[i].equals("-l")) { if ((i < (args.length - 1)) && (args[i + 1].charAt(0) != '-')) { try { leader_person = Integer.parseInt(args[i + 1]); } catch (NumberFormatException nfe) { String template = errorstrings.getString("Error_number_format"); String str = guistrings.getString("Error_passing_leader_number"); Object[] arguments = { str }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } i++; } } else if (args[i].equals("-x")) { i++; while ((i < args.length) && (args[i].charAt(0) != '-')) { try { String re = make_standard_RE(args[i]); if (re.indexOf("^") < 0) re = ".*" + re + ".*"; exclude.add(Pattern.compile(re)); } catch (PatternSyntaxException pse) { throw new JuggleExceptionUser(errorstrings.getString("Error_excluded_throws")); } i++; } i--; } else if (args[i].equals("-i")) { i++; while ((i < args.length) && (args[i].charAt(0) != '-')) { try { String re = make_standard_RE(args[i]); if (re.indexOf("^") < 0) re = ".*" + re; if (re.indexOf("$") < 0) re = re + ".*"; include.add(Pattern.compile(re)); } catch (PatternSyntaxException ps) { throw new JuggleExceptionUser(errorstrings.getString("Error_included_throws")); } i++; } i--; } else { String template = errorstrings.getString("Error_unrecognized_option"); Object[] arguments = { args[i] }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } } // if (mode != CUSTOM) initialize(); try { n = Integer.parseInt(args[0]); } catch (NumberFormatException nfe) { String template = errorstrings.getString("Error_number_format"); String str = guistrings.getString("balls"); Object[] arguments = { str }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } try { if (args[1].equals("-")) // signal to not specify a maximum throw ht = -1; else ht = Integer.parseInt(args[1]); } catch (NumberFormatException nfe) { String template = errorstrings.getString("Error_number_format"); String str = guistrings.getString("max._throw"); Object[] arguments = { str }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } try { if (args[2].equals("-")) { llow = rhythm_period; lhigh = -1; } else { int divider = args[2].indexOf('-'); if (divider == 0) { llow = rhythm_period; lhigh = Integer.parseInt(args[2].substring(1)); } else if (divider == (args[2].length() - 1)) { llow = Integer.parseInt(args[2].substring(0, divider)); lhigh = -1; } else if (divider > 0) { llow = Integer.parseInt(args[2].substring(0, divider)); lhigh = Integer.parseInt(args[2].substring(divider + 1)); } else { llow = lhigh = Integer.parseInt(args[2]); } } } catch (NumberFormatException nfe) { String template = errorstrings.getString("Error_number_format"); String str = guistrings.getString("period"); Object[] arguments = { str }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } if (n < 1) throw new JuggleExceptionUser(errorstrings.getString("Error_generator_too_few_balls")); if (lhigh == -1) { if (fullflag != 2) throw new JuggleExceptionUser(errorstrings.getString("Error_generator_must_be_prime_mode")); if (ht == -1) throw new JuggleExceptionUser(errorstrings.getString("Error_generator_underspecified")); lhigh = JLMath.choose(ht * hands, n); lhigh -= (lhigh % rhythm_period); } if (ht == -1) ht = n * lhigh; if (ht < 1) throw new JuggleExceptionUser(errorstrings.getString("Error_generator_height_too_small")); if ((llow < 1) || (lhigh < 1) || (llow > lhigh)) throw new JuggleExceptionUser(errorstrings.getString("Error_generator_period_problem")); output = new char[lhigh * CHARS_PER_THROW]; outputpos = 0; if ((jugglers > 1) && !juggler_permutations && (groundflag != 0)) throw new JuggleExceptionUser(errorstrings.getString("Error_juggler_permutations")); if (((llow % rhythm_period) != 0) || (lhigh % rhythm_period) != 0) { String template = errorstrings.getString("Error_period_multiple"); Object[] arguments = { new Integer(rhythm_period) }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } find_ground(); // find ground state /* The following variable slot_size serves two functions. It */ /* is the size of a slot used in the multiplexing filter, and */ /* it is the number of throws allocated in memory. The number */ /* of throws needs to be larger than L sometimes since these */ /* same structures are used to find starting and ending */ /* sequences (containing as many as HT elements). */ slot_size = ((ht > lhigh) ? ht : lhigh); slot_size += rhythm_period - (slot_size % rhythm_period); for (i = 0; i < hands; i++) for (j = 0; j < rhythm_period; j++) if ((k = rhythm_repunit[i][j]) > max_occupancy) max_occupancy = k; max_occupancy *= multiplex; if (max_occupancy == 1) /* no multiplexing, turn off filter */ mp_filter = 0; /* Now allocate the memory space for the states, rhythms, and */ /* throws in the pattern, plus other incidental variables. */ pattern_state = new int[lhigh+1][hands][ground_state_length]; // last index not ht because of find_start_end() pattern_holes = new int[lhigh][hands][ht]; pattern_throw_to = new int[slot_size][hands][max_occupancy];// first index not l because of find_start_end() pattern_throw_value = new int[slot_size][hands][max_occupancy]; pattern_rhythm = new int[slot_size+1][hands][ht]; for (i = 0; i < (slot_size + 1); i++) for (j = 0; j < hands; j++) for (k = 0; k < ht; k++) pattern_rhythm[i][j][k] = multiplex * rhythm_repunit[j][(k + i) % rhythm_period]; if (mp_filter != 0) /* allocate space for filter variables */ pattern_filter = new int[lhigh+1][hands][slot_size][3]; pattern_throwcount = new int[lhigh][hands]; if (jugglers > 1) { /* passing communication delay variables */ scratch1 = new int[hands]; scratch2 = new int[hands]; } // Include the regular expressions that define "true multiplexing" if (true_multiplex) { String include_RE = null; if (jugglers == 1) { if (mode == ASYNCH) include_RE = ".*\\[[^2]*\\].*"; else if (mode == SYNCH) include_RE = ".*\\[([^2\\]]*2x)*[^2\\]]*\\].*"; } else { if (mode == ASYNCH) include_RE = ".*\\[([^2\\]]*(2p|.p2|2p.))*[^2\\]]*\\].*"; else if (mode == SYNCH) include_RE = ".*\\[([^2\\]]*(2p|.p2|2p.|2x|2xp|.xp2|2xp.))*[^2\\]]*\\].*"; } if (include_RE != null) include.add(Pattern.compile(include_RE)); } if (connected_patterns) connections = new boolean[jugglers]; if ((jugglers > 1) && !juggler_permutations) { perm_scratch1 = new boolean[lhigh]; perm_scratch2 = new boolean[lhigh]; } } /* The following reformats the exclude/include terms into standard regular expressions. It exchanges "\x" for "x", where x is one of the RE metacharacters that conflicts with siteswap notation: []()| */ protected String make_standard_RE(String term) { String res; res = Pattern.compile("\\\\\\[").matcher(term).replaceAll("@"); res = Pattern.compile("\\[").matcher(res).replaceAll("\\\\["); res = Pattern.compile("@").matcher(res).replaceAll("["); res = Pattern.compile("\\\\\\]").matcher(res).replaceAll("@"); res = Pattern.compile("\\]").matcher(res).replaceAll("\\\\]"); res = Pattern.compile("@").matcher(res).replaceAll("]"); res = Pattern.compile("\\\\\\(").matcher(res).replaceAll("@"); res = Pattern.compile("\\(").matcher(res).replaceAll("\\\\("); res = Pattern.compile("@").matcher(res).replaceAll("("); res = Pattern.compile("\\\\\\)").matcher(res).replaceAll("@"); res = Pattern.compile("\\)").matcher(res).replaceAll("\\\\)"); res = Pattern.compile("@").matcher(res).replaceAll(")"); res = Pattern.compile("\\\\\\|").matcher(res).replaceAll("@"); res = Pattern.compile("\\|").matcher(res).replaceAll("\\\\|"); res = Pattern.compile("@").matcher(res).replaceAll("|"); return res; } public int runGenerator(GeneratorTarget t) { try { return runGenerator(t, -1, -1.0); // no limits } catch (JuggleException je) { } return 0; // can't happen } public int runGenerator(GeneratorTarget t, int max_num, double secs) throws JuggleExceptionUser { if ((groundflag == 1) && (ground_state_length > ht)) { return 0; } this.target = t; this.max_num = max_num; this.max_time = secs; this.max_time_millis = (long)(1000.0 * secs); this.start_time_millis = System.currentTimeMillis(); this.loop_counter = 0; int num = 0; for (l = llow; l <= lhigh; l += rhythm_period) num += gen_patterns(0, 0, 0, 0); if (numflag != 0) { if (num == 1) target.setStatus(guistrings.getString("Generator_patterns_1")); else { String template = guistrings.getString("Generator_patterns_ne1"); Object[] arguments = { new Integer(num) }; target.setStatus(MessageFormat.format(template, arguments)); } } return num; } // Now the protected methods /* The following routine initializes stuff for the built-in rhythms. */ /* This involves allocating and initializing arrays. */ protected void initialize() { switch (mode) { case ASYNCH: rhythm_repunit = new int[jugglers][1]; holdthrow = new int[jugglers]; person_number = new int[jugglers]; hands = jugglers; rhythm_period = 1; pattern_printx = false; for (int i = 0; i < hands; i++) { rhythm_repunit[i][0] = asynch_rhythm_repunit[0][0]; holdthrow[i] = 2; person_number[i] = i+1; } break; case SYNCH: rhythm_repunit = new int[2*jugglers][2]; holdthrow = new int[2*jugglers]; person_number = new int[2*jugglers]; hands = 2*jugglers; rhythm_period = 2; pattern_printx = true; for (int i = 0; i < hands; i++) { for (int j = 0; j < rhythm_period; j++) rhythm_repunit[i][j] = synch_rhythm_repunit[i%2][j]; holdthrow[i] = 2; person_number[i] = (i/2) + 1; } break; } } /* This routine reads a custom rhythm file and parses it to get the */ /* relevant information. If there is an error it prints a message */ /* and then exits. */ /* void custom_initialize(char *custom_file) // name of file { int i, j, k, left_delim, right_delim; int last_period, last_person, person, hold, second_pass; char ch, *file_buffer; FILE *fp; if ((fp = fopen(custom_file, "r")) == NULL) { printf("File error: cannot open '%s'\n", custom_file); exit(0); } if ((file_buffer = (char *)malloc(BUFFER_SIZE * sizeof(char))) == 0) die(); for (second_pass = 0; second_pass < 2; second_pass++) { hands = j = 0; jugglers = last_person = 1; do { ch = (char)(i = fgetc(fp)); if ((ch == (char)10) || (i == EOF)) { file_buffer[j] = (char)0; for (j = 0, k = 0; (ch = file_buffer[j]) && (ch != ';'); j++) if (ch == '|') { if (++k == 1) left_delim = j; else if (k == 2) right_delim = j; } if (ch == ';') file_buffer[j] = (char)0; // terminate at comment if (k) { if (k != 2) { printf("File error: need two rhythm delimiters per hand\n"); exit(0); } // At this point the line checks out. See if // period is what we got last time. if (hands && ((right_delim-left_delim-1) != last_period)) { printf("File error: rhythm period not constant\n"); exit(0); } last_period = right_delim - left_delim - 1; // Now parse the line we've read in file_buffer[left_delim] = (char)0; person = atoi(file_buffer); if (hands) { if (person == (last_person + 1)) { jugglers++; last_person = person; } else if (person != last_person) { printf("File error: person numbers goofed up\n"); exit(0); } } else if (person != 1) { printf("File error: must start with person number 1\n"); exit(0); } // Now put stuff in the allocated arrays if (second_pass) { person_number[hands] = person; hold = atoi(file_buffer + right_delim + 1); holdthrow[hands] = (hold ? hold : 2); // Fill the rhythm matrix for (j = 0; j < rhythm_period; j++) { ch = file_buffer[j + left_delim + 1]; if (((ch < '0') || (ch > '9')) && (ch != ' ')) { printf("File error: bad character in rhythm\n"); exit(0); } if (ch == ' ') ch = '0'; rhythm_repunit[hands][j] = (int)(ch - '0'); } } hands++; // got valid line, increment counter } j = 0; // reset buffer pointer for next read } else { file_buffer[j] = ch; if (++j >= BUFFER_SIZE) { printf("File error: input buffer overflow\n"); exit(0); } } } while (i != EOF); if (!hands) { printf("File error: must have at least one hand\n"); exit(0); } if (!second_pass) { // allocate space after first pass rhythm_period = last_period; rhythm_repunit = alloc_array(hands, rhythm_period); if ((holdthrow = (int *)malloc(hands * sizeof(int))) == 0) die(); if ((person_number = (int *)malloc(hands * sizeof(int))) == 0) die(); rewind(fp); // go back to start of file } } (void)fclose(fp); // close file and free memory free(file_buffer); } */ /* valid_throw -- checks if a given throw is valid. Check for */ /* excluded throws and a passing communication delay, */ /* as well a custom filter (if in CUSTOM mode). */ protected boolean valid_throw(int pos) { int i, j, k, balls_left, balls_thrown; // test pattern in progress against all exclusions for (i = 0; i < exclude.size(); i++) { Pattern regex = (Pattern)exclude.elementAt(i); /*System.out.println("test for string " + (new String(output, 0, outputpos)) + " = " + regex.matcher(new String(output, 0, outputpos)).matches());*/ if (regex.matcher(new String(output, 0, outputpos)).matches()) return false; } for (i = 0; i < hands; i++) { if (pattern_rhythm[pos][i][0] != 0) { // can we make a throw here? for (j = 0; (j < max_occupancy) && ((k = pattern_throw_value[pos][i][j]) != 0); j++) { if (mp_clustered) // need to check for clustered throws? continue; for (int l = 0; l < j; l++) { if ((pattern_throw_value[pos][i][j] == pattern_throw_value[pos][i][l]) && (pattern_throw_to[pos][i][j] == pattern_throw_to[pos][i][l])) return false; } } } } /* Now check if we are allowing for a sufficient */ /* communication delay, if we are passing. */ if ((jugglers > 1) && (pos < delaytime)) { /* need to check? */ /* First count the number of balls being thrown, */ /* assuming no multiplexing. Also check if leader is */ /* forcing others to multiplex or make no throw. */ for (balls_thrown = 0, i = 0; i < hands; i++) { if (pattern_rhythm[pos][i][0] != 0) { balls_thrown++; if ((pattern_state[pos][i][0] != 1) && (person_number[i] != leader_person)) return false; } } balls_left = n; for (i = 0; (i < ht) && (balls_left != 0); i++) { for (j = 0; (j < hands) && (balls_left != 0); j++) { if (pattern_rhythm[pos + 1][j][i] != 0) { if (--balls_left < balls_thrown) { scratch1[balls_left] = j; /* dest hand # */ scratch2[balls_left] = i + 1; /* dest value */ } } } } if (balls_left != 0) return false; /* this shouldn't happen, but die anyway */ for (i = 0; i < hands; i++) { if ((pattern_state[pos][i][0] != 0) && (person_number[i] != leader_person)) { for (j = 0, k = 1; (j < balls_thrown) && (k != 0); j++) if ((scratch1[j] == pattern_throw_to[pos][i][0]) && (scratch2[j] == pattern_throw_value[pos][i][0])) scratch2[j] = k = 0; // can't throw to spot again if (k != 0) return false; /* wasn't throwing to empty position */ } } } return true; } protected boolean valid_pattern() { int i, j, k, m, p; // test pattern in progress against all inclusions for (i = 0; i < include.size(); i++) { Pattern regex = (Pattern)include.elementAt(i); if (!regex.matcher(new String(output, 0, outputpos)).matches()) return false; } if ((mode == ASYNCH) && lameflag && (max_occupancy == 1)) { for (i = 0; i < (l - 1); i++) /* check for '11' sequence */ for (j = 0; j < hands; j++) if ((pattern_throw_value[i][j][0] == 1) && (person_number[pattern_throw_to[i][j][0]] == person_number[j]) && (pattern_throw_value[i+1][j][0] == 1) && (person_number[pattern_throw_to[i+1][j][0]] == person_number[j])) return false; } // Added 12/4/2002 // Is the pattern composite? If so, ensure we only print one rotation of it if ((fullflag == 0) && (rotflag == 0)) { for (i = 1; i < l; i++) { if ((i % rhythm_period) == 0) { // can we compare states? if (compare_states(pattern_state[0], pattern_state[i]) == 0) { if (compare_rotations(0, i) < 0) return false; } } } } // test whether passing pattern is connected if (connected_patterns) { for (i = 0; i < jugglers; i++) connections[i] = false; connections[0] = true; boolean changed = true; while (changed) { changed = false; for (i = 0; i < l; i++) { for (j = 0; j < hands; j++) { if (connections[person_number[j]-1]) continue; for (k = 0; (k < max_occupancy) && (pattern_throw_value[i][j][k] > 0); k++) { m = person_number[pattern_throw_to[i][j][k]]; if (connections[m - 1]) { connections[person_number[j]-1] = true; changed = true; } } } } } for (i = 0; i < jugglers; i++) if (!connections[i]) return false; } // Test to see whether there is a better permutation of jugglers // This algorithm is not guaranteed to eliminate all permuted duplicates, but will do so in the // vast majority of cases. if ((jugglers > 1) && !juggler_permutations) { for (m = 1; m <= (jugglers-1); m++) { // compare juggler m against juggler (m+1) for (i = 0; i < l; i++) perm_scratch1[i] = perm_scratch2[i] = false; for (p = 0; p < l; p++) { int scorem = -1, scoremp1 = -1, maxm = 0, maxmp1 = 0; for (i = 0; i < l; i++) { if (!perm_scratch1[i]) { int scoretemp = 0; for (j = 0; j < hands; j++) { if (person_number[j] != m) continue; for (k = 0; (k < max_occupancy) && (pattern_throw_value[i][j][k] > 0); k++) { scoretemp += 4 * pattern_throw_value[i][j][k] * (2*max_occupancy) * (2*max_occupancy); if (pattern_throw_to[i][j][k] != j) { scoretemp += 2 * (2*max_occupancy); if (person_number[pattern_throw_to[i][j][k]] != m) scoretemp += 1; } } } if (scoretemp > scorem) { scorem = scoretemp; maxm = i; } } if (!perm_scratch2[i]) { int scoretemp = 0; for (j = 0; j < hands; j++) { if (person_number[j] != (m+1)) continue; for (k = 0; (k < max_occupancy) && (pattern_throw_value[i][j][k] > 0); k++) { scoretemp += 4 * pattern_throw_value[i][j][k] * (2*max_occupancy) * (2*max_occupancy); if (pattern_throw_to[i][j][k] != j) { scoretemp += 2 * (2*max_occupancy); if (person_number[pattern_throw_to[i][j][k]] != (m+1)) scoretemp += 1; } } } if (scoretemp > scoremp1) { scoremp1 = scoretemp; maxmp1 = i; } } } if (scoremp1 > scorem) return false; if (scoremp1 < scorem) break; // go to the next pair of jugglers perm_scratch1[maxm] = perm_scratch2[maxmp1] = true; } } } return true; } // Added 12/9/2002 // This method assumes the throws are comparable, i.e., that pos1 is congruent to pos2 // mod rhythm_period protected int compare_rotations(int pos1, int pos2) { for (int i = 0; i < l; ) { int res = compare_loops((pos1+i)%l, (pos2+i)%l); if (res > 0) return 1; else if (res < 0) return -1; i++; for (; i < l; i++) { if (compare_states(pattern_state[pos1], pattern_state[(pos1+i)%l]) == 0) break; } } return 0; } // Added 12/4/2002 protected int compare_loops(int pos1, int pos2) { int[][] startstate = pattern_state[pos1]; int result = 0; int i = 0; // Rule 1: The longer loop is always greater // Rule 2: For loops of equal length, use throw-by-throw comparison // Rule 3: Loops are equal only if the respective throws are identical while (true) { i++; if (result == 0) result = compare_throws(pos1, pos2); if ((i % rhythm_period) == 0) { int cs1 = compare_states(pattern_state[pos1+1], startstate); int cs2 = compare_states(pattern_state[pos2+1], startstate); if (cs1 == 0) { if (cs2 == 0) return result; return -1; } if (cs2 == 0) return 1; } pos1++; pos2++; } } // Added 12/7/2002 // This method assumes the throws are comparable, i.e., that pos1 is congruent // to pos2 mod rhythm_period protected int compare_throws(int pos1, int pos2) { int[][] value1 = pattern_throw_value[pos1]; int[][] to1 = pattern_throw_to[pos1]; int[][] value2 = pattern_throw_value[pos2]; int[][] to2 = pattern_throw_to[pos2]; int[][] rhythm = pattern_rhythm[pos1]; // same as pos2 since throws comparable // Rule 1: Throws are equal only if identical for (int i = 0; i < hands; i++) { for (int j = 0; j < rhythm[i][0]; j++) { if (value1[i][j] > value2[i][j]) return 1; else if (value1[i][j] < value2[i][j]) return -1; else if (to1[i][j] > to2[i][j]) return 1; else if (to1[i][j] < to2[i][j]) return -1; } } return 0; } /* compare_states -- equality (0), lesser (-1), or greater (1) */ protected int compare_states(int state1[][], int state2[][]) { int i, j, mo1 = 0, mo2 = 0; for (i = 0; i < hands; i++) { for (j = 0; j < ht; j++) { if (state1[i][j] > mo1) mo1 = state1[i][j]; if (state2[i][j] > mo2) mo2 = state2[i][j]; } } if (mo1 > mo2) return 1; if (mo1 < mo2) return -1; for (j = (ht - 1); j >= 0; j--) { for (i = (hands - 1); i >= 0; i--) { mo1 = state1[i][j]; mo2 = state2[i][j]; if (mo1 > mo2) return 1; if (mo1 < mo2) return -1; } } return 0; } /* returns number as single character */ protected char convert_number(int value) { return Character.toLowerCase(Character.forDigit(value, 36)); } protected int print_throw(char[] out, int outpos, int[][] throw_value, int[][] throw_to, int[][] rhythm) { int i, j, k, m, q, lo_hand, hi_hand; boolean multiplex, parens; char ch; for (i = 0; i < rhythm.length; i++) if (rhythm[i][0] != 0) break; if (i == rhythm.length) // no throw on this beat return outpos; if (jugglers > 1) out[outpos++] = '<'; for (i = 1; i <= jugglers; i++) { // first find the hand numbers corresponding to person for (lo_hand = 0; person_number[lo_hand] != i; lo_hand++) ; for (hi_hand = lo_hand; (hi_hand < hands) && (person_number[hi_hand] == i); hi_hand++) ; // check rhythm to see if person is throwing this time for (j = lo_hand, k = 0; j < hi_hand; j++) if (rhythm[j][0] != 0) k++; if (k > 0) { // person should throw if (k > 1) { // more than one hand throwing? out[outpos++] = '('; parens = true; } else parens = false; for (j = lo_hand; j < hi_hand; j++) { if (rhythm[j][0] == 0) // this hand supposed to throw? continue; if ((max_occupancy > 1) && (throw_value[j][1] > 0)) { out[outpos++] = '['; // multiplexing? multiplex = true; } else multiplex = false; // Now loop thru the throws coming out of this hand for (k = 0; (k < max_occupancy) && (throw_value[j][k] > 0); k++) { m = throw_value[j][k]; out[outpos++] = convert_number(m); // print throw value if (hands > 1) { // potential ambiguity about destination? m = person_number[throw_to[j][k]]; // print destination hand, if needed if (pattern_printx) { // find hand # of destination person q = throw_to[j][k] - 1; int dest_hand = 0; while ((q >= 0) && (person_number[q] == m)) { q--; dest_hand++; } if (dest_hand != (j - lo_hand)) out[outpos++] = 'x'; } // print pass modifier and person number, if needed if (m != i) { out[outpos++] = 'p'; if (jugglers > 2) out[outpos++] = convert_number(m); } /* // destination person has 1 hand, don't print if ((ch != 'a') || ((q < (hands - 2)) && (person_number[q + 2] == m))) out[outpos++] = ch; // print it */ } if (multiplex && (jugglers > 1) && (k != (max_occupancy - 1)) && (throw_value[j][k + 1] > 0)) out[outpos++] = '/'; // another multiplexed throw? } if (k == 0) out[outpos++] = '0'; if (multiplex) out[outpos++] = ']'; if ((j < (hi_hand - 1)) && parens) // put comma between hands out[outpos++] = ','; } if (parens) out[outpos++] = ')'; } if (i < jugglers) // another person throwing next? out[outpos++] = '|'; } if (jugglers > 1) out[outpos++] = '>'; return outpos; } protected void print_pattern() { int i, j, excited = 0, skip; StringBuffer outputline = new StringBuffer(hands*(2*ground_state_length+l)*CHARS_PER_THROW + 10); StringBuffer outputline2 = new StringBuffer(hands*(2*ground_state_length+l)*CHARS_PER_THROW + 10); if (groundflag != 1) { if (sequenceflag) { if (mode == ASYNCH) { for (i = n - starting_seq_length; i > 0; i--) outputline.append(" "); } outputline.append(starting_seq, 0, starting_seq_length); outputline.append(" "); } else { excited = compare_states(ground_state, pattern_state[0]); if (excited != 0) outputline.append("* "); else outputline.append(" "); } } outputline.append(output, 0, outputpos); outputline2.append(output, 0, outputpos); if (groundflag != 1) { if (sequenceflag) { outputline.append(" "); outputline.append(ending_seq, 0, ending_seq_length); // add proper number of trailing spaces too, so formatting is aligned // in RTL languages if (mode == ASYNCH) { for (i = n - ending_seq_length; i > 0; i--) outputline.append(" "); } } else { if (excited != 0) outputline.append(" *"); else outputline.append(" "); } } target.writePattern(outputline.toString(), "siteswap", outputline2.toString().trim()); } /* The next function is part of the implementation of the */ /* multiplexing filter. It adds a throw to a filter slot, */ /* returning 1 if there is a collision, 0 otherwise. */ protected int mp_addthrow(int dest_slot[], int slot_hand, int type, int value, int from) { switch (type) { case MP_EMPTY: return 0; case MP_LOWER_BOUND: if (dest_slot[TYPE] == MP_EMPTY) { dest_slot[TYPE] = MP_LOWER_BOUND; dest_slot[VALUE] = value; dest_slot[FROM] = from; } return 0; case MP_THROW: if ((from == slot_hand) && (value == holdthrow[slot_hand])) return 0; /* throw is a hold, so ignore it */ switch (dest_slot[TYPE]) { case MP_EMPTY: dest_slot[TYPE] = MP_THROW; dest_slot[VALUE] = value; dest_slot[FROM] = from; return 0; case MP_LOWER_BOUND: if ((dest_slot[VALUE] <= value) || (dest_slot[VALUE] <= holdthrow[slot_hand])) { dest_slot[TYPE] = MP_THROW; dest_slot[VALUE] = value; dest_slot[FROM] = from; return 0; } break; /* this kills recursion */ case MP_THROW: if ((dest_slot[FROM] == from) && (dest_slot[VALUE] == value)) return 0; /* throws from same place (cluster) */ break; /* kills recursion */ } break; } return 1; } /* gen_loops -- Recursively generates loops, given a particular starting state. */ protected int gen_loops(int pos, int throws_made, int min_throw, int min_hand, int num) throws JuggleExceptionUser { /* int pos; /* slot number in pattern that we're constructing */ /* int throws_made; /* number of throws made out of current slot */ /* int min_throw; /* lowest we can throw this time */ /* int min_hand; /* lowest hand we can throw to this time */ /* unsigned int num; /* number of valid patterns counted */ int i, j, k, m, o; int outputpos_temp = outputpos; if (max_time > 0.0) { if (loop_counter++ > loop_counter_max) { loop_counter = 0; if ((System.currentTimeMillis() - start_time_millis) > max_time_millis) { String template = guistrings.getString("Generator_timeout"); Object[] arguments = { new Integer((int)max_time) }; throw new JuggleExceptionDone(MessageFormat.format(template, arguments)); } } } if (pos == l) { if ((compare_states(pattern_state[0], pattern_state[l]) == 0) && valid_pattern()) { if (numflag != 2) print_pattern(); if (num++ == max_num) { String template = guistrings.getString("Generator_spacelimit"); Object[] arguments = { new Integer(max_num) }; throw new JuggleExceptionDone(MessageFormat.format(template, arguments)); } } outputpos = outputpos_temp; return num; } if (throws_made == 0) for (i = 0; i < hands; i++) { pattern_throwcount[pos][i] = pattern_state[pos][i][0]; for (j = 0; j < ht; j++) { pattern_holes[pos][i][j] = pattern_rhythm[pos + 1][i][j]; if (j != (ht - 1)) pattern_holes[pos][i][j] -= pattern_state[pos][i][j + 1]; } for (j = 0; j < max_occupancy; j++) { pattern_throw_to[pos][i][j] = i; /* clear throw matrix */ pattern_throw_value[pos][i][j] = 0; } } for (i = 0; (i < hands) && (pattern_throwcount[pos][i] == 0); i++) ; if (i == hands) { /* done with current slot, move to next */ outputpos = print_throw(output, outputpos, pattern_throw_value[pos], pattern_throw_to[pos], pattern_rhythm[pos]); if (!valid_throw(pos)) { /* is the throw ok? */ outputpos = outputpos_temp; return num; } /* first calculate the next state in ptrn, given last throw */ for (j = 0; j < hands; j++) /* shift state to the left */ for (k = 0; k < ht; k++) pattern_state[pos + 1][j][k] = ( (k == (ht-1)) ? 0 : pattern_state[pos][j][k+1] ); /* add on the last throw */ for (j = 0; j < hands; j++) for (k = 0; (k < max_occupancy) && ((m = pattern_throw_value[pos][j][k]) != 0); k++) pattern_state[pos + 1][pattern_throw_to[pos][j][k]][m - 1]++; /* Check if this is a valid state for a period-L pattern */ /* This check added 01/19/98. */ for (j = 0; j < hands; j++) { for (k = 0; k < ht; k++) { o = k; while (o < (ht-l)) { if (pattern_state[pos + 1][j][o + l] > pattern_state[pos + 1][j][o]) { outputpos = outputpos_temp; return num; /* die (invalid state for this L) */ } o += l; } } } /* end of new section */ if (((pos + 1) % rhythm_period) == 0) { /* can we compare states? (rhythms must be same) */ j = compare_states(pattern_state[0], pattern_state[pos + 1]); if ((fullflag != 0) && (pos != (l - 1)) && (j == 0)) /* intersection */ { outputpos = outputpos_temp; return num; } if ((rotflag == 0) && (j == 1)) { /* prevents rotations from being printed */ outputpos = outputpos_temp; return num; } } if (fullflag == 2) { /* list only simple loops? */ for (j = 1; j <= pos; j++) if (((pos + 1 - j) % rhythm_period) == 0) { if (compare_states(pattern_state[j], pattern_state[pos + 1]) == 0) { outputpos = outputpos_temp; return num; } } } /* Now do the multiplexing filter. This ensures that, */ /* other than holds, objects from only one source are */ /* landing in any given hand (for example, a cluster of */ /* 3's). The implementation is a little complicated, */ /* since I want to cut off the recursion as quickly as */ /* possible to get speed on big searches. This */ /* precludes simply generating all patterns and then */ /* throwing out the unwanted ones. */ if (mp_filter != 0) { for (j = 0; j < hands; j++) { /* shift filter frame to left */ for (k = 0; k < (slot_size - 1); k++) { pattern_filter[pos + 1][j][k][TYPE] = pattern_filter[pos][j][k + 1][TYPE]; pattern_filter[pos + 1][j][k][FROM] = pattern_filter[pos][j][k + 1][FROM]; pattern_filter[pos + 1][j][k][VALUE] = pattern_filter[pos][j][k + 1][VALUE]; } pattern_filter[pos + 1][j][slot_size - 1][TYPE] = MP_EMPTY; /* empty slots shift in */ if (mp_addthrow( pattern_filter[pos + 1][j][l - 1], j, pattern_filter[pos][j][0][TYPE], pattern_filter[pos][j][0][VALUE], pattern_filter[pos][j][0][FROM]) != 0) { outputpos = outputpos_temp; return num; } } for (j = 0; j < hands; j++) /* add on last throw */ for (k = 0; (k < max_occupancy) && ((m = pattern_throw_value[pos][j][k]) != 0); k++) if (mp_addthrow( pattern_filter[pos + 1][pattern_throw_to[pos][j][k]][m - 1], pattern_throw_to[pos][j][k], MP_THROW, m, j) != 0) { outputpos = outputpos_temp; return num; /* problem, so end recursion */ } } num = gen_loops(pos + 1, 0, 1, 0, num); /* go to next slot */ } else { m = --pattern_throwcount[pos][i]; /* record throw */ k = min_hand; for (j = min_throw; j <= ht; j++) { for ( ; k < hands; k++) { if (pattern_holes[pos][k][j - 1] != 0) {/*can we throw to position?*/ pattern_holes[pos][k][j - 1]--; pattern_throw_to[pos][i][m] = k; pattern_throw_value[pos][i][m] = j; if (m != 0) num = gen_loops(pos, throws_made + 1, j, k, num); else num = gen_loops(pos, throws_made + 1, 1, 0, num); pattern_holes[pos][k][j - 1]++; } } k = 0; } pattern_throwcount[pos][i]++; } outputpos = outputpos_temp; return num; } /* The next routine finds valid starting and ending sequences for */ /* excited state patterns. Note that these sequences are not unique. */ // Rewritten on 12/31/03 protected void find_start_end() { int i, j, k, m, q; /* first find the starting sequence */ int start_beats = 0; findstarting1: do { for (j = 0; j < hands; j++) { for (k = 0; k < ht; k++) { // use p_s[1] as scratch if ((k + start_beats) < ground_state_length) pattern_state[1][j][k] = ground_state[j][k+start_beats]; else pattern_state[1][j][k] = 0; if (pattern_state[1][j][k] > pattern_state[0][j][k]) { start_beats += rhythm_period; continue findstarting1; } pattern_state[1][j][k] = pattern_state[0][j][k] - pattern_state[1][j][k]; } } break; } while (true); for (i = 0; i < start_beats; i++) { for (j = 0; j < hands; j++) { for (k = 0; k < max_occupancy; k++) { pattern_throw_value[i][j][k] = 0; pattern_throw_to[i][j][k] = j; } if ((i >= ground_state_length) || (ground_state[j][i] == 0)) continue; findstarting2: for (k = 0; k < ht; k++) { for (m = 0; m < hands; m++) { if (pattern_state[1][m][k] > 0) { pattern_state[1][m][k]--; pattern_throw_value[i][j][0] = k + start_beats - i; pattern_throw_to[i][j][0] = m; break findstarting2; } } } } } // write starting sequence to buffer starting_seq = new char[hands * start_beats * CHARS_PER_THROW]; starting_seq_length = 0; for (i = 0; i < start_beats; i++) { starting_seq_length = print_throw(starting_seq, starting_seq_length, pattern_throw_value[i], pattern_throw_to[i], pattern_rhythm[i]); } /* Now construct an ending sequence. Unlike the starting */ /* sequence above, this time work forward to ground state. */ int end_beats = 0; findending1: do { for (j = 0; j < hands; j++) { for (k = 0; k < ground_state_length; k++) { // use pattern_state[1] as scratch if ((k + end_beats) < ht) pattern_state[1][j][k] = pattern_state[0][j][k+end_beats]; else pattern_state[1][j][k] = 0; if (pattern_state[1][j][k] > ground_state[j][k]) { end_beats += rhythm_period; continue findending1; } pattern_state[1][j][k] = ground_state[j][k] - pattern_state[1][j][k]; } } break; } while (true); for (i = 0; i < end_beats; i++) { for (j = 0; j < hands; j++) { for (k = 0; k < max_occupancy; k++) { pattern_throw_value[i][j][k] = 0; pattern_throw_to[i][j][k] = j; } if (i >= ht) continue; for (q = 0; q < pattern_state[0][j][i]; q++) { findending2: for (k = 0; k < ground_state_length; k++) { for (m = 0; m < hands; m++) { if (pattern_state[1][m][k] > 0) { pattern_state[1][m][k]--; pattern_throw_value[i][j][q] = k + end_beats - i; pattern_throw_to[i][j][q] = m; break findending2; } } } } } } ending_seq = new char[hands * end_beats * CHARS_PER_THROW]; ending_seq_length = 0; for (j = 0; j < end_beats; j++) { ending_seq_length = print_throw(ending_seq, ending_seq_length, pattern_throw_value[j], pattern_throw_to[j], pattern_rhythm[j]); } } /* gen_patterns -- Recursively generates all possible starting */ /* states, calling gen_loops above to find the loops */ /* for each one. */ protected int gen_patterns(int balls_placed, int min_value, int min_to, int num) throws JuggleExceptionUser { int i, j, k, m, q; if ((balls_placed == n) || (groundflag == 1)) { if (groundflag == 1) { /* find only ground state patterns? */ for (i = 0; i < hands; i++) for (j = 0; j < ht; j++) pattern_state[0][i][j] = ground_state[i][j]; } else if ((groundflag == 2) && (compare_states(pattern_state[0], ground_state) == 0)) return num; /* don't find ground state patterns */ /* At this point our state is completed. Check to see */ /* if it's valid. (Position X must be at least as large */ /* as position X+L, where L = pattern length.) Also set */ /* up the initial multiplexing filter frame, if we need it. */ for (i = 0; i < hands; i++) { for (j = 0; j < ht; j++) { k = pattern_state[0][i][j]; if ((mp_filter != 0) && (k == 0)) pattern_filter[0][i][j][TYPE] = MP_EMPTY; else { if (mp_filter != 0) { pattern_filter[0][i][j][VALUE] = j + 1; pattern_filter[0][i][j][FROM] = i; pattern_filter[0][i][j][TYPE] = MP_LOWER_BOUND; } m = j; while ((m += l) < ht) { if ((q = pattern_state[0][i][m]) > k) return num; /* die (invalid state for this L) */ if ((mp_filter != 0) && (q != 0)) { if ((q < k) && (j > holdthrow[i])) return num; /* different throws into same hand */ pattern_filter[0][i][j][VALUE] = m + 1; /* new bound */ } } } } if (mp_filter != 0) for ( ; j < slot_size; j++) pattern_filter[0][i][j][TYPE] = MP_EMPTY; /* clear rest of slot */ } if ((numflag != 2) && sequenceflag) find_start_end();/* find starting and ending sequences for state */ return gen_loops(0, 0, 1, 0, num); /* find patterns thru state */ } if (balls_placed == 0) { /* startup, clear state */ for (i = 0; i < hands; i++) for (j = 0; j < ht; j++) pattern_state[0][i][j] = 0; } j = min_to; /* ensures each state is generated only once */ for (i = min_value; i < ht; i++) { for ( ; j < hands; j++) { if (pattern_state[0][j][i] < pattern_rhythm[0][j][i]) { pattern_state[0][j][i]++; num = gen_patterns(balls_placed + 1, i, j, num); /* recursion */ pattern_state[0][j][i]--; } } j = 0; } return num; } /* find_ground -- Find the ground state for our rhythm. Just put */ /* the balls in the lowest possible slots, with no */ /* multiplexing. */ protected void find_ground() { int i, j, balls_left; balls_left = n; for (i = 0; balls_left != 0; i++) { for (j = 0; (j < hands) && (balls_left != 0); j++) { if (rhythm_repunit[j][i % rhythm_period] != 0) { balls_left--; if (balls_left == 0) ground_state_length = i + 1; } } } if (ground_state_length < ht) ground_state_length = ht; ground_state = new int[hands][ground_state_length]; for (i = 0; i < hands; i++) /* clear ground state array */ for (j = 0; j < ground_state_length; j++) ground_state[i][j] = 0; balls_left = n; for (i = 0; balls_left != 0; i++) { for (j = 0; (j < hands) && (balls_left != 0); j++) { if (rhythm_repunit[j][i % rhythm_period] != 0) { /* available slots */ ground_state[j][i] = 1; balls_left--; } } } } public static void main(String[] args) { if (args.length < 3) { String template = guistrings.getString("Version"); Object[] arg1 = { Constants.version }; String output = "Juggling Lab " + MessageFormat.format(template, arg1).toLowerCase()+"\n"; template = guistrings.getString("Copyright_message"); Object[] arg2 = { Constants.year }; output += MessageFormat.format(template, arg2)+"\n\n"; output += guistrings.getString("GPL_message")+"\n\n"; output += guistrings.getString("Generator_intro"); System.out.println(output); } else { siteswapGenerator ssg = new siteswapGenerator(); try { ssg.initGenerator(args); ssg.runGenerator(new GeneratorTarget(System.out));// no pattern number limit } catch (Exception e) { System.out.println(errorstrings.getString("Error")+": "+e.getMessage()); // jugglinglab.util.ErrorDialog.handleException(e); } } } } jugglinglab-0.6.2+ds.1/source/jugglinglab/generator/siteswapGeneratorControl.java000077500000000000000000000476751323754603300302660ustar00rootroot00000000000000// siteswapGeneratorControl.java // // Copyright 2011 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.generator; import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.util.regex.*; import java.text.MessageFormat; import jugglinglab.util.*; import jugglinglab.core.*; class siteswapGeneratorControl extends JPanel { static ResourceBundle guistrings; static ResourceBundle errorstrings; static { guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } // text fields in control panel protected JTextField tf1, tf2, tf3, tf4, tf5, /*tf6,*/ tf7, /*tf8,*/ tf9; protected JRadioButton cb1, cb2, /*cb3,*/ cb4, cb5, cb6; protected JCheckBox cb7, cb8, cb9, cb10, cb12, cb13, cb14, cb15, cb16, cb17; protected JLabel lab1, lab2, /*lab3,*/ lab4, /*lab5,*/ lab13; protected JComboBox c1; protected final static int border = 10; public siteswapGeneratorControl() { this.setOpaque(false); GridBagLayout gb = new GridBagLayout(); this.setLayout(gb); JPanel p2 = new JPanel(); // top of window p2.setLayout(gb); JLabel lab6 = new JLabel(guistrings.getString("balls")); p2.add(lab6); gb.setConstraints(lab6, make_constraints(GridBagConstraints.LINE_END,0,0, new Insets(0,0,0,3))); tf1 = new JTextField(3); p2.add(tf1); gb.setConstraints(tf1, make_constraints(GridBagConstraints.LINE_START,1,0)); JLabel lab7 = new JLabel(guistrings.getString("max._throw")); p2.add(lab7); gb.setConstraints(lab7, make_constraints(GridBagConstraints.LINE_END,2,0, new Insets(0,15,0,3))); tf2 = new JTextField(3); p2.add(tf2); gb.setConstraints(tf2, make_constraints(GridBagConstraints.LINE_START,3,0)); JLabel lab8 = new JLabel(guistrings.getString("period")); p2.add(lab8); gb.setConstraints(lab8, make_constraints(GridBagConstraints.LINE_END,4,0, new Insets(0,15,0,3))); tf3 = new JTextField(3); p2.add(tf3); gb.setConstraints(tf3, make_constraints(GridBagConstraints.LINE_START,5,0)); JPanel p6 = new JPanel(); p6.setLayout(gb); JLabel lab14 = new JLabel(guistrings.getString("Jugglers")); p6.add(lab14); gb.setConstraints(lab14, make_constraints(GridBagConstraints.LINE_START,0,0)); c1 = new JComboBox(); for (int i = 1; i <= 6; i++) c1.addItem(Integer.toString(i)+" "); p6.add(c1); gb.setConstraints(c1, make_constraints(GridBagConstraints.LINE_START,0,1, new Insets(0,10,0,0))); JLabel lab9 = new JLabel(guistrings.getString("Rhythm")); p6.add(lab9); gb.setConstraints(lab9, make_constraints(GridBagConstraints.LINE_START,0,2, new Insets(8,0,0,0))); ButtonGroup bg1 = new ButtonGroup(); cb1 = new JRadioButton(guistrings.getString("asynch")); bg1.add(cb1); p6.add(cb1); gb.setConstraints(cb1, make_constraints(GridBagConstraints.LINE_START,0,3, new Insets(0,10,0,0))); cb2 = new JRadioButton(guistrings.getString("synch")); bg1.add(cb2); p6.add(cb2); gb.setConstraints(cb2, make_constraints(GridBagConstraints.LINE_START,0,4, new Insets(0,10,0,0))); /* cb3 = new JRadioButton("passing"); bg1.add(cb3); p6.add(cb3); gb.setConstraints(cb3, make_constraints(GridBagConstraints.LINE_START,0,5, new Insets(0,10,0,0))); */ JPanel p7 = new JPanel(); p7.setLayout(gb); JLabel lab10 = new JLabel(guistrings.getString("Compositions")); p7.add(lab10); gb.setConstraints(lab10, make_constraints(GridBagConstraints.LINE_START,0,0, new Insets(5,0,0,0))); ButtonGroup bg2 = new ButtonGroup(); cb5 = new JRadioButton(guistrings.getString("all")); bg2.add(cb5); p7.add(cb5); gb.setConstraints(cb5, make_constraints(GridBagConstraints.LINE_START,0,1, new Insets(0,10,0,0))); cb4 = new JRadioButton(guistrings.getString("non-obvious")); bg2.add(cb4); p7.add(cb4); gb.setConstraints(cb4, make_constraints(GridBagConstraints.LINE_START,0,2, new Insets(0,10,0,0))); cb6 = new JRadioButton(guistrings.getString("none_(prime_only)")); bg2.add(cb6); p7.add(cb6); gb.setConstraints(cb6, make_constraints(GridBagConstraints.LINE_START,0,3, new Insets(0,10,0,0))); JPanel p8 = new JPanel(); p8.setLayout(gb); JLabel lab11 = new JLabel(guistrings.getString("Find")); p8.add(lab11); gb.setConstraints(lab11, make_constraints(GridBagConstraints.LINE_START,0,0)); cb7 = new JCheckBox(guistrings.getString("ground_state_patterns"), null); p8.add(cb7); gb.setConstraints(cb7, make_constraints(GridBagConstraints.LINE_START,0,1, new Insets(0,10,0,0))); cb8 = new JCheckBox(guistrings.getString("excited_state_patterns"), null); p8.add(cb8); gb.setConstraints(cb8, make_constraints(GridBagConstraints.LINE_START,0,2, new Insets(0,10,0,0))); cb9 = new JCheckBox(guistrings.getString("transition_throws"), null); p8.add(cb9); gb.setConstraints(cb9, make_constraints(GridBagConstraints.LINE_START,0,3, new Insets(0,10,0,0))); cb10 = new JCheckBox(guistrings.getString("pattern_rotations"), null); p8.add(cb10); gb.setConstraints(cb10, make_constraints(GridBagConstraints.LINE_START,0,4, new Insets(0,10,0,0))); cb17 = new JCheckBox(guistrings.getString("juggler_permutations"), null); p8.add(cb17); gb.setConstraints(cb17, make_constraints(GridBagConstraints.LINE_START,0,5, new Insets(0,10,0,0))); cb15 = new JCheckBox(guistrings.getString("connected_patterns"), null); p8.add(cb15); gb.setConstraints(cb15, make_constraints(GridBagConstraints.LINE_START,0,6, new Insets(0,10,0,0))); JPanel p9 = new JPanel(); p9.setLayout(gb); JLabel lab12 = new JLabel(guistrings.getString("Multiplexing")); p9.add(lab12); gb.setConstraints(lab12, make_constraints(GridBagConstraints.LINE_START,0,0, new Insets(5,0,0,0))); cb12 = new JCheckBox(guistrings.getString("enable"), null); p9.add(cb12); gb.setConstraints(cb12, make_constraints(GridBagConstraints.LINE_START,0,1, new Insets(0,10,0,0))); JPanel p3 = new JPanel(); p3.setLayout(gb); tf9 = new JTextField(3); p3.add(tf9); gb.setConstraints(tf9, make_constraints(GridBagConstraints.LINE_START,1,0)); lab13 = new JLabel(guistrings.getString("simultaneous_throws")); p3.add(lab13); gb.setConstraints(lab13, make_constraints(GridBagConstraints.LINE_END,0,0, new Insets(0,0,0,3))); p9.add(p3); gb.setConstraints(p3, make_constraints(GridBagConstraints.LINE_START,0,2, new Insets(0,10,0,0))); cb13 = new JCheckBox(guistrings.getString("no_simultaneous_catches"), null); p9.add(cb13); gb.setConstraints(cb13, make_constraints(GridBagConstraints.LINE_START,0,3, new Insets(0,10,0,0))); cb14 = new JCheckBox(guistrings.getString("no_clustered_throws"), null); p9.add(cb14); gb.setConstraints(cb14, make_constraints(GridBagConstraints.LINE_START,0,4, new Insets(0,10,0,0))); cb16 = new JCheckBox(guistrings.getString("true_multiplexing"), null); p9.add(cb16); gb.setConstraints(cb16, make_constraints(GridBagConstraints.LINE_START,0,5, new Insets(0,10,0,0))); JPanel p4 = new JPanel(); // whole middle part of window p4.setLayout(gb); p4.add(p6); gb.setConstraints(p6, make_constraints(GridBagConstraints.FIRST_LINE_START,0,0)); p4.add(p7); gb.setConstraints(p7, make_constraints(GridBagConstraints.FIRST_LINE_START,0,1)); p4.add(p8); gb.setConstraints(p8, make_constraints(GridBagConstraints.FIRST_LINE_START,1,0)); p4.add(p9); gb.setConstraints(p9, make_constraints(GridBagConstraints.FIRST_LINE_START,1,1)); JPanel p1 = new JPanel(); p1.setLayout(gb); tf4 = new JTextField(10); p1.add(tf4); gb.setConstraints(tf4, make_constraints(GridBagConstraints.LINE_START,1,0)); tf5 = new JTextField(10); p1.add(tf5); gb.setConstraints(tf5, make_constraints(GridBagConstraints.LINE_START,1,1)); /* tf6 = new JTextField(10); p1.add(tf6); gb.setConstraints(tf6, make_constraints(GridBagConstraints.LINE_START,0,2)); */ tf7 = new JTextField(3); p1.add(tf7); gb.setConstraints(tf7, make_constraints(GridBagConstraints.LINE_START,1,2, new Insets(3,0,0,0))); /* tf8 = new JTextField(3); p1.add(tf8); gb.setConstraints(tf8, make_constraints(GridBagConstraints.LINE_END,0,4)); */ lab1 = new JLabel(guistrings.getString("Exclude_these_throws")); p1.add(lab1); gb.setConstraints(lab1, make_constraints(GridBagConstraints.LINE_END,0,0, new Insets(0,0,0,3))); lab2 = new JLabel(guistrings.getString("Include_these_throws")); p1.add(lab2); gb.setConstraints(lab2, make_constraints(GridBagConstraints.LINE_END,0,1, new Insets(0,0,0,3))); /* lab3 = new JLabel(guistrings.getString("Exclude_these_passes")); p1.add(lab3); gb.setConstraints(lab3, make_constraints(GridBagConstraints.LINE_END,1,2, new Insets(0,0,0,3))); */ lab4 = new JLabel(guistrings.getString("Passing_communication_delay")); p1.add(lab4); gb.setConstraints(lab4, make_constraints(GridBagConstraints.LINE_END,0,2, new Insets(3,0,0,3))); /* lab5 = new JLabel("Passing leader slot number"); p1.add(lab5); gb.setConstraints(lab5, make_constraints(GridBagConstraints.LINE_START,1,4, new Insets(0,0,0,3))); */ this.add(p2); // now make the whole window gb.setConstraints(p2, make_constraints(GridBagConstraints.CENTER,0,0, new Insets(border,border,5,border))); this.add(p4); gb.setConstraints(p4, make_constraints(GridBagConstraints.CENTER,0,1, new Insets(5,border,5,border))); this.add(p1); gb.setConstraints(p1, make_constraints(GridBagConstraints.CENTER,0,2, new Insets(5,border,5,border))); // now add action listeners to enable/disable items depending on context c1.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent ex) { if (c1.getSelectedIndex() > 0) { // lab3.setEnabled(true); // lab5.setEnabled(true); // tf6.setEnabled(true); cb15.setEnabled(true); cb17.setEnabled(cb7.isSelected() && cb8.isSelected()); if (cb7.isSelected() && !cb8.isSelected()) { lab4.setEnabled(true); tf7.setEnabled(true); } else { lab4.setEnabled(false); tf7.setEnabled(false); } // tf8.setEnabled(true); // lab1.setText(guistrings.getString("Exclude_these_self_throws")); // lab2.setText(guistrings.getString("Include_these_self_throws")); } else { // lab3.setEnabled(false); // lab5.setEnabled(false); // tf6.setEnabled(false); cb15.setEnabled(false); cb17.setEnabled(false); lab4.setEnabled(false); tf7.setEnabled(false); // tf8.setEnabled(false); // lab1.setText(guistrings.getString("Exclude_these_throws")); // lab2.setText(guistrings.getString("Include_these_throws")); } // Transfer focus back up so that the run button works c1.transferFocus(); } }); cb12.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent iv) { if (cb12.isSelected()) { cb13.setEnabled(true); cb14.setEnabled(true); lab13.setEnabled(true); tf9.setEnabled(true); cb16.setEnabled(true); } else { cb13.setEnabled(false); cb14.setEnabled(false); lab13.setEnabled(false); tf9.setEnabled(false); cb16.setEnabled(false); } } }); ActionListener temp = new ActionListener() { public void actionPerformed(ActionEvent ev) { if (!cb7.isSelected() || cb8.isSelected()) { lab4.setEnabled(false); tf7.setEnabled(false); } else { if (c1.getSelectedIndex() > 0) { lab4.setEnabled(true); tf7.setEnabled(true); } } cb17.setEnabled(cb7.isSelected() && cb8.isSelected() && (c1.getSelectedIndex() > 0)); cb9.setEnabled(cb8.isSelected()); } }; cb7.addActionListener(temp); cb8.addActionListener(temp); this.resetControl(); // apply defaults } public void resetControl() { tf1.setText("5"); // balls tf2.setText("7"); // max throw tf3.setText("5"); // period cb1.setSelected(true); // asynch mode cb5.setSelected(true); // show all compositions cb7.setSelected(true); // ground state patterns cb8.setSelected(true); // excited state patterns cb9.setSelected(false); // starting/ending sequences cb10.setSelected(false); // don't show rotated versions cb17.setSelected(false); // don't show permuted jugglers cb15.setSelected(true); // connected patterns cb12.setSelected(false); // multiplexing tf9.setText("2"); // number multiplexed throws cb13.setSelected(true); // no simultaneous catches cb14.setSelected(false); // allow clustered throws cb16.setSelected(false); // true multiplexing tf4.setText(""); // excluded throws tf5.setText(""); // included throws // tf6.setText(""); // excluded passes tf7.setText("0"); // passing communication delay // tf8.setText("1"); // passing leader slot number c1.setSelectedIndex(0); // one juggler // lab3.setEnabled(false); // passing is initially off cb15.setEnabled(false); cb17.setEnabled(false); lab4.setEnabled(false); // lab5.setEnabled(false); // tf6.setEnabled(false); tf7.setEnabled(false); // tf8.setEnabled(false); cb13.setEnabled(false); // multiplexing initially off cb14.setEnabled(false); lab13.setEnabled(false); tf9.setEnabled(false); cb16.setEnabled(false); cb9.setEnabled(true); // excited-state patterns initially on } protected static GridBagConstraints make_constraints(int location, int gridx, int gridy) { GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = location; gbc.fill = GridBagConstraints.NONE; gbc.gridheight = gbc.gridwidth = 1; gbc.gridx = gridx; gbc.gridy = gridy; gbc.weightx = gbc.weighty = 0.0; return gbc; } protected static GridBagConstraints make_constraints(int location, int gridx, int gridy, Insets ins) { GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = location; gbc.fill = GridBagConstraints.NONE; gbc.gridheight = gbc.gridwidth = 1; gbc.gridx = gridx; gbc.gridy = gridy; gbc.insets = ins; gbc.weightx = gbc.weighty = 0.0; return gbc; } public String getParams() { StringBuffer sb = new StringBuffer(256); String maxthrow = tf2.getText(); if (maxthrow.trim().length() == 0) maxthrow = "-"; String period = tf3.getText(); if (period.trim().length() == 0) period = "-"; sb.append(tf1.getText() + " " + maxthrow + " " + period); if (cb2.isSelected()) sb.append(" -s"); int jugglers = c1.getSelectedIndex() + 1; if (jugglers > 1) { sb.append(" -j "+jugglers); if (tf7.isEnabled() && (tf7.getText().length() > 0)) sb.append(" -d " + tf7.getText() + " -l 1"); if (cb17.isEnabled()) { if (cb17.isSelected()) sb.append(" -jp"); // juggler permutations } else sb.append(" -jp"); if (cb15.isSelected()) sb.append(" -cp"); // connected patterns } if (cb5.isSelected()) sb.append(" -f"); else if (cb6.isSelected()) sb.append(" -prime"); if (cb7.isSelected() && !cb8.isSelected()) sb.append(" -g"); else if (!cb7.isSelected() && cb8.isSelected()) sb.append(" -ng"); if (!cb9.isEnabled() || !cb9.isSelected()) sb.append(" -se"); if (cb10.isSelected()) sb.append(" -rot"); if (cb12.isSelected() && (tf9.getText().length() > 0)) { sb.append(" -m " + tf9.getText()); if (!cb13.isSelected()) sb.append(" -mf"); if (cb14.isSelected()) sb.append(" -mc"); if (cb16.isSelected()) sb.append(" -mt"); } if (tf4.getText().length() > 0) sb.append(" -x " + tf4.getText()); if (tf5.getText().length() > 0) sb.append(" -i " + tf5.getText()); return sb.toString(); } } jugglinglab-0.6.2+ds.1/source/jugglinglab/jml/000077500000000000000000000000001323754603300211225ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/source/jugglinglab/jml/EventImages.java000077500000000000000000000270501323754603300242030ustar00rootroot00000000000000// EventImages.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.jml; import jugglinglab.util.*; public class EventImages { protected JMLPattern pat = null; protected int numjugglers, numpaths; protected double looptime; protected Permutation loopperm = null; protected JMLEvent ev = null; protected int evjuggler, evhand, evtransitions; // hand is by index (0 or 1) protected double evtime; protected Permutation[][][] ea = null; protected int numentries; protected int[] transitiontype = null; protected int currentloop, currentj, currenth, currententry; public EventImages(JMLPattern pat, JMLEvent ev) throws JuggleExceptionUser { this.pat = pat; this.ev = ev; calcarray(); resetPosition(); ev.delay = 0; // delay relative to master -> none for ev ev.delayunits = numentries; } public JMLEvent getNext() { // move pointer to next in line do { if (++currenth == 2) { currenth = 0; if (++currentj == this.numjugglers) { currentj = 0; if (++currententry == this.numentries) { currententry = 0; currentloop++; } } } } while (ea[currentj][currenth][currententry] == null); return makeEvent(); } public JMLEvent getPrevious() { // move point to previous in line do { if (currenth-- == 0) { currenth = 1; if (currentj-- == 0) { currentj = this.numjugglers - 1; if (currententry-- == 0) { currententry = this.numentries - 1; currentloop--; } } } } while (ea[currentj][currenth][currententry] == null); return makeEvent(); } protected JMLEvent makeEvent() { JMLEvent newevent = ev.duplicate(currententry + numentries * currentloop, numentries); newevent.setHand(currentj+1, (currenth==0 ? HandLink.LEFT_HAND : HandLink.RIGHT_HAND)); if (currenth != evhand) { Coordinate c1 = newevent.getLocalCoordinate(); c1.x = -c1.x; newevent.setLocalCoordinate(c1); } Permutation p = ea[currentj][currenth][currententry]; Permutation lp = this.loopperm; int pow = currentloop; if (pow < 0) { lp = lp.getInverse(); pow = -pow; } while (pow > 0) { p = lp.apply(p); pow--; } for (int i = 0; i < this.evtransitions; i++) { JMLTransition tr = newevent.getTransition(i); int masterpath = ev.getTransition(i).getPath(); tr.setPath(p.getMapping(masterpath)); } newevent.setPathPermFromMaster(p); double t = this.evtime + (double)currentloop * this.looptime + (double)currententry * (this.looptime / (double)this.numentries); newevent.setT(t); return newevent; } public void resetPosition() { this.currentloop = 0; this.currentj = evjuggler; this.currenth = evhand; this.currententry = 0; } // Does this event have any transitions for the specified hand, after // symmetries are applied? public boolean hasJMLTransitionForHand(int jug, int han) { for (int i = 0; i < numentries; i++) { if (ea[jug-1][HandLink.index(han)][i] != null) return true; } return false; } // Does this event have any velocity-defining transitions (e.g., throws) // for the specified hand, after symmetries are applied? public boolean hasVDJMLTransitionForHand(int jug, int han) { int i; for (i = 0; i < numentries; i++) if (ea[jug-1][HandLink.index(han)][i] != null) break; if (i == numentries) return false; for (int j = 0; j < evtransitions; j++) if ((transitiontype[j] == JMLTransition.TRANS_THROW) || (transitiontype[j] == JMLTransition.TRANS_SOFTCATCH)) return true; return false; } public boolean hasJMLTransitionForPath(int path) { int[] cycle = loopperm.getCycle(path); for (int i = 0; i < numjugglers; i++) { for (int j = 0; j < numentries; j++) { for (int h = 0; h < 2; h++) { for (int k = 0; k < evtransitions; k++) { if (ea[i][h][j] != null) { int newp = ea[i][h][j].getMapping(ev.getTransition(k).getPath()); for (int l = 0; l < cycle.length; l++) { if (newp == cycle[l]) return true; } } } } } } return false; } public boolean hasVDJMLTransitionForPath(int path) { int[] cycle = loopperm.getCycle(path); for (int k = 0; k < evtransitions; k++) { if ((transitiontype[k] == JMLTransition.TRANS_THROW) || (transitiontype[k] == JMLTransition.TRANS_SOFTCATCH)) { for (int i = 0; i < numjugglers; i++) { for (int j = 0; j < numentries; j++) { for (int h = 0; h < 2; h++) { if (ea[i][h][j] != null) { int newp = ea[i][h][j].getMapping(ev.getTransition(k).getPath()); for (int l = 0; l < cycle.length; l++) { if (newp == cycle[l]) return true; } } } } } } } return false; } protected void calcarray() throws JuggleExceptionUser { this.numjugglers = pat.getNumberOfJugglers(); this.numpaths = pat.getNumberOfPaths(); this.looptime = pat.getLoopEndTime() - pat.getLoopStartTime(); this.loopperm = pat.getPathPermutation(); this.evjuggler = ev.getJuggler() - 1; this.evhand = HandLink.index(ev.getHand()); this.evtransitions = ev.getNumberOfTransitions(); this.evtime = ev.getT(); int numsyms = pat.getNumberOfSymmetries() - 1; JMLSymmetry[] sym = new JMLSymmetry[numsyms]; int[] symperiod = new int[numsyms]; int[] deltaentries = new int[numsyms]; Permutation invdelayperm = null; this.numentries = 1; for (int i = 0, j = 0; i <= numsyms; i++) { JMLSymmetry temp = pat.getSymmetry(i); switch (temp.getType()) { case JMLSymmetry.TYPE_DELAY: invdelayperm = temp.getPathPerm().getInverse(); break; case JMLSymmetry.TYPE_SWITCH: sym[j] = temp; symperiod[j] = temp.getJugglerPerm().getOrder(); deltaentries[j] = 0; j++; break; case JMLSymmetry.TYPE_SWITCHDELAY: sym[j] = temp; symperiod[j] = temp.getJugglerPerm().getOrder(); this.numentries = Permutation.lcm(this.numentries, symperiod[j]); deltaentries[j] = -1; j++; break; } } for (int i = 0; i < numsyms; i++) // assume exactly one delay symmetry if (deltaentries[i] == -1) // signals a switchdelay symmetry deltaentries[i] = this.numentries / symperiod[i]; // System.out.println("numentries = "+numentries); this.ea = new Permutation[numjugglers][2][numentries]; this.transitiontype = new int[evtransitions]; Permutation idperm = new Permutation(numpaths, false); // identity ev.setPathPermFromMaster(idperm); ea[evjuggler][evhand][0] = idperm; for (int i = 0; i < evtransitions; i++) { JMLTransition tr = ev.getTransition(i); transitiontype[i] = tr.getType(); } boolean changed; do { // System.out.println("{"+ea[0][0][0][0]+","+ea[0][0][1][0]+"},{"+ea[0][1][0][0]+","+ea[0][1][1][0]+"}"); changed = false; for (int i = 0; i < numsyms; i++) { for (int j = 0; j < numjugglers; j++) { for (int k = 0; k < 2; k++) { for (int l = 0; l < numentries; l++) { // apply symmetry to event int newj = sym[i].getJugglerPerm().getMapping(j+1); if (newj != 0) { int newk = (newj < 0 ? (1-k) : k); if (newj < 0) newj = -newj; newj--; Permutation p = ea[j][k][l]; if (p != null) { p = sym[i].getPathPerm().apply(p); int newl = l + deltaentries[i]; // map back into range if (newl >= numentries) { p = invdelayperm.apply(p); newl -= numentries; } // System.out.println("newj = "+newj+", newk = "+newk+", newl = "+newl); // check for consistency if (ea[newj][newk][newl] != null) { if (!p.equals(ea[newj][newk][newl])) throw new JuggleExceptionUser("Symmetries inconsistent"); } else { ea[newj][newk][newl] = p; changed = true; } } } } } } } } while (changed); // System.out.println("**** done with event"); /* int[][][] ea = eventlist.getEventArray(); for (int j = 0; j < numjugglers; j++) { for (int k = 0; k < 2; k++) { for (int l = 0; l < numentries; l++) { System.out.println("ea["+(j+1)+","+k+","+l+"] = "+ea[j][k][l][0]); } } }*/ } }jugglinglab-0.6.2+ds.1/source/jugglinglab/jml/HandLink.java000077500000000000000000000074341323754603300234700ustar00rootroot00000000000000// HandLink.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.jml; import jugglinglab.util.*; import jugglinglab.curve.*; public class HandLink { protected int jugglernum; protected int handnum; protected JMLEvent startevent, endevent; protected VelocityRef startvelref, endvelref; protected Curve hp; protected boolean ismaster; protected HandLink[] duplicates; // if master protected HandLink master; // if duplicate public static final int NO_HAND = 0; public static final int LEFT_HAND = 1; public static final int RIGHT_HAND = 2; public HandLink(int jugglernum, int handnum, JMLEvent startevent, JMLEvent endevent) { this.jugglernum = jugglernum; this.handnum = handnum; this.startevent = startevent; this.endevent = endevent; this.hp = null; this.ismaster = true; this.duplicates = null; this.master = null; } public static int index(int handdescription) { return (handdescription == LEFT_HAND ? 0 : 1); } public int getJuggler() { return jugglernum; } public int getHand() { return handnum; } public JMLEvent getStartEvent() { return startevent; } public JMLEvent getEndEvent() { return endevent; } public VelocityRef getStartVelocityRef() { return startvelref; } public void setStartVelocityRef(VelocityRef vr) { this.startvelref = vr; } public VelocityRef getEndVelocityRef() { return endvelref; } public void setEndVelocityRef(VelocityRef vr) { this.endvelref = vr; } public void setHandCurve(Curve hp) { this.hp = hp; } public Curve getHandCurve() { return hp; } public boolean isMaster() { return ismaster; } public String toString() { String result = null; Coordinate start = startevent.getGlobalCoordinate(); result = "Link from (x="+start.x+",y="+start.y+",z="+start.z+",t="+ startevent.getT()+") "; Coordinate end = endevent.getGlobalCoordinate(); result += "to (x="+end.x+",y="+end.y+",z="+end.z+",t="+ endevent.getT()+")"; VelocityRef vr = getStartVelocityRef(); if (vr != null) { Coordinate vel = vr.getVelocity(); result += "\n start velocity (x="+vel.x+",y="+vel.y+",z="+vel.z+")"; } vr = getEndVelocityRef(); if (vr != null) { Coordinate vel = vr.getVelocity(); result += "\n end velocity (x="+vel.x+",y="+vel.y+",z="+vel.z+")"; } Curve hp = getHandCurve(); if (hp != null) { Coordinate maxcoord = hp.getMax(startevent.getT(), endevent.getT()); Coordinate mincoord = hp.getMin(startevent.getT(), endevent.getT()); result += "\n minimum (x="+mincoord.x+",y="+mincoord.y+",z="+mincoord.z+")"; result += "\n maximum (x="+maxcoord.x+",y="+maxcoord.y+",z="+maxcoord.z+")"; } else result += "\n no handpath"; return result; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/jml/JMLAttributes.java000077500000000000000000000035531323754603300244670ustar00rootroot00000000000000// JMLAttributes.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.jml; import java.util.*; public class JMLAttributes { protected JMLNode parentTag; protected int size; protected Vector names; protected Vector values; public JMLAttributes(JMLNode parent) { parentTag = parent; size = 0; } public int getNumberOfAttributes() { return size; } public void addAttribute(String name, String value) { if (size == 0) { names = new Vector(); values = new Vector(); } names.addElement(name); values.addElement(value); size++; } public String getAttributeName(int index) { return (String)names.elementAt(index); } public String getAttributeValue(int index) { return (String)values.elementAt(index); } public String getAttribute(String name) { for (int i = 0; i < size; i++) if (name.equalsIgnoreCase(getAttributeName(i))) return getAttributeValue(i); return null; } }jugglinglab-0.6.2+ds.1/source/jugglinglab/jml/JMLDefs.java000077500000000000000000000070201323754603300232130ustar00rootroot00000000000000// JMLDefs.java // // Copyright 2002 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.jml; public class JMLDefs { public static final String default_JML_on_save = "1.2"; public static final String default_JML_on_load = "1.0"; public static final String jmldtd = "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n"+ "\n"; public static final String[] jmlprefix = { "", "" }; public static final String[] jmlsuffix = { }; public static final String[] taglist = { "jml", "pattern", "patternlist", "title", "prop", "setup", "symmetry", "event", "throw", "catch", "softcatch", "line", "holding", "position" }; } jugglinglab-0.6.2+ds.1/source/jugglinglab/jml/JMLEvent.java000077500000000000000000000255651323754603300234310ustar00rootroot00000000000000// JMLEvent.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.jml; import jugglinglab.util.*; import java.util.*; import java.io.*; public class JMLEvent { // static ResourceBundle guistrings; static ResourceBundle errorstrings; static { // guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } protected double x, y, z; // coordinates in local frame protected double gx, gy, gz; // coordinates in global frame protected boolean globaldirty; // global coordinates need to be recalced? protected double t; protected int juggler; protected int hand; protected Vector transitions = null; protected int[][][] eventarray; protected int delay; protected int delayunits; protected Permutation pathpermfrommaster = null; protected JMLEvent master; // null if this is a master event public boolean calcpos; protected JMLEvent prev, next; // for doubly-linked event list public JMLEvent() { this.master = null; this.prev = this.next = null; this.calcpos = false; this.transitions = new Vector(); this.globaldirty = true; } public Coordinate getLocalCoordinate() { return new Coordinate(x,y,z); } public void setLocalCoordinate(Coordinate c) { this.x = c.x; this.y = c.y; this.z = c.z; this.globaldirty = true; } public Coordinate getGlobalCoordinate() { return (globaldirty ? null : new Coordinate(gx,gy,gz)); } public void setGlobalCoordinate(Coordinate c) { this.gx = c.x; this.gy = c.y; this.gz = c.z; this.globaldirty = false; } public double getT() { return t; } public void setT(double t) { this.t = t; } public int getHand() { return hand; } public void setHand(String strhand) throws JuggleExceptionUser { int index = strhand.indexOf(":"); if (index == -1) { this.juggler = 1; if (strhand.equalsIgnoreCase("left")) this.hand = HandLink.LEFT_HAND; else if (strhand.equalsIgnoreCase("right")) this.hand = HandLink.RIGHT_HAND; else throw new JuggleExceptionUser(errorstrings.getString("Error_hand_name")+" '"+strhand+"'"); } else { this.juggler = Integer.valueOf(strhand.substring(0,index)).intValue(); String substr = strhand.substring(index+1); if (substr.equalsIgnoreCase("left")) this.hand = HandLink.LEFT_HAND; else if (substr.equalsIgnoreCase("right")) this.hand = HandLink.RIGHT_HAND; else throw new JuggleExceptionUser(errorstrings.getString("Error_hand_name")+" '"+strhand+"'"); } } public void setHand(int j, int h) { this.juggler = j; this.hand = h; // HandLink.LEFT_HAND or HandLink.RIGHT_HAND } public int getJuggler() { return juggler; } public int getNumberOfTransitions() { return transitions.size(); } public JMLTransition getTransition(int index) { return (JMLTransition)transitions.elementAt(index); } public void addTransition(JMLTransition trans) { transitions.addElement(trans); } public void removeTransition(int index) { transitions.removeElementAt(index); } public void removeTransition(JMLTransition trans) { for (int i = 0; i < getNumberOfTransitions(); i++) { if (getTransition(i) == trans) { removeTransition(i); return; } } } public boolean isMaster() { return (master==null); } public JMLEvent getMaster() { return master; } public void setMaster(JMLEvent master) { this.master = master; } public JMLEvent getPrevious() { return prev; } public void setPrevious(JMLEvent prev) { this.prev = prev; } public JMLEvent getNext() { return next; } public void setNext(JMLEvent next) { this.next = next; } public Permutation getPathPermFromMaster() { return pathpermfrommaster; } public void setPathPermFromMaster(Permutation p) { this.pathpermfrommaster = p; } public boolean isDelayOf(JMLEvent ev2) { JMLEvent mast1 = (this.getMaster()==null ? this : this.getMaster()); JMLEvent mast2 = (ev2.getMaster()==null ? ev2 : ev2.getMaster()); if (mast1 != mast2) return false; if ((this.getJuggler() != ev2.getJuggler()) || (this.getHand() != ev2.getHand())) return false; int totaldelay = this.delay - ev2.delay; if (totaldelay < 0) totaldelay = -totaldelay; if ((totaldelay % this.delayunits) == 0) return true; return false; } public JMLTransition getPathTransition(int path, int transtype) { for (int i = 0; i < getNumberOfTransitions(); i++) { JMLTransition tr = getTransition(i); if (tr.getPath() == path) { if ((transtype == JMLTransition.TRANS_ANY) || (transtype == tr.getType())) return tr; } } return null; } public JMLEvent duplicate(int delay, int delayunits) { JMLEvent dup = new JMLEvent(); dup.setLocalCoordinate(getLocalCoordinate()); dup.setT(getT()); dup.setHand(getJuggler(), getHand()); dup.delay = delay; dup.delayunits = delayunits; dup.calcpos = calcpos; for (int i = 0; i < getNumberOfTransitions(); i++) { JMLTransition trans = getTransition(i).duplicate(); dup.addTransition(trans); } dup.setMaster(isMaster() ? this : this.master); return dup; } // Methods to handle JML public void readJML(JMLNode current, String jmlvers, int njugglers, int npaths) throws JuggleExceptionUser { JMLAttributes at = current.getAttributes(); double tempx=0.0, tempy=0.0, tempz=0.0, tempt=0.0; String handstr = null; try { for (int i = 0; i < at.getNumberOfAttributes(); i++) { // System.out.println("att. "+i+" = "+at.getAttributeValue(i)); if (at.getAttributeName(i).equalsIgnoreCase("x")) tempx = Double.valueOf(at.getAttributeValue(i)).doubleValue(); else if (at.getAttributeName(i).equalsIgnoreCase("y")) tempy = Double.valueOf(at.getAttributeValue(i)).doubleValue(); else if (at.getAttributeName(i).equalsIgnoreCase("z")) tempz = Double.valueOf(at.getAttributeValue(i)).doubleValue(); else if (at.getAttributeName(i).equalsIgnoreCase("t")) tempt = Double.valueOf(at.getAttributeValue(i)).doubleValue(); else if (at.getAttributeName(i).equalsIgnoreCase("hand")) handstr = at.getAttributeValue(i); } } catch (NumberFormatException nfe) { throw new JuggleExceptionUser(errorstrings.getString("Error_event_coordinate")); } // JML version 1.0 used a different coordinate system -- convert if (jmlvers.equals("1.0")) { double temp = tempy; tempy = tempz; tempz = temp; } setLocalCoordinate(new Coordinate(tempx,tempy,tempz)); setT(tempt); if (handstr == null) throw new JuggleExceptionUser(errorstrings.getString("Error_unspecified_hand")); setHand(handstr); if ((this.juggler > njugglers) || (this.juggler < 1)) throw new JuggleExceptionUser(errorstrings.getString("Error_juggler_out_of_range")); // process current event node children for (int i = 0; i < current.getNumberOfChildren(); i++) { JMLNode child = current.getChildNode(i); String type = child.getNodeType(); at = child.getAttributes(); String path = null, throwtype = null, mod = null; for (int j = 0; j < at.getNumberOfAttributes(); j++) { String value = at.getAttributeValue(j); if (at.getAttributeName(j).equalsIgnoreCase("path")) path = value; else if (at.getAttributeName(j).equalsIgnoreCase("type")) throwtype = value; else if (at.getAttributeName(j).equalsIgnoreCase("mod")) mod = value; } if (path == null) throw new JuggleExceptionUser(errorstrings.getString("Error_no_path")); int pnum = Integer.valueOf(path).intValue(); if ((pnum > npaths) || (pnum < 1)) throw new JuggleExceptionUser(errorstrings.getString("Error_path_out_of_range")); if (type.equalsIgnoreCase("throw")) addTransition(new JMLTransition(JMLTransition.TRANS_THROW, pnum, throwtype, mod)); else if (type.equalsIgnoreCase("catch")) addTransition(new JMLTransition(JMLTransition.TRANS_CATCH, pnum, null, null)); else if (type.equalsIgnoreCase("softcatch")) addTransition(new JMLTransition(JMLTransition.TRANS_SOFTCATCH, pnum, null, null)); else if (type.equalsIgnoreCase("holding")) addTransition(new JMLTransition(JMLTransition.TRANS_HOLDING, pnum, null, null)); if (child.getNumberOfChildren() != 0) throw new JuggleExceptionUser(errorstrings.getString("Error_event_subtag")); } } public void writeJML(PrintWriter wr) throws IOException { Coordinate c = getLocalCoordinate(); wr.println(""); for (int i = 0; i < getNumberOfTransitions(); i++) getTransition(i).writeJML(wr); wr.println(""); } } jugglinglab-0.6.2+ds.1/source/jugglinglab/jml/JMLNode.java000077500000000000000000000160161323754603300232240ustar00rootroot00000000000000// JMLNode.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.jml; import java.util.Vector; import java.io.*; import jugglinglab.util.*; public class JMLNode { protected String nodeType; // from taglist in JMLDefs.java protected String nodeValue; // nodes with character content protected JMLNode parentNode; protected Vector childNodes; protected JMLNode previousSibling; protected JMLNode nextSibling; protected JMLAttributes attributes; public JMLNode(String nodeType) { this.nodeType = nodeType; childNodes = new Vector(); attributes = new JMLAttributes(this); } public String getNodeType() { return nodeType; } public String getNodeValue() { return nodeValue; } public void setNodeValue(String nodeValue) { this.nodeValue = nodeValue; } public JMLNode getParentNode() { return parentNode; } public void setParentNode(JMLNode parent) { parentNode = parent; } public int getNumberOfChildren() { return childNodes.size(); } public JMLNode getChildNode(int index) { return (JMLNode)childNodes.elementAt(index); } public JMLNode getFirstChild() { return (JMLNode)childNodes.firstElement(); } public JMLNode getLastChild() { return (JMLNode)childNodes.lastElement(); } public JMLNode getPreviousSibling() { return previousSibling; } public void setPreviousSibling(JMLNode sibling) { this.previousSibling = sibling; } public JMLNode getNextSibling() { return nextSibling; } public void setNextSibling(JMLNode sibling) { this.nextSibling = sibling; } public void addAttribute(String name, String value) { attributes.addAttribute(name, value); } public JMLAttributes getAttributes() { return attributes; } // Inserts a child node newChild before the existing child node refChild. public void insertBefore(JMLNode newChild, JMLNode refChild) { if (refChild != null) { int refindex = childNodes.indexOf(refChild); childNodes.insertElementAt(newChild, refindex); // now fix references newChild.setParentNode(this); JMLNode prevsibling = refChild.getPreviousSibling(); if (prevsibling != null) prevsibling.setNextSibling(newChild); newChild.setPreviousSibling(prevsibling); newChild.setNextSibling(refChild); refChild.setPreviousSibling(newChild); } else { this.appendChild(newChild); } } // Replaces the child node oldChild with newChild in the set of children // of the given node. public void replaceChild(JMLNode newChild, JMLNode oldChild) throws JuggleExceptionInternal { if (childNodes.contains(oldChild)) { int refindex = childNodes.indexOf(oldChild); JMLNode prev = oldChild.getPreviousSibling(); JMLNode next = oldChild.getNextSibling(); childNodes.setElementAt(newChild, refindex); newChild.setPreviousSibling(prev); newChild.setNextSibling(next); newChild.setParentNode(this); } else throw new JuggleExceptionInternal("Node to replace doesn't exist"); } // Removes the child node indicated by oldChild from the list of children. public void removeChild(JMLNode oldChild) throws JuggleExceptionInternal { if (childNodes.removeElement(oldChild)) { JMLNode prev = oldChild.getPreviousSibling(); JMLNode next = oldChild.getNextSibling(); if (prev != null) prev.setNextSibling(next); if (next != null) next.setPreviousSibling(prev); } else throw new JuggleExceptionInternal("Node to remove doesn't exist"); } public void appendChild(JMLNode newChild) { JMLNode lastnode = null; if (childNodes.size() != 0) { lastnode = (JMLNode)childNodes.lastElement(); lastnode.setNextSibling(newChild); } childNodes.addElement(newChild); newChild.setPreviousSibling(lastnode); newChild.setNextSibling(null); newChild.setParentNode(this); } public boolean hasChildNodes() { return (childNodes.size() != 0); } public void writeNode(PrintWriter write, int indentlevel) throws IOException { int i; StringBuffer result = new StringBuffer(); /* for (i = 0; i < indentlevel; i++) result.append('\t'); */ result.append("<" + nodeType); // output attributes for (i = 0; i < attributes.getNumberOfAttributes(); i++) { result.append(" " + attributes.getAttributeName(i)); result.append("=\"" + JMLNode.xmlescape(attributes.getAttributeValue(i)) + "\""); } if (getNumberOfChildren() == 0) { if (nodeValue == null) result.append("/>"); else result.append(">" + JMLNode.xmlescape(nodeValue) + ""); write.println(result.toString()); result = new StringBuffer(); } else { result.append('>'); write.println(result.toString()); result = new StringBuffer(); if (nodeValue != null) { /* for (i = 0; i <= indentlevel; i++) result.append('\t'); */ result.append(JMLNode.xmlescape(nodeValue)); write.println(result.toString()); result = new StringBuffer(); } write.flush(); for (i = 0; i < getNumberOfChildren(); i++) getChildNode(i).writeNode(write, indentlevel + 1); /* for (i = 0; i < indentlevel; i++) result.append('\t'); */ result.append(""); write.println(result.toString()); } write.flush(); } public static String xmlescape(String in) { String result = in.replace("&", "&"); result = result.replace("<", "<"); result = result.replace(">", ">"); result = result.replace("'", "'"); result = result.replace("\"", """); return result; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/jml/JMLParser.java000077500000000000000000000303451323754603300235740ustar00rootroot00000000000000// JMLParser.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.jml; import java.io.*; import java.net.*; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import javax.xml.parsers.ParserConfigurationException; import org.xml.sax.*; import org.xml.sax.helpers.DefaultHandler; import jugglinglab.util.*; public class JMLParser extends DefaultHandler { protected boolean patternStarted; protected boolean patternFinished; protected JMLNode rootNode; // tree of JML tags protected JMLNode currentNode; protected static final boolean saxdebug = false; // print messages during parsing? public static final int JML_INVALID = 0; public static final int JML_PATTERN = 1; public static final int JML_LIST = 2; public JMLParser() { patternStarted = patternFinished = false; } // --------------- call parser to create pattern from XML ----------------- public void parse(Reader read) throws SAXException, IOException { try { SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setValidating(true); SAXParser parser = factory.newSAXParser(); // Parse the document. parser.parse(new InputSource(read), this); } catch (ParserConfigurationException pce) { throw new SAXException(pce.getMessage()); } } // Implementation of org.xml.sax.EntityResolver public InputSource resolveEntity(String publicId, String systemId) { if (saxdebug) { System.out.print("Resolve entity:"); if (publicId != null) System.out.print(" publicId=\"" + publicId + '"'); System.out.println(" systemId=\"" + systemId + '"'); } if (systemId.equalsIgnoreCase("file://jml.dtd")) { if (saxdebug) { System.out.println("--------- jml.dtd -----------"); System.out.println(JMLDefs.jmldtd); System.out.println("-----------------------------"); } return new InputSource(new StringReader(JMLDefs.jmldtd)); } return null; } // Implementation of org.xml.sax.DTDHandler public void notationDecl(String name, String publicId, String systemId) { if (saxdebug) { System.out.print("Notation declaration: " + name); if (publicId != null) System.out.print(" publicId=\"" + publicId + '"'); if (systemId != null) System.out.print(" systemId=\"" + systemId + '"'); System.out.print('\n'); } } public void unparsedEntityDecl(String name, String publicId, String systemId, String notationName) { if (saxdebug) { System.out.print("Unparsed Entity Declaration: " + name); if (publicId != null) System.out.print(" publicId=\"" + publicId + '"'); if (systemId != null) System.out.print(" systemId=\"" + systemId + '"'); System.out.println(" notationName=\"" + notationName + '"'); } } // Implementation of org.xml.sax.ContentHandler public void setDocumentLocator(Locator locator) { super.setDocumentLocator(locator); if (saxdebug) System.out.println("Document locator supplied."); } public void startDocument() throws SAXException { if (saxdebug) System.out.println("Start document"); try { startJMLPattern(); } catch (JuggleException je) { throw new SAXException(je.getMessage()); } } public void endDocument() throws SAXException { if (saxdebug) System.out.println("End document"); try { endJMLPattern(); } catch (JuggleException je) { throw new SAXException(je.getMessage()); } } public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { if (saxdebug) { System.out.println("Start element: " + qName); for (int i = 0; i < atts.getLength(); i++) { System.out.println(" Attribute: " + atts.getQName(i) + ' ' + atts.getType(i) + " \"" + atts.getValue(i) + '"'); } } try { startJMLElement(qName); for (int i = 0; i < atts.getLength(); i++) addJMLAttribute(atts.getQName(i), atts.getValue(i)); } catch (JuggleException je) { throw new SAXException(je.getMessage()); } } public void endElement(String namespaceURI, String localName, String qName) throws SAXException { if (saxdebug) System.out.println("End element: " + qName); try { endJMLElement(qName); } catch (JuggleException je) { throw new SAXException(je.getMessage()); } } public void characters(char ch[], int start, int length) throws SAXException { if (saxdebug) { System.out.print("Characters: "); display(ch, start, length); } try { addJMLText(new String(ch, start, length)); } catch (JuggleException je) { throw new SAXException(je.getMessage()); } } public void ignorableWhitespace(char ch[], int start, int length) { if (saxdebug) { System.out.print("Ignorable Whitespace: "); display(ch, start, length); } } public void processingInstruction(String target, String data) { if (saxdebug) System.out.println("Processing instruction: " + target + ' ' + data); } // Implementation of org.xml.sax.ErrorHandler public void warning(SAXParseException exception) throws SAXException { // throw new SAXException("Warning: " + // exception.getMessage() + " (" + // exception.getSystemId() + ':' + // exception.getLineNumber() + ',' + // exception.getColumnNumber() + ')'); throw exception; } public void error(SAXParseException exception) throws SAXException { // throw new SAXException("Recoverable Error: " + // exception.getMessage() + " (" + // exception.getSystemId() + ':' + // exception.getLineNumber() + ',' + // exception.getColumnNumber() + ')'); throw exception; } public void fatalError(SAXParseException exception) throws SAXException { // throw new SAXException("Fatal Error: " + // exception.getMessage() + " (" + // exception.getSystemId() + ':' + // exception.getLineNumber() + ',' + // exception.getColumnNumber() + ')'); throw exception; } // Utility routines. /** * Display text, escaping some characters. */ private static void display(char ch[], int start, int length) { if (saxdebug) { for (int i = start; i < start + length; i++) { switch (ch[i]) { case '\n': System.out.print("\\n"); break; case '\t': System.out.print("\\t"); break; default: System.out.print(ch[i]); break; } } System.out.print("\n"); } } // ------------------------------------------------------------------------ // Methods for pattern creation, used to create the JMLNode tree. // ------------------------------------------------------------------------ public void startJMLPattern() throws JuggleExceptionInternal { if (patternStarted) throw new JuggleExceptionInternal("startJMLPattern(): pattern already started"); patternStarted = true; } public void startJMLElement(String name) throws JuggleExceptionInternal { if (!patternStarted) throw new JuggleExceptionInternal("startJMLEleent(): pattern not started"); if (patternFinished) throw new JuggleExceptionInternal("startJMLElement(): pattern already finished"); if ((currentNode == null) && (rootNode != null)) throw new JuggleExceptionInternal("startJMLElement(): can only have one root element"); JMLNode newNode = new JMLNode(name); if (currentNode != null) { currentNode.appendChild(newNode); currentNode = newNode; } else rootNode = currentNode = newNode; } public void endJMLElement(String name) throws JuggleExceptionInternal { if (!patternStarted) throw new JuggleExceptionInternal("endJMLElement(): pattern not started"); if (patternFinished) throw new JuggleExceptionInternal("endJMLElement(): pattern already finished"); if (currentNode == null) throw new JuggleExceptionInternal("endJMLElement(): no correspanding startElement()"); currentNode = currentNode.getParentNode(); } public void addJMLAttribute(String name, String value) throws JuggleExceptionInternal { if (!patternStarted) throw new JuggleExceptionInternal("addJMLAttribute(): pattern not started"); if (patternFinished) throw new JuggleExceptionInternal("addJMLAttribute(): pattern already finished"); if (currentNode == null) throw new JuggleExceptionInternal("addJMLAttribute(): no element to add to"); currentNode.addAttribute(name, value); } public void addJMLText(String text) throws JuggleExceptionInternal { if (!patternStarted) throw new JuggleExceptionInternal("addJMLText(): pattern not started"); if (patternFinished) throw new JuggleExceptionInternal("addJMLText(): pattern already finished"); if (currentNode == null) throw new JuggleExceptionInternal("addJMLText(): no element to add to"); String newvalue = null; if (currentNode.getNodeValue() == null) newvalue = text; else newvalue = currentNode.getNodeValue() + text; currentNode.setNodeValue(newvalue); } public void endJMLPattern() throws JuggleExceptionInternal { if (!patternStarted) throw new JuggleExceptionInternal("endJMLPattern(): pattern not started"); if (patternFinished) throw new JuggleExceptionInternal("endJMLPattern(): pattern already finished"); if (rootNode == null) throw new JuggleExceptionInternal("endJMLPattern(): empty pattern"); if (currentNode != null) throw new JuggleExceptionInternal("endJMLPattern(): missing endElement()"); patternFinished = true; } public JMLNode getTree() { return rootNode; } public int getFileType() { if (rootNode.getNodeType().equalsIgnoreCase("jml")) { if (rootNode.getNumberOfChildren() == 1) { String child = rootNode.getChildNode(0).getNodeType(); if (child.equalsIgnoreCase("pattern")) return JML_PATTERN; else if (child.equalsIgnoreCase("patternlist")) return JML_LIST; else return JML_INVALID; } else return JML_INVALID; } else return JML_INVALID; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/jml/JMLPattern.java000077500000000000000000001631001323754603300237510ustar00rootroot00000000000000// JMLPattern.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.jml; import java.io.*; import java.util.*; import java.text.MessageFormat; import org.xml.sax.*; import jugglinglab.core.*; import jugglinglab.prop.*; import jugglinglab.path.*; import jugglinglab.curve.*; import jugglinglab.util.*; import jugglinglab.renderer.*; /* This is one of the core classes, representing a juggling pattern in generalized form. It is used in three steps: 1) Define a pattern, in one of three ways: A) Manually, by calling methods in this class. B) Parsing from pre-existing JML stream (file, user input, etc.). (JML = Juggling Markup Language, an XML document type) C) Output from a Notation class, which converts from other notations. 2) Call layoutPattern() to calculate flight paths for all the props and hands. 3) Call various methods to get information about the pattern, e.g., prop/hand coordinates at points in time. */ public class JMLPattern { // static ResourceBundle guistrings; static ResourceBundle errorstrings; static { // guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } protected String version = JMLDefs.default_JML_on_save; // JML version number protected String title; protected int numjugglers; protected int numpaths; protected Vector props; protected int[] propassignment; protected boolean[][] hasVDHandJMLTransition; // whether pattern has a velocity-defining transition, // for each juggler/hand protected boolean[] hasVDPathJMLTransition; // for each path protected Vector symmetries; protected JMLEvent eventlist; protected JMLPosition positionlist; protected boolean laidout, valid; protected Vector[] pathlinks; // for each path protected Vector[][] handlinks; // for each juggler/hand protected Curve[] jugglercurve; // coordinates for each juggler protected Curve[] jugglerangle; // angles for each juggler public JMLPattern() { laidout = false; valid = true; // false; eventlist = null; positionlist = null; pathlinks = null; handlinks = null; props = new Vector(); symmetries = new Vector(); } public JMLPattern(JMLNode root) throws JuggleExceptionUser { this(); readJML(root); valid = true; } // Used to specify the jml version number, when pattern is part of a patternlist public JMLPattern(JMLNode root, String jmlvers) throws JuggleExceptionUser { this(); this.loadingversion = jmlvers; readJML(root); valid = true; } public JMLPattern(Reader read) throws JuggleExceptionUser, SAXException, IOException { this(); JMLParser parser = new JMLParser(); parser.parse(read); readJML(parser.getTree()); valid = true; } // ------------------------------------------------------------------------ // Methods to define the pattern // ------------------------------------------------------------------------ // public void setJMLVersion(String version) { this.version = version; } public void setTitle(String title) { this.title = title == null ? null : title.trim(); } public void setNumberOfJugglers(int n) { this.numjugglers = n; } public void setNumberOfPaths(int n) { this.numpaths = n; } public void addProp(PropDef pd) { props.addElement(pd); } public void removeProp(int propnum) { props.removeElementAt(propnum-1); for (int i = 1; i <= getNumberOfPaths(); i++) { if (getPropAssignment(i) > propnum) setPropAssignment(i, getPropAssignment(i)-1); } } public void setPropAssignment(int pathnum, int propnum) { propassignment[pathnum-1] = propnum; } public void setPropAssignments(int[] pa) { this.propassignment = pa; } public void addSymmetry(JMLSymmetry sym) { symmetries.addElement(sym); } public void addEvent(JMLEvent ev) { if ((eventlist == null) || (eventlist.getT() > ev.getT())) { ev.setPrevious(null); ev.setNext(eventlist); if (eventlist != null) eventlist.setPrevious(ev); eventlist = ev; return; } JMLEvent current = eventlist; while (current.getNext() != null) { current = current.getNext(); if (current.getT() > ev.getT()) { ev.setNext(current); ev.setPrevious(current.getPrevious()); current.getPrevious().setNext(ev); current.setPrevious(ev); return; } } current.setNext(ev); ev.setNext(null); ev.setPrevious(current); laidout = false; } public void removeEvent(JMLEvent ev) { if (eventlist == ev) { eventlist = ev.getNext(); if (eventlist != null) eventlist.setPrevious(null); return; } JMLEvent next = ev.getNext(); JMLEvent prev = ev.getPrevious(); if (next != null) next.setPrevious(prev); if (prev != null) prev.setNext(next); } public JMLEvent getEventList() { return eventlist; } public void addPosition(JMLPosition pos) throws JuggleExceptionUser { if ((pos.getT() < getLoopStartTime()) || (pos.getT() > getLoopEndTime())) return; // throw new JuggleExceptionUser(" time out of range"); if ((positionlist == null) || (positionlist.getT() > pos.getT())) { pos.setPrevious(null); pos.setNext(positionlist); if (positionlist != null) positionlist.setPrevious(pos); positionlist = pos; return; } JMLPosition current = positionlist; while (current.getNext() != null) { current = current.getNext(); if (current.getT() > pos.getT()) { pos.setNext(current); pos.setPrevious(current.getPrevious()); current.getPrevious().setNext(pos); current.setPrevious(pos); return; } } current.setNext(pos); pos.setNext(null); pos.setPrevious(current); } public void removePosition(JMLPosition pos) { if (positionlist == pos) { positionlist = pos.getNext(); if (positionlist != null) positionlist.setPrevious(null); return; } JMLPosition next = pos.getNext(); JMLPosition prev = pos.getPrevious(); if (next != null) next.setPrevious(prev); if (prev != null) prev.setNext(next); } public JMLPosition getPositionList() { return positionlist; } // ------------------------------------------------------------------------ // Lay out the spatial paths in the pattern // ------------------------------------------------------------------------ public void layoutPattern() throws JuggleExceptionInternal, JuggleExceptionUser { if (!valid) throw new JuggleExceptionInternal("Cannot do layout of invalid pattern"); if (getNumberOfProps() == 0) this.addProp(new PropDef("ball", null)); for (int i = 0; i < getNumberOfProps(); i++) ((PropDef)props.elementAt(i)).layoutProp(); this.buildEventList(); this.findMasterEvents(); this.findPositions(); this.gotoGlobalCoordinates(); this.buildLinkLists(); this.layoutHandPaths(); if (jugglinglab.core.Constants.DEBUG_LAYOUT) { for (int i = 0; i < getNumberOfPaths(); i++) { System.out.println(pathlinks[i].size()+" pathlinks for path "+(i+1)+":"); for (int jtemp = 0; jtemp < pathlinks[i].size(); jtemp++) System.out.println(" "+(PathLink)(pathlinks[i].elementAt(jtemp))); } for (int i = 0; i < getNumberOfJugglers(); i++) { for (int j = 0; j < 2; j++) { System.out.println(handlinks[i][j].size()+" handlinks for juggler "+(i+1)+ ", hand "+(j+1)+":"); for (int k = 0; k < handlinks[i][j].size(); k++) System.out.println(" "+(HandLink)(handlinks[i][j].elementAt(k))); } } } laidout = true; } // Step 1: construct the list of events // extend events in list using known symmetries public void buildEventList() throws JuggleExceptionInternal, JuggleExceptionUser { // figure out how many events there are int numevents = 0; JMLEvent current = eventlist; while (current != null) { if ((current.getJuggler() < 1) || (current.getJuggler() > numjugglers)) throw new JuggleExceptionUser(errorstrings.getString("Error_juggler_outofrange")); if (current.isMaster()) numevents++; else removeEvent(current); current = current.getNext(); } // construct event images for extending event list EventImages[] ei = new EventImages[numevents]; current = eventlist; for (int i = 0; i < numevents; i++) { ei[i] = new EventImages(this, current); current = current.getNext(); } // arrays used for creating the event list boolean[][] needHandEvent = new boolean[numjugglers][2]; boolean[][] needVDHandEvent = new boolean[numjugglers][2]; boolean[] needPathEvent = new boolean[numpaths]; boolean[] needSpecialPathEvent = new boolean[numpaths]; this.hasVDHandJMLTransition = new boolean[numjugglers][2]; this.hasVDPathJMLTransition = new boolean[numpaths]; // make sure each hand and path are hit at least once for (int i = 0; i < numjugglers; i++) { boolean hasJMLTransitionForLeft = false; boolean hasJMLTransitionForRight = false; hasVDHandJMLTransition[i][0] = hasVDHandJMLTransition[i][1] = false; for (int j = 0; j < numevents; j++) { if (hasJMLTransitionForLeft == false) hasJMLTransitionForLeft = ei[j].hasJMLTransitionForHand(i+1, HandLink.LEFT_HAND); if (hasJMLTransitionForRight == false) hasJMLTransitionForRight = ei[j].hasJMLTransitionForHand(i+1, HandLink.RIGHT_HAND); if (hasVDHandJMLTransition[i][0] == false) hasVDHandJMLTransition[i][0] = ei[j].hasVDJMLTransitionForHand(i+1, HandLink.LEFT_HAND); if (hasVDHandJMLTransition[i][1] == false) hasVDHandJMLTransition[i][1] = ei[j].hasVDJMLTransitionForHand(i+1, HandLink.RIGHT_HAND); } if (hasJMLTransitionForLeft == false) { String template = errorstrings.getString("Error_no_left_events"); Object[] arguments = { new Integer(i+1) }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } if (hasJMLTransitionForRight == false) { String template = errorstrings.getString("Error_no_right_events"); Object[] arguments = { new Integer(i+1) }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } needVDHandEvent[i][0] = hasVDHandJMLTransition[i][0]; // set up for later needVDHandEvent[i][1] = hasVDHandJMLTransition[i][1]; needHandEvent[i][0] = needHandEvent[i][1] = true; } for (int i = 0; i < numpaths; i++) { boolean hasPathJMLTransition = false; hasVDPathJMLTransition[i] = false; for (int j = 0; j < numevents; j++) { if (hasPathJMLTransition == false) hasPathJMLTransition = ei[j].hasJMLTransitionForPath(i+1); if (hasVDPathJMLTransition[i] == false) hasVDPathJMLTransition[i] = ei[j].hasVDJMLTransitionForPath(i+1); } if (hasPathJMLTransition == false) { String template = errorstrings.getString("Error_no_path_events"); Object[] arguments = { new Integer(i+1) }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } needPathEvent[i] = true; // set up for later needSpecialPathEvent[i] = false; } // queue used to store events while building event list JMLEvent[] eventqueue = new JMLEvent[numevents]; for (int i = 0; i < numevents; i++) eventqueue[i] = ei[i].getPrevious(); // seed the queue // start by extending each master event backward in time boolean contin = false; do { // find latest event in queue JMLEvent maxevent = eventqueue[0]; double maxtime = maxevent.getT(); int maxnum = 0; for (int i = 1; i < numevents; i++) { if (eventqueue[i].getT() > maxtime) { maxevent = eventqueue[i]; maxtime = maxevent.getT(); maxnum = i; } } this.addEvent(maxevent); // add to event list eventqueue[maxnum] = ei[maxnum].getPrevious(); // restock queue // now update the needs arrays, so we know when to stop if (maxtime < this.getLoopStartTime()) { int jug = maxevent.getJuggler() - 1; int han = HandLink.index(maxevent.getHand()); if (hasVDHandJMLTransition[jug][han] == false) needHandEvent[jug][han] = false; for (int i = 0; i < maxevent.getNumberOfTransitions(); i++) { JMLTransition tr = maxevent.getTransition(i); int path = tr.getPath() - 1; switch (tr.getType()) { case JMLTransition.TRANS_THROW: needPathEvent[path] = false; needVDHandEvent[jug][han] = needHandEvent[jug][han] = false; needSpecialPathEvent[path] = false; break; case JMLTransition.TRANS_CATCH: break; case JMLTransition.TRANS_SOFTCATCH: if (needVDHandEvent[jug][han] == true) needSpecialPathEvent[path] = true; // need corresponding throw to get velocity needVDHandEvent[jug][han] = needHandEvent[jug][han] = false; break; case JMLTransition.TRANS_HOLDING: if (hasVDPathJMLTransition[path] == false) // if no throws for this path, then done needPathEvent[path] = false; break; } } } // do we need to continue adding earlier events? contin = false; for (int i = 0; i < numjugglers; i++) { contin |= needHandEvent[i][0]; contin |= needHandEvent[i][1]; contin |= needVDHandEvent[i][0]; contin |= needVDHandEvent[i][1]; } for (int i = 0; i < numpaths; i++) { contin |= needPathEvent[i]; contin |= needSpecialPathEvent[i]; } } while (contin); // reset things to go forward in time for (int i = 0; i < numjugglers; i++) { needVDHandEvent[i][0] = hasVDHandJMLTransition[i][0]; needVDHandEvent[i][1] = hasVDHandJMLTransition[i][1]; needHandEvent[i][0] = needHandEvent[i][1] = true; } for (int i = 0; i < numpaths; i++) { needPathEvent[i] = true; needSpecialPathEvent[i] = false; } for (int i = 0; i < numevents; i++) { ei[i].resetPosition(); eventqueue[i] = ei[i].getNext(); } do { // find earliest event in queue JMLEvent minevent = eventqueue[0]; double mintime = minevent.getT(); int minnum = 0; for (int i = 1; i < numevents; i++) { if (eventqueue[i].getT() < mintime) { minevent = eventqueue[i]; mintime = minevent.getT(); minnum = i; } } this.addEvent(minevent); // add to event list eventqueue[minnum] = ei[minnum].getNext(); // restock queue // now update the needs arrays, so we know when to stop if (mintime > this.getLoopEndTime()) { int jug = minevent.getJuggler() - 1; int han = HandLink.index(minevent.getHand()); // if this hand has no throws/catches, then need to build out event list // past a certain time, due to how the hand layout is done in this case // (see layoutHandPaths() below) if ((hasVDHandJMLTransition[jug][han] == false) && (mintime > (2 * getLoopEndTime() - getLoopStartTime()))) needHandEvent[jug][han] = false; for (int i = 0; i < minevent.getNumberOfTransitions(); i++) { JMLTransition tr = minevent.getTransition(i); int path = tr.getPath() - 1; switch (tr.getType()) { case JMLTransition.TRANS_THROW: needPathEvent[path] = false; if (needVDHandEvent[jug][han] == true) // need corresponding catch to get velocity needSpecialPathEvent[path] = true; needVDHandEvent[jug][han] = needHandEvent[jug][han] = false; break; case JMLTransition.TRANS_CATCH: needPathEvent[path] = false; needSpecialPathEvent[path] = false; break; case JMLTransition.TRANS_SOFTCATCH: needPathEvent[path] = false; needVDHandEvent[jug][han] = needHandEvent[jug][han] = false; needSpecialPathEvent[path] = false; break; case JMLTransition.TRANS_HOLDING: if (hasVDPathJMLTransition[path] == false) // if no throws for this path, needPathEvent[path] = false; // then done break; } } } // do we need to continue adding earlier events? contin = false; for (int i = 0; i < numjugglers; i++) { contin |= needHandEvent[i][0]; contin |= needHandEvent[i][1]; contin |= needVDHandEvent[i][0]; contin |= needVDHandEvent[i][1]; } for (int i = 0; i < numpaths; i++) { contin |= needPathEvent[i]; contin |= needSpecialPathEvent[i]; } } while (contin); } // Step 2: figure out which events should be considered master events public void findMasterEvents() throws JuggleExceptionInternal, JuggleExceptionUser { boolean rebuildList = false; JMLEvent ev = eventlist; while (ev != null) { if (ev.isMaster()) { JMLEvent newmaster = ev; double tmaster = getLoopEndTime(); if ((ev.getT() >= getLoopStartTime()) && (ev.getT() < tmaster)) tmaster = ev.getT(); JMLEvent ev2 = eventlist; while (ev2 != null) { if (ev2.getMaster() == ev) { if ((ev2.getT() >= getLoopStartTime()) && (ev2.getT() < tmaster)) { newmaster = ev2; tmaster = ev2.getT(); } } ev2 = ev2.getNext(); } if (newmaster != ev) { rebuildList = true; ev2 = eventlist; while (ev2 != null) { if (ev2.getMaster() == ev) ev2.setMaster(newmaster); ev2 = ev2.getNext(); } newmaster.setMaster(null); ev.setMaster(newmaster); } } ev = ev.getNext(); } if (rebuildList) buildEventList(); } // Step 3: find positions/angles for all jugglers at all points in time, // using specified tags. This is done by finding spline functions // passing through the specified locations and angles. public void findPositions() throws JuggleExceptionInternal { this.jugglercurve = new splineCurve[this.getNumberOfJugglers()]; this.jugglerangle = ( (Constants.ANGLE_LAYOUT_METHOD == Curve.lineCurve) ? (Curve[])(new lineCurve[this.getNumberOfJugglers()]) : (Curve[])(new splineCurve[this.getNumberOfJugglers()]) ); for (int i = 1; i <= this.getNumberOfJugglers(); i++) { int num = 0; JMLPosition current = this.positionlist; while (current != null) { if (current.getJuggler() == i) num++; current = current.getNext(); } if (num == 0) { jugglercurve[i-1] = new splineCurve(); jugglerangle[i-1] = ( (Constants.ANGLE_LAYOUT_METHOD == Curve.lineCurve) ? (Curve)(new lineCurve()) : (Curve)(new splineCurve()) ); double[] times = new double[2]; times[0] = this.getLoopStartTime(); times[1] = this.getLoopEndTime(); Coordinate[] positions = new Coordinate[2]; Coordinate[] angles = new Coordinate[2]; positions[0] = new Coordinate(); angles[0] = new Coordinate(); // default juggler body positions if (this.getNumberOfJugglers() == 1) { positions[0].setCoordinate(0.0, 0.0, 100.0); angles[0].setCoordinate(0.0, 0.0, 0.0); } else { double r = 70.0; double theta = 360.0 / (double)this.getNumberOfJugglers(); if (r * Math.sin(JLMath.toRad(0.5*theta)) < 65.0) r = 65.0 / Math.sin(JLMath.toRad(0.5*theta)); positions[0].setCoordinate(r*Math.cos(JLMath.toRad(theta*(double)(i-1))), r*Math.sin(JLMath.toRad(theta*(double)(i-1))), 100.0); angles[0].setCoordinate(90.0 + theta*(double)(i-1), 0.0, 0.0); } positions[1] = positions[0]; angles[1] = angles[0]; jugglercurve[i-1].setCurve(positions, times); jugglercurve[i-1].calcCurve(); jugglerangle[i-1].setCurve(angles, times); jugglerangle[i-1].calcCurve(); } else { jugglercurve[i-1] = new splineCurve(); jugglerangle[i-1] = ( (Constants.ANGLE_LAYOUT_METHOD == Curve.lineCurve) ? (Curve)(new lineCurve()) : (Curve)(new splineCurve()) ); double[] times = new double[num+1]; Coordinate[] positions = new Coordinate[num+1]; Coordinate[] angles = new Coordinate[num+1]; current = this.positionlist; int j = 0; while (current != null) { if (current.getJuggler() == i) { times[j] = current.getT(); positions[j] = current.getCoordinate(); angles[j] = new Coordinate(current.getAngle(),0.0,0.0); j++; } current = current.getNext(); } times[num] = times[0] + this.getLoopEndTime() - this.getLoopStartTime(); positions[num] = positions[0]; angles[num] = new Coordinate(angles[0]); for (j = 1; j <= num; j++) { while ((angles[j].x - angles[j-1].x) > 180.0) angles[j].x -= 360.0; while ((angles[j].x - angles[j-1].x) < -180.0) angles[j].x += 360.0; } jugglercurve[i-1].setCurve(positions, times); jugglercurve[i-1].calcCurve(); jugglerangle[i-1].setCurve(angles, times); jugglerangle[i-1].calcCurve(); } } } // Step 4: transform event coordinates from local to global reference frame public void gotoGlobalCoordinates() { JMLEvent ev = eventlist; while (ev != null) { Coordinate lc = ev.getLocalCoordinate(); int juggler = ev.getJuggler(); double t = ev.getT(); ev.setGlobalCoordinate(this.convertLocalToGlobal(lc, juggler, t)); ev = ev.getNext(); } } // Step 5: construct the links connecting events; build PathLink and HandLink lists protected void buildLinkLists() throws JuggleExceptionUser, JuggleExceptionInternal { int i, j, k; this.pathlinks = new Vector[getNumberOfPaths()]; for (i = 0; i < getNumberOfPaths(); i++) { // build the PathLink list for the ith path pathlinks[i] = new Vector(); JMLEvent ev = this.eventlist; JMLEvent lastev = null; JMLTransition lasttr = null; done1: while (true) { // find the next transition for this path JMLTransition tr = null; while (true) { tr = ev.getPathTransition(i+1, JMLTransition.TRANS_ANY); if (tr != null) break; ev = ev.getNext(); if (ev == null) break done1; } if (lastev != null) { PathLink pl = new PathLink(i+1, lastev, ev); switch (tr.getType()) { case JMLTransition.TRANS_THROW: case JMLTransition.TRANS_HOLDING: if (lasttr.getType() == JMLTransition.TRANS_THROW) { String template = errorstrings.getString("Error_successive_throws"); Object[] arguments = { new Integer(i+1) }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } if (lastev.getJuggler() != ev.getJuggler()) { String template = errorstrings.getString("Error_juggler_changed"); Object[] arguments = { new Integer(i+1) }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } if (lastev.getHand() != ev.getHand()) { String template = errorstrings.getString("Error_hand_changed"); Object[] arguments = { new Integer(i+1) }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } pl.setInHand(ev.getJuggler(), ev.getHand()); break; case JMLTransition.TRANS_CATCH: if (lasttr.getType() != JMLTransition.TRANS_THROW) { String template = errorstrings.getString("Error_successive_catches"); Object[] arguments = { new Integer(i+1) }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } pl.setThrow(lasttr.getThrowType(), lasttr.getMod()); break; case JMLTransition.TRANS_SOFTCATCH: if (lasttr.getType() != JMLTransition.TRANS_THROW) { String template = errorstrings.getString("Error_successive_catches"); Object[] arguments = { new Integer(i+1) }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } pl.setThrow(lasttr.getThrowType(), lasttr.getMod()); break; } pathlinks[i].addElement(pl); if (lasttr != null) lasttr.setOutgoingPathLink(pl); tr.setIncomingPathLink(pl); } lastev = ev; lasttr = tr; ev = ev.getNext(); if (ev == null) break done1; } if (pathlinks[i].size() == 0) throw new JuggleExceptionInternal("No event found for path "+(i+1)); } // now build the HandLink lists handlinks = new Vector[getNumberOfJugglers()][2]; for (i = 0; i < getNumberOfJugglers(); i++) { // build the HandLink list for the ith juggler for (j = 0; j < 2; j++) { int handnum = (j == 0 ? HandLink.LEFT_HAND : HandLink.RIGHT_HAND); handlinks[i][j] = new Vector(); JMLEvent ev = this.eventlist; JMLEvent lastev = null; VelocityRef vr = null; VelocityRef lastvr = null; done2: while (true) { // find the next event touching hand while (true) { if ((ev.getJuggler() == (i+1)) && (ev.getHand() == handnum)) break; ev = ev.getNext(); if (ev == null) break done2; } // find velocity of hand path ending vr = null; if ((ev.getJuggler() == (i+1)) && (ev.getHand() == handnum)) { for (k = 0; k < ev.getNumberOfTransitions(); k++) { JMLTransition tr = ev.getTransition(k); if (tr.getType() == JMLTransition.TRANS_THROW) { PathLink pl = tr.getOutgoingPathLink(); if (pl != null) vr = new VelocityRef(pl.getPath(), true); } else if (tr.getType() == JMLTransition.TRANS_SOFTCATCH) { PathLink pl = tr.getIncomingPathLink(); if (pl != null) vr = new VelocityRef(pl.getPath(), false); } } } if (lastev != null) { // add HandLink from lastev to ev HandLink hl = new HandLink(i, handnum, lastev, ev); hl.setStartVelocityRef(lastvr); // may be null, which is ok hl.setEndVelocityRef(vr); handlinks[i][j].addElement(hl); } lastev = ev; lastvr = vr; ev = ev.getNext(); if (ev == null) break done2; } } } } // Step 6: do a physical layout of the handlink paths // (Props were physically laid out in PathLink.setThrow() in Step 5 above) protected void layoutHandPaths() throws JuggleExceptionInternal { // go through HandLink lists, creating Path objects and calculating paths for (int i = 0; i < getNumberOfJugglers(); i++) { for (int j = 0; j < 2; j++) { // There are two cases -- a hand has throw or softcatch events (which define // hand velocities at points in time), or it does not (no velocities known). // To determine the spline paths, we need to solve for hand velocity at each // of its events, but this is done differently in the two cases. if (hasVDHandJMLTransition[i][j]) { int num = 0; HandLink startlink = null; for (int k = 0; k < handlinks[i][j].size(); k++) { HandLink hl = (HandLink)handlinks[i][j].elementAt(k); if (hl.getStartVelocityRef() != null) { // this is guaranteed to happen before the loop start time, given // the way we built the event list above startlink = hl; num = 1; } if ((hl.getEndVelocityRef() != null) && (startlink != null)) { Coordinate[] pos = new Coordinate[num+1]; double[] times = new double[num+1]; Curve hp = new splineCurve(); for (int l = 0; l < num; l++) { HandLink hl2 = (HandLink)handlinks[i][j].elementAt(k-num+1+l); pos[l] = hl2.getStartEvent().getGlobalCoordinate(); times[l] = hl2.getStartEvent().getT(); hl2.setHandCurve(hp); } pos[num] = hl.getEndEvent().getGlobalCoordinate(); times[num] = hl.getEndEvent().getT(); Coordinate startvel = startlink.getStartVelocityRef().getVelocity(); Coordinate endvel = hl.getEndVelocityRef().getVelocity(); hp.setCurve(pos, times, startvel, endvel); hp.calcCurve(); startlink = null; } num++; } } else { // Build chain and solve for velocities. This implementation is a little // inefficient since it builds the second chain by a duplicate calculation rather // than a copy. Sketch of algorithm: // find first handlink that straddles loopStartTime -- call it startlink // startevent = first event in startlink // delayedstartevent = corresponding event 1 delay period after startevent // find handlink that ends with delayedstartevent -- call it endlink // build spline hand path from startlink to endlink, and calculate (chain 1) // startlink = next link after endlink // delayed2startevent = corresponding event 1 delay period after delayedstartevent // find handlink that ends with delayed2startevent -- call it endlink // build spline hand path from startlink to endlink, and calculate (chain 2) int k; HandLink hl = null; for (k = 0; k < handlinks[i][j].size(); k++) { hl = (HandLink)handlinks[i][j].elementAt(k); if (hl.getEndEvent().getT() > getLoopStartTime()) break; } for (int chain = 0; chain < 2; chain++) { HandLink startlink = hl; JMLEvent startevent = startlink.getStartEvent(); int num = 1; // number of links in chain while (hl.getEndEvent().isDelayOf(startevent) == false) { hl = (HandLink)handlinks[i][j].elementAt(++k); num++; } Coordinate[] pos = new Coordinate[num+1]; double[] times = new double[num+1]; Curve hp = new splineCurve(); for (int l = 0; l < num; l++) { HandLink hl2 = (HandLink)handlinks[i][j].elementAt(k-num+1+l); pos[l] = hl2.getStartEvent().getGlobalCoordinate(); times[l] = hl2.getStartEvent().getT(); hl2.setHandCurve(hp); } pos[num] = hl.getEndEvent().getGlobalCoordinate(); times[num] = hl.getEndEvent().getT(); hp.setCurve(pos, times, null, null); // null endpoint velocities signals to calculate hp.calcCurve(); if (chain == 0) hl = (HandLink)handlinks[i][j].elementAt(++k); } } } } } // ------------------------------------------------------------------------ // Methods used by animator to get prop and body locations at specified times. // ------------------------------------------------------------------------ public String getTitle() { return title; } public int getNumberOfJugglers() { return numjugglers; } public int getNumberOfPaths() { return numpaths; } public int getNumberOfProps() { return props.size(); } public Prop getProp(int propnum) { return getPropDef(propnum).getProp(); } public PropDef getPropDef(int propnum) { return ((PropDef)props.elementAt(propnum-1)); } public int getPropAssignment(int path) { return propassignment[path-1]; } public int getNumberOfSymmetries() { return symmetries.size(); } public JMLSymmetry getSymmetry(int index) { return (JMLSymmetry)symmetries.elementAt(index); } public double getLoopStartTime() { return 0.0; } public double getLoopEndTime() { for (int i = 0; i < getNumberOfSymmetries(); i++) if (getSymmetry(i).getType() == JMLSymmetry.TYPE_DELAY) return getSymmetry(i).getDelay(); return -1.0; } // returns path coordinate in global frame public void getPathCoordinate(int path, double time, Coordinate newPosition) throws JuggleExceptionInternal { for (int i = 0; i < pathlinks[path-1].size(); i++) { PathLink pl = (PathLink)pathlinks[path-1].elementAt(i); if ((time >= pl.getStartEvent().getT()) && (time <= pl.getEndEvent().getT())) { if (pl.isInHand()) { int jug = pl.getHoldingJuggler(); int hand = pl.getHoldingHand(); this.getHandCoordinate(jug, hand, time, newPosition); return; } else { pl.getPath().getCoordinate(time, newPosition); return; } } } throw new JuggleExceptionInternal("time t="+time+" is out of path range"); } // returns orientation of prop on given path, in global frame // result is {pitch, yaw, roll} public double getPathOrientation(int path, double time, Coordinate axis) { axis.x = 0.0; // components of unit vector to rotate around axis.y = 0.0; axis.z = 1.0; return (3.0*time); } // returns juggler coordinate in global frame public void getJugglerPosition(int juggler, double time, Coordinate newPosition) { Curve p = jugglercurve[juggler-1]; while (time < p.getStartTime()) time += (this.getLoopEndTime() - this.getLoopStartTime()); while (time > p.getEndTime()) time -= (this.getLoopEndTime() - this.getLoopStartTime()); p.getCoordinate(time, newPosition); } // returns angle (in degrees) between local x axis and global x axis // (rotation around vertical z axis) public double getJugglerAngle(int juggler, double time) { Curve p = jugglerangle[juggler-1]; while (time < p.getStartTime()) time += (this.getLoopEndTime() - this.getLoopStartTime()); while (time > p.getEndTime()) time -= (this.getLoopEndTime() - this.getLoopStartTime()); Coordinate coord = new Coordinate(); p.getCoordinate(time, coord); return coord.x; } // Convert from local juggler frame to global frame public Coordinate convertLocalToGlobal(Coordinate lc, int juggler, double time) { Coordinate origin = new Coordinate(); this.getJugglerPosition(juggler, time, origin); double angle = JLMath.toRad(this.getJugglerAngle(juggler, time)); lc.y += Juggler.pattern_y; Coordinate gc = new Coordinate( origin.x + lc.x * Math.cos(angle) - lc.y * Math.sin(angle), origin.y + lc.x * Math.sin(angle) + lc.y * Math.cos(angle), origin.z + lc.z); return gc; } // Convert from global to local frame for a juggler public Coordinate convertGlobalToLocal(Coordinate gc, int juggler, double t) { Coordinate origin = new Coordinate(); this.getJugglerPosition(juggler, t, origin); double angle = JLMath.toRad(this.getJugglerAngle(juggler, t)); Coordinate c2 = Coordinate.sub(gc, origin); Coordinate lc = new Coordinate(c2.x * Math.cos(angle) + c2.y * Math.sin(angle), -c2.x * Math.sin(angle) + c2.y * Math.cos(angle), c2.z); lc.y -= Juggler.pattern_y; return lc; } // returns hand coordinate in global frame public void getHandCoordinate(int juggler, int hand, double time, Coordinate newPosition) throws JuggleExceptionInternal { int handindex = (hand == HandLink.LEFT_HAND) ? 0 : 1; for (int i = 0; i < handlinks[juggler-1][handindex].size(); i++) { HandLink hl = (HandLink)handlinks[juggler-1][handindex].elementAt(i); if ((time >= hl.getStartEvent().getT()) && (time < hl.getEndEvent().getT())) { Curve hp = hl.getHandCurve(); if (hp == null) throw new JuggleExceptionInternal("getHandCoordinate() null pointer"); hl.getHandCurve().getCoordinate(time, newPosition); return; } } throw new JuggleExceptionInternal("time t="+time+" (j="+juggler+",h="+handindex+") is out of handpath range"); } // Get volume of any catch made between time1 and time2; if no catch, returns 0.0 public double getPathCatchVolume(int path, double time1, double time2) { int i; PathLink pl1 = null, pl2 = null; boolean wasinair = false; boolean gotcatch = false; for (i = 0; i < pathlinks[path-1].size(); i++) { pl1 = (PathLink)pathlinks[path-1].elementAt(i); if ((time1 >= pl1.getStartEvent().getT()) && (time1 <= pl1.getEndEvent().getT())) break; } if (i == pathlinks[path-1].size()) return 0.0; while (true) { pl2 = (PathLink)pathlinks[path-1].elementAt(i); if (!pl2.isInHand()) wasinair = true; if (pl2.isInHand() && wasinair) { gotcatch = true; break; } if ((time2 >= pl2.getStartEvent().getT()) && (time2 <= pl2.getEndEvent().getT())) break; i++; if (i == pathlinks[path-1].size()) i = 0; } // Java 1.2 doesn't provide a way to adjust the playback volume of an audio clip, // so this is just yes/no for now if (gotcatch) return 1.0; return 0.0; } // Get volume of any bounce between time1 and time2; if no catch, returns 0.0 public double getPathBounceVolume(int path, double time1, double time2) { int i; PathLink pl = null; for (i = 0; i < pathlinks[path-1].size(); i++) { pl = (PathLink)pathlinks[path-1].elementAt(i); if ((time1 >= pl.getStartEvent().getT()) && (time1 <= pl.getEndEvent().getT())) break; } if (i == pathlinks[path-1].size()) return 0.0; while (true) { pl = (PathLink)pathlinks[path-1].elementAt(i); Path p = pl.getPath(); if (p instanceof bouncePath) { bouncePath bp = (bouncePath)p; double vol = bp.getBounceVolume(time1, time2); if (vol > 0.0) return vol; } if ((time2 >= pl.getStartEvent().getT()) && (time2 <= pl.getEndEvent().getT())) break; i++; if (i == pathlinks[path-1].size()) i = 0; } return 0.0; } public Coordinate getPathMax(int path) { // maximum of each coordinate Coordinate result = null; double t1 = getLoopStartTime(); double t2 = getLoopEndTime(); for (int i = 0; i < pathlinks[path-1].size(); i++) { PathLink pl = (PathLink)pathlinks[path-1].elementAt(i); if (pl.isInHand()) result = Coordinate.max(result, getHandMax(pl.getHoldingJuggler(), pl.getHoldingHand())); else result = Coordinate.max(result, pl.getPath().getMax(t1, t2)); } return result; } public Coordinate getPathMin(int path) { Coordinate result = null; double t1 = getLoopStartTime(); double t2 = getLoopEndTime(); for (int i = 0; i < pathlinks[path-1].size(); i++) { PathLink pl = (PathLink)pathlinks[path-1].elementAt(i); if (pl.isInHand()) result = Coordinate.min(result, getHandMin(pl.getHoldingJuggler(), pl.getHoldingHand())); else result = Coordinate.min(result, pl.getPath().getMin(t1, t2)); } return result; } public Coordinate getHandMax(int juggler, int hand) { Coordinate result = null; double t1 = getLoopStartTime(); double t2 = getLoopEndTime(); int handnum = (hand == HandLink.LEFT_HAND) ? 0 : 1; for (int i = 0; i < handlinks[juggler-1][handnum].size(); i++) { HandLink hl = (HandLink)handlinks[juggler-1][handnum].elementAt(i); Curve hp = hl.getHandCurve(); if (hp != null) result = Coordinate.max(result, hp.getMax(t1, t2)); } return result; } public Coordinate getHandMin(int juggler, int hand) { Coordinate result = null; double t1 = getLoopStartTime(); double t2 = getLoopEndTime(); int handnum = (hand == HandLink.LEFT_HAND) ? 0 : 1; for (int i = 0; i < handlinks[juggler-1][handnum].size(); i++) { HandLink hl = (HandLink)handlinks[juggler-1][handnum].elementAt(i); Curve hp = hl.getHandCurve(); if (hp != null) result = Coordinate.min(result, hp.getMin(t1, t2)); } return result; } public Coordinate getJugglerMax(int juggler) { return jugglercurve[juggler-1].getMax(); } public Coordinate getJugglerMin(int juggler) { return jugglercurve[juggler-1].getMin(); } public Permutation getPathPermutation() { for (int i = 0; i < getNumberOfSymmetries(); i++) if (getSymmetry(i).getType() == JMLSymmetry.TYPE_DELAY) return getSymmetry(i).getPathPerm(); return null; } public int getPeriod() { return getPeriod(getPathPermutation(), this.propassignment); } public static int getPeriod(Permutation perm, int[] propassign) { int i, j, k, cperiod, period = 1; boolean matches; int size = perm.getSize(); boolean[] notdone = new boolean[size]; for (i = 0; i < size; i++) notdone[i] = true; for (i = 0; i < size; i++) { if (notdone[i]) { int[] cycle = perm.getCycle(i+1); for (j = 0; j < cycle.length; j++) { notdone[cycle[j]-1] = false; cycle[j] = propassign[cycle[j]-1]; } // now find the period of the current cycle for (cperiod = 1; cperiod < cycle.length; cperiod++) { if ((cycle.length % cperiod) == 0) { matches = true; for (k = 0; k < cycle.length; k++) { if (cycle[k] != cycle[(k+cperiod)%cycle.length]) { matches = false; break; } } if (matches) break; } } period = Permutation.lcm(period, cperiod); } } return period; } public boolean isValid() { return valid; } public boolean isLaidout() { return laidout; } protected void printEventList() { JMLEvent current = eventlist; java.io.PrintWriter pw = new java.io.PrintWriter(System.out); while (current != null) { if (current.isMaster()) System.out.println(" Master event:"); else System.out.println(" Slave event; master at t="+current.getMaster().getT()); try { current.writeJML(pw); } catch (java.io.IOException ioe) { } pw.flush(); current = current.getNext(); } } // ------------------------------------------------------------------------ // Use the JMLNode tree to build our internal pattern representation // ------------------------------------------------------------------------ String loadingversion = null; protected void readJML(JMLNode current) throws JuggleExceptionUser { // process current node, then treat subnodes recursively String type = current.getNodeType(); if (type.equalsIgnoreCase("jml")) { loadingversion = current.getAttributes().getAttribute("version"); if (loadingversion == null) loadingversion = JMLDefs.default_JML_on_load; } else if (type.equalsIgnoreCase("pattern")) { // do nothing } else if (type.equalsIgnoreCase("title")) { this.setTitle(current.getNodeValue()); } else if (type.equalsIgnoreCase("prop")) { PropDef pd = new PropDef(); pd.readJML(current, loadingversion); this.addProp(pd); } else if (type.equalsIgnoreCase("setup")) { JMLAttributes at = current.getAttributes(); String jugglerstring, pathstring, propstring; jugglerstring = at.getAttribute("jugglers"); pathstring = at.getAttribute("paths"); propstring = at.getAttribute("props"); try { if (jugglerstring != null) this.setNumberOfJugglers(Integer.valueOf(jugglerstring).intValue()); else this.setNumberOfJugglers(1); this.setNumberOfPaths(Integer.valueOf(pathstring).intValue()); } catch (Exception ex) { throw new JuggleExceptionUser(errorstrings.getString("Error_setup_tag")); } int[] pa = new int[numpaths]; if (propstring != null) { StringTokenizer st = new StringTokenizer(propstring, ","); if (st.countTokens() != numpaths) throw new JuggleExceptionUser(errorstrings.getString("Error_prop_assignments")); try { for (int i = 0; i < numpaths; i++) { pa[i] = Integer.valueOf(st.nextToken()).intValue(); if ((pa[i] < 1) || (pa[i] > getNumberOfProps())) throw new JuggleExceptionUser(errorstrings.getString("Error_prop_number")); } } catch (NumberFormatException nfe) { throw new JuggleExceptionUser(errorstrings.getString("Error_prop_format")); } } else { for (int i = 0; i < numpaths; i++) pa[i] = 1; } this.setPropAssignments(pa); } else if (type.equalsIgnoreCase("symmetry")) { JMLSymmetry sym = new JMLSymmetry(); sym.readJML(current, numjugglers, numpaths, loadingversion); this.addSymmetry(sym); } else if (type.equalsIgnoreCase("event")) { JMLEvent ev = new JMLEvent(); ev.readJML(current, loadingversion, getNumberOfJugglers(), getNumberOfPaths()); // look at subnodes this.addEvent(ev); return; // stop recursive descent } else if (type.equalsIgnoreCase("position")) { JMLPosition pos = new JMLPosition(); pos.readJML(current, loadingversion); this.addPosition(pos); return; } else { String template = errorstrings.getString("Error_unknown_tag"); Object[] arguments = { type }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } for (int i = 0; i < current.getNumberOfChildren(); i++) readJML(current.getChildNode(i)); } public static String toStringTruncated(double val, int digits) { String result = Double.toString(val); if (result.indexOf('E') > 0) { if (val < 0.0) { val = -val; result = "-"; } else result = ""; result += Integer.toString((int)val); if (digits < 1) return result; result += "."; val -= (double)((int)val); for (int i = 0; i < digits; i++) val *= 10.0; String rem = Integer.toString((int)val); for (int i = rem.length(); i < digits; i++) result += "0"; result += rem; } int decimalpos = result.indexOf('.'); if (decimalpos < 0) return result; int endpos = decimalpos + digits + 1; if (endpos > result.length()) endpos = result.length(); while (endpos > 0) { int ch = result.charAt(endpos-1); if (ch == '.') { endpos--; break; } else if (ch == '0') { endpos--; } else break; } return result.substring(0, endpos); } public void writeJML(Writer wr, boolean title) throws IOException { PrintWriter write = new PrintWriter(wr); for (int i = 0; i < JMLDefs.jmlprefix.length; i++) write.println(JMLDefs.jmlprefix[i]); write.println(""); write.println(""); if (title) write.println("" + JMLNode.xmlescape(this.title) + ""); for (int i = 0; i < props.size(); i++) ((PropDef)props.elementAt(i)).writeJML(write); String out = ""); for (int i = 0; i < symmetries.size(); i++) ((JMLSymmetry)symmetries.elementAt(i)).writeJML(write); JMLPosition pos = positionlist; while (pos != null) { pos.writeJML(write); pos = pos.getNext(); } JMLEvent ev = eventlist; while (ev != null) { if (ev.isMaster()) ev.writeJML(write); ev = ev.getNext(); } write.println(""); write.println(""); for (int i = 0; i < JMLDefs.jmlsuffix.length; i++) write.println(JMLDefs.jmlsuffix[i]); write.flush(); } public String toString() { StringWriter sw = new StringWriter(); try { writeJML(sw, true); } catch (IOException ioe) { } return sw.toString(); } public Object clone() { try { return new JMLPattern(new StringReader(this.toString())); } catch (Exception e) { } return null; } }jugglinglab-0.6.2+ds.1/source/jugglinglab/jml/JMLPosition.java000066400000000000000000000112571323754603300241420ustar00rootroot00000000000000// JMLPosition.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.jml; import jugglinglab.util.*; import java.util.*; import java.io.*; public class JMLPosition { // static ResourceBundle guistrings; static ResourceBundle errorstrings; static { // guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } protected double x, y, z, t, angle; protected int juggler; protected JMLPosition prev, next; // for doubly-linked event list public JMLPosition() { this.prev = this.next = null; } public Coordinate getCoordinate() { return new Coordinate(x,y,z); } public void setCoordinate(Coordinate c) { this.x = c.x; this.y = c.y; this.z = c.z; } public double getAngle() { return angle; } public void setAngle(double angle) { this.angle = angle; } public double getT() { return t; } public void setT(double t) { this.t = t; } public int getJuggler() { return juggler; } public void setJuggler(String strjuggler) throws JuggleExceptionUser { this.juggler = Integer.parseInt(strjuggler); } public void setJuggler(int j) { this.juggler = j; } public JMLPosition getPrevious() { return prev; } public void setPrevious(JMLPosition prev) { this.prev = prev; } public JMLPosition getNext() { return next; } public void setNext(JMLPosition next) { this.next = next; } // Methods to handle JML public void readJML(JMLNode current, String jmlvers) throws JuggleExceptionUser { JMLAttributes at = current.getAttributes(); double tempx=0.0, tempy=0.0, tempz=0.0, tempt=0.0, tempangle=0.0; String jugglerstr = "1"; try { for (int i = 0; i < at.getNumberOfAttributes(); i++) { // System.out.println("att. "+i+" = "+at.getAttributeValue(i)); if (at.getAttributeName(i).equalsIgnoreCase("x")) tempx = Double.valueOf(at.getAttributeValue(i)).doubleValue(); else if (at.getAttributeName(i).equalsIgnoreCase("y")) tempy = Double.valueOf(at.getAttributeValue(i)).doubleValue(); else if (at.getAttributeName(i).equalsIgnoreCase("z")) tempz = Double.valueOf(at.getAttributeValue(i)).doubleValue(); else if (at.getAttributeName(i).equalsIgnoreCase("t")) tempt = Double.valueOf(at.getAttributeValue(i)).doubleValue(); else if (at.getAttributeName(i).equalsIgnoreCase("angle")) tempangle = Double.valueOf(at.getAttributeValue(i)).doubleValue(); else if (at.getAttributeName(i).equalsIgnoreCase("juggler")) jugglerstr = at.getAttributeValue(i); } } catch (NumberFormatException nfe) { throw new JuggleExceptionUser(errorstrings.getString("Error_position_coordinate")); } setCoordinate(new Coordinate(tempx,tempy,tempz)); setT(tempt); setAngle(tempangle); if (jugglerstr == null) throw new JuggleExceptionUser(errorstrings.getString("Error_position_nojuggler")); setJuggler(jugglerstr); if (current.getNumberOfChildren() != 0) throw new JuggleExceptionUser(errorstrings.getString("Error_position_subtag")); } public void writeJML(PrintWriter wr) throws IOException { Coordinate c = getCoordinate(); wr.println(""); } } jugglinglab-0.6.2+ds.1/source/jugglinglab/jml/JMLSymmetry.java000066400000000000000000000123021323754603300241570ustar00rootroot00000000000000// JMLSymmetry.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.jml; import java.util.*; import java.io.*; import jugglinglab.util.*; public class JMLSymmetry { // static ResourceBundle guistrings; static ResourceBundle errorstrings; static { // guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } int type; int numjugglers; int numpaths; Permutation jugglerperm = null; Permutation pathperm = null; double delay = -1.0; static final public int TYPE_DELAY = 1; // types of symmetries static final public int TYPE_SWITCH = 2; static final public int TYPE_SWITCHDELAY = 3; public JMLSymmetry() {} public JMLSymmetry(int type, int numjugglers, String jugperm, int numpaths, String pathperm, double delay) throws JuggleExceptionUser { setType(type); setJugglerPerm(numjugglers, jugperm); setPathPerm(numpaths, pathperm); setDelay(delay); } public int getType() { return type; } protected void setType(int type) { this.type = type; } public int getNumberOfJugglers() { return numjugglers; } public Permutation getJugglerPerm() { return jugglerperm; } protected void setJugglerPerm(int nj, String jp) throws JuggleExceptionUser { this.numjugglers = nj; try { if (jp == null) this.jugglerperm = new Permutation(numjugglers, true); else this.jugglerperm = new Permutation(numjugglers, jp, true); } catch (JuggleException je) { throw new JuggleExceptionUser(je.getMessage()); } } public int getNumberOfPaths() { return numpaths; } public Permutation getPathPerm() { return pathperm; } protected void setPathPerm(int np, String pp) throws JuggleExceptionUser { this.numpaths = np; try { if (pp == null) this.pathperm = new Permutation(numpaths, false); else this.pathperm = new Permutation(numpaths, pp, false); } catch (JuggleException je) { throw new JuggleExceptionUser(je.getMessage()); } } public double getDelay() { return delay; } public void setDelay(double del) { this.delay = del; } public void readJML(JMLNode current, int numjug, int numpat, String version) throws JuggleExceptionUser { JMLAttributes at = current.getAttributes(); String symtype, pathperm, jugglerperm, delaystring; int symtypenum; double delay=-1.0; symtype = at.getAttribute("type"); jugglerperm = at.getAttribute("jperm"); pathperm = at.getAttribute("pperm"); delaystring = at.getAttribute("delay"); if (delaystring != null) { try { delay = Double.valueOf(delaystring).doubleValue(); } catch (NumberFormatException nfe) { throw new JuggleExceptionUser(errorstrings.getString("Error_symmetry_format")); } } if (symtype == null) throw new JuggleExceptionUser(errorstrings.getString("Error_symmetry_notype")); if (symtype.equalsIgnoreCase("delay")) symtypenum = TYPE_DELAY; else if (symtype.equalsIgnoreCase("switch")) symtypenum = TYPE_SWITCH; else if (symtype.equalsIgnoreCase("switchdelay")) symtypenum = TYPE_SWITCHDELAY; else throw new JuggleExceptionUser(errorstrings.getString("Error_symmetry_type")); setType(symtypenum); setJugglerPerm(numjug, jugglerperm); setPathPerm(numpat, pathperm); setDelay(delay); } public void writeJML(PrintWriter wr) throws IOException { String out = ""; break; case TYPE_SWITCH: out += "switch\" jperm=\""+jugglerperm.toString(true)+ "\" pperm=\""+pathperm.toString(true)+"\"/>"; break; case TYPE_SWITCHDELAY: out += "switchdelay\" jperm=\""+jugglerperm.toString(true)+ "\" pperm=\""+pathperm.toString(true)+"\"/>"; break; } wr.println(out); } }jugglinglab-0.6.2+ds.1/source/jugglinglab/jml/JMLTransition.java000066400000000000000000000064421323754603300244700ustar00rootroot00000000000000// JMLTransition.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.jml; import java.io.*; public class JMLTransition { protected int path; protected String type; protected String mod; protected PathLink ipl, opl; protected int transitiontype; public static final int TRANS_NONE = 0; public static final int TRANS_THROW = 1; public static final int TRANS_CATCH = 2; public static final int TRANS_SOFTCATCH = 3; public static final int TRANS_HOLDING = 4; public static final int TRANS_ANY = 5; public JMLTransition(int transtype, int path, String type, String mod) { this.transitiontype = transtype; this.type = type; this.mod = mod; this.ipl = this.opl = null; this.path = path; } public int getType() { return transitiontype; } public void setType(int t) { this.transitiontype = t; } public int getPath() { return path; } public void setPath(int p) { this.path = p; } public String getThrowType() { return type; } public void setThrowType(String type) { this.type = type; } public String getMod() { return mod; } public void setMod(String mod) { this.mod = mod; } public void setIncomingPathLink(PathLink ipl) { this.ipl = ipl; } public PathLink getIncomingPathLink() { return ipl; } public void setOutgoingPathLink(PathLink opl) { this.opl = opl; } public PathLink getOutgoingPathLink() { return opl; } public JMLTransition duplicate() { JMLTransition tr = new JMLTransition(transitiontype, path, type, mod); return tr; } public void writeJML(PrintWriter wr) throws IOException { switch (getType()) { case TRANS_THROW: String out = ""); break; case TRANS_CATCH: wr.println(""); break; case TRANS_SOFTCATCH: wr.println(""); break; case TRANS_HOLDING: wr.println(""); break; } } }jugglinglab-0.6.2+ds.1/source/jugglinglab/jml/PathLink.java000077500000000000000000000063471323754603300235140ustar00rootroot00000000000000// PathLink.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.jml; import jugglinglab.path.*; import jugglinglab.util.*; public class PathLink { protected int pathnum; protected JMLEvent startevent, endevent; protected int catchtype; protected String throwtype, mod; protected Path proppath; protected boolean inhand; protected int juggler, hand; protected boolean ismaster; protected PathLink[] duplicates; // if master protected PathLink master; // if duplicate public PathLink(int pathnum, JMLEvent startevent, JMLEvent endevent) { this.pathnum = pathnum; this.startevent = startevent; this.endevent = endevent; this.proppath = null; this.inhand = false; } public void setThrow(String type, String mod) throws JuggleExceptionUser, JuggleExceptionInternal { proppath = Path.getPath(type); proppath.initPath(mod); proppath.setStart(startevent.getGlobalCoordinate(), startevent.getT()); proppath.setEnd(endevent.getGlobalCoordinate(), endevent.getT()); proppath.calcPath(); this.throwtype = type; this.mod = mod; this.inhand = false; } public void setInHand(int juggler, int hand) { this.inhand = true; this.juggler = juggler; this.hand = hand; } public Path getPath() { return proppath; } public int getCatch() { return catchtype; } public void setCatch(int catchtype) { this.catchtype = catchtype; } public int getPathNum() { return pathnum; } public JMLEvent getStartEvent() { return startevent; } public JMLEvent getEndEvent() { return endevent; } public boolean isInHand() { return inhand; } public int getHoldingJuggler() { return juggler; } public int getHoldingHand() { return hand; } public boolean isMaster() { return ismaster; } public String toString() { String result = null; if (inhand) { result = "In hand, "; } else { result = "Not in hand (type=\""+throwtype+"\", mod=\""+ mod+"\"), "; } Coordinate start = startevent.getGlobalCoordinate(); result += "from (x="+start.x+",y="+start.y+",z="+start.z+",t="+ startevent.getT()+") "; Coordinate end = endevent.getGlobalCoordinate(); result += "to (x="+end.x+",y="+end.y+",z="+end.z+",t="+endevent.getT()+")"; return result; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/jml/PropDef.java000077500000000000000000000040751323754603300233350ustar00rootroot00000000000000// PropDef.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.jml; import java.util.*; import java.io.*; import jugglinglab.prop.*; import jugglinglab.util.*; public class PropDef { String proptype, mod; Prop prop; public PropDef() { proptype = mod = null; prop = null; } public PropDef(String proptype, String mod) { this(); setType(proptype); setMod(mod); } public String getType() { return proptype; } protected void setType(String type) { this.proptype = type; } public String getMod() { return mod; } protected void setMod(String spec) { this.mod = spec; } public Prop getProp() { return prop; } public void layoutProp() throws JuggleExceptionUser { this.prop = Prop.getProp(getType()); prop.initProp(getMod()); } public void readJML(JMLNode current, String version) { JMLAttributes at = current.getAttributes(); setType(at.getAttribute("type")); setMod(at.getAttribute("mod")); } public void writeJML(PrintWriter wr) throws IOException { String out = ""; else out += "/>"; wr.println(out); } }jugglinglab-0.6.2+ds.1/source/jugglinglab/jml/VelocityRef.java000077500000000000000000000024151323754603300242250ustar00rootroot00000000000000// VelocityRef.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.jml; import jugglinglab.util.*; import jugglinglab.path.*; public class VelocityRef { protected Path pp; protected boolean start; public VelocityRef(Path pp, boolean start) { this.pp = pp; this.start = start; } public Coordinate getVelocity() { if (start) return pp.getStartVelocity(); else return pp.getEndVelocity(); } } jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/000077500000000000000000000000001323754603300221735ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/Notation.java000077500000000000000000000061251323754603300246400ustar00rootroot00000000000000// Notation.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.notation; import java.awt.*; import java.util.*; import jugglinglab.core.*; import jugglinglab.jml.*; import jugglinglab.util.*; public abstract class Notation { // static ResourceBundle guistrings; static ResourceBundle errorstrings; static { // guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } static Hashtable hash = null; // The built-in notations public static final String[] builtinNotations = { "Siteswap" }; // these should be in the same order as in the builtinNotations array public static final int NOTATION_NONE = 0; public static final int NOTATION_SITESWAP = 1; // This is a factory to create Notations from names. Note the // naming convention. public static Notation getNotation(String name) throws JuggleExceptionUser, JuggleExceptionInternal { if (hash == null) hash = new Hashtable(); Notation not = (Notation)hash.get(name.toLowerCase()); if (not == null) { Notation newnot = null; try { Object obj = Class.forName("jugglinglab.notation."+ name.toLowerCase()+"Notation").newInstance(); if (!(obj instanceof Notation)) throw new JuggleExceptionInternal(errorstrings.getString("Error_notation_bad")+": '"+name+"'"); newnot = (Notation)obj; } catch (ClassNotFoundException cnfe) { throw new JuggleExceptionUser(errorstrings.getString("Error_notation_notfound")+": '"+name+"'"); } catch (IllegalAccessException iae) { throw new JuggleExceptionUser(errorstrings.getString("Error_notation_cantaccess")+": '"+name+"'"); } catch (InstantiationException ie) { throw new JuggleExceptionInternal(errorstrings.getString("Error_notation_cantcreate")+": '"+name+"'"); } hash.put(name.toLowerCase(), newnot); return newnot; } return not; } public abstract String getName(); public abstract JMLPattern getJMLPattern(String pattern) throws JuggleExceptionUser, JuggleExceptionInternal; } jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/NotationControl.java000077500000000000000000000025451323754603300262030ustar00rootroot00000000000000// NotationControl.java // // Copyright 2003 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.notation; import java.util.*; import javax.swing.*; import jugglinglab.util.*; public abstract class NotationControl extends JPanel { static ResourceBundle guistrings; static ResourceBundle errorstrings; static { guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } public abstract String getPattern(); public abstract void resetNotationControl(); public abstract String getHandsName(); } jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/NotationGUI.java000077500000000000000000000366761323754603300252230ustar00rootroot00000000000000// NotationGUI.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.notation; import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; import java.util.*; import java.text.MessageFormat; import javax.swing.*; import javax.swing.event.*; import org.xml.sax.*; import jugglinglab.*; import jugglinglab.core.*; import jugglinglab.generator.*; import jugglinglab.jml.*; import jugglinglab.util.*; import jugglinglab.view.*; public class NotationGUI extends JPanel implements ActionListener { static ResourceBundle guistrings; static ResourceBundle errorstrings; static { guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } protected JTabbedPane jtp = null; protected JFrame parent = null; protected View animtarget = null; protected PatternList patlist = null; protected boolean patlisttab = false; protected int currentnum = -1; protected JButton juggle = null; protected JButton run = null; protected JLabel busy = null; // protected Notation not = null; // protected NotationControl control = null; // Execution limits for generator protected static final int max_patterns = 1000; protected static final double max_time = 15.0; public NotationGUI(JFrame parent) throws JuggleExceptionInternal { this(parent, null, null, false); } public NotationGUI(JFrame p, View v, PatternList pl, boolean patlisttab) { this.parent = p; this.animtarget = v; this.patlist = pl; this.patlisttab = (pl == null) ? patlisttab : true; } public JButton getDefaultButton() { if (jtp == null) return null; if (jtp.getSelectedIndex() == 0) return this.juggle; else return this.run; } public JMenu createNotationMenu() { JMenu notationmenu = new JMenu(guistrings.getString("Notation")); ButtonGroup buttonGroup = new ButtonGroup(); for (int i = 0; i < Notation.builtinNotations.length; i++) { JRadioButtonMenuItem notationitem = new JRadioButtonMenuItem(Notation.builtinNotations[i]); notationitem.setActionCommand("notation"+(i+1)); notationitem.addActionListener(this); notationmenu.add(notationitem); buttonGroup.add(notationitem); } // notationmenu.getItem(0).setSelected(true); // start in siteswap notation return notationmenu; } protected static final String[] helpItems = new String[] { "About Juggling Lab" }; protected static final String[] helpCommands = new String[] { "about" }; public JMenu createHelpMenu(boolean include_about) { if (!include_about) return null; JMenu helpmenu = new JMenu(guistrings.getString("Help")); for (int i = (include_about ? 0 : 1); i < helpItems.length; i++) { if (helpItems[i] == null) helpmenu.addSeparator(); else { JMenuItem helpitem = new JMenuItem(guistrings.getString(helpItems[i].replace(' ', '_'))); helpitem.setActionCommand(helpCommands[i]); helpitem.addActionListener(this); helpmenu.add(helpitem); } } return helpmenu; } public void actionPerformed(ActionEvent ae) { String command = ae.getActionCommand(); try { if (command.startsWith("notation")) { try { int num = Integer.parseInt(command.substring(8)); if (num != currentnum) { setNotation(num); if (parent != null) parent.pack(); currentnum = num; } } catch (NumberFormatException nfe) { throw new JuggleExceptionInternal("Error in notation number coding"); } } else if (command.equals("about")) doMenuCommand(HELP_ABOUT); } catch (Exception e) { ErrorDialog.handleException(e); } } public static final int HELP_NONE = 0; public static final int HELP_ABOUT = 1; public void doMenuCommand(int action) { switch (action) { case HELP_NONE: break; case HELP_ABOUT: showAboutBox(); break; } } // input is for example Notation.NOTATION_SITESWAP public void setNotation(int num) throws JuggleExceptionUser, JuggleExceptionInternal { if (num > Notation.builtinNotations.length) return; Notation not = null; NotationControl control = null; if (num != Notation.NOTATION_NONE) { try { not = Notation.getNotation(Notation.builtinNotations[num-1]); Class nc = Class.forName("jugglinglab.notation."+Notation.builtinNotations[num-1].toLowerCase()+"NotationControl"); control = (NotationControl)(nc.newInstance()); } catch (JuggleExceptionUser je) { throw new JuggleExceptionInternal("Could not create notation \""+Notation.builtinNotations[num-1]+"\""); } catch (ClassNotFoundException cnfe) { throw new JuggleExceptionUser("Could not find "+Notation.builtinNotations[num-1].toLowerCase()+"NotationControl class"); } catch (IllegalAccessException iae) { } catch (InstantiationException ie) { } } if (jtp != null) remove(jtp); jtp = new JTabbedPane(); PatternList pl = patlist; if (control != null) { final Notation fnot = not; final NotationControl fcontrol = control; JPanel np1 = new JPanel(); np1.setLayout(new BorderLayout()); np1.add(control, BorderLayout.PAGE_START); JPanel np2 = new JPanel(); np2.setLayout(new FlowLayout(FlowLayout.TRAILING)); JButton nbut1 = new JButton(guistrings.getString("Defaults")); nbut1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { try { fcontrol.resetNotationControl(); } catch (Exception e) { jugglinglab.util.ErrorDialog.handleException(e); } } }); np2.add(nbut1); this.juggle = new JButton(guistrings.getString("Juggle")); this.juggle.setDefaultCapable(true); juggle.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { PatternWindow jaw2 = null; try { String p = fcontrol.getPattern(); JMLPattern pat = fnot.getJMLPattern(p); String handsname = fcontrol.getHandsName(); if (handsname != null) pat.setTitle(pat.getTitle() + " " + handsname); if (animtarget != null) animtarget.restartView(pat, new AnimatorPrefs()); else jaw2 = new PatternWindow(pat.getTitle(), pat, new AnimatorPrefs()); } catch (JuggleExceptionUser je) { if (jaw2 != null) jaw2.dispose(); new ErrorDialog(NotationGUI.this, je.getMessage()); } catch (Exception e) { if (jaw2 != null) jaw2.dispose(); jugglinglab.util.ErrorDialog.handleException(e); } } }); np2.add(juggle); np1.add(np2, BorderLayout.PAGE_END); jtp.addTab(guistrings.getString("Pattern_entry"), np1); final Generator gen = Generator.getGenerator(Notation.builtinNotations[num-1]); if (gen != null) { if ((pl == null) && patlisttab) pl = new PatternList(animtarget); final PatternList plf = pl; JPanel p1 = new JPanel(); p1.setLayout(new BorderLayout()); p1.add(gen.getGeneratorControls(), BorderLayout.PAGE_START); JPanel p2 = new JPanel(); p2.setLayout(new FlowLayout(FlowLayout.TRAILING)); JButton but1 = new JButton(guistrings.getString("Defaults")); but1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { gen.resetGeneratorControls(); } }); p2.add(but1); this.run = new JButton(guistrings.getString("Run")); run.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { Thread t = new Thread() { public void run() { busy.setVisible(true); run.setEnabled(false); PatternListWindow pw = null; try { gen.initGenerator(); GeneratorTarget pwot = null; if (plf != null) { plf.clearList(); pwot = new GeneratorTarget(plf); //jtp.setSelectedComponent(plf); } else { pw = new PatternListWindow(fnot.getName()+" "+guistrings.getString("Patterns")); pwot = new GeneratorTarget(pw); } gen.runGenerator(pwot, max_patterns, max_time); if (plf != null) jtp.setSelectedComponent(plf); } catch (JuggleExceptionDone ex) { if (plf != null) jtp.setSelectedComponent(plf); Component parent = pw; if (pw == null) parent = plf; new LabelDialog(parent, guistrings.getString("Generator_stopped_title"), ex.getMessage()); } catch (JuggleExceptionUser ex) { if (pw != null) pw.dispose(); new ErrorDialog(NotationGUI.this, ex.getMessage()); } catch (Exception e) { if (pw != null) pw.dispose(); jugglinglab.util.ErrorDialog.handleException(e); } busy.setVisible(false); run.setEnabled(true); } }; t.start(); } }); p2.add(run); busy = new JLabel(guistrings.getString("Processing")); busy.setVisible(false); JPanel p3 = new JPanel(); p3.setLayout(new BorderLayout()); JPanel p4 = new JPanel(); GridBagLayout gb = new GridBagLayout(); p4.setLayout(gb); p4.add(busy); gb.setConstraints(busy, make_constraints(GridBagConstraints.LINE_START, 0, 0, new Insets(0,10,0,0))); p3.add(p4, BorderLayout.LINE_START); p3.add(p2, BorderLayout.LINE_END); p1.add(p3, BorderLayout.PAGE_END); // Change the default button when the tab changes jtp.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { getRootPane().setDefaultButton(getDefaultButton()); } }); jtp.addTab(guistrings.getString("Generator"), p1); } } if (pl != null) { jtp.addTab(guistrings.getString("Pattern_list_tab"), pl); if (patlist != null) jtp.setSelectedComponent(pl); // if we loaded from a file } setLayout(new BorderLayout()); add(jtp, BorderLayout.CENTER); GridBagLayout gb = new GridBagLayout(); setLayout(gb); add(jtp); GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = GridBagConstraints.LINE_START; gbc.fill = GridBagConstraints.BOTH; gbc.gridwidth = gbc.gridheight = 1; gbc.gridx = 0; gbc.gridy = 0; gbc.insets = new Insets(0,0,0,0); gbc.weightx = 1.0; gbc.weighty = 1.0; gb.setConstraints(jtp, gbc); if (parent != null) parent.getRootPane().setDefaultButton(getDefaultButton()); } protected void showAboutBox() { final JFrame aboutBox = new JFrame(guistrings.getString("About_Juggling_Lab")); aboutBox.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); JPanel aboutPanel = new JPanel(new BorderLayout()); aboutBox.getContentPane().add(aboutPanel, BorderLayout.CENTER); java.net.URL url = this.getClass().getResource("/resources/about.gif"); if (url != null) { ImageIcon aboutPicture = new ImageIcon(url, "A lab"); if (aboutPicture != null) { JLabel aboutLabel = new JLabel(aboutPicture); aboutPanel.add(aboutLabel, BorderLayout.LINE_START); } } JPanel textPanel = new JPanel(); aboutPanel.add(textPanel, BorderLayout.LINE_END); GridBagLayout gb = new GridBagLayout(); textPanel.setLayout(gb); JLabel abouttext1 = new JLabel("Juggling Lab"); abouttext1.setFont(new Font("SansSerif", Font.BOLD, 18)); textPanel.add(abouttext1); gb.setConstraints(abouttext1, make_constraints(GridBagConstraints.LINE_START,0,0, new Insets(15,15,0,15))); String template = guistrings.getString("Version"); Object[] arguments = { Constants.version }; JLabel abouttext5 = new JLabel(MessageFormat.format(template, arguments)); abouttext5.setFont(new Font("SansSerif", Font.PLAIN, 12)); textPanel.add(abouttext5); gb.setConstraints(abouttext5, make_constraints(GridBagConstraints.LINE_START,0,1, new Insets(0,15,0,15))); String template2 = guistrings.getString("Copyright_message"); Object[] arguments2 = { Constants.year }; JLabel abouttext6 = new JLabel(MessageFormat.format(template2, arguments2)); abouttext6.setFont(new Font("SansSerif", Font.PLAIN, 10)); textPanel.add(abouttext6); gb.setConstraints(abouttext6, make_constraints(GridBagConstraints.LINE_START,0,2, new Insets(15,15,15,15))); JLabel abouttext3 = new JLabel(guistrings.getString("GPL_message")); abouttext3.setFont(new Font("SansSerif", Font.PLAIN, 10)); textPanel.add(abouttext3); gb.setConstraints(abouttext3, make_constraints(GridBagConstraints.LINE_START,0,3, new Insets(0,15,0,15))); JButton okbutton = new JButton(guistrings.getString("OK")); textPanel.add(okbutton); gb.setConstraints(okbutton, make_constraints(GridBagConstraints.LINE_END,0,4, new Insets(15,15,15,15))); okbutton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { aboutBox.setVisible(false); aboutBox.dispose(); } }); Locale loc = JLLocale.getLocale(); aboutBox.applyComponentOrientation(ComponentOrientation.getOrientation(loc)); aboutBox.pack(); aboutBox.setResizable(false); aboutBox.setVisible(true); } protected static GridBagConstraints make_constraints(int location, int gridx, int gridy, Insets ins) { GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = location; gbc.fill = GridBagConstraints.NONE; gbc.gridheight = gbc.gridwidth = 1; gbc.gridx = gridx; gbc.gridy = gridy; gbc.insets = ins; gbc.weightx = gbc.weighty = 0.0; return gbc; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/ParseException.java000066400000000000000000000140371323754603300257740ustar00rootroot00000000000000/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 5.0 */ /* JavaCCOptions:KEEP_LINE_COL=null */ package jugglinglab.notation; /** * This exception is thrown when parse errors are encountered. * You can explicitly create objects of this exception type by * calling the method generateParseException in the generated * parser. * * You can modify this class to customize your error reporting * mechanisms so long as you retain the public fields. */ public class ParseException extends Exception { /** * The version identifier for this Serializable class. * Increment only if the serialized form of the * class changes. */ private static final long serialVersionUID = 1L; /** * This constructor is used by the method "generateParseException" * in the generated parser. Calling this constructor generates * a new object of this type with the fields "currentToken", * "expectedTokenSequences", and "tokenImage" set. */ public ParseException(Token currentTokenVal, int[][] expectedTokenSequencesVal, String[] tokenImageVal ) { super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal)); currentToken = currentTokenVal; expectedTokenSequences = expectedTokenSequencesVal; tokenImage = tokenImageVal; } /** * The following constructors are for use by you for whatever * purpose you can think of. Constructing the exception in this * manner makes the exception behave in the normal way - i.e., as * documented in the class "Throwable". The fields "errorToken", * "expectedTokenSequences", and "tokenImage" do not contain * relevant information. The JavaCC generated code does not use * these constructors. */ public ParseException() { super(); } /** Constructor with message. */ public ParseException(String message) { super(message); } /** * This is the last token that has been consumed successfully. If * this object has been created due to a parse error, the token * followng this token will (therefore) be the first error token. */ public Token currentToken; /** * Each entry in this array is an array of integers. Each array * of integers represents a sequence of tokens (by their ordinal * values) that is expected at this point of the parse. */ public int[][] expectedTokenSequences; /** * This is a reference to the "tokenImage" array of the generated * parser within which the parse error occurred. This array is * defined in the generated ...Constants interface. */ public String[] tokenImage; /** * It uses "currentToken" and "expectedTokenSequences" to generate a parse * error message and returns it. If this object has been created * due to a parse error, and you do not catch it (it gets thrown * from the parser) the correct error message * gets displayed. */ private static String initialise(Token currentToken, int[][] expectedTokenSequences, String[] tokenImage) { String eol = System.getProperty("line.separator", "\n"); StringBuffer expected = new StringBuffer(); int maxSize = 0; for (int i = 0; i < expectedTokenSequences.length; i++) { if (maxSize < expectedTokenSequences[i].length) { maxSize = expectedTokenSequences[i].length; } for (int j = 0; j < expectedTokenSequences[i].length; j++) { expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' '); } if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) { expected.append("..."); } expected.append(eol).append(" "); } String retval = "Encountered \""; Token tok = currentToken.next; for (int i = 0; i < maxSize; i++) { if (i != 0) retval += " "; if (tok.kind == 0) { retval += tokenImage[0]; break; } retval += " " + tokenImage[tok.kind]; retval += " \""; retval += add_escapes(tok.image); retval += " \""; tok = tok.next; } retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn; retval += "." + eol; if (expectedTokenSequences.length == 1) { retval += "Was expecting:" + eol + " "; } else { retval += "Was expecting one of:" + eol + " "; } retval += expected.toString(); return retval; } /** * The end of line string for this machine. */ protected String eol = System.getProperty("line.separator", "\n"); /** * Used to convert raw characters to their escaped version * when these raw version cannot be used as part of an ASCII * string literal. */ static String add_escapes(String str) { StringBuffer retval = new StringBuffer(); char ch; for (int i = 0; i < str.length(); i++) { switch (str.charAt(i)) { case 0 : continue; case '\b': retval.append("\\b"); continue; case '\t': retval.append("\\t"); continue; case '\n': retval.append("\\n"); continue; case '\f': retval.append("\\f"); continue; case '\r': retval.append("\\r"); continue; case '\"': retval.append("\\\""); continue; case '\'': retval.append("\\\'"); continue; case '\\': retval.append("\\\\"); continue; default: if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { String s = "0000" + Integer.toString(ch, 16); retval.append("\\u" + s.substring(s.length() - 4, s.length())); } else { retval.append(ch); } continue; } } return retval.toString(); } } /* JavaCC - OriginalChecksum=41711de4c02147f1ce582c08cd3f4dfe (do not edit this line) */ jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/SimpleCharStream.java000066400000000000000000000266651323754603300262600ustar00rootroot00000000000000/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 5.0 */ /* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ package jugglinglab.notation; /** * An implementation of interface CharStream, where the stream is assumed to * contain only ASCII characters (without unicode processing). */ public class SimpleCharStream { /** Whether parser is static. */ public static final boolean staticFlag = false; int bufsize; int available; int tokenBegin; /** Position in buffer. */ public int bufpos = -1; protected int bufline[]; protected int bufcolumn[]; protected int column = 0; protected int line = 1; protected boolean prevCharIsCR = false; protected boolean prevCharIsLF = false; protected java.io.Reader inputStream; protected char[] buffer; protected int maxNextCharInd = 0; protected int inBuf = 0; protected int tabSize = 8; protected void setTabSize(int i) { tabSize = i; } protected int getTabSize(int i) { return tabSize; } protected void ExpandBuff(boolean wrapAround) { char[] newbuffer = new char[bufsize + 2048]; int newbufline[] = new int[bufsize + 2048]; int newbufcolumn[] = new int[bufsize + 2048]; try { if (wrapAround) { System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos); buffer = newbuffer; System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos); bufline = newbufline; System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos); bufcolumn = newbufcolumn; maxNextCharInd = (bufpos += (bufsize - tokenBegin)); } else { System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); buffer = newbuffer; System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); bufline = newbufline; System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); bufcolumn = newbufcolumn; maxNextCharInd = (bufpos -= tokenBegin); } } catch (Throwable t) { throw new Error(t.getMessage()); } bufsize += 2048; available = bufsize; tokenBegin = 0; } protected void FillBuff() throws java.io.IOException { if (maxNextCharInd == available) { if (available == bufsize) { if (tokenBegin > 2048) { bufpos = maxNextCharInd = 0; available = tokenBegin; } else if (tokenBegin < 0) bufpos = maxNextCharInd = 0; else ExpandBuff(false); } else if (available > tokenBegin) available = bufsize; else if ((tokenBegin - available) < 2048) ExpandBuff(true); else available = tokenBegin; } int i; try { if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1) { inputStream.close(); throw new java.io.IOException(); } else maxNextCharInd += i; return; } catch(java.io.IOException e) { --bufpos; backup(0); if (tokenBegin == -1) tokenBegin = bufpos; throw e; } } /** Start. */ public char BeginToken() throws java.io.IOException { tokenBegin = -1; char c = readChar(); tokenBegin = bufpos; return c; } protected void UpdateLineColumn(char c) { column++; if (prevCharIsLF) { prevCharIsLF = false; line += (column = 1); } else if (prevCharIsCR) { prevCharIsCR = false; if (c == '\n') { prevCharIsLF = true; } else line += (column = 1); } switch (c) { case '\r' : prevCharIsCR = true; break; case '\n' : prevCharIsLF = true; break; case '\t' : column--; column += (tabSize - (column % tabSize)); break; default : break; } bufline[bufpos] = line; bufcolumn[bufpos] = column; } /** Read a character. */ public char readChar() throws java.io.IOException { if (inBuf > 0) { --inBuf; if (++bufpos == bufsize) bufpos = 0; return buffer[bufpos]; } if (++bufpos >= maxNextCharInd) FillBuff(); char c = buffer[bufpos]; UpdateLineColumn(c); return c; } @Deprecated /** * @deprecated * @see #getEndColumn */ public int getColumn() { return bufcolumn[bufpos]; } @Deprecated /** * @deprecated * @see #getEndLine */ public int getLine() { return bufline[bufpos]; } /** Get token end column number. */ public int getEndColumn() { return bufcolumn[bufpos]; } /** Get token end line number. */ public int getEndLine() { return bufline[bufpos]; } /** Get token beginning column number. */ public int getBeginColumn() { return bufcolumn[tokenBegin]; } /** Get token beginning line number. */ public int getBeginLine() { return bufline[tokenBegin]; } /** Backup a number of characters. */ public void backup(int amount) { inBuf += amount; if ((bufpos -= amount) < 0) bufpos += bufsize; } /** Constructor. */ public SimpleCharStream(java.io.Reader dstream, int startline, int startcolumn, int buffersize) { inputStream = dstream; line = startline; column = startcolumn - 1; available = bufsize = buffersize; buffer = new char[buffersize]; bufline = new int[buffersize]; bufcolumn = new int[buffersize]; } /** Constructor. */ public SimpleCharStream(java.io.Reader dstream, int startline, int startcolumn) { this(dstream, startline, startcolumn, 4096); } /** Constructor. */ public SimpleCharStream(java.io.Reader dstream) { this(dstream, 1, 1, 4096); } /** Reinitialise. */ public void ReInit(java.io.Reader dstream, int startline, int startcolumn, int buffersize) { inputStream = dstream; line = startline; column = startcolumn - 1; if (buffer == null || buffersize != buffer.length) { available = bufsize = buffersize; buffer = new char[buffersize]; bufline = new int[buffersize]; bufcolumn = new int[buffersize]; } prevCharIsLF = prevCharIsCR = false; tokenBegin = inBuf = maxNextCharInd = 0; bufpos = -1; } /** Reinitialise. */ public void ReInit(java.io.Reader dstream, int startline, int startcolumn) { ReInit(dstream, startline, startcolumn, 4096); } /** Reinitialise. */ public void ReInit(java.io.Reader dstream) { ReInit(dstream, 1, 1, 4096); } /** Constructor. */ public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException { this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); } /** Constructor. */ public SimpleCharStream(java.io.InputStream dstream, int startline, int startcolumn, int buffersize) { this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); } /** Constructor. */ public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, int startcolumn) throws java.io.UnsupportedEncodingException { this(dstream, encoding, startline, startcolumn, 4096); } /** Constructor. */ public SimpleCharStream(java.io.InputStream dstream, int startline, int startcolumn) { this(dstream, startline, startcolumn, 4096); } /** Constructor. */ public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException { this(dstream, encoding, 1, 1, 4096); } /** Constructor. */ public SimpleCharStream(java.io.InputStream dstream) { this(dstream, 1, 1, 4096); } /** Reinitialise. */ public void ReInit(java.io.InputStream dstream, String encoding, int startline, int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException { ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); } /** Reinitialise. */ public void ReInit(java.io.InputStream dstream, int startline, int startcolumn, int buffersize) { ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); } /** Reinitialise. */ public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException { ReInit(dstream, encoding, 1, 1, 4096); } /** Reinitialise. */ public void ReInit(java.io.InputStream dstream) { ReInit(dstream, 1, 1, 4096); } /** Reinitialise. */ public void ReInit(java.io.InputStream dstream, String encoding, int startline, int startcolumn) throws java.io.UnsupportedEncodingException { ReInit(dstream, encoding, startline, startcolumn, 4096); } /** Reinitialise. */ public void ReInit(java.io.InputStream dstream, int startline, int startcolumn) { ReInit(dstream, startline, startcolumn, 4096); } /** Get token literal value. */ public String GetImage() { if (bufpos >= tokenBegin) return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); else return new String(buffer, tokenBegin, bufsize - tokenBegin) + new String(buffer, 0, bufpos + 1); } /** Get the suffix. */ public char[] GetSuffix(int len) { char[] ret = new char[len]; if ((bufpos + 1) >= len) System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); else { System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, len - bufpos - 1); System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1); } return ret; } /** Reset buffer when finished. */ public void Done() { buffer = null; bufline = null; bufcolumn = null; } /** * Method to adjust line and column numbers for the start of a token. */ public void adjustBeginLineColumn(int newLine, int newCol) { int start = tokenBegin; int len; if (bufpos >= tokenBegin) { len = bufpos - tokenBegin + inBuf + 1; } else { len = bufsize - tokenBegin + bufpos + 1 + inBuf; } int i = 0, j = 0, k = 0; int nextColDiff = 0, columnDiff = 0; while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) { bufline[j] = newLine; nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; bufcolumn[j] = newCol + columnDiff; columnDiff = nextColDiff; i++; } if (i < len) { bufline[j] = newLine++; bufcolumn[j] = newCol + columnDiff; while (i++ < len) { if (bufline[j = start % bufsize] != bufline[++start % bufsize]) bufline[j] = newLine++; else bufline[j] = newLine; } } line = bufline[j]; column = bufcolumn[j]; } } /* JavaCC - OriginalChecksum=a339d6a57dc2ff69dfbb05d635557708 (do not edit this line) */ jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/SiteswapParser.java000066400000000000000000001354041323754603300260210ustar00rootroot00000000000000/* Generated By:JavaCC: Do not edit this line. SiteswapParser.java */ package jugglinglab.notation; // This file is part of Juggling Lab. It was automatically generated by JavaCC // from the grammar file "SiteswapParser.jj". // // DO NOT EDIT THIS FILE DIRECTLY, AS YOUR CHANGES WILL LIKELY BE OVERWRITTEN public class SiteswapParser implements SiteswapParserConstants { private static int jugglers; private static int current_juggler; private static int current_beat; private static int current_beat_sub; public static SiteswapTreeItem parsePattern(String pat) throws ParseException { java.io.StringReader sr = new java.io.StringReader(pat); java.io.Reader r = new java.io.BufferedReader(sr); SiteswapParser parser = new SiteswapParser(r); jugglers = -1; return (parser.MakeTree()); } // For test purposes public static void main(String args[]) throws ParseException { String in = args[0]; System.out.println("parsing pattern: "+in); System.out.println(parsePattern(in)); } final public SiteswapTreeItem MakeTree() throws ParseException { SiteswapTreeItem b; switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[0] = jj_gen; ; } b = Pattern(); jj_consume_token(0); {if (true) return b;} throw new Error("Missing return statement in function"); } final public SiteswapTreeItem Pattern() throws ParseException { SiteswapTreeItem b, c; int n; b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_PATTERN); label_1: while (true) { if (jj_2_1(2147483647)) { c = GroupedPattern(); } else { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case NUM: case LET: case 9: case 14: case 16: case 18: case 19: case 21: case 22: c = SoloSequence(); break; case 23: c = PassingSequence(); break; case 26: n = Wildcard(); c = new SiteswapTreeItem(SiteswapTreeItem.TYPE_WILDCARD); c.beats = n; break; default: jj_la1[1] = jj_gen; jj_consume_token(-1); throw new ParseException(); } } b.addChild(c); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case NUM: case LET: case 9: case 14: case 16: case 18: case 19: case 21: case 22: case 23: case 26: ; break; default: jj_la1[2] = jj_gen; break label_1; } } switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case 8: jj_consume_token(8); b.switchrepeat = true; break; default: jj_la1[3] = jj_gen; ; } b.jugglers = jugglers; {if (true) return b;} throw new Error("Missing return statement in function"); } final public SiteswapTreeItem GroupedPattern() throws ParseException { SiteswapTreeItem b, c; int n; b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_GROUPED_PATTERN); jj_consume_token(9); c = Pattern(); b.addChild(c); b.repeats = 1; switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case 10: jj_consume_token(10); n = Number(); b.repeats = n; break; default: jj_la1[4] = jj_gen; ; } jj_consume_token(11); {if (true) return b;} throw new Error("Missing return statement in function"); } final public SiteswapTreeItem SoloSequence() throws ParseException { SiteswapTreeItem b, c; Token s=null; b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_SOLO_SEQUENCE); current_juggler = 1; current_beat = 0; label_2: while (true) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case NUM: case LET: case 14: case 16: case 18: case 19: c = SoloMultiThrow(); current_beat++; b.addChild(c); break; case 9: c = SoloPairedThrow(); current_beat += 2; switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case 12: jj_consume_token(12); current_beat--; break; default: jj_la1[5] = jj_gen; ; } b.addChild(c); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[6] = jj_gen; ; } break; case 21: case 22: c = SoloHandSpecifier(); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[7] = jj_gen; ; } b.addChild(c); break; default: jj_la1[8] = jj_gen; jj_consume_token(-1); throw new ParseException(); } if (jj_2_2(2147483647)) { ; } else { break label_2; } } if (jugglers == -1) jugglers = 1; else if (jugglers != 1) { {if (true) throw new ParseException("Inconsistent number of jugglers");} } b.source_juggler = 1; b.beats = current_beat; {if (true) return b;} throw new Error("Missing return statement in function"); } final public SiteswapTreeItem SoloPairedThrow() throws ParseException { SiteswapTreeItem b, c; b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_SOLO_PAIRED_THROW); jj_consume_token(9); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[9] = jj_gen; ; } c = SoloMultiThrow(); b.addChild(c); jj_consume_token(13); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[10] = jj_gen; ; } c = SoloMultiThrow(); b.addChild(c); jj_consume_token(11); b.source_juggler = 1; b.seq_beatnum = current_beat; {if (true) return b;} throw new Error("Missing return statement in function"); } final public SiteswapTreeItem SoloMultiThrow() throws ParseException { SiteswapTreeItem b, c; b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_SOLO_MULTI_THROW); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case NUM: case LET: case 18: case 19: c = SoloSingleThrow(); b.addChild(c); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[11] = jj_gen; ; } break; case 14: jj_consume_token(14); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[12] = jj_gen; ; } label_3: while (true) { c = SoloSingleThrow(); b.addChild(c); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[13] = jj_gen; ; } switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case NUM: case LET: case 18: case 19: ; break; default: jj_la1[14] = jj_gen; break label_3; } } jj_consume_token(15); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[15] = jj_gen; ; } break; case 16: jj_consume_token(16); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[16] = jj_gen; ; } label_4: while (true) { c = SoloSingleThrow(); b.addChild(c); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[17] = jj_gen; ; } switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case NUM: case LET: case 18: case 19: ; break; default: jj_la1[18] = jj_gen; break label_4; } } jj_consume_token(17); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[19] = jj_gen; ; } break; default: jj_la1[20] = jj_gen; jj_consume_token(-1); throw new ParseException(); } b.source_juggler = 1; b.seq_beatnum = current_beat; {if (true) return b;} throw new Error("Missing return statement in function"); } final public SiteswapTreeItem SoloSingleThrow() throws ParseException { SiteswapTreeItem b; Token t; String mod; b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_SOLO_SINGLE_THROW); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case NUM: t = jj_consume_token(NUM); b.value = Character.digit((t.image.toCharArray())[0], 36); break; case LET: t = jj_consume_token(LET); b.value = Character.digit((t.image.toCharArray())[0], 36); break; case 18: jj_consume_token(18); b.value = 25; break; case 19: jj_consume_token(19); b.value = 33; break; default: jj_la1[21] = jj_gen; jj_consume_token(-1); throw new ParseException(); } switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case 19: jj_consume_token(19); b.x = true; break; default: jj_la1[22] = jj_gen; ; } switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case MOD: mod = Modifier(); b.mod = mod; break; default: jj_la1[23] = jj_gen; ; } switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case 20: jj_consume_token(20); break; default: jj_la1[24] = jj_gen; ; } b.source_juggler = 1; b.dest_juggler = 1; b.seq_beatnum = current_beat; {if (true) return b;} throw new Error("Missing return statement in function"); } final public SiteswapTreeItem SoloHandSpecifier() throws ParseException { SiteswapTreeItem b; b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_HAND_SPEC); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case 21: jj_consume_token(21); b.spec_left = false; break; case 22: jj_consume_token(22); b.spec_left = true; break; default: jj_la1[25] = jj_gen; jj_consume_token(-1); throw new ParseException(); } b.source_juggler = 1; b.seq_beatnum = current_beat; {if (true) return b;} throw new Error("Missing return statement in function"); } final public SiteswapTreeItem PassingSequence() throws ParseException { SiteswapTreeItem b, c; b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_PASSING_SEQUENCE); current_beat = 0; label_5: while (true) { c = PassingGroup(); b.jugglers = c.jugglers; b.addChild(c); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case 23: ; break; default: jj_la1[26] = jj_gen; break label_5; } } b.beats = current_beat; {if (true) return b;} throw new Error("Missing return statement in function"); } final public SiteswapTreeItem PassingGroup() throws ParseException { SiteswapTreeItem b, c; b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_PASSING_GROUP); current_juggler = 1; jj_consume_token(23); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[27] = jj_gen; ; } c = PassingThrows(); b.beats = c.beats; b.addChild(c); current_juggler++; label_6: while (true) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case 24: ; break; default: jj_la1[28] = jj_gen; break label_6; } jj_consume_token(24); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[29] = jj_gen; ; } c = PassingThrows(); if (c.beats != b.beats) { {if (true) throw new ParseException("Inconsistent number of beats between jugglers");} } b.addChild(c); current_juggler++; } jj_consume_token(25); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[30] = jj_gen; ; } b.jugglers = current_juggler - 1; if (jugglers == -1) jugglers = b.jugglers; else if (b.jugglers != jugglers) { {if (true) throw new ParseException("Inconsistent number of jugglers");} } b.seq_beatnum = current_beat; current_beat += b.beats; {if (true) return b;} throw new Error("Missing return statement in function"); } final public SiteswapTreeItem PassingThrows() throws ParseException { SiteswapTreeItem b, c; b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_PASSING_THROWS); current_beat_sub = 0; label_7: while (true) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case NUM: case LET: case 14: case 16: case 18: case 19: c = PassingMultiThrow(); current_beat_sub++; b.addChild(c); break; case 9: c = PassingPairedThrow(); current_beat_sub += 2; switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case 12: jj_consume_token(12); current_beat_sub--; break; default: jj_la1[31] = jj_gen; ; } switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[32] = jj_gen; ; } b.addChild(c); break; case 21: case 22: c = PassingHandSpecifier(); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[33] = jj_gen; ; } b.addChild(c); break; default: jj_la1[34] = jj_gen; jj_consume_token(-1); throw new ParseException(); } if (jj_2_3(2147483647)) { ; } else { break label_7; } } b.source_juggler = current_juggler; b.beats = current_beat_sub; b.seq_beatnum = current_beat; {if (true) return b;} throw new Error("Missing return statement in function"); } final public SiteswapTreeItem PassingPairedThrow() throws ParseException { SiteswapTreeItem b, c; b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_PASSING_PAIRED_THROW); jj_consume_token(9); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[35] = jj_gen; ; } c = PassingMultiThrow(); b.addChild(c); jj_consume_token(13); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[36] = jj_gen; ; } c = PassingMultiThrow(); b.addChild(c); jj_consume_token(11); b.source_juggler = current_juggler; b.seq_beatnum = current_beat + current_beat_sub; {if (true) return b;} throw new Error("Missing return statement in function"); } final public SiteswapTreeItem PassingMultiThrow() throws ParseException { SiteswapTreeItem b, c; b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_PASSING_MULTI_THROW); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case NUM: case LET: case 18: case 19: c = PassingSingleThrow(); b.addChild(c); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[37] = jj_gen; ; } break; case 14: jj_consume_token(14); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[38] = jj_gen; ; } label_8: while (true) { c = PassingSingleThrow(); b.addChild(c); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[39] = jj_gen; ; } switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case NUM: case LET: case 18: case 19: ; break; default: jj_la1[40] = jj_gen; break label_8; } } jj_consume_token(15); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[41] = jj_gen; ; } break; case 16: jj_consume_token(16); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[42] = jj_gen; ; } label_9: while (true) { c = PassingSingleThrow(); b.addChild(c); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[43] = jj_gen; ; } switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case NUM: case LET: case 18: case 19: ; break; default: jj_la1[44] = jj_gen; break label_9; } } jj_consume_token(17); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case SPC: jj_consume_token(SPC); break; default: jj_la1[45] = jj_gen; ; } break; default: jj_la1[46] = jj_gen; jj_consume_token(-1); throw new ParseException(); } b.source_juggler = current_juggler; b.seq_beatnum = current_beat + current_beat_sub; {if (true) return b;} throw new Error("Missing return statement in function"); } final public SiteswapTreeItem PassingSingleThrow() throws ParseException { SiteswapTreeItem b, c; Token t; int dest, d; String mod; b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_PASSING_SINGLE_THROW); dest = current_juggler; switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case NUM: t = jj_consume_token(NUM); b.value = Character.digit((t.image.toCharArray())[0], 36); break; case LET: t = jj_consume_token(LET); b.value = Character.digit((t.image.toCharArray())[0], 36); break; case 18: jj_consume_token(18); b.value = 25; break; case 19: jj_consume_token(19); b.value = 33; break; default: jj_la1[47] = jj_gen; jj_consume_token(-1); throw new ParseException(); } switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case 19: jj_consume_token(19); b.x = true; break; default: jj_la1[48] = jj_gen; ; } switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case 18: jj_consume_token(18); dest = current_juggler + 1; switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case NUM: d = Number(); dest = d; break; default: jj_la1[49] = jj_gen; ; } break; default: jj_la1[50] = jj_gen; ; } switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case MOD: mod = Modifier(); b.mod = mod; break; default: jj_la1[51] = jj_gen; ; } switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case 20: jj_consume_token(20); break; default: jj_la1[52] = jj_gen; ; } b.source_juggler = current_juggler; b.dest_juggler = dest; b.seq_beatnum = current_beat + current_beat_sub; {if (true) return b;} throw new Error("Missing return statement in function"); } final public SiteswapTreeItem PassingHandSpecifier() throws ParseException { SiteswapTreeItem b; b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_HAND_SPEC); switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case 21: jj_consume_token(21); b.spec_left = false; break; case 22: jj_consume_token(22); b.spec_left = true; break; default: jj_la1[53] = jj_gen; jj_consume_token(-1); throw new ParseException(); } b.source_juggler = current_juggler; b.seq_beatnum = current_beat + current_beat_sub; {if (true) return b;} throw new Error("Missing return statement in function"); } final public int Number() throws ParseException { Token n; String s = ""; label_10: while (true) { n = jj_consume_token(NUM); s += n.image; switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case NUM: ; break; default: jj_la1[54] = jj_gen; break label_10; } } int val = -1; try { val = Integer.parseInt(s); } catch (NumberFormatException mfe) { } {if (true) return val;} throw new Error("Missing return statement in function"); } final public int Wildcard() throws ParseException { int beats = 0; label_11: while (true) { jj_consume_token(26); beats++; switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case 26: ; break; default: jj_la1[55] = jj_gen; break label_11; } } {if (true) return beats;} throw new Error("Missing return statement in function"); } final public String Modifier() throws ParseException { Token t; String mod = ""; t = jj_consume_token(MOD); mod += t.image; label_12: while (true) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case MOD: case 21: case 22: ; break; default: jj_la1[56] = jj_gen; break label_12; } switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case MOD: t = jj_consume_token(MOD); mod += t.image; break; case 22: jj_consume_token(22); mod += "L"; break; case 21: jj_consume_token(21); mod += "R"; break; default: jj_la1[57] = jj_gen; jj_consume_token(-1); throw new ParseException(); } } {if (true) return mod;} throw new Error("Missing return statement in function"); } private boolean jj_2_1(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_1(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(0, xla); } } private boolean jj_2_2(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_2(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(1, xla); } } private boolean jj_2_3(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_3(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(2, xla); } } private boolean jj_3R_74() { if (jj_3R_23()) return true; Token xsp; xsp = jj_scanpos; if (jj_3R_78()) jj_scanpos = xsp; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; return false; } private boolean jj_3R_84() { Token xsp; xsp = jj_scanpos; if (jj_3R_85()) { jj_scanpos = xsp; if (jj_3R_86()) { jj_scanpos = xsp; if (jj_3R_87()) return true; } } return false; } private boolean jj_3R_14() { if (jj_3R_22()) return true; return false; } private boolean jj_3_2() { Token xsp; xsp = jj_scanpos; if (jj_3R_14()) { jj_scanpos = xsp; if (jj_3R_15()) { jj_scanpos = xsp; if (jj_3R_16()) return true; } } return false; } private boolean jj_3R_73() { if (jj_3R_22()) return true; return false; } private boolean jj_3R_68() { Token xsp; xsp = jj_scanpos; if (jj_3R_73()) { jj_scanpos = xsp; if (jj_3R_74()) { jj_scanpos = xsp; if (jj_3R_75()) return true; } } return false; } private boolean jj_3R_79() { Token xsp; if (jj_3R_84()) return true; while (true) { xsp = jj_scanpos; if (jj_3R_84()) { jj_scanpos = xsp; break; } } return false; } private boolean jj_3R_83() { if (jj_scan_token(21)) return true; return false; } private boolean jj_3R_82() { if (jj_scan_token(22)) return true; return false; } private boolean jj_3R_81() { if (jj_scan_token(MOD)) return true; return false; } private boolean jj_3R_77() { Token xsp; xsp = jj_scanpos; if (jj_3R_81()) { jj_scanpos = xsp; if (jj_3R_82()) { jj_scanpos = xsp; if (jj_3R_83()) return true; } } return false; } private boolean jj_3R_52() { Token xsp; if (jj_3R_68()) return true; while (true) { xsp = jj_scanpos; if (jj_3R_68()) { jj_scanpos = xsp; break; } } return false; } private boolean jj_3R_80() { if (jj_scan_token(24)) return true; Token xsp; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; if (jj_3R_79()) return true; return false; } private boolean jj_3R_71() { if (jj_scan_token(MOD)) return true; Token xsp; while (true) { xsp = jj_scanpos; if (jj_3R_77()) { jj_scanpos = xsp; break; } } return false; } private boolean jj_3R_21() { if (jj_scan_token(10)) return true; if (jj_3R_30()) return true; return false; } private boolean jj_3R_13() { if (jj_scan_token(9)) return true; if (jj_3R_20()) return true; Token xsp; xsp = jj_scanpos; if (jj_3R_21()) jj_scanpos = xsp; if (jj_scan_token(11)) return true; return false; } private boolean jj_3R_70() { if (jj_scan_token(26)) return true; return false; } private boolean jj_3_1() { if (jj_3R_13()) return true; return false; } private boolean jj_3R_54() { Token xsp; if (jj_3R_70()) return true; while (true) { xsp = jj_scanpos; if (jj_3R_70()) { jj_scanpos = xsp; break; } } return false; } private boolean jj_3R_44() { if (jj_3R_54()) return true; return false; } private boolean jj_3R_43() { if (jj_3R_53()) return true; return false; } private boolean jj_3R_42() { if (jj_3R_52()) return true; return false; } private boolean jj_3R_76() { if (jj_scan_token(23)) return true; Token xsp; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; if (jj_3R_79()) return true; while (true) { xsp = jj_scanpos; if (jj_3R_80()) { jj_scanpos = xsp; break; } } if (jj_scan_token(25)) return true; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; return false; } private boolean jj_3R_45() { if (jj_scan_token(NUM)) return true; return false; } private boolean jj_3R_41() { if (jj_3R_13()) return true; return false; } private boolean jj_3R_29() { if (jj_scan_token(8)) return true; return false; } private boolean jj_3R_69() { if (jj_3R_76()) return true; return false; } private boolean jj_3R_30() { Token xsp; if (jj_3R_45()) return true; while (true) { xsp = jj_scanpos; if (jj_3R_45()) { jj_scanpos = xsp; break; } } return false; } private boolean jj_3R_28() { Token xsp; xsp = jj_scanpos; if (jj_3R_41()) { jj_scanpos = xsp; if (jj_3R_42()) { jj_scanpos = xsp; if (jj_3R_43()) { jj_scanpos = xsp; if (jj_3R_44()) return true; } } } return false; } private boolean jj_3R_40() { if (jj_scan_token(22)) return true; return false; } private boolean jj_3R_39() { if (jj_scan_token(21)) return true; return false; } private boolean jj_3R_20() { Token xsp; if (jj_3R_28()) return true; while (true) { xsp = jj_scanpos; if (jj_3R_28()) { jj_scanpos = xsp; break; } } xsp = jj_scanpos; if (jj_3R_29()) jj_scanpos = xsp; return false; } private boolean jj_3R_53() { Token xsp; if (jj_3R_69()) return true; while (true) { xsp = jj_scanpos; if (jj_3R_69()) { jj_scanpos = xsp; break; } } return false; } private boolean jj_3R_35() { if (jj_scan_token(22)) return true; return false; } private boolean jj_3R_27() { Token xsp; xsp = jj_scanpos; if (jj_3R_39()) { jj_scanpos = xsp; if (jj_3R_40()) return true; } return false; } private boolean jj_3R_34() { if (jj_scan_token(21)) return true; return false; } private boolean jj_3R_67() { if (jj_3R_71()) return true; return false; } private boolean jj_3R_66() { if (jj_scan_token(18)) return true; Token xsp; xsp = jj_scanpos; if (jj_3R_72()) jj_scanpos = xsp; return false; } private boolean jj_3R_72() { if (jj_3R_30()) return true; return false; } private boolean jj_3R_64() { if (jj_scan_token(19)) return true; return false; } private boolean jj_3R_63() { if (jj_scan_token(18)) return true; return false; } private boolean jj_3R_65() { if (jj_scan_token(19)) return true; return false; } private boolean jj_3R_24() { Token xsp; xsp = jj_scanpos; if (jj_3R_34()) { jj_scanpos = xsp; if (jj_3R_35()) return true; } return false; } private boolean jj_3R_62() { if (jj_scan_token(LET)) return true; return false; } private boolean jj_3R_60() { if (jj_3R_71()) return true; return false; } private boolean jj_3R_58() { if (jj_scan_token(19)) return true; return false; } private boolean jj_3R_61() { if (jj_scan_token(NUM)) return true; return false; } private boolean jj_3R_57() { if (jj_scan_token(18)) return true; return false; } private boolean jj_3R_59() { if (jj_scan_token(19)) return true; return false; } private boolean jj_3R_56() { if (jj_scan_token(LET)) return true; return false; } private boolean jj_3R_55() { if (jj_scan_token(NUM)) return true; return false; } private boolean jj_3R_49() { Token xsp; xsp = jj_scanpos; if (jj_3R_61()) { jj_scanpos = xsp; if (jj_3R_62()) { jj_scanpos = xsp; if (jj_3R_63()) { jj_scanpos = xsp; if (jj_3R_64()) return true; } } } xsp = jj_scanpos; if (jj_3R_65()) jj_scanpos = xsp; xsp = jj_scanpos; if (jj_3R_66()) jj_scanpos = xsp; xsp = jj_scanpos; if (jj_3R_67()) jj_scanpos = xsp; xsp = jj_scanpos; if (jj_scan_token(20)) jj_scanpos = xsp; return false; } private boolean jj_3R_51() { if (jj_3R_49()) return true; Token xsp; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; return false; } private boolean jj_3R_46() { Token xsp; xsp = jj_scanpos; if (jj_3R_55()) { jj_scanpos = xsp; if (jj_3R_56()) { jj_scanpos = xsp; if (jj_3R_57()) { jj_scanpos = xsp; if (jj_3R_58()) return true; } } } xsp = jj_scanpos; if (jj_3R_59()) jj_scanpos = xsp; xsp = jj_scanpos; if (jj_3R_60()) jj_scanpos = xsp; xsp = jj_scanpos; if (jj_scan_token(20)) jj_scanpos = xsp; return false; } private boolean jj_3R_48() { if (jj_3R_46()) return true; Token xsp; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; return false; } private boolean jj_3R_50() { if (jj_3R_49()) return true; Token xsp; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; return false; } private boolean jj_3R_38() { if (jj_scan_token(16)) return true; Token xsp; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; if (jj_3R_51()) return true; while (true) { xsp = jj_scanpos; if (jj_3R_51()) { jj_scanpos = xsp; break; } } if (jj_scan_token(17)) return true; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; return false; } private boolean jj_3R_47() { if (jj_3R_46()) return true; Token xsp; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; return false; } private boolean jj_3R_33() { if (jj_scan_token(16)) return true; Token xsp; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; if (jj_3R_48()) return true; while (true) { xsp = jj_scanpos; if (jj_3R_48()) { jj_scanpos = xsp; break; } } if (jj_scan_token(17)) return true; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; return false; } private boolean jj_3R_19() { if (jj_3R_27()) return true; return false; } private boolean jj_3R_37() { if (jj_scan_token(14)) return true; Token xsp; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; if (jj_3R_50()) return true; while (true) { xsp = jj_scanpos; if (jj_3R_50()) { jj_scanpos = xsp; break; } } if (jj_scan_token(15)) return true; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; return false; } private boolean jj_3R_36() { if (jj_3R_49()) return true; Token xsp; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; return false; } private boolean jj_3R_32() { if (jj_scan_token(14)) return true; Token xsp; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; if (jj_3R_47()) return true; while (true) { xsp = jj_scanpos; if (jj_3R_47()) { jj_scanpos = xsp; break; } } if (jj_scan_token(15)) return true; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; return false; } private boolean jj_3R_31() { if (jj_3R_46()) return true; Token xsp; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; return false; } private boolean jj_3R_25() { Token xsp; xsp = jj_scanpos; if (jj_3R_36()) { jj_scanpos = xsp; if (jj_3R_37()) { jj_scanpos = xsp; if (jj_3R_38()) return true; } } return false; } private boolean jj_3R_16() { if (jj_3R_24()) return true; return false; } private boolean jj_3R_22() { Token xsp; xsp = jj_scanpos; if (jj_3R_31()) { jj_scanpos = xsp; if (jj_3R_32()) { jj_scanpos = xsp; if (jj_3R_33()) return true; } } return false; } private boolean jj_3R_18() { if (jj_3R_26()) return true; return false; } private boolean jj_3R_87() { if (jj_3R_27()) return true; Token xsp; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; return false; } private boolean jj_3R_26() { if (jj_scan_token(9)) return true; Token xsp; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; if (jj_3R_25()) return true; if (jj_scan_token(13)) return true; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; if (jj_3R_25()) return true; if (jj_scan_token(11)) return true; return false; } private boolean jj_3R_88() { if (jj_scan_token(12)) return true; return false; } private boolean jj_3R_15() { if (jj_3R_23()) return true; return false; } private boolean jj_3R_23() { if (jj_scan_token(9)) return true; Token xsp; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; if (jj_3R_22()) return true; if (jj_scan_token(13)) return true; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; if (jj_3R_22()) return true; if (jj_scan_token(11)) return true; return false; } private boolean jj_3R_86() { if (jj_3R_26()) return true; Token xsp; xsp = jj_scanpos; if (jj_3R_88()) jj_scanpos = xsp; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; return false; } private boolean jj_3R_75() { if (jj_3R_24()) return true; Token xsp; xsp = jj_scanpos; if (jj_scan_token(7)) jj_scanpos = xsp; return false; } private boolean jj_3R_85() { if (jj_3R_25()) return true; return false; } private boolean jj_3R_17() { if (jj_3R_25()) return true; return false; } private boolean jj_3_3() { Token xsp; xsp = jj_scanpos; if (jj_3R_17()) { jj_scanpos = xsp; if (jj_3R_18()) { jj_scanpos = xsp; if (jj_3R_19()) return true; } } return false; } private boolean jj_3R_78() { if (jj_scan_token(12)) return true; return false; } /** Generated Token Manager. */ public SiteswapParserTokenManager token_source; SimpleCharStream jj_input_stream; /** Current token. */ public Token token; /** Next token. */ public Token jj_nt; private int jj_ntk; private Token jj_scanpos, jj_lastpos; private int jj_la; private int jj_gen; final private int[] jj_la1 = new int[58]; static private int[] jj_la1_0; static { jj_la1_init_0(); } private static void jj_la1_init_0() { jj_la1_0 = new int[] {0x80,0x4ed4230,0x4ed4230,0x100,0x400,0x1000,0x80,0x80,0x6d4230,0x80,0x80,0x80,0x80,0x80,0xc0030,0x80,0x80,0x80,0xc0030,0x80,0xd4030,0xc0030,0x80000,0x40,0x100000,0x600000,0x800000,0x80,0x1000000,0x80,0x80,0x1000,0x80,0x80,0x6d4230,0x80,0x80,0x80,0x80,0x80,0xc0030,0x80,0x80,0x80,0xc0030,0x80,0xd4030,0xc0030,0x80000,0x10,0x40000,0x40,0x100000,0x600000,0x10,0x4000000,0x600040,0x600040,}; } final private JJCalls[] jj_2_rtns = new JJCalls[3]; private boolean jj_rescan = false; private int jj_gc = 0; /** Constructor with InputStream. */ public SiteswapParser(java.io.InputStream stream) { this(stream, null); } /** Constructor with InputStream and supplied encoding */ public SiteswapParser(java.io.InputStream stream, String encoding) { try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); } token_source = new SiteswapParserTokenManager(jj_input_stream); token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 58; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } /** Reinitialise. */ public void ReInit(java.io.InputStream stream) { ReInit(stream, null); } /** Reinitialise. */ public void ReInit(java.io.InputStream stream, String encoding) { try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); } token_source.ReInit(jj_input_stream); token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 58; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } /** Constructor. */ public SiteswapParser(java.io.Reader stream) { jj_input_stream = new SimpleCharStream(stream, 1, 1); token_source = new SiteswapParserTokenManager(jj_input_stream); token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 58; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } /** Reinitialise. */ public void ReInit(java.io.Reader stream) { jj_input_stream.ReInit(stream, 1, 1); token_source.ReInit(jj_input_stream); token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 58; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } /** Constructor with generated Token Manager. */ public SiteswapParser(SiteswapParserTokenManager tm) { token_source = tm; token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 58; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } /** Reinitialise. */ public void ReInit(SiteswapParserTokenManager tm) { token_source = tm; token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 58; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } private Token jj_consume_token(int kind) throws ParseException { Token oldToken; if ((oldToken = token).next != null) token = token.next; else token = token.next = token_source.getNextToken(); jj_ntk = -1; if (token.kind == kind) { jj_gen++; if (++jj_gc > 100) { jj_gc = 0; for (int i = 0; i < jj_2_rtns.length; i++) { JJCalls c = jj_2_rtns[i]; while (c != null) { if (c.gen < jj_gen) c.first = null; c = c.next; } } } return token; } token = oldToken; jj_kind = kind; throw generateParseException(); } static private final class LookaheadSuccess extends java.lang.Error { } final private LookaheadSuccess jj_ls = new LookaheadSuccess(); private boolean jj_scan_token(int kind) { if (jj_scanpos == jj_lastpos) { jj_la--; if (jj_scanpos.next == null) { jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken(); } else { jj_lastpos = jj_scanpos = jj_scanpos.next; } } else { jj_scanpos = jj_scanpos.next; } if (jj_rescan) { int i = 0; Token tok = token; while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; } if (tok != null) jj_add_error_token(kind, i); } if (jj_scanpos.kind != kind) return true; if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls; return false; } /** Get the next Token. */ final public Token getNextToken() { if (token.next != null) token = token.next; else token = token.next = token_source.getNextToken(); jj_ntk = -1; jj_gen++; return token; } /** Get the specific Token. */ final public Token getToken(int index) { Token t = token; for (int i = 0; i < index; i++) { if (t.next != null) t = t.next; else t = t.next = token_source.getNextToken(); } return t; } private int jj_ntk() { if ((jj_nt=token.next) == null) return (jj_ntk = (token.next=token_source.getNextToken()).kind); else return (jj_ntk = jj_nt.kind); } private java.util.List jj_expentries = new java.util.ArrayList(); private int[] jj_expentry; private int jj_kind = -1; private int[] jj_lasttokens = new int[100]; private int jj_endpos; private void jj_add_error_token(int kind, int pos) { if (pos >= 100) return; if (pos == jj_endpos + 1) { jj_lasttokens[jj_endpos++] = kind; } else if (jj_endpos != 0) { jj_expentry = new int[jj_endpos]; for (int i = 0; i < jj_endpos; i++) { jj_expentry[i] = jj_lasttokens[i]; } jj_entries_loop: for (java.util.Iterator it = jj_expentries.iterator(); it.hasNext();) { int[] oldentry = (int[])(it.next()); if (oldentry.length == jj_expentry.length) { for (int i = 0; i < jj_expentry.length; i++) { if (oldentry[i] != jj_expentry[i]) { continue jj_entries_loop; } } jj_expentries.add(jj_expentry); break jj_entries_loop; } } if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind; } } /** Generate ParseException. */ public ParseException generateParseException() { jj_expentries.clear(); boolean[] la1tokens = new boolean[27]; if (jj_kind >= 0) { la1tokens[jj_kind] = true; jj_kind = -1; } for (int i = 0; i < 58; i++) { if (jj_la1[i] == jj_gen) { for (int j = 0; j < 32; j++) { if ((jj_la1_0[i] & (1< jj_gen) { jj_la = p.arg; jj_lastpos = jj_scanpos = p.first; switch (i) { case 0: jj_3_1(); break; case 1: jj_3_2(); break; case 2: jj_3_3(); break; } } p = p.next; } while (p != null); } catch(LookaheadSuccess ls) { } } jj_rescan = false; } private void jj_save(int index, int xla) { JJCalls p = jj_2_rtns[index]; while (p.gen > jj_gen) { if (p.next == null) { p = p.next = new JJCalls(); break; } p = p.next; } p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla; } static final class JJCalls { int gen; Token first; int arg; JJCalls next; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/SiteswapParser.jj000066400000000000000000000232461323754603300255030ustar00rootroot00000000000000// SiteswapParser.jj // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* This is a parser grammar file for use with the parser generator JavaCC (https://javacc.dev.java.net/) Process this file using JavaCC ("javacc SiteswapParser.jj") to generate the following source files: SiteswapParser.java SiteswapParserConstants.java SiteswapParserTokenManager.java ParseException.java SimpleCharStream.java Token.java TokenMgrError.java It is wise to avoid directly editing any of the source files above, as JavaCC will overwrite any changes if this file is processed again later. */ options { STATIC = false; } PARSER_BEGIN(SiteswapParser) package jugglinglab.notation; // This file is part of Juggling Lab. It was automatically generated by JavaCC // from the grammar file "SiteswapParser.jj". // // DO NOT EDIT THIS FILE DIRECTLY, AS YOUR CHANGES WILL LIKELY BE OVERWRITTEN public class SiteswapParser { private static int jugglers; private static int current_juggler; private static int current_beat; private static int current_beat_sub; public static SiteswapTreeItem parsePattern(String pat) throws ParseException { java.io.StringReader sr = new java.io.StringReader(pat); java.io.Reader r = new java.io.BufferedReader(sr); SiteswapParser parser = new SiteswapParser(r); jugglers = -1; return (parser.MakeTree()); } // For test purposes public static void main(String args[]) throws ParseException { String in = args[0]; System.out.println("parsing pattern: "+in); System.out.println(parsePattern(in)); } } PARSER_END(SiteswapParser) SKIP : { "\t" | "\n" | "\r" } TOKEN : { | | | } SiteswapTreeItem MakeTree() : { SiteswapTreeItem b; } { [] b=Pattern() { return b; } } SiteswapTreeItem Pattern() : { SiteswapTreeItem b, c; int n; } { { b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_PATTERN); } ( ( LOOKAHEAD(GroupedPattern()) c=GroupedPattern() | c=SoloSequence() | c=PassingSequence() | n=Wildcard() { c = new SiteswapTreeItem(SiteswapTreeItem.TYPE_WILDCARD); c.beats = n; } ) { b.addChild(c); } )+ ["*" { b.switchrepeat = true; } ] { b.jugglers = jugglers; return b; } } SiteswapTreeItem GroupedPattern() : { SiteswapTreeItem b, c; int n; } { { b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_GROUPED_PATTERN); } "(" c=Pattern() { b.addChild(c); b.repeats = 1; } ["^" n=Number() { b.repeats = n; } ] ")" { return b; } } SiteswapTreeItem SoloSequence() : { SiteswapTreeItem b, c; Token s=null; } { { b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_SOLO_SEQUENCE); current_juggler = 1; current_beat = 0; } ( LOOKAHEAD(SoloMultiThrow() | SoloPairedThrow() | SoloHandSpecifier()) ( c=SoloMultiThrow() { current_beat++; b.addChild(c); } | c=SoloPairedThrow() { current_beat += 2; } ["!" { current_beat--; } ] { b.addChild(c); } [] | c=SoloHandSpecifier() [] { b.addChild(c); } ) )+ { if (jugglers == -1) jugglers = 1; else if (jugglers != 1) { throw new ParseException("Inconsistent number of jugglers"); } b.source_juggler = 1; b.beats = current_beat; return b; } } SiteswapTreeItem SoloPairedThrow() : { SiteswapTreeItem b, c; } { { b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_SOLO_PAIRED_THROW); } "(" [] c=SoloMultiThrow() { b.addChild(c); } "," [] c=SoloMultiThrow() { b.addChild(c); } ")" { b.source_juggler = 1; b.seq_beatnum = current_beat; return b; } } SiteswapTreeItem SoloMultiThrow() : { SiteswapTreeItem b, c; } { { b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_SOLO_MULTI_THROW); } ( c=SoloSingleThrow() { b.addChild(c); } [] | "[" [] ( c=SoloSingleThrow() { b.addChild(c); } [] )+ "]" [] | "{" [] ( c=SoloSingleThrow() { b.addChild(c); } [] )+ "}" [] ) { b.source_juggler = 1; b.seq_beatnum = current_beat; return b; } } SiteswapTreeItem SoloSingleThrow() : { SiteswapTreeItem b; Token t; String mod; } { { b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_SOLO_SINGLE_THROW); } ( ( t= { b.value = Character.digit((t.image.toCharArray())[0], 36); } | t= { b.value = Character.digit((t.image.toCharArray())[0], 36); } | "p" { b.value = 25; } | "x" { b.value = 33; } ) ["x" { b.x = true; } ] [mod=Modifier() { b.mod = mod; } ] ["/"] ) { b.source_juggler = 1; b.dest_juggler = 1; b.seq_beatnum = current_beat; return b; } } SiteswapTreeItem SoloHandSpecifier() : { SiteswapTreeItem b; } { { b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_HAND_SPEC); } ( "R" { b.spec_left = false; } | "L" { b.spec_left = true; } ) { b.source_juggler = 1; b.seq_beatnum = current_beat; return b; } } SiteswapTreeItem PassingSequence() : { SiteswapTreeItem b, c; } { { b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_PASSING_SEQUENCE); current_beat = 0; } ( c=PassingGroup() { b.jugglers = c.jugglers; b.addChild(c); } )+ { b.beats = current_beat; return b; } } SiteswapTreeItem PassingGroup() : { SiteswapTreeItem b, c; } { { b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_PASSING_GROUP); current_juggler = 1; } "<" [] c=PassingThrows() { b.beats = c.beats; b.addChild(c); current_juggler++; } ( "|" [] c=PassingThrows() { if (c.beats != b.beats) { throw new ParseException("Inconsistent number of beats between jugglers"); } b.addChild(c); current_juggler++; } )* ">" [] { b.jugglers = current_juggler - 1; if (jugglers == -1) jugglers = b.jugglers; else if (b.jugglers != jugglers) { throw new ParseException("Inconsistent number of jugglers"); } b.seq_beatnum = current_beat; current_beat += b.beats; return b; } } SiteswapTreeItem PassingThrows() : { SiteswapTreeItem b, c; } { { b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_PASSING_THROWS); current_beat_sub = 0; } ( LOOKAHEAD(PassingMultiThrow() | PassingPairedThrow() | PassingHandSpecifier()) ( c=PassingMultiThrow() { current_beat_sub++; b.addChild(c); } | c=PassingPairedThrow() { current_beat_sub += 2; } ["!" { current_beat_sub--; } ] [] { b.addChild(c); } | c=PassingHandSpecifier() [] { b.addChild(c); } ) )+ { b.source_juggler = current_juggler; b.beats = current_beat_sub; b.seq_beatnum = current_beat; return b; } } SiteswapTreeItem PassingPairedThrow() : { SiteswapTreeItem b, c; } { { b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_PASSING_PAIRED_THROW); } "(" [] c=PassingMultiThrow() { b.addChild(c); } "," [] c=PassingMultiThrow() { b.addChild(c); } ")" { b.source_juggler = current_juggler; b.seq_beatnum = current_beat + current_beat_sub; return b; } } SiteswapTreeItem PassingMultiThrow() : { SiteswapTreeItem b, c; } { { b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_PASSING_MULTI_THROW); } ( c=PassingSingleThrow() { b.addChild(c); } [] | "[" [] ( c=PassingSingleThrow() { b.addChild(c); } [] )+ "]" [] | "{" [] ( c=PassingSingleThrow() { b.addChild(c); } [] )+ "}" [] ) { b.source_juggler = current_juggler; b.seq_beatnum = current_beat + current_beat_sub; return b; } } SiteswapTreeItem PassingSingleThrow() : { SiteswapTreeItem b, c; Token t; int dest, d; String mod; } { { b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_PASSING_SINGLE_THROW); dest = current_juggler; } ( ( t= { b.value = Character.digit((t.image.toCharArray())[0], 36); } | t= { b.value = Character.digit((t.image.toCharArray())[0], 36); } | "p" { b.value = 25; } | "x" { b.value = 33; } ) ["x" { b.x = true; } ] ["p" { dest = current_juggler + 1; } [d=Number() { dest = d; } ]] [mod=Modifier() { b.mod = mod; } ] ["/"] ) { b.source_juggler = current_juggler; b.dest_juggler = dest; b.seq_beatnum = current_beat + current_beat_sub; return b; } } SiteswapTreeItem PassingHandSpecifier() : { SiteswapTreeItem b; } { { b = new SiteswapTreeItem(SiteswapTreeItem.TYPE_HAND_SPEC); } ( "R" { b.spec_left = false; } | "L" { b.spec_left = true; } ) { b.source_juggler = current_juggler; b.seq_beatnum = current_beat + current_beat_sub; return b; } } int Number() : { Token n; String s = ""; } { ( n= { s += n.image; } )+ { int val = -1; try { val = Integer.parseInt(s); } catch (NumberFormatException mfe) { } return val; } } int Wildcard() : { int beats = 0; } { ( "?" { beats++; } )+ { return beats; } } String Modifier() : { Token t; String mod = ""; } { t= { mod += t.image; } ( t= { mod += t.image; } | "L" { mod += "L"; } | "R" { mod += "R"; } )* { return mod; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/SiteswapParserConstants.java000066400000000000000000000016621323754603300277140ustar00rootroot00000000000000/* Generated By:JavaCC: Do not edit this line. SiteswapParserConstants.java */ package jugglinglab.notation; /** * Token literal values and constants. * Generated by org.javacc.parser.OtherFilesGen#start() */ public interface SiteswapParserConstants { /** End of File. */ int EOF = 0; /** RegularExpression Id. */ int NUM = 4; /** RegularExpression Id. */ int LET = 5; /** RegularExpression Id. */ int MOD = 6; /** RegularExpression Id. */ int SPC = 7; /** Lexical state. */ int DEFAULT = 0; /** Literal token values. */ String[] tokenImage = { "", "\"\\t\"", "\"\\n\"", "\"\\r\"", "", "", "", "", "\"*\"", "\"(\"", "\"^\"", "\")\"", "\"!\"", "\",\"", "\"[\"", "\"]\"", "\"{\"", "\"}\"", "\"p\"", "\"x\"", "\"/\"", "\"R\"", "\"L\"", "\"<\"", "\"|\"", "\">\"", "\"?\"", }; } jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/SiteswapParserTokenManager.java000066400000000000000000000217511323754603300303140ustar00rootroot00000000000000/* Generated By:JavaCC: Do not edit this line. SiteswapParserTokenManager.java */ package jugglinglab.notation; /** Token Manager. */ public class SiteswapParserTokenManager implements SiteswapParserConstants { /** Debug output. */ public java.io.PrintStream debugStream = System.out; /** Set debug output. */ public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; } private final int jjStopStringLiteralDfa_0(int pos, long active0) { switch (pos) { default : return -1; } } private final int jjStartNfa_0(int pos, long active0) { return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1); } private int jjStopAtPos(int pos, int kind) { jjmatchedKind = kind; jjmatchedPos = pos; return pos + 1; } private int jjMoveStringLiteralDfa0_0() { switch(curChar) { case 33: return jjStopAtPos(0, 12); case 40: return jjStopAtPos(0, 9); case 41: return jjStopAtPos(0, 11); case 42: return jjStopAtPos(0, 8); case 44: return jjStopAtPos(0, 13); case 47: return jjStopAtPos(0, 20); case 60: return jjStopAtPos(0, 23); case 62: return jjStopAtPos(0, 25); case 63: return jjStopAtPos(0, 26); case 76: return jjStopAtPos(0, 22); case 82: return jjStopAtPos(0, 21); case 91: return jjStopAtPos(0, 14); case 93: return jjStopAtPos(0, 15); case 94: return jjStopAtPos(0, 10); case 112: return jjStopAtPos(0, 18); case 120: return jjStopAtPos(0, 19); case 123: return jjStopAtPos(0, 16); case 124: return jjStopAtPos(0, 24); case 125: return jjStopAtPos(0, 17); default : return jjMoveNfa_0(0, 0); } } private int jjMoveNfa_0(int startState, int curPos) { int startsAt = 0; jjnewStateCnt = 4; int i = 1; jjstateSet[0] = startState; int kind = 0x7fffffff; for (;;) { if (++jjround == 0x7fffffff) ReInitRounds(); if (curChar < 64) { long l = 1L << curChar; do { switch(jjstateSet[--i]) { case 0: if ((0x3ff000000000000L & l) != 0L) { if (kind > 4) kind = 4; } else if (curChar == 32) { if (kind > 7) kind = 7; jjCheckNAdd(3); } break; case 3: if (curChar != 32) break; kind = 7; jjCheckNAdd(3); break; default : break; } } while(i != startsAt); } else if (curChar < 128) { long l = 1L << (curChar & 077); do { switch(jjstateSet[--i]) { case 0: if ((0x7fbeffeL & l) != 0L) { if (kind > 6) kind = 6; jjCheckNAdd(2); } else if ((0x6fefffe00000000L & l) != 0L) { if (kind > 5) kind = 5; } break; case 1: if ((0x6fefffe00000000L & l) != 0L) kind = 5; break; case 2: if ((0x7fbeffeL & l) == 0L) break; kind = 6; jjCheckNAdd(2); break; default : break; } } while(i != startsAt); } else { int i2 = (curChar & 0xff) >> 6; long l2 = 1L << (curChar & 077); do { switch(jjstateSet[--i]) { default : break; } } while(i != startsAt); } if (kind != 0x7fffffff) { jjmatchedKind = kind; jjmatchedPos = curPos; kind = 0x7fffffff; } ++curPos; if ((i = jjnewStateCnt) == (startsAt = 4 - (jjnewStateCnt = startsAt))) return curPos; try { curChar = input_stream.readChar(); } catch(java.io.IOException e) { return curPos; } } } static final int[] jjnextStates = { }; /** Token literal values. */ public static final String[] jjstrLiteralImages = { "", null, null, null, null, null, null, null, "\52", "\50", "\136", "\51", "\41", "\54", "\133", "\135", "\173", "\175", "\160", "\170", "\57", "\122", "\114", "\74", "\174", "\76", "\77", }; /** Lexer state names. */ public static final String[] lexStateNames = { "DEFAULT", }; static final long[] jjtoToken = { 0x7fffff1L, }; static final long[] jjtoSkip = { 0xeL, }; protected SimpleCharStream input_stream; private final int[] jjrounds = new int[4]; private final int[] jjstateSet = new int[8]; protected char curChar; /** Constructor. */ public SiteswapParserTokenManager(SimpleCharStream stream){ if (SimpleCharStream.staticFlag) throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer."); input_stream = stream; } /** Constructor. */ public SiteswapParserTokenManager(SimpleCharStream stream, int lexState){ this(stream); SwitchTo(lexState); } /** Reinitialise parser. */ public void ReInit(SimpleCharStream stream) { jjmatchedPos = jjnewStateCnt = 0; curLexState = defaultLexState; input_stream = stream; ReInitRounds(); } private void ReInitRounds() { int i; jjround = 0x80000001; for (i = 4; i-- > 0;) jjrounds[i] = 0x80000000; } /** Reinitialise parser. */ public void ReInit(SimpleCharStream stream, int lexState) { ReInit(stream); SwitchTo(lexState); } /** Switch to specified lex state. */ public void SwitchTo(int lexState) { if (lexState >= 1 || lexState < 0) throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); else curLexState = lexState; } protected Token jjFillToken() { final Token t; final String curTokenImage; final int beginLine; final int endLine; final int beginColumn; final int endColumn; String im = jjstrLiteralImages[jjmatchedKind]; curTokenImage = (im == null) ? input_stream.GetImage() : im; beginLine = input_stream.getBeginLine(); beginColumn = input_stream.getBeginColumn(); endLine = input_stream.getEndLine(); endColumn = input_stream.getEndColumn(); t = Token.newToken(jjmatchedKind, curTokenImage); t.beginLine = beginLine; t.endLine = endLine; t.beginColumn = beginColumn; t.endColumn = endColumn; return t; } int curLexState = 0; int defaultLexState = 0; int jjnewStateCnt; int jjround; int jjmatchedPos; int jjmatchedKind; /** Get the next Token. */ public Token getNextToken() { Token matchedToken; int curPos = 0; EOFLoop : for (;;) { try { curChar = input_stream.BeginToken(); } catch(java.io.IOException e) { jjmatchedKind = 0; matchedToken = jjFillToken(); return matchedToken; } try { input_stream.backup(0); while (curChar <= 13 && (0x2600L & (1L << curChar)) != 0L) curChar = input_stream.BeginToken(); } catch (java.io.IOException e1) { continue EOFLoop; } jjmatchedKind = 0x7fffffff; jjmatchedPos = 0; curPos = jjMoveStringLiteralDfa0_0(); if (jjmatchedKind != 0x7fffffff) { if (jjmatchedPos + 1 < curPos) input_stream.backup(curPos - jjmatchedPos - 1); if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) { matchedToken = jjFillToken(); return matchedToken; } else { continue EOFLoop; } } int error_line = input_stream.getEndLine(); int error_column = input_stream.getEndColumn(); String error_after = null; boolean EOFSeen = false; try { input_stream.readChar(); input_stream.backup(1); } catch (java.io.IOException e1) { EOFSeen = true; error_after = curPos <= 1 ? "" : input_stream.GetImage(); if (curChar == '\n' || curChar == '\r') { error_line++; error_column = 0; } else error_column++; } if (!EOFSeen) { input_stream.backup(1); error_after = curPos <= 1 ? "" : input_stream.GetImage(); } throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR); } } private void jjCheckNAdd(int state) { if (jjrounds[state] != jjround) { jjstateSet[jjnewStateCnt++] = state; jjrounds[state] = jjround; } } private void jjAddStates(int start, int end) { do { jjstateSet[jjnewStateCnt++] = jjnextStates[start]; } while (start++ != end); } private void jjCheckNAddTwoStates(int state1, int state2) { jjCheckNAdd(state1); jjCheckNAdd(state2); } } jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/SiteswapTreeItem.java000066400000000000000000000126141323754603300263000ustar00rootroot00000000000000// SiteswapTreeItem.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.notation; import java.util.*; public class SiteswapTreeItem { static final int TYPE_PATTERN = 1; static final int TYPE_GROUPED_PATTERN = 2; static final int TYPE_SOLO_SEQUENCE = 3; static final int TYPE_SOLO_PAIRED_THROW = 4; static final int TYPE_SOLO_MULTI_THROW = 5; static final int TYPE_SOLO_SINGLE_THROW = 6; static final int TYPE_PASSING_SEQUENCE = 7; static final int TYPE_PASSING_GROUP = 8; static final int TYPE_PASSING_THROWS = 9; static final int TYPE_PASSING_PAIRED_THROW = 10; static final int TYPE_PASSING_MULTI_THROW = 11; static final int TYPE_PASSING_SINGLE_THROW = 12; static final int TYPE_WILDCARD = 13; static final int TYPE_HAND_SPEC = 14; int type; Vector children; // variables that the parser determines: int jugglers; // for type 1, 7, 8 int repeats; // for type 2 boolean switchrepeat = false; // for type 1 int beats; // for types 3, 7, 8, 9, 13 int seq_beatnum; // for types 4, 5, 6, 8, 9, 10, 11, 12, 14 int source_juggler; // for types 3, 4, 5, 6, 9, 10, 11, 12, 14 int value; // for types 6, 12 boolean x = false; // for types 6, 12 int dest_juggler; // for types 6, 12 // Note: can be > # jugglers -> mod down into range String mod; // for types 6, 12 boolean spec_left = false; // for type 14 // variables determined by subsequent layout stages: int throw_sum; int beatnum; boolean left; boolean vanilla_asynch; boolean synch_throw; SiteswapTreeItem transition; // used only for Wildcard type -- holds the calculated transition sequence public SiteswapTreeItem(int type) { this.type = type; this.children = new Vector(); this.synch_throw = false; } public void addChild(SiteswapTreeItem item) { children.addElement(item); } public SiteswapTreeItem getChild(int index) { return (SiteswapTreeItem)(children.elementAt(index)); } public void removeChildren() { this.children = new Vector(); } public int getNumberOfChildren() { return children.size(); } public Object clone() { SiteswapTreeItem result = new SiteswapTreeItem(this.type); result.repeats = this.repeats; result.switchrepeat = this.switchrepeat; result.beats = this.beats; result.seq_beatnum = this.seq_beatnum; result.source_juggler = this.source_juggler; result.value = this.value; result.x = this.x; result.dest_juggler = this.dest_juggler; result.mod = this.mod; result.spec_left = this.spec_left; for (int i = 0; i < getNumberOfChildren(); i++) result.addChild((SiteswapTreeItem)(getChild(i).clone())); return result; } public String toString() { return toString(0); } private static final String[] typenames = { "Pattern", "Grouped Pattern", "Solo Sequence", "Solo Paired Throw", "Solo Multi Throw", "Solo Single Throw", "Passing Sequence", "Passing Group", "Passing Throws", "Passing Paired Throw", "Passing Multi Throw", "Passing Single Throw", "Wildcard", "Hand Specifier" }; private String toString(int indentlevel) { String result = ""; for (int i = 0; i < indentlevel; i++) result += " "; result += typenames[type-1] + "("; if (field_active(0, type)) result += "jugglers=" + jugglers + ", "; if (field_active(1, type)) result += "repeats=" + repeats + ", "; if (field_active(2, type)) result += "*=" + switchrepeat + ", "; if (field_active(3, type)) result += "beats=" + beats + ", "; if (field_active(4, type)) result += "seq_beatnum=" + seq_beatnum + ", "; if (field_active(5, type)) result += "fromj=" + source_juggler + ", "; if (field_active(6, type)) result += "val=" + value + ", "; if (field_active(7, type)) result += "x=" + x + ", "; if (field_active(8, type)) result += "toj=" + dest_juggler + ", "; if (field_active(9, type)) result += "mod=" + mod + ", "; if (field_active(10, type)) result += "spec_left=" + spec_left; result += ") {\n"; for (int i = 0; i < getNumberOfChildren(); i++) { SiteswapTreeItem item = getChild(i); result += item.toString(indentlevel + 1); } for (int i = 0; i < indentlevel; i++) result += " "; result += "}\n"; return result; } // the following is just the "for types" comments above private static final int[][] field_defined_types = { {1, 7, 8}, {2}, {1}, {3, 7, 8, 9, 13}, {4, 5, 6, 8, 9, 10, 11, 12, 14}, {3, 4, 5, 6, 9, 10, 11, 12, 14}, {6, 12}, {6, 12}, {6, 12}, {6, 12}, {14} }; private static boolean field_active(int fieldnum, int type) { int[] a = field_defined_types[fieldnum]; for (int i = 0; i < a.length; i++) { if (a[i] == type) return true; } return false; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/Token.java000066400000000000000000000077661323754603300241360ustar00rootroot00000000000000/* Generated By:JavaCC: Do not edit this line. Token.java Version 5.0 */ /* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ package jugglinglab.notation; /** * Describes the input token stream. */ public class Token implements java.io.Serializable { /** * The version identifier for this Serializable class. * Increment only if the serialized form of the * class changes. */ private static final long serialVersionUID = 1L; /** * An integer that describes the kind of this token. This numbering * system is determined by JavaCCParser, and a table of these numbers is * stored in the file ...Constants.java. */ public int kind; /** The line number of the first character of this Token. */ public int beginLine; /** The column number of the first character of this Token. */ public int beginColumn; /** The line number of the last character of this Token. */ public int endLine; /** The column number of the last character of this Token. */ public int endColumn; /** * The string image of the token. */ public String image; /** * A reference to the next regular (non-special) token from the input * stream. If this is the last token from the input stream, or if the * token manager has not read tokens beyond this one, this field is * set to null. This is true only if this token is also a regular * token. Otherwise, see below for a description of the contents of * this field. */ public Token next; /** * This field is used to access special tokens that occur prior to this * token, but after the immediately preceding regular (non-special) token. * If there are no such special tokens, this field is set to null. * When there are more than one such special token, this field refers * to the last of these special tokens, which in turn refers to the next * previous special token through its specialToken field, and so on * until the first special token (whose specialToken field is null). * The next fields of special tokens refer to other special tokens that * immediately follow it (without an intervening regular token). If there * is no such token, this field is null. */ public Token specialToken; /** * An optional attribute value of the Token. * Tokens which are not used as syntactic sugar will often contain * meaningful values that will be used later on by the compiler or * interpreter. This attribute value is often different from the image. * Any subclass of Token that actually wants to return a non-null value can * override this method as appropriate. */ public Object getValue() { return null; } /** * No-argument constructor */ public Token() {} /** * Constructs a new token for the specified Image. */ public Token(int kind) { this(kind, null); } /** * Constructs a new token for the specified Image and Kind. */ public Token(int kind, String image) { this.kind = kind; this.image = image; } /** * Returns the image. */ public String toString() { return image; } /** * Returns a new Token object, by default. However, if you want, you * can create and return subclass objects based on the value of ofKind. * Simply add the cases to the switch for all those special cases. * For example, if you have a subclass of Token called IDToken that * you want to create if ofKind is ID, simply add something like : * * case MyParserConstants.ID : return new IDToken(ofKind, image); * * to the following switch statement. Then you can cast matchedToken * variable to the appropriate type and use sit in your lexical actions. */ public static Token newToken(int ofKind, String image) { switch(ofKind) { default : return new Token(ofKind, image); } } public static Token newToken(int ofKind) { return newToken(ofKind, null); } } /* JavaCC - OriginalChecksum=4e1f2ca90d298da017bd1b0cfec4e06c (do not edit this line) */ jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/TokenMgrError.java000066400000000000000000000112501323754603300255750ustar00rootroot00000000000000/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 5.0 */ /* JavaCCOptions: */ package jugglinglab.notation; /** Token Manager Error. */ public class TokenMgrError extends Error { /** * The version identifier for this Serializable class. * Increment only if the serialized form of the * class changes. */ private static final long serialVersionUID = 1L; /* * Ordinals for various reasons why an Error of this type can be thrown. */ /** * Lexical error occurred. */ static final int LEXICAL_ERROR = 0; /** * An attempt was made to create a second instance of a static token manager. */ static final int STATIC_LEXER_ERROR = 1; /** * Tried to change to an invalid lexical state. */ static final int INVALID_LEXICAL_STATE = 2; /** * Detected (and bailed out of) an infinite loop in the token manager. */ static final int LOOP_DETECTED = 3; /** * Indicates the reason why the exception is thrown. It will have * one of the above 4 values. */ int errorCode; // JKB changes to this block: boolean EOFSeen; int lexState; int errorLine; int errorColumn; String errorAfter; char curChar; /** * Replaces unprintable characters by their escaped (or unicode escaped) * equivalents in the given string */ protected static final String addEscapes(String str) { StringBuffer retval = new StringBuffer(); char ch; for (int i = 0; i < str.length(); i++) { switch (str.charAt(i)) { case 0 : continue; case '\b': retval.append("\\b"); continue; case '\t': retval.append("\\t"); continue; case '\n': retval.append("\\n"); continue; case '\f': retval.append("\\f"); continue; case '\r': retval.append("\\r"); continue; case '\"': retval.append("\\\""); continue; case '\'': retval.append("\\\'"); continue; case '\\': retval.append("\\\\"); continue; default: if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { String s = "0000" + Integer.toString(ch, 16); retval.append("\\u" + s.substring(s.length() - 4, s.length())); } else { retval.append(ch); } continue; } } return retval.toString(); } /** * Returns a detailed message for the Error when it is thrown by the * token manager to indicate a lexical error. * Parameters : * EOFSeen : indicates if EOF caused the lexical error * curLexState : lexical state in which this error occurred * errorLine : line number when the error occurred * errorColumn : column number when the error occurred * errorAfter : prefix that was seen before this error occurred * curchar : the offending character * Note: You can customize the lexical error message by modifying this method. */ protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) { return("Lexical error at line " + errorLine + ", column " + errorColumn + ". Encountered: " + (EOFSeen ? " " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") + "after : \"" + addEscapes(errorAfter) + "\""); } /** * You can also modify the body of this method to customize your error messages. * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not * of end-users concern, so you can return something like : * * "Internal Error : Please file a bug report .... " * * from this method for such cases in the release version of your parser. */ public String getMessage() { return super.getMessage(); } /* * Constructors of various flavors follow. */ /** No arg constructor. */ public TokenMgrError() { } /** Constructor with message and reason. */ public TokenMgrError(String message, int reason) { super(message); errorCode = reason; } /** Full Constructor. */ public TokenMgrError(boolean EOFSeenVal, int lexStateVal, int errorLineVal, int errorColumnVal, String errorAfterVal, char curCharVal, int reason) { this(LexicalError(EOFSeenVal, lexStateVal, errorLineVal, errorColumnVal, errorAfterVal, curCharVal), reason); EOFSeen = EOFSeenVal; lexState = lexStateVal; errorLine = errorLineVal; errorColumn = errorColumnVal; errorAfter = errorAfterVal; curChar = curCharVal; } } /* JavaCC - OriginalChecksum=79b94454935a9ff7b33267f9f70063d2 (do not edit this line) */ jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/mhnBody.java000066400000000000000000000162511323754603300244430ustar00rootroot00000000000000// mhnBody.java // // Copyright 2003 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.notation; import java.util.*; import java.text.MessageFormat; import jugglinglab.jml.*; import jugglinglab.util.*; public class mhnBody { // static ResourceBundle guistrings; static ResourceBundle errorstrings; static { // guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } protected int jugglers = 0; protected int[] size = null; protected int[][] coords = null; protected double[][][][] bodypath = null; public mhnBody(String bodies) throws JuggleExceptionUser, JuggleExceptionInternal { // delete the '<' and '>' characters first int pos; while ((pos = bodies.indexOf('<')) >= 0) { bodies = bodies.substring(0,pos) + bodies.substring(pos+1,bodies.length()); } while ((pos = bodies.indexOf('>')) >= 0) { bodies = bodies.substring(0,pos) + bodies.substring(pos+1,bodies.length()); } while ((pos = bodies.indexOf('{')) >= 0) { bodies = bodies.substring(0,pos) + bodies.substring(pos+1,bodies.length()); } while ((pos = bodies.indexOf('}')) >= 0) { bodies = bodies.substring(0,pos) + bodies.substring(pos+1,bodies.length()); } StringTokenizer st1 = new StringTokenizer(bodies, "|!", false); jugglers = st1.countTokens(); size = new int[jugglers]; coords = new int[jugglers][]; bodypath = new double[jugglers][][][]; for (int j = 0; j < jugglers; j++) { String str = st1.nextToken(); // System.out.println("str["+j+"] = "+str); for (int k = 0; k < 3; k++) { pos = 0; int numcoords = 0; for (int l = 0; l < str.length(); ) { char ch = str.charAt(l); if (ch == ' ') { l++; continue; } if (ch == '.') { if (numcoords == 0) { if (k == 1) { coords[j][pos] = 1; bodypath[j][pos] = new double[1][]; bodypath[j][pos][0] = null; } } else if (k == 1) { coords[j][pos] = numcoords; bodypath[j][pos] = new double[numcoords][]; } pos++; numcoords = 0; l++; continue; } if (ch == '-') { if (k == 2) bodypath[j][pos][numcoords] = null; numcoords++; l++; continue; } if (ch == '(') { int endindex = str.indexOf(')', l+1); if (endindex < 0) throw new JuggleExceptionUser(errorstrings.getString("Error_body_noparen")); if (k == 2) { bodypath[j][pos][numcoords] = new double[4]; bodypath[j][pos][numcoords][3] = 100.0; // default z String str2 = str.substring(l+1, endindex); try { StringTokenizer st4 = new StringTokenizer(str2, ",", false); bodypath[j][pos][numcoords][0] = Double.valueOf(st4.nextToken()).doubleValue(); if (st4.hasMoreTokens()) bodypath[j][pos][numcoords][1] = Double.valueOf(st4.nextToken()).doubleValue(); if (st4.hasMoreTokens()) bodypath[j][pos][numcoords][2] = Double.valueOf(st4.nextToken()).doubleValue(); if (st4.hasMoreTokens()) bodypath[j][pos][numcoords][3] = Double.valueOf(st4.nextToken()).doubleValue(); } catch (NumberFormatException e) { throw new JuggleExceptionUser(errorstrings.getString("Error_body_coordinate")); } catch (NoSuchElementException e) { throw new JuggleExceptionInternal("No such element exception in \"body\""); } } numcoords++; l = endindex + 1; continue; } String template = errorstrings.getString("Error_body_character"); Object[] arguments = { Character.toString(ch) }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } if (k == 0) { size[j] = pos; coords[j] = new int[pos]; bodypath[j] = new double[pos][][]; } if (numcoords != 0) throw new JuggleExceptionUser(errorstrings.getString("Error_body_badending")); } } } public int getNumberOfJugglers() { return jugglers; } public int getPeriod(int juggler) { int j = (juggler - 1) % jugglers; return size[j]; } public int getNumberOfPositions(int juggler, int pos) { int j = (juggler - 1) % jugglers; return coords[j][pos]; } // pos and index start from 0: public JMLPosition getPosition(int juggler, int pos, int index) { if ((pos >= getPeriod(juggler)) || (index >= getNumberOfPositions(juggler, pos))) return null; int j = (juggler - 1) % jugglers; if (bodypath[j][pos][index] == null) return null; JMLPosition result = new JMLPosition(); result.setJuggler(juggler); result.setCoordinate(new Coordinate(bodypath[j][pos][index][1], bodypath[j][pos][index][2], bodypath[j][pos][index][3])); result.setAngle(bodypath[j][pos][index][0]); return result; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/mhnHands.java000066400000000000000000000206271323754603300246050ustar00rootroot00000000000000// mhnHands.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.notation; import java.util.*; import java.text.MessageFormat; import jugglinglab.util.*; public class mhnHands { // static ResourceBundle guistrings; static ResourceBundle errorstrings; static { // guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } protected int jugglers = 0; protected int[] size = null; protected int[][] coords = null; protected int[][] catches = null; protected double[][][][] handpath = null; public mhnHands(String hands) throws JuggleExceptionUser, JuggleExceptionInternal { // delete the '<' and '>' characters first int pos; while ((pos = hands.indexOf('<')) >= 0) { hands = hands.substring(0,pos) + hands.substring(pos+1,hands.length()); } while ((pos = hands.indexOf('>')) >= 0) { hands = hands.substring(0,pos) + hands.substring(pos+1,hands.length()); } while ((pos = hands.indexOf('{')) >= 0) { hands = hands.substring(0,pos) + hands.substring(pos+1,hands.length()); } while ((pos = hands.indexOf('}')) >= 0) { hands = hands.substring(0,pos) + hands.substring(pos+1,hands.length()); } StringTokenizer st1 = new StringTokenizer(hands, "|!", false); jugglers = st1.countTokens(); size = new int[jugglers]; coords = new int[jugglers][]; catches = new int[jugglers][]; handpath = new double[jugglers][][][]; for (int j = 0; j < jugglers; j++) { String str = st1.nextToken(); // System.out.println("str["+j+"] = "+str); for (int k = 0; k < 3; k++) { pos = 0; int numcoords = 0; boolean gotthrow = false, gotcatch = false; for (int l = 0; l < str.length(); ) { char ch = str.charAt(l); if (ch == ' ') { l++; continue; } if (ch == '.') { if (k == 1) { coords[j][pos] = numcoords; if (coords[j][pos] < 2) throw new JuggleExceptionUser(errorstrings.getString("Error_hands_toofewcoords")); handpath[j][pos] = new double[numcoords][]; } else if (k == 2) { if (!gotcatch) catches[j][pos] = coords[j][pos] - 1; if (handpath[j][pos][0] == null) throw new JuggleExceptionUser(errorstrings.getString("Error_hands_nothrow")); if (handpath[j][pos][catches[j][pos]] == null) throw new JuggleExceptionUser(errorstrings.getString("Error_hands_nocatch")); } gotthrow = gotcatch = false; pos++; numcoords = 0; l++; continue; } if (ch == '-') { if (k == 2) handpath[j][pos][numcoords] = null; numcoords++; l++; continue; } if ((ch == 'T') || (ch == 't')) { if (numcoords != 0) throw new JuggleExceptionUser(errorstrings.getString("Error_hands_Tnotstart")); if (gotthrow) throw new JuggleExceptionUser(errorstrings.getString("Error_hands_toomanycoords")); gotthrow = true; l++; continue; } if ((ch == 'C') || (ch == 'c')) { if (numcoords == 0) throw new JuggleExceptionUser(errorstrings.getString("Error_hands_Catstart")); if (gotcatch) throw new JuggleExceptionUser(errorstrings.getString("Error_hands_toomanycatches")); if (k == 1) catches[j][pos] = numcoords; gotcatch = true; l++; continue; } if (ch == '(') { int endindex = str.indexOf(')', l+1); if (endindex < 0) throw new JuggleExceptionUser(errorstrings.getString("Error_hands_noparen")); if (k == 2) { handpath[j][pos][numcoords] = new double[3]; String str2 = str.substring(l+1, endindex); try { StringTokenizer st4 = new StringTokenizer(str2, ",", false); handpath[j][pos][numcoords][0] = Double.valueOf(st4.nextToken()).doubleValue(); if (st4.hasMoreTokens()) handpath[j][pos][numcoords][2] = Double.valueOf(st4.nextToken()).doubleValue(); if (st4.hasMoreTokens()) handpath[j][pos][numcoords][1] = Double.valueOf(st4.nextToken()).doubleValue(); } catch (NumberFormatException e) { throw new JuggleExceptionUser(errorstrings.getString("Error_hands_coordinate")); } catch (NoSuchElementException e) { throw new JuggleExceptionInternal("No such element exception in \"hands\""); } } numcoords++; l = endindex + 1; continue; } String template = errorstrings.getString("Error_hands_character"); Object[] arguments = { Character.toString(ch) }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } if (k == 0) { size[j] = pos; catches[j] = new int[pos]; coords[j] = new int[pos]; handpath[j] = new double[pos][][]; } if (numcoords != 0) throw new JuggleExceptionUser(errorstrings.getString("Error_hands_badending")); } } } public int getPeriod(int juggler) { int j = (juggler - 1) % jugglers; return size[j]; } public int getNumberOfCoordinates(int juggler, int pos) { int j = (juggler - 1) % jugglers; return coords[j][pos]; } // throw index is always 0: public int getCatchIndex(int juggler, int pos) { int j = (juggler - 1) % jugglers; return catches[j][pos]; } // both pos and index are indexed from 0: public Coordinate getCoordinate(int juggler, int pos, int index) { if ((pos >= getPeriod(juggler)) || (index >= getNumberOfCoordinates(juggler, pos))) return null; int j = (juggler - 1) % jugglers; if (handpath[j][pos][index] == null) return null; return new Coordinate(handpath[j][pos][index][0], handpath[j][pos][index][1], handpath[j][pos][index][2]); } } jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/mhnNotation.java000066400000000000000000001630771323754603300253520ustar00rootroot00000000000000// mhnNotation.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.notation; import java.util.*; import java.awt.*; import java.awt.event.*; import jugglinglab.core.*; import jugglinglab.util.*; import jugglinglab.jml.*; public class mhnNotation extends Notation { public String getName() { return "MHN"; } public JMLPattern getJMLPattern(String config) throws JuggleExceptionUser, JuggleExceptionInternal { return null; // only implemented for siteswapNotation } protected static JMLPattern getJML(mhnPattern p) throws JuggleExceptionUser, JuggleExceptionInternal { findMasterThrows(p); assignPaths(p); findThrowSources(p); setCatchOrder(p); JMLPattern result = convertPatternToJML(p); return result; } protected static void findMasterThrows(mhnPattern p) throws JuggleExceptionInternal { // start by making every throw a master throw for (int i = 0; i < p.indexes; i++) { for (int j = 0; j < p.numjugglers; j++) { for (int h = 0; h < 2; h++) { for (int slot = 0; slot < p.max_occupancy; slot++) { mhnThrow mhnt = p.th[j][h][i][slot]; if (mhnt != null) { mhnt.master = mhnt; mhnt.source = null; } } } } } boolean changed = true; while (changed) { changed = false; for (int s = 0; s < p.getNumberOfSymmetries(); s++) { mhnSymmetry sym = p.getSymmetry(s); Permutation jperm = sym.getJugglerPerm(); int delay = sym.getDelay(); for (int i = 0; i < p.indexes; i++) { int imagei = i + delay; if (imagei >= p.indexes) continue; for (int j = 0; j < p.numjugglers; j++) { for (int h = 0; h < 2; h++) { for (int slot = 0; slot < p.max_occupancy; slot++) { mhnThrow mhnt = p.th[j][h][i][slot]; if (mhnt == null) continue; int imagej = jperm.getMapping(j+1); int imageh = ((imagej > 0) ? h : 1-h); imagej = Math.abs(imagej) - 1; mhnThrow imaget = p.th[imagej][imageh][imagei][slot]; if (imaget == null) throw new JuggleExceptionInternal("Problem finding master throws"); mhnThrow m = mhnt.master; mhnThrow im = imaget.master; if (m == im) continue; // we have a disagreement about which is the master; // choose one of them and set them equal mhnThrow newm = m; if (m.index > im.index) newm = im; else if (m.index == im.index) { if (m.juggler > im.juggler) newm = im; else if (m.juggler == im.juggler) { if (m.hand > im.hand) newm = im; } } mhnt.master = imaget.master = newm; changed = true; } } } } } } if (Constants.DEBUG_PARSING) { for (int i = 0; i < p.indexes; i++) { for (int j = 0; j < p.numjugglers; j++) { for (int h = 0; h < 2; h++) { for (int slot = 0; slot < p.max_occupancy; slot++) { mhnThrow mhnt = p.th[j][h][i][slot]; if ((mhnt != null) && (mhnt.master == mhnt)) System.out.println("master throw at j="+j+",h="+h+",i="+i+",slot="+slot); } } } } } } protected static void assignPaths(mhnPattern p) throws JuggleExceptionUser, JuggleExceptionInternal { // first figure out how the throws are filling other throws; // this is complicated by the fact that we allow multiplexing for (int i = 0; i < p.indexes; i++) { for (int j = 0; j < p.numjugglers; j++) { for (int h = 0; h < 2; h++) { for (int slot = 0; slot < p.max_occupancy; slot++) { mhnThrow sst = p.th[j][h][i][slot]; if ((sst == null) || (sst.master != sst)) // loop over master throws continue; int targetslot = 0; while (targetslot < p.max_occupancy) { // find value of targetslot that works boolean itworks = true; // loop over all throws that have sst as master for (int i2 = 0; i2 < p.indexes; i2++) { for (int j2 = 0; j2 < p.numjugglers; j2++) { for (int h2 = 0; h2 < 2; h2++) { for (int slot2 = 0; slot2 < p.max_occupancy; slot2++) { mhnThrow sst2 = p.th[j2][h2][i2][slot2]; if ((sst2 == null) || (sst2.master != sst)) continue; if (sst2.targetindex >= p.indexes) continue; mhnThrow target = p.th[sst2.targetjuggler-1][sst2.targethand][sst2.targetindex][targetslot]; if (target == null) itworks = false; else itworks &= (target.source == null); // target also unfilled? } } } } if (itworks) break; targetslot++; } if (targetslot == p.max_occupancy) throw new JuggleExceptionUser(errorstrings.getString("Error_badpattern")); // loop again over all throws that have sst as master for (int i2 = 0; i2 < p.indexes; i2++) { for (int j2 = 0; j2 < p.numjugglers; j2++) { for (int h2 = 0; h2 < 2; h2++) { for (int slot2 = 0; slot2 < p.max_occupancy; slot2++) { mhnThrow sst2 = p.th[j2][h2][i2][slot2]; if ((sst2 == null) || (sst2.master != sst)) continue; if (sst2.targetindex >= p.indexes) continue; mhnThrow target2 = p.th[sst2.targetjuggler-1][sst2.targethand][sst2.targetindex][targetslot]; if (target2 == null) throw new JuggleExceptionInternal("Got null target in assignPaths()"); sst2.target = target2; // hook source and target together target2.source = sst2; } } } } } } } } // assign path numbers to all of the throws int currentpath = 1; for (int i = 0; i < p.indexes; i++) { for (int j = 0; j < p.numjugglers; j++) { for (int h = 0; h < 2; h++) { for (int slot = 0; slot < p.max_occupancy; slot++) { mhnThrow sst = p.th[j][h][i][slot]; if (sst != null) { mhnThrow filler = sst.source; if (filler == null) { if (currentpath > p.numpaths) { if (jugglinglab.core.Constants.DEBUG_LAYOUT) { System.out.println("j="+j+", h="+h+", index="+i+", slot="+slot+"\n"); System.out.println("---------------------------"); for (int tempi = 0; tempi <= i; tempi++) { for (int temph = 0; temph < 2; temph++) { for (int tempslot = 0; tempslot < p.max_occupancy; tempslot++) { mhnThrow tempsst = p.th[0][temph][tempi][tempslot]; System.out.println("index="+tempi+", hand="+temph+", slot="+tempslot+":"); if (tempsst == null) System.out.println(" null entry"); else System.out.println(" targetindex="+tempsst.targetindex+", targethand="+ tempsst.targethand+", targetslot="+tempsst.targetslot+ ", pathnum="+tempsst.pathnum); } } } System.out.println("---------------------------"); } throw new JuggleExceptionUser(errorstrings.getString("Error_badpattern")); } sst.pathnum = currentpath++; } else sst.pathnum = filler.pathnum; } } } } } if (currentpath <= p.numpaths) throw new JuggleExceptionInternal("Problem assigning path numbers 2"); } // set the mhnThrow.source field protected static void findThrowSources(mhnPattern p) throws JuggleExceptionInternal { for (int i = p.indexes-1; i >= 0; i--) { for (int j = 0; j < p.numjugglers; j++) { for (int h = 0; h < 2; h++) { for (int slot = 0; slot < p.max_occupancy; slot++) { mhnThrow sst = p.th[j][h][i][slot]; if (sst == null) continue; if (sst.source == null) { if ((i + p.getPeriod()) < p.indexes) { mhnThrow sst2 = p.th[j][h][i+p.getPeriod()][slot].source; if (sst2 == null) throw new JuggleExceptionInternal("Could not get throw source 1"); mhnThrow sst3 = new mhnThrow(); sst3.juggler = sst2.juggler; sst3.hand = sst2.hand; sst3.index = sst2.index - p.getPeriod(); sst3.slot = sst2.slot; sst3.targetjuggler = j; sst3.targethand = h; sst3.targetindex = i; sst3.targetslot = slot; sst3.handsindex = -1; // undefined sst3.pathnum = sst.pathnum; sst3.mod = sst2.mod; sst3.master = sst2.master; sst3.source = null; sst3.target = sst; sst.source = sst3; } else throw new JuggleExceptionInternal("Could not get throw source 2"); } } } } } } // Decide whether the catches immediately prior to the two given throws should be // made in the order given, or whether they should be switched. // // The following implementation isn't ideal; we would like a function that is // invariant with respect to the various pattern symmetries we can apply, but // I don't think this is possible with respect to the jugglers. protected static boolean isCatchOrderIncorrect(mhnThrow t1, mhnThrow t2) { // first look at the time spent in the air; catch higher throws first if (t1.source.index > t2.source.index) return true; if (t1.source.index < t2.source.index) return false; // look at which juggler it's from; catch from "faraway" jugglers first int jdiff1 = Math.abs(t1.juggler - t1.source.juggler); int jdiff2 = Math.abs(t2.juggler - t2.source.juggler); if (jdiff1 < jdiff2) return true; if (jdiff1 > jdiff2) return false; // look at which hand it's from; catch from same hand first int hdiff1 = Math.abs(t1.hand - t1.source.hand); int hdiff2 = Math.abs(t2.hand - t2.source.hand); if (hdiff1 > hdiff2) return true; if (hdiff1 < hdiff2) return false; return false; } // set the mhnThrow.catching and mhnThrow.catchnum fields protected static void setCatchOrder(mhnPattern p) throws JuggleExceptionInternal { mhnThrow[][][][] th = p.getThrows(); // figure out the correct catch order for master throws only... for (int k = 0; k < p.getIndexes(); k++) { for (int j = 0; j < p.getNumberOfJugglers(); j++) { for (int h = 0; h < 2; h++) { int slotcatches = 0; for (int slot = 0; slot < p.getMaxOccupancy(); slot++) { mhnThrow sst = th[j][h][k][slot]; if (sst == null) break; sst.catching = (sst.source.mod.charAt(0) != 'H'); if (sst.catching) sst.catchnum = slotcatches++; } // Arrange the order of the catches, if more than one if (slotcatches < 2) continue; for (int slot1 = 0; slot1 < p.getMaxOccupancy(); slot1++) { mhnThrow sst1 = th[j][h][k][slot1]; if (sst1 == null) break; if (sst1.master != sst1) // only master throws break; if (sst1.catching) { for (int slot2 = (slot1+1); slot2 < p.getMaxOccupancy(); slot2++) { mhnThrow sst2 = th[j][h][k][slot2]; if (sst2 == null) break; if (sst2.master != sst2) break; if (sst2.catching) { boolean switchcatches = false; if (sst1.catchnum < sst2.catchnum) switchcatches = isCatchOrderIncorrect(sst1, sst2); else switchcatches = isCatchOrderIncorrect(sst2, sst1); if (switchcatches) { int temp = sst1.catchnum; sst1.catchnum = sst2.catchnum; sst2.catchnum = temp; } } } } } } } } // ...and then copy that over to the non-master throws for (int k = 0; k < p.getIndexes(); k++) { for (int j = 0; j < p.getNumberOfJugglers(); j++) { for (int h = 0; h < 2; h++) { for (int slot = 0; slot < p.getMaxOccupancy(); slot++) { mhnThrow sst = th[j][h][k][slot]; if (sst == null) break; if (sst.master == sst) // skip master throws break; sst.catchnum = sst.master.catchnum; } } } } } // The following are default spatial coordinates to use protected static final double[] samethrowx = { 0.0, 20.0, 25.0, 12.0, 10.0, 7.5, 5.0, 5.0, 5.0 }; protected static final double[] crossingthrowx = { 0.0, 20.0, 25.0, 12.0, 10.0, 18.0, 25.0, 25.0, 30.0 }; protected static final double[] catchx = { 0.0, 30.0, 25.0, 30.0, 40.0, 45.0, 45.0, 50.0, 50.0 }; protected static final double restingx = 25.0; // The following is used when multiple catches are made in a hand, on the same beat. // It specifies the fraction of a beat to spread the catches over. protected static final double splitcatchfactor = 0.4; protected static JMLPattern convertPatternToJML(mhnPattern p) throws JuggleExceptionUser, JuggleExceptionInternal { JMLPattern result = new JMLPattern(); // result.setJMLVersion("1.1"); // Step 1 -- Set up the basic pattern information: // pattern title needs to be set elsewhere result.setNumberOfJugglers(p.getNumberOfJugglers()); result.setNumberOfPaths(p.getNumberOfPaths()); if (p.bps <= 0.0) // signal that we should calculate bps p.bps = calcBps(p); int balls = p.getNumberOfPaths(); int props = (p.color == null) ? 1 : Math.min(balls, p.color.length); for (int i = 0; i < props; i++) { String mod = null; if (p.propdiam != mhnPattern.propdiam_default) mod = "diam="+p.propdiam; if (p.color != null) { String colorstr = "color="+p.color[i]; if (mod == null) mod = colorstr; else mod = mod + ";" + colorstr; } result.addProp(new PropDef(p.getPropName(), mod)); } int[] pa = new int[balls]; for (int i = 0; i < balls; i++) pa[i] = 1 + (i % props); result.setPropAssignments(pa); // Step 2 -- Add the symmetries to the pattern: for (int i = 0; i < p.getNumberOfSymmetries(); i++) { mhnSymmetry sss = p.getSymmetry(i); int symtype; int[] pathmap = new int[balls+1]; switch (sss.getType()) { case mhnSymmetry.TYPE_DELAY: symtype = JMLSymmetry.TYPE_DELAY; // figure out the path mapping { mhnThrow[][][][] th = p.getThrows(); for (int k = 0; k < (p.getIndexes()-sss.getDelay()); k++) { for (int j = 0; j < p.getNumberOfJugglers(); j++) { for (int h = 0; h < 2; h++) { for (int slot = 0; slot < p.getMaxOccupancy(); slot++) { mhnThrow sst = th[j][h][k][slot]; if ((sst != null) && (sst.pathnum != -1)) { mhnThrow sst2 = th[j][h][k+sss.getDelay()][slot]; if (sst2 == null) throw new JuggleExceptionUser(errorstrings.getString("Error_badpattern_paths")); if ((sst.pathnum == 0) || (sst2.pathnum == 0)) throw new JuggleExceptionUser(errorstrings.getString("Error_badpattern_paths")); if (pathmap[sst.pathnum] == 0) pathmap[sst.pathnum] = sst2.pathnum; else if (pathmap[sst.pathnum] != sst2.pathnum) throw new JuggleExceptionUser(errorstrings.getString("Error_badpattern_delay")); } } } } } } break; case mhnSymmetry.TYPE_SWITCH: symtype = JMLSymmetry.TYPE_SWITCH; break; case mhnSymmetry.TYPE_SWITCHDELAY: symtype = JMLSymmetry.TYPE_SWITCHDELAY; // figure out the path mapping { Permutation jugperm = sss.getJugglerPerm(); mhnThrow[][][][] th = p.getThrows(); for (int k = 0; k < (p.getIndexes()-sss.getDelay()); k++) { for (int j = 0; j < p.getNumberOfJugglers(); j++) { for (int h = 0; h < 2; h++) { for (int slot = 0; slot < p.getMaxOccupancy(); slot++) { mhnThrow sst = th[j][h][k][slot]; if ((sst != null) && (sst.pathnum != -1)) { int map = jugperm.getMapping(j+1); int newj = Math.abs(map)-1; int newh = ((map > 0) ? h : 1-h); mhnThrow sst2 = th[newj][newh][k+sss.getDelay()][slot]; if (sst2 == null) throw new JuggleExceptionUser(errorstrings.getString("Error_badpattern_paths")); if ((sst.pathnum == 0) || (sst2.pathnum == 0)) throw new JuggleExceptionUser(errorstrings.getString("Error_badpattern_paths")); if (pathmap[sst.pathnum] == 0) pathmap[sst.pathnum] = sst2.pathnum; else if (pathmap[sst.pathnum] != sst2.pathnum) throw new JuggleExceptionUser(errorstrings.getString("Error_badpattern_switchdelay")); } } } } } } break; default: throw new JuggleExceptionUser(errorstrings.getString("Error_unknown_symmetry")); } // convert path mapping to a string String pathmapstring = ""; for (int j = 1; j < balls; j++) pathmapstring += pathmap[j] + ","; pathmapstring += pathmap[balls]; JMLSymmetry sym = new JMLSymmetry(symtype, sss.getNumberOfJugglers(), sss.getJugglerPerm().toString(), p.getNumberOfPaths(), pathmapstring, (double)sss.getDelay() / p.bps); result.addSymmetry(sym); } /* Permutation delayperm = null; for (int z = 0; z < result.getNumberOfSymmetries(); z++) { // store delay permutation for later JMLSymmetry tempsym = result.getSymmetry(z); if (tempsym.getType() == JMLSymmetry.TYPE_DELAY) delayperm = tempsym.getPathPerm(); }*/ // Step 3 -- Add the primary events to the pattern: // We'll need to keep track of which hands/paths don't get any events, // so we can add positioning events in later steps // boolean[] pathcaught = new boolean[p.getNumberOfPaths()]; boolean[][] handtouched = new boolean[p.getNumberOfJugglers()][2]; for (int j = 0; j < p.getNumberOfJugglers(); j++) for (int h = 0; h < 2; h++) handtouched[j][h] = false; boolean[] pathtouched = new boolean[p.getNumberOfPaths()]; for (int j = 0; j < p.getNumberOfPaths(); j++) pathtouched[j] = false; mhnThrow[][][][] th = p.getThrows(); for (int k = 0; k < p.getPeriod(); k++) { for (int j = 0; j < p.getNumberOfJugglers(); j++) { for (int h = 0; h < 2; h++) { mhnThrow sst = th[j][h][k][0]; if ((sst == null) || (sst.master != sst)) continue; // Step 3a -- Add transitions to the on-beat event (throw or holding transitions): JMLEvent ev = new JMLEvent(); double throwxsum = 0.0; int num_throws = 0; boolean onethrown = false; for (int slot = 0; slot < p.getMaxOccupancy(); slot++) { mhnThrow sst2 = th[j][h][k][slot]; if (sst2 == null) continue; String type = null, mod = null; switch (sst2.mod.charAt(0)) { case 'B': type = "bounce"; mod = null; if (sst2.mod.indexOf("F") != -1) { if (mod == null) mod = "forced=true"; else mod = mod + ";forced=true"; } if (sst2.mod.indexOf("H") != -1) { if (mod == null) mod = "hyper=true"; else mod = mod + ";hyper=true"; } int bounces = 1; for (int i = 1; i < sst2.mod.length(); i++) { if (sst2.mod.charAt(i) == 'B') bounces++; } if (bounces > 1) { if (mod == null) mod = "bounces=" + bounces; else mod = mod + ";bounces=" + bounces; } if (p.bouncefrac != mhnPattern.bouncefrac_default) if (mod == null) mod = "bouncefrac=" + p.bouncefrac; else mod = mod + ";bouncefrac=" + p.bouncefrac; if (p.gravity != mhnPattern.gravity_default) { if (mod == null) mod = "g=" + p.gravity; else mod = mod + ";g=" + p.gravity; } break; case 'F': type = "bounce"; mod = "forced=true"; if (p.bouncefrac != mhnPattern.bouncefrac_default) mod += ";bouncefrac="+p.bouncefrac; if (p.gravity != mhnPattern.gravity_default) mod = mod + ";g=" + p.gravity; break; case 'H': type = "hold"; mod = null; break; case 'T': default: type = "toss"; mod = null; if (p.gravity != mhnPattern.gravity_default) mod = "g=" + p.gravity; break; } if (sst2.mod.charAt(0) != 'H') { ev.addTransition(new JMLTransition(JMLTransition.TRANS_THROW, sst2.pathnum, type, mod)); int throwval = sst2.targetindex - k; // System.out.println("slot = "+k+", hand = "+h+", throwval = "+throwval); if (throwval == 1) onethrown = true; if (sst2.targethand == h) { throwxsum += ((throwval > 8) ? samethrowx[8] : samethrowx[throwval]); } else { throwxsum += ((throwval > 8) ? crossingthrowx[8] : crossingthrowx[throwval]); } num_throws++; } else if (p.hands != null) { if (sst2.pathnum != -1) { // -1 signals a 0 throw // add holding transition if there's a ball in hand and "hands" is specified ev.addTransition(new JMLTransition(JMLTransition.TRANS_HOLDING, sst2.pathnum, type, mod)); pathtouched[sst2.pathnum-1] = true; } } } // Step 3b -- Finish off the on-beat event based on the transitions we've added: // set the event position if (p.hands == null) { if (num_throws > 0) { double throwxav = throwxsum / (double)num_throws; if (h == mhnPattern.LEFT_HAND) throwxav = -throwxav; ev.setLocalCoordinate(new Coordinate(throwxav,0.0,0.0)); ev.calcpos = false; } else { // mark event to calculate coordinate later ev.calcpos = true; } } else { Coordinate c = p.hands.getCoordinate(sst.juggler, sst.handsindex, 0); if (h == mhnPattern.LEFT_HAND) c.x = -c.x; ev.setLocalCoordinate(c); ev.calcpos = false; } // set the event time double throwtime; if (onethrown) throwtime = ((double)k - 0.25*p.dwell) / p.bps; else throwtime = (double)k / p.bps; ev.setT(throwtime); // set the event juggler and hand ev.setHand(j+1, (h==mhnPattern.RIGHT_HAND ? HandLink.RIGHT_HAND : HandLink.LEFT_HAND)); // add it to the pattern result.addEvent(ev); // record which hands are touched by this event, for later reference for (int i2 = 0; i2 < p.indexes; i2++) { for (int j2 = 0; j2 < p.numjugglers; j2++) { for (int h2 = 0; h2 < 2; h2++) { for (int slot2 = 0; slot2 < p.max_occupancy; slot2++) { mhnThrow sst2 = th[j2][h2][i2][slot2]; if ((sst2 != null) && (sst2.master == sst)) handtouched[j2][h2] = true; } } } } // Step 3c -- Add any catching (or holding) events immediately prior to the on-beat event // added in Step 3b above: // calculate pathcaught[], catchxsum, num_catches, and onecaught /* for (int z = 0; z < p.getNumberOfPaths(); z++) pathcaught[z] = false; */ double catchxsum = 0.0; int num_catches = 0; boolean onecaught = false; for (int slot = 0; slot < p.getMaxOccupancy(); slot++) { mhnThrow sst2 = th[j][h][k][slot]; if (sst2 == null) break; if (!sst2.catching) continue; int catchpath = sst2.pathnum; int catchval = k - sst2.source.index; /* if (pathcaught[catchpath-1] == true) throw new JuggleExceptionInternal("Caught path "+catchpath+" twice");*/ // pathcaught[catchpath-1] = true; pathtouched[catchpath-1] = true; // System.out.println("catching value "+catchval); catchxsum += ((catchval > 8) ? catchx[8] : catchx[catchval]); num_catches++; if (catchval == 1) onecaught = true; } // Now add the event(s). There are two cases to consider: (1) all catches happen at // the same event, or (2) multiple catch events are made in succession. double lastcatchtime = 0.0; if ((splitcatchfactor == 0.0) || (num_catches < 2)) { // Case 1: everything happens at a single event ev = new JMLEvent(); // first set the event position if (p.hands == null) { if (num_catches > 0) { double cx = catchxsum / (double)num_catches; // System.out.println("average catch pos. = "+cx); ev.setLocalCoordinate(new Coordinate((h==mhnPattern.RIGHT_HAND?cx:-cx),0.0,0.0)); ev.calcpos = false; } else { // mark event to calculate coordinate later ev.calcpos = true; } } else { int pos = sst.handsindex - 2; while (pos < 0) pos += p.hands.getPeriod(sst.juggler); int index = p.hands.getCatchIndex(sst.juggler, pos); Coordinate c = p.hands.getCoordinate(sst.juggler, pos, index); if (h == mhnPattern.LEFT_HAND) c.x = -c.x; ev.setLocalCoordinate(c); ev.calcpos = false; } // set the event time if (onecaught) lastcatchtime = ((double)k - 0.5*p.dwell) / p.bps; else lastcatchtime = ((double)k - p.dwell) / p.bps; ev.setT(lastcatchtime); // set the event juggler and hand ev.setHand(j+1, (h==mhnPattern.RIGHT_HAND ? HandLink.RIGHT_HAND : HandLink.LEFT_HAND)); // add all the transitions for (int slot = 0; slot < p.getMaxOccupancy(); slot++) { mhnThrow sst2 = th[j][h][k][slot]; if (sst2 == null) break; if (sst2.catching) { ev.addTransition(new JMLTransition(JMLTransition.TRANS_CATCH, sst2.pathnum, null, null)); } else if (p.hands != null) { if (sst2.pathnum != -1) { // -1 signals a 0 throw // add holding transition if there's a ball in hand and "hands" is specified ev.addTransition(new JMLTransition(JMLTransition.TRANS_HOLDING, sst2.pathnum, null, null)); pathtouched[sst2.pathnum-1] = true; } } } // add event to the pattern result.addEvent(ev); } else { // Case 2: separate event for each catch; we know that numcatches>1 here for (int slot = 0; slot < p.getMaxOccupancy(); slot++) { mhnThrow sst2 = th[j][h][k][slot]; if (sst2 == null) continue; // we only need to add catch transitions here; holding transitions will be // added in Step 8 if (sst2.catching) { ev = new JMLEvent(); // first set the event position if (p.hands == null) { double cx = catchxsum / (double)num_catches; // System.out.println("average catch pos. = "+cx); ev.setLocalCoordinate(new Coordinate((h==mhnPattern.RIGHT_HAND?cx:-cx),0.0,0.0)); } else { int pos = sst.handsindex - 2; while (pos < 0) pos += p.hands.getPeriod(sst.juggler); int index = p.hands.getCatchIndex(sst.juggler, pos); Coordinate c = p.hands.getCoordinate(sst.juggler, pos, index); if (h == mhnPattern.LEFT_HAND) c.x = -c.x; ev.setLocalCoordinate(c); } ev.calcpos = false; // set the event time double catchtime; if (onecaught) catchtime = ((double)k - 0.5*p.dwell + ((double)sst2.catchnum/(double)(num_catches-1) - 0.5) * splitcatchfactor) / p.bps; else catchtime = ((double)k - p.dwell + ((double)sst2.catchnum/(double)(num_catches-1) - 0.5) * splitcatchfactor) / p.bps; ev.setT(catchtime); if (sst.catchnum == (num_catches-1)) lastcatchtime = catchtime; // set the event juggler and hand ev.setHand(j+1, (h==mhnPattern.RIGHT_HAND ? HandLink.RIGHT_HAND : HandLink.LEFT_HAND)); // add the transition ev.addTransition(new JMLTransition(JMLTransition.TRANS_CATCH, sst2.pathnum, null, null)); // add catch event to the pattern result.addEvent(ev); } } } // Step 3d -- Add other hand positioning events between the catch/throw/catch events, // if they are specified: if (p.hands == null) continue; // add other events between the previous catch and the current throw int pos = sst.handsindex - 2; while (pos < 0) pos += p.hands.getPeriod(sst.juggler); int catchindex = p.hands.getCatchIndex(sst.juggler, pos); int numcoords = p.hands.getNumberOfCoordinates(sst.juggler, pos) - catchindex; for (int di = 1; di < numcoords; di++) { Coordinate c = p.hands.getCoordinate(sst.juggler, pos, catchindex+di); if (c == null) continue; ev = new JMLEvent(); if (h == mhnPattern.LEFT_HAND) c.x = -c.x; ev.setLocalCoordinate(c); ev.calcpos = false; ev.setT(lastcatchtime + (double)di*(throwtime-lastcatchtime)/numcoords); ev.setHand(sst.juggler, (h==mhnPattern.RIGHT_HAND?HandLink.RIGHT_HAND:HandLink.LEFT_HAND)); result.addEvent(ev); } // figure out when the next catch or hold is: double nextcatchtime = lastcatchtime; for (int tempk = (k+1); tempk < p.getIndexes(); tempk++) { int next_num_catches = 0; boolean next_gotevent = false; boolean next_onecaught = false; for (int tempslot = 0; tempslot < p.getMaxOccupancy(); tempslot++) { mhnThrow tempsst = th[j][h][tempk][tempslot]; if (tempsst == null) break; next_gotevent = true; if (tempsst.catching) { next_num_catches++; if ((tempk - tempsst.source.index) == 1) next_onecaught = true; } } if (next_gotevent) { if (next_num_catches < 2) { if (next_onecaught) nextcatchtime = ((double)tempk - 0.5*p.dwell) / p.bps; else nextcatchtime = ((double)tempk - p.dwell) / p.bps; } else { if (next_onecaught) nextcatchtime = ((double)tempk - 0.5*p.dwell - 0.5*splitcatchfactor) / p.bps; else nextcatchtime = ((double)tempk - p.dwell - 0.5*splitcatchfactor) / p.bps; } break; } } if (nextcatchtime == lastcatchtime) throw new JuggleExceptionInternal("Couldn't find next catch/hold past t="+lastcatchtime); // add other events between the current throw and the next catch pos = sst.handsindex; numcoords = p.hands.getCatchIndex(sst.juggler, pos); for (int di = 1; di < numcoords; di++) { Coordinate c = p.hands.getCoordinate(sst.juggler, pos, di); if (c == null) continue; ev = new JMLEvent(); if (h == mhnPattern.LEFT_HAND) c.x = -c.x; ev.setLocalCoordinate(c); ev.calcpos = false; ev.setT(throwtime + (double)di*(nextcatchtime-throwtime)/numcoords); ev.setHand(sst.juggler, (h==mhnPattern.RIGHT_HAND?HandLink.RIGHT_HAND:HandLink.LEFT_HAND)); result.addEvent(ev); } } // Step 3e -- Define a body position for this juggler and beat, if one is specified: if (p.bodies != null) { int index = k % p.bodies.getPeriod(j+1); int coords = p.bodies.getNumberOfPositions(j+1, index); for (int z = 0; z < coords; z++) { JMLPosition jmlp = p.bodies.getPosition(j+1, index, z); if (jmlp != null) { jmlp.setT(((double)k + (double)z / (double)coords) / p.bps); result.addPosition(jmlp); } } } } } // Step 4 -- Add simple positioning events for hands that got no events: for (int j = 0; j < p.getNumberOfJugglers(); j++) { for (int h = 0; h < 2; h++) { if (!handtouched[j][h]) { JMLEvent ev = new JMLEvent(); ev.setLocalCoordinate(new Coordinate((h==mhnPattern.RIGHT_HAND?restingx:-restingx),0.0,0.0)); ev.setT(-1.0); ev.setHand(j+1, (h==0?HandLink.RIGHT_HAND:HandLink.LEFT_HAND)); ev.calcpos = false; result.addEvent(ev); } } } // Step 5 -- Add transitions for paths that got no events: // first, apply all pattern symmetries to figure out which paths don't get touched for (int j = 0; j < result.getNumberOfSymmetries(); j++) { Permutation perm = result.getSymmetry(j).getPathPerm(); for (int k = 0; k < p.getNumberOfPaths(); k++) { if (pathtouched[k]) { for (int l = 1; l < perm.getOrder(k+1); l++) { pathtouched[perm.getMapping(k+1,l) - 1] = true; } } } } // next, add transitions for the untouched paths for (int k = 0; k < p.getNumberOfPaths(); k++) { if (pathtouched[k]) continue; // figure out which hand it should belong in int hand = HandLink.LEFT_HAND; int juggler = 0; top: for (int tempk = 0; tempk < p.getIndexes(); tempk++) { for (int tempj = 0; tempj < p.getNumberOfJugglers(); tempj++) { for (int temph = 0; temph < 2; temph++) { for (int slot = 0; slot < p.getMaxOccupancy(); slot++) { mhnThrow sst = th[tempj][temph][tempk][slot]; if ((sst != null) && (sst.pathnum == (k+1))) { hand = (temph==mhnPattern.RIGHT_HAND?HandLink.RIGHT_HAND:HandLink.LEFT_HAND); juggler = tempj; break top; } } } } } // add transitions to each of that hand's events JMLEvent ev = result.getEventList(); while (ev != null) { if ((ev.getHand() == hand) && (ev.getJuggler() == (juggler+1))) { ev.addTransition(new JMLTransition(JMLTransition.TRANS_HOLDING, (k+1), null, null)); // mark related paths as touched pathtouched[k] = true; for (int j = 0; j < result.getNumberOfSymmetries(); j++) { Permutation perm = result.getSymmetry(j).getPathPerm(); for (int l = 1; l < perm.getOrder(k+1); l++) { pathtouched[perm.getMapping(k+1,l) - 1] = true; } } } ev = ev.getNext(); } // if (ev == null) // throw new JuggleExceptionUser("Could not find event for hand"); } // Step 6 -- Do a build of the full event list so we can scan through it chronologically in Steps 7 and 8: result.buildEventList(); // Step 7 -- Specify positions for events that don't have them defined yet: for (int j = 1; j <= p.getNumberOfJugglers(); j++) { for (int h = 0; h < 2; h++) { int hand = (h==mhnPattern.RIGHT_HAND?HandLink.RIGHT_HAND:HandLink.LEFT_HAND); JMLEvent ev = result.getEventList(); JMLEvent start = null; int scanstate = 1; // 1 = starting, 2 = on defined event, 3 = on undefined event while (ev != null) { if ((ev.getJuggler() == j) && (ev.getHand() == hand)) { // System.out.println("j = "+j+", h = "+h+", t = "+ev.getT()+", calcpos = "+ev.calcpos); // System.out.println(" initial state = "+scanstate); if (ev.calcpos) { scanstate = 3; } else { switch (scanstate) { case 1: scanstate = 2; break; case 2: break; case 3: if (start != null) { JMLEvent end = ev; double t_end = end.getT(); Coordinate pos_end = end.getLocalCoordinate(); double t_start = start.getT(); Coordinate pos_start = start.getLocalCoordinate(); ev = start.getNext(); while (ev != end) { if ((ev.getJuggler() == j) && (ev.getHand() == hand)) { double t = ev.getT(); double x = pos_start.x + (t - t_start)* (pos_end.x - pos_start.x) / (t_end - t_start); double y = pos_start.y + (t - t_start)* (pos_end.y - pos_start.y) / (t_end - t_start); double z = pos_start.z + (t - t_start)* (pos_end.z - pos_start.z) / (t_end - t_start); ev.setLocalCoordinate(new Coordinate(x, y, z)); ev.calcpos = false; } ev = ev.getNext(); } } scanstate = 2; break; } start = ev; } // System.out.println(" final state = "+scanstate); } ev = ev.getNext(); } // do a last scan through to define any remaining undefined positions ev = result.getEventList(); while (ev != null) { if ((ev.getJuggler() == j) && (ev.getHand() == hand) && ev.calcpos) { ev.setLocalCoordinate(new Coordinate((h==mhnPattern.RIGHT_HAND?restingx:-restingx),0.0,0.0)); ev.calcpos = false; } ev = ev.getNext(); } } } // Step 8 -- Scan through the list of events, and look for cases where we need to add additional // transitions. These are marked by cases where the catch and throw transitions for // a given path have intervening events in that hand; we want to add transitions to // these intervening events: for (int k = 0; k < p.getNumberOfPaths(); k++) { boolean add_mode = false; boolean found_event = false; int add_juggler = 0, add_hand = 0; JMLEvent ev = result.getEventList(); while (ev != null) { JMLTransition tr = ev.getPathTransition((k+1), JMLTransition.TRANS_ANY); if (tr != null) { switch (tr.getType()) { case JMLTransition.TRANS_THROW: if ((found_event == false) && (add_mode == false)) { // first event mentioning path is a throw // rewind to beginning of list and add holds add_mode = true; add_juggler = ev.getJuggler(); add_hand = ev.getHand(); ev = result.getEventList(); continue; } add_mode = false; break; case JMLTransition.TRANS_CATCH: case JMLTransition.TRANS_SOFTCATCH: add_mode = true; add_juggler = ev.getJuggler(); add_hand = ev.getHand(); break; case JMLTransition.TRANS_HOLDING: if ((found_event == false) && (add_mode == false)) { // first event mentioning path is a hold // rewind to beginning of list and add holds add_mode = true; add_juggler = ev.getJuggler(); add_hand = ev.getHand(); ev = result.getEventList(); continue; } add_mode = true; add_juggler = ev.getJuggler(); add_hand = ev.getHand(); break; } found_event = true; } else if (add_mode) { if ((ev.getJuggler()==add_juggler) && (ev.getHand()==add_hand) && ev.isMaster()) ev.addTransition(new JMLTransition(JMLTransition.TRANS_HOLDING, (k+1), null, null)); } ev = ev.getNext(); } } if (jugglinglab.core.Constants.DEBUG_LAYOUT) System.out.println(result); return result; } protected static final double[] throwspersec = { 2.00, 2.00, 2.00, 2.90, 3.40, 4.10, 4.25, 5.00, 5.00, 5.50 }; protected static double calcBps(mhnPattern p) { double result = 0.0; mhnThrow[][][][] th = p.getThrows(); int numberaveraged = 0; for (int k = 0; k < p.getPeriod(); k++) { for (int j = 0; j < p.getNumberOfJugglers(); j++) { for (int h = 0; h < 2; h++) { for (int slot = 0; slot < p.getMaxOccupancy(); slot++) { mhnThrow sst = th[j][h][k][slot]; if (sst != null) { int throwval = sst.targetindex - k; if (throwval > 2) { result += throwspersec[(throwval > 9) ? 9 : throwval]; numberaveraged++; } } } } } } if (numberaveraged > 0) result /= (double)numberaveraged; else result = 2.0; return result; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/mhnNotationControl.java000066400000000000000000000300141323754603300266730ustar00rootroot00000000000000// mhnNotationControl.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.notation; import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.util.*; import jugglinglab.util.*; import jugglinglab.prop.Prop; public class mhnNotationControl extends NotationControl { protected static final String[] builtinHandsNames = { "inside", "outside", "half", "Mills" }; protected static final String[] builtinHandsStrings = { "(10)(32.5).", "(32.5)(10).", "(32.5)(10).(10)(32.5).", "(-25)(2.5).(25)(-2.5).(-25)(0)." }; protected static final String[] builtinBodyNames = { "line", "feed", "backtoback", "sidetoside", "circles" }; protected static final String[] builtinBodyStrings = { "<(90).|(270,-125).|(90,125).|(270,-250).|(90,250).|(270,-375).>", "<(90,75).|(270,-75,50).|(270,-75,-50).|(270,-75,150).|(270,-75,-150).>", "<(270,35).|(90,-35).|(0,0,35).|(180,0,-35).>", "<(0).|(0,100).|(0,-100).|(0,200).|(0,-200).|(0,300).>", "(0,75,0)...(90,0,75)...(180,-75,0)...(270,0,-75)..." }; // text fields in control panel protected JTextField tf1, tf2, tf3, tf4, tf5, tf6; protected JComboBox cb1, cb2, cb3; protected boolean cb1_selected = false, cb2_selected = false; protected final static int border = 10; protected final static int hspacing = 5; protected final static int vspacing = 12; public mhnNotationControl() { this.setOpaque(false); this.setLayout(new BorderLayout()); JPanel p1 = new JPanel(); GridBagLayout gb = new GridBagLayout(); p1.setLayout(gb); JLabel lab1 = new JLabel(guistrings.getString("Pattern")); p1.add(lab1); gb.setConstraints(lab1, make_constraints(GridBagConstraints.LINE_END,0,0, new Insets(border,border,0,hspacing))); tf1 = new JTextField(15); p1.add(tf1); gb.setConstraints(tf1, make_constraints(GridBagConstraints.LINE_START,1,0, new Insets(border,0,0,border))); JLabel lab3 = new JLabel(guistrings.getString("Beats_per_second")); p1.add(lab3); gb.setConstraints(lab3, make_constraints(GridBagConstraints.LINE_END,0,1, new Insets(2*vspacing,border,0,hspacing))); tf3 = new JTextField(4); p1.add(tf3); gb.setConstraints(tf3, make_constraints(GridBagConstraints.LINE_START,1,1, new Insets(2*vspacing,0,0,border))); JLabel lab2 = new JLabel(guistrings.getString("Dwell_beats")); p1.add(lab2); gb.setConstraints(lab2, make_constraints(GridBagConstraints.LINE_END,0,2, new Insets(vspacing,border,0,hspacing))); tf2 = new JTextField(4); p1.add(tf2); gb.setConstraints(tf2, make_constraints(GridBagConstraints.LINE_START,1,2, new Insets(vspacing,0,0,border))); JLabel lab4 = new JLabel(guistrings.getString("Hand_movement")); p1.add(lab4); gb.setConstraints(lab4, make_constraints(GridBagConstraints.LINE_END,0,3, new Insets(vspacing,border,0,hspacing))); cb1 = new JComboBox(); cb1.addItem(guistrings.getString("MHNHands_name_default")); for (int i = 0; i < builtinHandsNames.length; i++) { String item = "MHNHands_name_" + builtinHandsNames[i]; cb1.addItem(guistrings.getString(item)); } cb1.addItem(guistrings.getString("MHNHands_name_custom")); p1.add(cb1); gb.setConstraints(cb1, make_constraints(GridBagConstraints.LINE_START,1,3, new Insets(vspacing,0,0,border))); tf4 = new JTextField(15); p1.add(tf4); gb.setConstraints(tf4, make_constraints(GridBagConstraints.LINE_START,1,4, new Insets(5,0,0,border))); cb1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { int index = cb1.getSelectedIndex(); cb1_selected = true; // System.out.println("Selected item number "+index); if (index == 0) { tf4.setText(""); tf4.setEnabled(false); } else if (index == (builtinHandsNames.length+1)) { tf4.setEnabled(true); } else { tf4.setText(builtinHandsStrings[index-1]); tf4.setCaretPosition(0); tf4.setEnabled(true); } } }); tf4.getDocument().addDocumentListener(new DocumentListener() { public void changedUpdate(DocumentEvent de) {} public void insertUpdate(DocumentEvent de) { if (!cb1_selected) cb1.setSelectedIndex(builtinHandsNames.length+1); cb1_selected = false; } public void removeUpdate(DocumentEvent de) { if (!cb1_selected) cb1.setSelectedIndex(builtinHandsNames.length+1); } }); JLabel lab5 = new JLabel(guistrings.getString("Body_movement")); p1.add(lab5); gb.setConstraints(lab5, make_constraints(GridBagConstraints.LINE_END,0,5, new Insets(vspacing,border,0,hspacing))); cb2 = new JComboBox(); cb2.addItem(guistrings.getString("MHNBody_name_default")); for (int i = 0; i < builtinBodyNames.length; i++) { String item = "MHNBody_name_" + builtinBodyNames[i]; cb2.addItem(guistrings.getString(item)); } cb2.addItem(guistrings.getString("MHNBody_name_custom")); p1.add(cb2); gb.setConstraints(cb2, make_constraints(GridBagConstraints.LINE_START,1,5, new Insets(vspacing,0,0,border))); tf5 = new JTextField(15); p1.add(tf5); gb.setConstraints(tf5, make_constraints(GridBagConstraints.LINE_START,1,6, new Insets(5,0,0,border))); cb2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { int index = cb2.getSelectedIndex(); cb2_selected = true; // System.out.println("Selected item number "+index); if (index == 0) { tf5.setText(""); tf5.setEnabled(false); } else if (index == (builtinBodyNames.length+1)) { tf5.setEnabled(true); } else { tf5.setText(builtinBodyStrings[index-1]); tf5.setCaretPosition(0); tf5.setEnabled(true); } } }); tf5.getDocument().addDocumentListener(new DocumentListener() { public void changedUpdate(DocumentEvent de) {} public void insertUpdate(DocumentEvent de) { if (!cb2_selected) cb2.setSelectedIndex(builtinBodyNames.length+1); cb2_selected = false; } public void removeUpdate(DocumentEvent de) { if (!cb2_selected) cb2.setSelectedIndex(builtinBodyNames.length+1); } }); JLabel prop_label = new JLabel(guistrings.getString("Prop_type")); p1.add(prop_label); gb.setConstraints(prop_label, make_constraints(GridBagConstraints.LINE_END,0,7, new Insets(vspacing,border,0,hspacing))); cb3 = new JComboBox(); for (int i = 0; i < Prop.builtinProps.length; i++) { String item = "Prop_name_" + Prop.builtinProps[i].toLowerCase(); cb3.addItem(guistrings.getString(item)); } p1.add(cb3); gb.setConstraints(cb3, make_constraints(GridBagConstraints.LINE_START,1,7, new Insets(vspacing,0,0,border))); JLabel lab6 = new JLabel(guistrings.getString("Manual_settings")); p1.add(lab6); gb.setConstraints(lab6, make_constraints(GridBagConstraints.LINE_START,0,8, new Insets(2*vspacing,border,0,hspacing))); tf6 = new JTextField(25); p1.add(tf6); GridBagConstraints gbc6 = make_constraints(GridBagConstraints.LINE_END,0,9, new Insets(5,border+hspacing,0,border)); gbc6.gridwidth = 2; gb.setConstraints(tf6, gbc6); this.resetNotationControl(); this.add(p1, BorderLayout.PAGE_START); } protected static GridBagConstraints make_constraints(int location, int gridx, int gridy) { GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = location; gbc.fill = GridBagConstraints.NONE; gbc.gridheight = gbc.gridwidth = 1; gbc.gridx = gridx; gbc.gridy = gridy; gbc.weightx = gbc.weighty = 0.0; return gbc; } protected static GridBagConstraints make_constraints(int location, int gridx, int gridy, Insets ins) { GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = location; gbc.fill = GridBagConstraints.NONE; gbc.gridheight = gbc.gridwidth = 1; gbc.gridx = gridx; gbc.gridy = gridy; gbc.insets = ins; gbc.weightx = gbc.weighty = 0.0; return gbc; } public String getPattern() { StringBuffer sb = new StringBuffer(256); sb.append("pattern="); sb.append(tf1.getText()); sb.append(";prop=" + Prop.builtinProps[cb3.getSelectedIndex()].toLowerCase()); if (tf2.getText().length() > 0) { if (!tf2.getText().equals(new Double(mhnPattern.dwell_default).toString())) { sb.append(";dwell="); sb.append(tf2.getText()); } } if (tf3.getText().length() > 0) { sb.append(";bps="); sb.append(tf3.getText()); } if (tf4.getText().length() > 0) { sb.append(";hands="); sb.append(tf4.getText()); } if (tf5.getText().length() > 0) { sb.append(";body="); sb.append(tf5.getText()); } if (tf6.getText().length() > 0) { sb.append(";"); sb.append(tf6.getText()); } return sb.toString(); } public void resetNotationControl() { tf1.setText("3"); // pattern tf2.setText(new Double(mhnPattern.dwell_default).toString()); // dwell beats tf3.setText(""); // beats per second tf4.setText(""); cb1.setSelectedIndex(0); tf5.setText(""); cb2.setSelectedIndex(0); tf6.setText(""); cb3.setSelectedIndex(0); } public String getHandsName() { int index = cb1.getSelectedIndex(); if ((index == 0) || (index == (builtinHandsNames.length+1))) return null; return builtinHandsNames[index-1]; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/mhnPattern.java000066400000000000000000000144031323754603300251600ustar00rootroot00000000000000// mhnPattern.java // // Copyright 2003 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.notation; import java.util.*; import jugglinglab.util.*; public class mhnPattern { // static ResourceBundle guistrings; static ResourceBundle errorstrings; static { // guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } protected static double bps_default = -1.0; // calculate bps protected static double dwell_default = 1.3; protected static double gravity_default = 980.0; protected static double propdiam_default = 10.0; protected static double bouncefrac_default = 0.9; protected static String prop_default = "ball"; // input parameters: protected String pattern; protected double bps = bps_default; protected double dwell = dwell_default; protected double gravity = gravity_default; protected double propdiam = propdiam_default; protected double bouncefrac = bouncefrac_default; protected String prop = prop_default; protected String[] color = null; // internal variables: protected int numjugglers; protected int numpaths; protected int period; protected int max_occupancy; protected mhnThrow[][][][] th; protected mhnHands hands = null; protected mhnBody bodies = null; protected int max_throw; protected int indexes; protected Vector symmetry = null; public static final int RIGHT_HAND = 0; public static final int LEFT_HAND = 1; protected int getNumberOfJugglers() { return numjugglers; } protected int getNumberOfPaths() { return numpaths; } protected int getPeriod() { return period; } protected int getIndexes() { return indexes; } protected int getMaxOccupancy() { return max_occupancy; } protected int getMaxThrow() { return max_throw; } protected mhnThrow[][][][] getThrows() { return th; } protected int getNumberOfSymmetries() { return symmetry.size(); } protected String getPropName() { return prop; } protected void addSymmetry(mhnSymmetry ss) { symmetry.addElement(ss); } protected mhnSymmetry getSymmetry(int i) { return (mhnSymmetry)(symmetry.elementAt(i)); } public void parseInput(String config) throws JuggleExceptionUser, JuggleExceptionInternal { if (config.indexOf((int)'=') == -1) { // just the pattern pattern = config; return; } ParameterList pl = new ParameterList(config); String temp = null; pattern = pl.getParameter("pattern"); if (pattern == null) throw new JuggleExceptionUser(errorstrings.getString("Error_no_pattern")); if ((temp = pl.getParameter("bps")) != null) { try { bps = Double.valueOf(temp).doubleValue(); } catch (NumberFormatException nfe) { throw new JuggleExceptionUser(errorstrings.getString("Error_bps_value")); } } if ((temp = pl.getParameter("dwell")) != null) { try { dwell = Double.valueOf(temp).doubleValue(); } catch (NumberFormatException nfe) { throw new JuggleExceptionUser(errorstrings.getString("Error_dwell_value")); } } if ((temp = pl.getParameter("hands")) != null) hands = new mhnHands(temp); if ((temp = pl.getParameter("body")) != null) bodies = new mhnBody(temp); if ((temp = pl.getParameter("gravity")) != null) { try { gravity = Double.valueOf(temp).doubleValue(); } catch (NumberFormatException e) { } } if ((temp = pl.getParameter("propdiam")) != null) { try { propdiam = Double.valueOf(temp).doubleValue(); } catch (NumberFormatException e) { } } if ((temp = pl.getParameter("bouncefrac")) != null) { try { bouncefrac = Double.valueOf(temp).doubleValue(); } catch (NumberFormatException e) { } } if ((temp = pl.getParameter("prop")) != null) { prop = temp; } if ((temp = pl.getParameter("colors")) != null) { if (temp.trim().equals("mixed")) temp = "{red}{green}{blue}{yellow}{cyan}{magenta}{orange}{pink}{gray}{black}"; StringTokenizer st1 = new StringTokenizer(temp, "}", false); StringTokenizer st2 = null; String str = null; int numcolors = st1.countTokens(); color = new String[numcolors]; // Parse the colors parameter for (int i = 0; i < numcolors; i++) { // Look for next {...} block str = st1.nextToken().replace('{', ' ').trim(); // Parse commas st2 = new StringTokenizer(str, ",", false); switch (st2.countTokens()) { case 1: // Use the value as a color name color[i] = st2.nextToken().trim().toLowerCase(); break; case 3: // Use the three values as RGB values color[i] = "{" + str + "}"; break; default: throw new JuggleExceptionUser(errorstrings.getString("Error_color_format")); } // System.out.println("color "+i+" = "+color[i]); } } } } jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/mhnSymmetry.java000066400000000000000000000042141323754603300253730ustar00rootroot00000000000000// mhnSymmetry.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.notation; import jugglinglab.util.*; public class mhnSymmetry { int type; int numjugglers; Permutation jugglerperm = null; int delay = -1; static final public int TYPE_DELAY = 1; // types of symmetries static final public int TYPE_SWITCH = 2; static final public int TYPE_SWITCHDELAY = 3; public mhnSymmetry(int type, int numjugglers, String jugperm, int delay) throws JuggleExceptionUser { setType(type); setJugglerPerm(numjugglers, jugperm); setDelay(delay); } public int getType() { return type; } protected void setType(int type) { this.type = type; } public int getNumberOfJugglers() { return numjugglers; } public Permutation getJugglerPerm() { return jugglerperm; } protected void setJugglerPerm(int nj, String jp) throws JuggleExceptionUser { this.numjugglers = nj; try { if (jp == null) this.jugglerperm = new Permutation(numjugglers, true); else this.jugglerperm = new Permutation(numjugglers, jp, true); } catch (JuggleException je) { throw new JuggleExceptionUser(je.getMessage()); } } public int getDelay() { return delay; } protected void setDelay(int del) { this.delay = del; } }jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/mhnThrow.java000066400000000000000000000040401323754603300246420ustar00rootroot00000000000000// mhnThrow.java // // Copyright 2003 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.notation; import jugglinglab.util.*; public class mhnThrow { public int juggler; ///< indexed from 0 public int hand; ///< mhnPattern.RIGHT_HAND or LEFT_HAND public int index; public int slot; public int targetjuggler; ///< indexed from 0 public int targethand; ///< mhnPattern.RIGHT_HAND or LEFT_HAND public int targetindex; public int targetslot; public int handsindex; ///< index of throw in hands sequence, if one exists public int pathnum = -1; public String mod; public mhnThrow master = null; public mhnThrow source = null; public mhnThrow target = null; public boolean catching = false; ///< are we catching just before this throw? public int catchnum = -1; ///< order (starting at 1) to make catches public mhnThrow() {} public mhnThrow(int j, int h, int i, int s, int tj, int th, int ti, int ts, String m) { this.juggler = j; this.hand = h; this.index = i; this.slot = s; this.targetjuggler = tj; this.targethand = th; // 0 for right hand, 1 for left hand this.targetindex = ti; this.targetslot = ts; this.mod = m; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/siteswapNotation.java000077500000000000000000000067101323754603300264200ustar00rootroot00000000000000// siteswapNotation.java // // Copyright 2003 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.notation; import java.util.*; import jugglinglab.jml.*; import jugglinglab.util.*; public class siteswapNotation extends mhnNotation { public String getName() { return "Siteswap"; } public JMLPattern getJMLPattern(String config) throws JuggleExceptionUser, JuggleExceptionInternal { // This entire method will need to be double-checked for suitability with siteswap2 notation siteswapPattern p = new siteswapPattern(); // delete newlines and carriage returns from string int pos; while ((pos = config.indexOf('\n')) >= 0) { config = config.substring(0,pos) + config.substring(pos+1,config.length()); } while ((pos = config.indexOf('\r')) >= 0) { config = config.substring(0,pos) + config.substring(pos+1,config.length()); } p.parseInput(config); String origpattern = p.pattern; // see if we need to repeat the pattern to match hand or body periods: if ((p.hands != null) || (p.bodies != null)) { p.parsePattern(); int patperiod = p.getNorepPeriod(); int handperiod = 1; if (p.hands != null) { for (int i = 1; i <= p.getNumberOfJugglers(); i++) handperiod = Permutation.lcm(handperiod, p.hands.getPeriod(i)); } int bodyperiod = 1; if (p.bodies != null) { for (int i = 1; i <= p.getNumberOfJugglers(); i++) bodyperiod = Permutation.lcm(bodyperiod, p.bodies.getPeriod(i)); } int totalperiod = patperiod; totalperiod = Permutation.lcm(totalperiod, handperiod); totalperiod = Permutation.lcm(totalperiod, bodyperiod); if (totalperiod != patperiod) { int repeats = totalperiod / patperiod; p.pattern = "(" + p.pattern + "^" + repeats + ")"; } } p.parsePattern(); // The following is a hack to support the legacy "mat_HR" parameter // from JuggleAnim. Adjust bps to achieve the desired maximum throw height. /* if (p.mat_hr > 0.0) { try { p.bps = Math.sqrt(p.gravity / (800.0 * p.mat_hr * (double)p.getMaxThrow())) * ((double)p.getMaxThrow() - p.dwell); } catch (ArithmeticException e) { } } */ JMLPattern result = getJML(p); result.setTitle(origpattern); if (jugglinglab.core.Constants.DEBUG_LAYOUT) System.out.println(result); return result; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/siteswapNotationControl.java000066400000000000000000000017211323754603300277530ustar00rootroot00000000000000// siteswapNotationControl.java // // Copyright 2003 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.notation; public class siteswapNotationControl extends mhnNotationControl { } jugglinglab-0.6.2+ds.1/source/jugglinglab/notation/siteswapPattern.java000066400000000000000000000531411323754603300262370ustar00rootroot00000000000000// siteswapPattern.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.notation; import java.util.*; import java.text.*; import jugglinglab.util.*; public class siteswapPattern extends mhnPattern { protected boolean oddperiod = false; // only works after parsePattern() is called: protected int getNorepPeriod() { return (oddperiod ? getPeriod()/2 : getPeriod()); } public void parseInput(String config) throws JuggleExceptionUser, JuggleExceptionInternal { if (config.indexOf((int)'=') == -1) // just the pattern pattern = config; else { super.parseInput(config); // parse params common to all MHN notations parseLegacyParameters(config); // parse legacy JuggleAnim params } } protected void parseLegacyParameters(String config) throws JuggleExceptionUser, JuggleExceptionInternal { ParameterList pl = new ParameterList(config); int tempint; double tempdouble; String temp = null; double rightthrowx = 0.2; // JuggleAnim uses meters; Juggling Lab uses centimeters double rightcatchx = 0.5; double leftthrowx = 0.2; double leftcatchx = 0.5; boolean gotthrowcatch = false; if ((temp = pl.getParameter("tps")) != null) { try { bps = Double.valueOf(temp).doubleValue(); } catch (NumberFormatException nfe) { } } if ((temp = pl.getParameter("dratio")) != null) { try { tempdouble = Double.valueOf(temp).doubleValue(); if ((tempdouble > 0.0) && (tempdouble < 1.9)) dwell = 2.0 * tempdouble; } catch (NumberFormatException e) { } } if ((temp = pl.getParameter("throwx")) != null) { try { tempdouble = Double.valueOf(temp).doubleValue(); rightthrowx = leftthrowx = tempdouble; gotthrowcatch = true; } catch (NumberFormatException e) { } } if ((temp = pl.getParameter("rightthrowx")) != null) { try { tempdouble = Double.valueOf(temp).doubleValue(); rightthrowx = tempdouble; gotthrowcatch = true; } catch (NumberFormatException e) { } } if ((temp = pl.getParameter("leftthrowx")) != null) { try { tempdouble = Double.valueOf(temp).doubleValue(); leftthrowx = tempdouble; gotthrowcatch = true; } catch (NumberFormatException e) { } } if ((temp = pl.getParameter("catchx")) != null) { try { tempdouble = Double.valueOf(temp).doubleValue(); rightcatchx = leftcatchx = tempdouble; gotthrowcatch = true; } catch (NumberFormatException e) { } } if ((temp = pl.getParameter("rightcatchx")) != null) { try { tempdouble = Double.valueOf(temp).doubleValue(); rightcatchx = tempdouble; gotthrowcatch = true; } catch (NumberFormatException e) { } } if ((temp = pl.getParameter("leftcatchx")) != null) { try { tempdouble = Double.valueOf(temp).doubleValue(); leftcatchx = tempdouble; gotthrowcatch = true; } catch (NumberFormatException e) { } } if ((temp = pl.getParameter("balldiam")) != null) { try { propdiam = 100.0 * Double.valueOf(temp).doubleValue(); } catch (NumberFormatException e) { } } if ((temp = pl.getParameter("g")) != null) { try { gravity = 100.0 * Double.valueOf(temp).doubleValue(); } catch (NumberFormatException e) { } } if ((temp = pl.getParameter("mat_style")) != null) { throw new JuggleExceptionUser(errorstrings.getString("Error_unsupported_setting")+": 'mat_style'"); } if ((temp = pl.getParameter("mat_DR")) != null) { throw new JuggleExceptionUser(errorstrings.getString("Error_unsupported_setting")+": 'mat_DR'"); } if ((temp = pl.getParameter("mat_HR")) != null) { throw new JuggleExceptionUser(errorstrings.getString("Error_unsupported_setting")+": 'mat_HR'"); } if ((hands == null) && gotthrowcatch) { // not created by hands parameter hands = new mhnHands("("+(100.0*rightthrowx)+")("+(100.0*rightcatchx)+").("+ (100.0*leftthrowx)+")("+(100.0*leftcatchx)+")."); } } public void parsePattern() throws JuggleExceptionUser, JuggleExceptionInternal { // first clear out the internal variables th = null; symmetry = new Vector(); SiteswapTreeItem tree = null; // should probably be class variable try { // System.out.println("---------------"); // System.out.println("Parsing pattern \"" + pattern + "\""); tree = SiteswapParser.parsePattern(pattern); // System.out.println(""); // System.out.println(tree.toString()); } catch (ParseException pe) { // System.out.println("---------------"); // System.out.println("Parse error:"); // System.out.println(pe.getMessage()); // System.out.println("---------------"); String template = errorstrings.getString("Error_pattern_syntax"); String problem = ParseException.add_escapes(pe.currentToken.next.image); Object[] arguments = { problem, new Integer(pe.currentToken.next.beginColumn) }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } catch (TokenMgrError tme) { String template = errorstrings.getString("Error_pattern_syntax"); String problem = TokenMgrError.addEscapes(String.valueOf(tme.curChar)); Object[] arguments = { problem, new Integer(tme.errorColumn - 1) }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } // Need to use tree to fill in mhnPattern internal variables: /* protected int numjugglers; protected int numpaths; protected int period; protected int max_occupancy; protected mhnThrow[][][][] th; protected mhnHands hands = null; protected mhnBody bodies = null; protected int max_throw; protected int indexes; protected Vector symmetry = null; */ this.numjugglers = tree.jugglers; this.max_occupancy = 0; // calculated in doFirstPass() this.max_throw = 0; this.right_on_even = new boolean[this.numjugglers]; for (int i = 0; i < this.numjugglers; i++) right_on_even[i] = true; tree.beatnum = 0; doFirstPass(tree); if (!tree.switchrepeat) { if (tree.vanilla_asynch && ((tree.beats % 2) == 1)) { tree.switchrepeat = true; tree.beats *= 2; tree.throw_sum *= 2; this.oddperiod = true; } } this.period = tree.beats; if ((tree.throw_sum % tree.beats) != 0) throw new JuggleExceptionUser(errorstrings.getString("Error_siteswap_bad_average")); this.numpaths = tree.throw_sum / tree.beats; this.indexes = this.max_throw + this.period + 1; this.th = new mhnThrow[numjugglers][2][indexes][max_occupancy]; /* System.out.println("period = "+period+", numpaths = "+numpaths+", max_throw = "+ max_throw+", max_occupancy = "+max_occupancy); */ doSecondPass(tree, false, 0); // Finally, add pattern symmetries addSymmetry(new mhnSymmetry(mhnSymmetry.TYPE_DELAY, numjugglers, null, period)); if (tree.switchrepeat) { // know that tree is of type Pattern StringBuffer sb = new StringBuffer(); for (int i = 1; i <= numjugglers; i++) sb.append("("+i+","+i+"*)"); addSymmetry(new mhnSymmetry(mhnSymmetry.TYPE_SWITCHDELAY, numjugglers, sb.toString(), period/2)); } // Random error check, not sure where this should go if ((bodies != null) && (bodies.getNumberOfJugglers() < this.getNumberOfJugglers())) throw new JuggleExceptionUser(errorstrings.getString("Error_jugglers_body")); } // The following are methods used to find transitions between patterns // First item in array argument is assumed to be a GroupedPattern type protected int[][] findExitState(SiteswapTreeItem[] item) { return null; } // Last item in array argument is assumed to be a GroupedPattern type protected int[][] findEntranceState(SiteswapTreeItem[] item) { return null; } protected SiteswapTreeItem findShortestTransition(int[][] start, int[][] end, int minbeats, boolean evenbeats) { return null; } // First pass through the tree: // 1) Assign hands to "Single Throw" types // 2) Determine whether any Pattern items need switchrepeat turned on // 3) Calculate sti.beats for Pattern and GroupedPattern types // 4) Determine absolute beat numbers for each throw // 5) Calculate max_throw, period, numpaths, and max_occupancy // 6) Resolve wildcards // What we need to evaluate wildcards: // boolean[] right_on_even; // asynch throws on even beat numbers made with right hand? protected void doFirstPass(SiteswapTreeItem sti) throws JuggleExceptionUser, JuggleExceptionInternal { SiteswapTreeItem child = null; sti.throw_sum = 0; sti.vanilla_asynch = true; switch (sti.type) { case SiteswapTreeItem.TYPE_PATTERN: // Can contain Grouped_Pattern, Solo_Sequence, Passing_Sequence, or Wildcard sti.beats = 0; for (int i = 0; i < sti.getNumberOfChildren(); i++) { child = sti.getChild(i); child.beatnum = sti.beatnum + sti.beats; if (child.type == SiteswapTreeItem.TYPE_WILDCARD) { // resolve this wildcard by finding a suitable transition sequence child.transition = null; // remove any previously-found transition sequence // First find the pattern state immediately prior to the wildcard SiteswapTreeItem[] item = new SiteswapTreeItem[sti.getNumberOfChildren()]; int index = sti.getNumberOfChildren() - 1; boolean done = false; for (int j = i-1; j >= 0; j--) { item[index--] = sti.getChild(j); if (sti.getChild(j).type == SiteswapTreeItem.TYPE_GROUPED_PATTERN) { done = true; break; } if (sti.getChild(j).type == SiteswapTreeItem.TYPE_WILDCARD) throw new JuggleExceptionUser("Can only have one wildcard between grouped patterns"); } if (!done) { int beatsum = 0; for (int j = sti.getNumberOfChildren()-1; j > i; j--) { SiteswapTreeItem c = sti.getChild(j); item[index--] = c; if (c.type == SiteswapTreeItem.TYPE_GROUPED_PATTERN) { done = true; break; } if (c.type == SiteswapTreeItem.TYPE_WILDCARD) throw new JuggleExceptionUser("Can only have one wildcard between grouped patterns"); } } if (!done) throw new JuggleExceptionUser("Must have at least one grouped subpattern to use wildcard"); SiteswapTreeItem[] item2 = new SiteswapTreeItem[sti.getNumberOfChildren() - 1 - index]; index++; for (int j = 0; index < sti.getNumberOfChildren(); j++, index++) item2[j] = item[index]; for (int j = item2.length; j >= 0; j--) { /* Need to assign beatnum to items in item2[] beatsum += c.beats; c.beatnum = sti.beat - beatsum; doFirstPass(c); // make sure child has hands assigned */ } int[][] start_state = findExitState(item2); // Next find the pattern state we need to end up at. Two cases: even number of transition beats, and odd. index = 0; done = false; for (int j = i+1; j < sti.getNumberOfChildren(); j++) { item[index++] = sti.getChild(j); if (sti.getChild(j).type == SiteswapTreeItem.TYPE_GROUPED_PATTERN) { done = true; break; } if (sti.getChild(j).type == SiteswapTreeItem.TYPE_WILDCARD) throw new JuggleExceptionUser("Can only have one wildcard between grouped patterns"); } if (!done) { for (int j = 0; j < i; j++) { SiteswapTreeItem c = sti.getChild(j); item[index++] = c; if (c.type == SiteswapTreeItem.TYPE_GROUPED_PATTERN) { done = true; break; } if (c.type == SiteswapTreeItem.TYPE_WILDCARD) throw new JuggleExceptionUser("Can only have one wildcard between grouped patterns"); } } if (!done) throw new JuggleExceptionUser("Must have at least one grouped subpattern to use wildcard"); item2 = new SiteswapTreeItem[index]; for (int j = 0; j < index; j++) item2[j] = item[j]; for (int transition_beats = 0; transition_beats < 2; transition_beats++) { for (int j = 0; j < item2.length; j++) { /* Need to assign beatnum to items in item2[] beatsum += c.beats; c.beatnum = sti.beat - beatsum; doFirstPass(c); // make sure child has hands assigned */ } int[][] finish_state = findEntranceState(item2); // Rest of stuff goes here (find transition, fill in child.transition) } } doFirstPass(child); sti.beats += child.beats; sti.throw_sum += child.throw_sum; sti.vanilla_asynch &= child.vanilla_asynch; } if (sti.switchrepeat) { sti.beats *= 2; sti.throw_sum *= 2; } break; case SiteswapTreeItem.TYPE_GROUPED_PATTERN: // Contains only a Pattern type (single child) child = sti.getChild(0); if (sti.getNumberOfChildren() > 1) { sti.removeChildren(); sti.addChild(child); } child.beatnum = sti.beatnum; doFirstPass(child); for (int i = 1; i < sti.repeats; i++) { SiteswapTreeItem child2 = (SiteswapTreeItem)(child.clone()); sti.addChild(child2); child2.beatnum = sti.beatnum + i * child.beats; doFirstPass(child2); } sti.beats = child.beats * sti.repeats; sti.throw_sum = child.throw_sum * sti.repeats; sti.vanilla_asynch &= child.vanilla_asynch; break; case SiteswapTreeItem.TYPE_SOLO_SEQUENCE: // Contains Solo Paired Throw, Solo Multi Throw, or Hand Specifier types for (int i = 0; i < sti.getNumberOfChildren(); i++) { child = sti.getChild(i); child.beatnum = sti.beatnum + child.seq_beatnum; doFirstPass(child); sti.throw_sum += child.throw_sum; sti.vanilla_asynch &= child.vanilla_asynch; } break; case SiteswapTreeItem.TYPE_SOLO_PAIRED_THROW: // Contains only Solo Multi Throw type for (int i = 0; i < sti.getNumberOfChildren(); i++) { child = sti.getChild(i); child.beatnum = sti.beatnum; doFirstPass(child); child.left = (i == 0); child.synch_throw = true; sti.throw_sum += child.throw_sum; } sti.vanilla_asynch = false; break; case SiteswapTreeItem.TYPE_SOLO_MULTI_THROW: // Contains only Solo Single Throw type for (int i = 0; i < sti.getNumberOfChildren(); i++) { child = sti.getChild(i); child.beatnum = sti.beatnum; doFirstPass(child); sti.throw_sum += child.value; } if ((sti.beatnum % 2) == 0) sti.left = !right_on_even[sti.source_juggler - 1]; else sti.left = right_on_even[sti.source_juggler - 1]; if (sti.getNumberOfChildren() > this.max_occupancy) this.max_occupancy = sti.getNumberOfChildren(); break; case SiteswapTreeItem.TYPE_SOLO_SINGLE_THROW: // No children if (sti.value > this.max_throw) this.max_throw = sti.value; break; case SiteswapTreeItem.TYPE_PASSING_SEQUENCE: // Contains only Passing Group type case SiteswapTreeItem.TYPE_PASSING_GROUP: // Contains only Passing Throws type for (int i = 0; i < sti.getNumberOfChildren(); i++) { child = sti.getChild(i); child.beatnum = sti.beatnum; doFirstPass(child); sti.throw_sum += child.throw_sum; sti.vanilla_asynch &= child.vanilla_asynch; } break; case SiteswapTreeItem.TYPE_PASSING_THROWS: // Contains Passing Paired Throw, Passing Multi Throw, or Hand Specifier types for (int i = 0; i < sti.getNumberOfChildren(); i++) { child = sti.getChild(i); child.beatnum = sti.beatnum + child.seq_beatnum; doFirstPass(child); sti.throw_sum += child.throw_sum; sti.vanilla_asynch &= child.vanilla_asynch; } break; case SiteswapTreeItem.TYPE_PASSING_PAIRED_THROW: // Contains only Passing Multi Throw type for (int i = 0; i < sti.getNumberOfChildren(); i++) { child = sti.getChild(i); child.beatnum = sti.beatnum; doFirstPass(child); child.left = (i == 0); child.synch_throw = true; sti.throw_sum += child.throw_sum; } sti.vanilla_asynch = false; break; case SiteswapTreeItem.TYPE_PASSING_MULTI_THROW: // Contains only Passing Single Throw type for (int i = 0; i < sti.getNumberOfChildren(); i++) { child = sti.getChild(i); child.beatnum = sti.beatnum; doFirstPass(child); sti.throw_sum += child.value; } if ((sti.beatnum % 2) == 0) sti.left = !right_on_even[sti.source_juggler - 1]; else sti.left = right_on_even[sti.source_juggler - 1]; if (sti.getNumberOfChildren() > this.max_occupancy) this.max_occupancy = sti.getNumberOfChildren(); break; case SiteswapTreeItem.TYPE_PASSING_SINGLE_THROW: // No children if (sti.value > this.max_throw) this.max_throw = sti.value; break; case SiteswapTreeItem.TYPE_WILDCARD: if (sti.transition != null) { sti.transition.beatnum = sti.beatnum; doFirstPass(sti.transition); // copy variables from sti.transition to sti sti.throw_sum = sti.transition.throw_sum; sti.vanilla_asynch = sti.transition.vanilla_asynch; sti.beats = sti.transition.beats; } else throw new JuggleExceptionInternal("Wildcard not resolved"); break; case SiteswapTreeItem.TYPE_HAND_SPEC: if ((sti.beatnum % 2) == 0) right_on_even[sti.source_juggler - 1] = !sti.spec_left; else right_on_even[sti.source_juggler - 1] = sti.spec_left; sti.throw_sum = 0; if (sti.beatnum > 0) sti.vanilla_asynch = false; break; } } // Second pass through the tree: // 1) Fill in the th[] array with mhnThrow objects protected void doSecondPass(SiteswapTreeItem sti, boolean switchhands, int beatoffset) throws JuggleExceptionUser { SiteswapTreeItem child = null; switch (sti.type) { case SiteswapTreeItem.TYPE_PATTERN: // Can contain Grouped_Pattern, Solo_Sequence, or Passing_Sequence for (int i = 0; i < sti.getNumberOfChildren(); i++) { child = sti.getChild(i); doSecondPass(child, switchhands, beatoffset); } if (sti.switchrepeat) { for (int i = 0; i < sti.getNumberOfChildren(); i++) { child = sti.getChild(i); doSecondPass(child, !switchhands, beatoffset + sti.beats/2); } } break; case SiteswapTreeItem.TYPE_GROUPED_PATTERN: case SiteswapTreeItem.TYPE_SOLO_SEQUENCE: case SiteswapTreeItem.TYPE_SOLO_PAIRED_THROW: case SiteswapTreeItem.TYPE_PASSING_SEQUENCE: case SiteswapTreeItem.TYPE_PASSING_GROUP: case SiteswapTreeItem.TYPE_PASSING_THROWS: case SiteswapTreeItem.TYPE_PASSING_PAIRED_THROW: for (int i = 0; i < sti.getNumberOfChildren(); i++) { child = sti.getChild(i); doSecondPass(child, switchhands, beatoffset); } break; case SiteswapTreeItem.TYPE_SOLO_MULTI_THROW: case SiteswapTreeItem.TYPE_PASSING_MULTI_THROW: int index = sti.beatnum + beatoffset; while (index < this.indexes) { for (int i = 0; i < sti.getNumberOfChildren(); i++) { child = sti.getChild(i); int source_hand; if (switchhands) source_hand = (sti.left ? RIGHT_HAND : LEFT_HAND); else source_hand = (sti.left ? LEFT_HAND : RIGHT_HAND); int dest_hand = ((child.value % 2) == 0) ? source_hand : (1-source_hand); if (child.x) dest_hand = 1 - dest_hand; String mod = child.mod; if (mod == null) { mod = "T"; // default throw modifier if ((child.source_juggler == child.dest_juggler) && (source_hand == dest_hand)) { if (child.value <= 2) // want something more sophisticated? mod = "H"; } } int dest_juggler = child.dest_juggler; if (dest_juggler > getNumberOfJugglers()) dest_juggler = 1 + (dest_juggler-1) % getNumberOfJugglers(); mhnThrow t = new mhnThrow(child.source_juggler, source_hand, index, i, dest_juggler, dest_hand, index+child.value, -1, mod); if (hands != null) { int idx = index; if (sti.synch_throw && (source_hand == RIGHT_HAND)) idx++; idx %= hands.getPeriod(child.source_juggler); t.handsindex = idx; } th[child.source_juggler-1][source_hand][index][i] = t; // System.out.println("added throw value "+child.value+" at index "+index); } index += this.period; } break; } } } jugglinglab-0.6.2+ds.1/source/jugglinglab/path/000077500000000000000000000000001323754603300212745ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/source/jugglinglab/path/Path.java000066400000000000000000000106421323754603300230360ustar00rootroot00000000000000// Path.java // // Copyright 2002 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.path; import java.util.*; import jugglinglab.util.*; public abstract class Path { // static ResourceBundle guistrings; static ResourceBundle errorstrings; static { // guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } protected double start_time, end_time; protected Coordinate start_coord = null, end_coord = null; // The built-in path types public static final String[] builtinPaths = { "Toss", "Bounce" }; // This is a factory to create Paths from names. Note the // naming convention. public static Path getPath(String name) throws JuggleExceptionUser { if (name == null) throw new JuggleExceptionUser("Prop type not specified"); try { Object obj = Class.forName("jugglinglab.path."+name.toLowerCase()+"Path").newInstance(); // if (obj == null) // throw new JuggleExceptionUser("Cannot create Path type '"+name+"'"); if (!(obj instanceof Path)) throw new JuggleExceptionUser("Path type '"+name+"' doesn't work"); return (Path)obj; } catch (ClassNotFoundException cnfe) { throw new JuggleExceptionUser("Path type '"+name+"' not found"); } catch (IllegalAccessException iae) { throw new JuggleExceptionUser("Cannot access '"+name+"' path file (security)"); } catch (InstantiationException ie) { throw new JuggleExceptionUser("Couldn't create '"+name+"' path"); } } public abstract String getName(); public abstract ParameterDescriptor[] getParameterDescriptors(); public abstract void initPath(String st) throws JuggleExceptionUser; public void setStart(Coordinate position, double time) { start_coord = position; start_time = time; } public void setEnd(Coordinate position, double time) { end_coord = position; end_time = time; } public abstract void calcPath() throws JuggleExceptionInternal; public double getStartTime() { return start_time; } public double getEndTime() { return end_time; } public double getDuration() { return (end_time-start_time); } public void translateTime(double deltat) { start_time += deltat; end_time += deltat; } // for hand layout purposes public abstract Coordinate getStartVelocity(); public abstract Coordinate getEndVelocity(); public abstract void getCoordinate(double time, Coordinate newPosition); // for screen layout purposes public Coordinate getMax() { return getMax2(start_time, end_time); } public Coordinate getMin() { return getMin2(start_time, end_time); } public Coordinate getMax(double begin, double end) { if ((end < start_time) || (begin > end_time)) return null; return getMax2(begin, end); } public Coordinate getMin(double begin, double end) { if ((end < start_time) || (begin > end_time)) return null; return getMin2(begin, end); } protected abstract Coordinate getMax2(double begin, double end); protected abstract Coordinate getMin2(double begin, double end); // utility for getMax/getMin protected Coordinate check(Coordinate result, double t, boolean findmax) { Coordinate loc = new Coordinate(0.0,0.0,0.0); this.getCoordinate(t, loc); if (findmax) result = Coordinate.max(result, loc); else result = Coordinate.min(result, loc); return result; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/path/bouncePath.java000066400000000000000000000631511323754603300242350ustar00rootroot00000000000000// bouncePath.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.path; import java.text.MessageFormat; import jugglinglab.util.*; public class bouncePath extends Path { protected static final int bounces_def = 1; // number of bounces protected static final boolean forced_def = false; protected static final boolean hyper_def = false; protected static final double bounceplane_def = 0.0; // floor level protected static final double bouncefrac_def = 0.9; protected static final double g_def = 980.0; // using CGS units protected double bx, cx; protected double by, cy; protected double az[], bz[], cz[]; protected double endtime[]; protected int bounces = bounces_def; protected boolean forced = forced_def; // true -> forced throw protected boolean hyper = hyper_def; // true -> same type of catch (lift/forced) as throw protected double bounceplane = bounceplane_def; protected double bouncefrac = bouncefrac_def; protected double g = g_def; protected double bouncefracsqrt; protected double bouncetime; protected int numbounces; // actual number of bounces (<= this.bounces) public String getName() { return "Bounce"; } public ParameterDescriptor[] getParameterDescriptors() { ParameterDescriptor[] result = new ParameterDescriptor[6]; result[0] = new ParameterDescriptor("bounces", ParameterDescriptor.TYPE_INT, null, new Integer(bounces_def), new Integer(bounces)); result[1] = new ParameterDescriptor("forced", ParameterDescriptor.TYPE_BOOLEAN, null, new Boolean(forced_def), new Boolean(forced)); result[2] = new ParameterDescriptor("hyper", ParameterDescriptor.TYPE_BOOLEAN, null, new Boolean(hyper_def), new Boolean(hyper)); result[3] = new ParameterDescriptor("bounceplane", ParameterDescriptor.TYPE_FLOAT, null, new Double(bounceplane_def), new Double(bounceplane)); result[4] = new ParameterDescriptor("bouncefrac", ParameterDescriptor.TYPE_FLOAT, null, new Double(bouncefrac_def), new Double(bouncefrac)); result[5] = new ParameterDescriptor("g", ParameterDescriptor.TYPE_FLOAT, null, new Double(g_def), new Double(g)); return result; } public void initPath(String st) throws JuggleExceptionUser { // default bounce characteristics int bounces = bounces_def; boolean forced = forced_def; boolean hyper = hyper_def; double bounceplane = bounceplane_def; double bouncefrac = bouncefrac_def; double g = g_def; // now parse for edits to the above variables ParameterList pl = new ParameterList(st); for (int i = 0; i < pl.getNumberOfParameters(); i++) { String pname = pl.getParameterName(i); String pvalue = pl.getParameterValue(i); if (pname.equalsIgnoreCase("bounces")) { try { bounces = Integer.valueOf(pvalue).intValue(); } catch (NumberFormatException nfe) { String template = errorstrings.getString("Error_number_format"); Object[] arguments = { "bounces" }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } } else if (pname.equalsIgnoreCase("forced")) { forced = Boolean.valueOf(pvalue).booleanValue(); } else if (pname.equalsIgnoreCase("hyper")) { hyper = Boolean.valueOf(pvalue).booleanValue(); } else if (pname.equalsIgnoreCase("bounceplane")) { try { bounceplane = Double.valueOf(pvalue).doubleValue(); } catch (NumberFormatException nfe) { String template = errorstrings.getString("Error_number_format"); Object[] arguments = { "bounceplane" }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } } else if (pname.equalsIgnoreCase("bouncefrac")) { try { bouncefrac = Double.valueOf(pvalue).doubleValue(); } catch (NumberFormatException nfe) { String template = errorstrings.getString("Error_number_format"); Object[] arguments = { "bouncefrac" }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } } else if (pname.equalsIgnoreCase("g")) { try { g = Double.valueOf(pvalue).doubleValue(); } catch (NumberFormatException nfe) { String template = errorstrings.getString("Error_number_format"); Object[] arguments = { "g" }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } } else throw new JuggleExceptionUser(errorstrings.getString("Error_path_badmod")+": '"+pname+"'"); } this.bounces = bounces; this.forced = forced; this.hyper = hyper; this.bounceplane = bounceplane; this.bouncefrac = bouncefrac; try { this.bouncefracsqrt = Math.sqrt(bouncefrac); } catch (ArithmeticException e) { this.bouncefracsqrt = 1.0; } this.g = g; this.az = new double[bounces + 1]; this.bz = new double[bounces + 1]; this.cz = new double[bounces + 1]; this.endtime = new double[bounces + 1]; for (int i = 0; i <= bounces; i++) az[i] = -0.5 * g; } // The next function does all the real work of figuring out the ball's // path. It solves a cubic equation to find the time when the ball hits // the ground public void calcPath() throws JuggleExceptionInternal { if ((start_coord == null) || (end_coord == null)) return; double t2 = getDuration(); // First do the x and y coordinates -- these are simple. cx = start_coord.x; bx = (end_coord.x - start_coord.x) / t2; cy = start_coord.y; by = (end_coord.y - start_coord.y) / t2; cz[0] = start_coord.z; double[] root = new double[4]; boolean[] liftcatch = new boolean[4]; int numroots; for (this.numbounces = bounces; numbounces > 0; numbounces--) { numroots = 0; double f1 = bouncefracsqrt; for (int i = 1; i < numbounces; i++) f1 *= bouncefracsqrt; double k = ((bouncefracsqrt == 1.0) ? 2.0*(double)numbounces : 1.0 + f1 + 2.0*bouncefracsqrt*(1.0-f1/bouncefracsqrt)/(1.0-bouncefracsqrt)); double u = 2.0 * this.g * (start_coord.z - bounceplane); double l = 2.0 * this.g * (end_coord.z - bounceplane); double f2 = f1 * f1; double c = u - l / f2; double kk = k * k; double gt = this.g * t2; double v0; // We are solving the following equation for v0 (the throw velocity), where // the constants are as defined above: // // gt = v0 + k*sqrt(v0^2+u) +- f1*sqrt(v0^2+c) // // The plus sign on the last term corresponds to a lift catch, and v0 > 0 // corresponds to a lift (upward) throw. When this equation is converted to a // polynomial in the usual way, the result is quartic: // // c4*v0^4 + c3*v0^3 + c2*v0^2 + c1*v0 + c0 = 0 // // When there is only one bounce, c4=0 always and we reduce to a cubic. double[] coef = new double[5]; coef[4] = 1.0 + kk*kk + f2*f2 - 2.0*kk - 2.0*f2 - 2.0*kk*f2; coef[3] = -4.0*gt + 4.0*f2*gt + 4.0*kk*gt; coef[2] = 6.0*gt*gt + 2.0*kk*kk*u + 2.0*f2*f2*c - 2.0*f2*c - 2.0*f2*gt*gt - 2.0*kk*gt*gt - 2.0*kk*u - 2.0*kk*f2*c - 2.0*kk*f2*u; coef[1] = -4.0*gt*gt*gt + 4.0*f2*gt*c + 4.0*kk*gt*u; coef[0] = gt*gt*gt*gt + kk*kk*u*u + f2*f2*c*c - 2.0*gt*gt*f2*c - 2.0*kk*gt*gt*u - 2.0*kk*f2*u*c; double[] realroot = new double[4]; int numrealroots = 0; if (numbounces > 1) { // More than one bounce, need to solve the quartic case for (int i = 0; i < 4; i++) coef[i] /= coef[4]; numrealroots = findRealRootsPolynomial(coef, 4, realroot); // numrealroots = findRealRootsQuartic(coef[0], coef[1], coef[2], coef[3], realroot); } else { // A single bounce, which reduces to a cubic polynomial (coef[4]=0) for (int i = 0; i < 3; i++) coef[i] /= coef[3]; numrealroots = findRealRootsPolynomial(coef, 3, realroot); // numrealroots = findRealRootsCubic(coef[0], coef[1], coef[2], realroot); } // Check whether the roots found are physical; due to the way the // equation was converted into a polynomial, nonphysical extra solutions // with (v0^2+c)<0 are generated. Check for these. for (int i = 0; i < numrealroots; i++) { v0 = realroot[i]; if ((v0*v0 + c) >= 0.0) { root[numroots] = v0; liftcatch[numroots] = ((gt - v0 - k*Math.sqrt(v0*v0+u)) > 0.0); numroots++; } } /* System.out.println(numroots + " roots found with "+numbounces+" bounces"); for (int i = 0; i < numroots; i++) System.out.println(" v0["+i+"] = "+root[i]+" -- "+(liftcatch[i]?"lift catch":"forced catch")); */ if (numroots == 0) continue; // no solution -> go to the next fewer number of bounces // Select which root to use. First try to get the forced and hyper values as // desired. If no solution, try to get forced, then try to get hyper as desired. boolean choseroot = false; v0 = root[0]; // default for (int i = 0; i < numroots; i++) { if ((forced && (root[i]>0.0)) || (!forced && (root[i]<0.0))) continue; if ((hyper && !(liftcatch[i]^forced)) || (!hyper && (liftcatch[i]^forced))) continue; v0 = root[i]; choseroot = true; break; } if (!choseroot) { for (int i = 0; i < numroots; i++) { if ((forced && (root[i]>0.0)) || (!forced && (root[i]<0.0))) continue; v0 = root[i]; choseroot = true; break; } } if (!choseroot) { for (int i = 0; i < numroots; i++) { if ((hyper && !(liftcatch[i]^(root[i]<0.0))) || (!hyper && (liftcatch[i]^(root[i]<0.0)))) continue; v0 = root[i]; choseroot = true; break; } } /* double lhs = gt - v0 - k*Math.sqrt(v0*v0+u); double rhs = f1 * Math.sqrt(v0*v0+c); System.out.println("Using root v0 = "+v0+" -- lhs = "+lhs+", rhs = "+rhs); */ // finally, set the remaining path variables based on our solution of v0 bz[0] = v0; if (az[0] < 0.0) endtime[0] = (-v0 - Math.sqrt(v0*v0 - 4.0*az[0]*(cz[0]-bounceplane))) / (2.0*az[0]); else endtime[0] = (-v0 + Math.sqrt(v0*v0 - 4.0*az[0]*(cz[0]-bounceplane))) / (2.0*az[0]); double vrebound = (-v0 - 2.0*az[0]*endtime[0])*bouncefracsqrt; for (int i = 1; i <= numbounces; i++) { bz[i] = vrebound - 2.0*az[i]*endtime[i-1]; cz[i] = bounceplane - az[i]*endtime[i-1]*endtime[i-1] - bz[i]*endtime[i-1]; endtime[i] = endtime[i-1] - vrebound / az[i]; vrebound = bouncefracsqrt * vrebound; } endtime[numbounces] = getDuration(); // fix this assignment from the above loop return; } throw new JuggleExceptionInternal("No root found in bouncePath"); } public Coordinate getStartVelocity() { return new Coordinate(bx, by, bz[0]); } public Coordinate getEndVelocity() { return new Coordinate(bx, by, bz[numbounces] + 2.0*az[numbounces]*(end_time-start_time)); } public void getCoordinate(double time, Coordinate newPosition) { if ((time < start_time) || (time > end_time)) return; time -= start_time; double zpos = 0.0; for (int i = 0; i <= numbounces; i++) { if ((time < endtime[i]) || (i == numbounces)) { zpos = cz[i] + time*(bz[i] + az[i]*time); break; } } newPosition.setCoordinate(cx+bx*time, cy+by*time, zpos); } protected Coordinate getMax2(double start, double end) { Coordinate result = null; double tlow = Math.max(start_time, start); double thigh = Math.min(end_time, end); result = check(result, tlow, true); result = check(result, thigh, true); if (az[0] < 0.0) { double te = -bz[0] / (2.0*az[0]) + start_time; if ((tlow < te) && (te < Math.min(thigh, start_time+endtime[0]))) result = check(result, te, true); } if (az[numbounces] < 0.0) { double te = -bz[numbounces] / (2.0*az[numbounces]) + start_time; if ((Math.max(tlow,start_time+endtime[numbounces-1]) < te) && (te < thigh)) result = check(result, te, true); } if ((tlow < (start_time+endtime[0])) && ((start_time+endtime[0]) < thigh)) result = check(result, start_time+endtime[0], true); for (int i = 1; i < numbounces; i++) { if (az[i] < 0.0) { double te = -bz[i] / (2.0*az[i]) + start_time; if ((Math.max(tlow,start_time+endtime[i-1]) < te) && (te < Math.min(thigh, start_time+endtime[i]))) result = check(result, te, true); } if ((tlow < (start_time+endtime[i])) && ((start_time+endtime[i]) < thigh)) result = check(result, start_time+endtime[i], true); } return result; } protected Coordinate getMin2(double start, double end) { Coordinate result = null; double tlow = Math.max(start_time, start); double thigh = Math.min(end_time, end); result = check(result, tlow, false); result = check(result, thigh, false); if (az[0] > 0.0) { double te = -bz[0] / (2.0*az[0]) + start_time; if ((tlow < te) && (te < Math.min(thigh, start_time+endtime[0]))) result = check(result, te, false); } if (az[numbounces] > 0.0) { double te = -bz[numbounces] / (2.0*az[numbounces]) + start_time; if ((Math.max(tlow,start_time+endtime[numbounces-1]) < te) && (te < thigh)) result = check(result, te, false); } if ((tlow < (start_time+endtime[0])) && ((start_time+endtime[0]) < thigh)) result = check(result, start_time+endtime[0], false); for (int i = 1; i < numbounces; i++) { if (az[i] > 0.0) { double te = -bz[i] / (2.0*az[i]) + start_time; if ((Math.max(tlow,start_time+endtime[i-1]) < te) && (te < Math.min(thigh, start_time+endtime[i]))) result = check(result, te, false); } if ((tlow < (start_time+endtime[i])) && ((start_time+endtime[i]) < thigh)) result = check(result, start_time+endtime[i], false); } return result; } /* // Find the real roots of the polynomial equation x^3 + k2*x^2 + k1*x + k0 = 0 // // Algorithm adapted from Numerical Recipes in C (1st edition), page 157 static protected int findRealRootsCubic(double k0, double k1, double k2, double[] roots) { double q = k2*k2/9.0 - k1/3.0; double r = k2*k2*k2/27.0 - k1*k2/6.0 + k0/2.0; double D = r*r - q*q*q; if (D > 0.0) { // one real root double k = Math.pow(Math.sqrt(D) + Math.abs(r), 1.0/3.0); roots[0] = ((r>0.0) ? -(k+q/k) : (k+q/k)) - k2/3.0; return 1; } else { // three real roots double theta = Math.acos(r / Math.sqrt(q*q*q)) / 3.0; double k = -2.0 * Math.sqrt(q); double p = 2.0 * Math.PI / 3.0; roots[0] = k * Math.cos(theta) - k2/3.0; roots[1] = k * Math.cos(theta + p) - k2/3.0; roots[2] = k * Math.cos(theta + 2.0*p) - k2/3.0; return 3; } } // The problem with this routine is that we don't know it will return all // real roots. There may be cases where R and sqrt(A+-B) are both imaginary // and the imaginary parts cancel. static protected int findRealRootsQuartic(double k0, double k1, double k2, double k3, double[] roots) { // first solve ancillary cubic problem double m2 = -k2; double m1 = k1*k3 - 4.0*k0; double m0 = 4.0*k2*k0 - k1*k1 - k3*k3*k0; double[] realroots = new double[3]; findRealRootsCubic(m0, m1, m2, realroots); double Rsq = 0.25*k3*k3 - k2 + realroots[0]; if (Rsq < 0.0) return 0; // no real roots int numroots = 0; double R = Math.sqrt(Rsq); double A = 0.75*k3*k3 - Rsq - 2.0*k2; double B = 0.25*(4.0*k3*k2 - 8.0*k1 - k3*k3*k3) / R; if ((A+B) >= 0.0) { roots[numroots++] = -0.25*k3 + 0.5*R + 0.5*Math.sqrt(A+B); roots[numroots++] = -0.25*k3 + 0.5*R - 0.5*Math.sqrt(A+B); } if ((A-B) >= 0.0) { roots[numroots++] = -0.25*k3 - 0.5*R + 0.5*Math.sqrt(A-B); roots[numroots++] = -0.25*k3 - 0.5*R - 0.5*Math.sqrt(A-B); } return numroots; } */ static protected double evalPolynomial(double[] coef, int degree, double x) { double result = coef[0]; double term = x; for (int i = 1; i < degree; i++) { result += coef[i] * term; term *= x; } return (result + term); // add on x^n term } // returns other endpoint of interval static protected double bracketOpenInterval(double[] coef, int degree, double endpoint, boolean pinf) { boolean endpointpositive = (evalPolynomial(coef, degree, endpoint) > 0.0); double result = endpoint; double adder = (pinf ? 1.0 : -1.0); do { result += adder; adder *= 2.0; } while ((evalPolynomial(coef, degree, result) > 0.0) == endpointpositive); return result; } // Find roots of polynomial by successive bisection static protected double findRoot(double[] coef, int degree, double xlow, double xhigh) { double val1, val2, valtemp, t; val1 = evalPolynomial(coef, degree, xlow); val2 = evalPolynomial(coef, degree, xhigh); if (val1*val2 > 0.0) return 0.5*(xlow+xhigh); // should never happen! while (Math.abs(xlow-xhigh) > 1e-6) { t = 0.5*(xlow+xhigh); valtemp = evalPolynomial(coef, degree, t); if (valtemp*val1 > 0.0) { xlow = t; val1 = valtemp; } else { xhigh = t; val2 = valtemp; } } return xlow; } // Find real roots of the polynomial expression: // c0 + c1*x + c2*x^2 + ... + c(n-1)*x^(n-1) + x^n = 0 // // where 'n' is the degree of the polynomial, and the x^n coefficient is always 1.0. // The c's are passed in as the 'coef' array static protected int findRealRootsPolynomial(double[] coef, int degree, double[] result) { // First a few special cases: if (degree == 0) { return 0; } else if (degree == 1) { result[0] = -coef[0]; return 1; } else if (degree == 2) { // Quadratic formula with a=1.0 double D = coef[1]*coef[1] - 4.0*coef[0]; if (D < 0.0) { return 0; } else if (D == 0.0) { result[0] = -0.5*coef[1]; return 1; } else { double t = Math.sqrt(D); result[0] = -0.5*(coef[1] + t); result[1] = -0.5*(coef[1] - t); return 2; } } else if (degree == 3) { // Algorithm adapted from Numerical Recipes in C (1st edition), page 157 double q = coef[2]*coef[2]/9.0 - coef[1]/3.0; double r = coef[2]*coef[2]*coef[2]/27.0 - coef[1]*coef[2]/6.0 + coef[0]/2.0; double D = r*r - q*q*q; if (D > 0.0) { // one real root double k = Math.pow(Math.sqrt(D) + Math.abs(r), 1.0/3.0); result[0] = ((r>0.0) ? -(k+q/k) : (k+q/k)) - coef[2]/3.0; return 1; } else { // three real roots double theta = Math.acos(r / Math.sqrt(q*q*q)) / 3.0; double k = -2.0 * Math.sqrt(q); double p = 2.0 * Math.PI / 3.0; result[0] = k * Math.cos(theta) - coef[2]/3.0; result[1] = k * Math.cos(theta + p) - coef[2]/3.0; result[2] = k * Math.cos(theta + 2.0*p) - coef[2]/3.0; return 3; } } // We have degree>=4, so the special cases don't apply. We proceed by finding // the extrema of our polynomial, and using these to bracket each zero. double[] dcoef = new double[degree-1]; double[] extremum = new double[degree-1]; for (int i = 0; i < (degree-1); i++) dcoef[i] = (i+1)*coef[i+1] / (double)degree; int numextrema = findRealRootsPolynomial(dcoef, degree-1, extremum); boolean pinfpositive = true; boolean minfpositive = ((degree % 2) == 0); int numroots = 0; if (numextrema == 0) { boolean zeropositive = (coef[0] > 0.0); if (zeropositive != pinfpositive) { double endpoint2 = bracketOpenInterval(coef, degree, 0.0, true); result[numroots++] = findRoot(coef, degree, 0.0, endpoint2); } if (zeropositive != minfpositive) { double endpoint2 = bracketOpenInterval(coef, degree, 0.0, false); result[numroots++] = findRoot(coef, degree, endpoint2, 0.0); } return numroots; } // Sort the extrema using a bubble sort for (int i = 0; i < numextrema; i++) { for (int j = i; j < numextrema; j++) { if (extremum[i] > extremum[j]) { double temp = extremum[i]; extremum[i] = extremum[j]; extremum[j] = temp; } } } boolean[] extremumpositive = new boolean[numextrema]; for (int i = 0; i < numextrema; i++) extremumpositive[i] = (evalPolynomial(coef, degree, extremum[i]) > 0.0); if (minfpositive != extremumpositive[0]) { // there is a zero left of the first extremum; bracket it and find it double endpoint2 = bracketOpenInterval(coef, degree, extremum[0], false); result[numroots++] = findRoot(coef, degree, endpoint2, extremum[0]); } for (int i = 0; i < (numextrema-1); i++) { if (extremumpositive[i] != extremumpositive[i+1]) { result[numroots++] = findRoot(coef, degree, extremum[i], extremum[i+1]); } } if (pinfpositive != extremumpositive[numextrema-1]) { // there is a zero right of the last extremum; bracket it and find it double endpoint2 = bracketOpenInterval(coef, degree, extremum[numextrema-1], true); result[numroots++] = findRoot(coef, degree, extremum[numextrema-1], endpoint2); } return numroots; } // The returned quantity isn't actually used for volume, so just treat it as yes/no public double getBounceVolume(double time1, double time2) { if ((time2 < start_time) || (time1 > end_time)) return 0.0; time1 -= start_time; time2 -= start_time; for (int i = 0; i < numbounces; i++) { if (time1 < endtime[i]) { if (time2 > endtime[i]) return 1.0; return 0.0; } } return 0.0; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/path/tossPath.java000066400000000000000000000105331323754603300237460ustar00rootroot00000000000000// tossPath.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.path; import java.text.MessageFormat; import jugglinglab.util.*; public class tossPath extends Path { protected static final double g_def = 980; // using CGS units protected double bx, cx; protected double by, cy; protected double az, bz, cz; protected double g = g_def; public String getName() { return "Toss"; } public ParameterDescriptor[] getParameterDescriptors() { ParameterDescriptor[] result = new ParameterDescriptor[1]; result[0] = new ParameterDescriptor("g", ParameterDescriptor.TYPE_FLOAT, null, new Double(g_def), new Double(g)); return result; } public void initPath(String st) throws JuggleExceptionUser { double g = g_def; // now parse for edits to the above variables ParameterList pl = new ParameterList(st); for (int i = 0; i < pl.getNumberOfParameters(); i++) { String pname = pl.getParameterName(i); String pvalue = pl.getParameterValue(i); if (pname.equalsIgnoreCase("g")) { try { g = Double.valueOf(pvalue).doubleValue(); } catch (NumberFormatException nfe) { String template = errorstrings.getString("Error_number_format"); Object[] arguments = { "g" }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } } else throw new JuggleExceptionUser(errorstrings.getString("Error_path_badmod")+": '"+pname+"'"); } this.g = g; az = -0.5 * g; } public void calcPath() throws JuggleExceptionInternal { if (start_coord == null || end_coord == null) throw new JuggleExceptionInternal("Error in parabolic path: endpoints not set"); double t = getDuration(); cx = start_coord.x; bx = (end_coord.x - start_coord.x) / t; cy = start_coord.y; by = (end_coord.y - start_coord.y) / t; cz = start_coord.z; bz = (end_coord.z - start_coord.z) / t - az * t; } public Coordinate getStartVelocity() { return new Coordinate(bx, by, bz); } public Coordinate getEndVelocity() { return new Coordinate(bx, by, bz+2.0*az*getDuration()); } public void getCoordinate(double time, Coordinate newPosition) { if ((time < start_time) || (time > end_time)) return; time -= start_time; newPosition.setCoordinate(cx+bx*time, cy+by*time, cz+time*(bz+az*time)); } protected Coordinate getMax2(double begin, double end) { Coordinate result = null; double tlow = Math.max(start_time, begin); double thigh = Math.min(end_time, end); result = check(result, tlow, true); result = check(result, thigh, true); if (az < 0.0) { double te = -bz / (2.0*az) + start_time; if ((tlow < te) && (te < thigh)) result = check(result, te, true); } return result; } protected Coordinate getMin2(double begin, double end) { Coordinate result = null; double tlow = Math.max(start_time, begin); double thigh = Math.min(end_time, end); result = check(result, tlow, false); result = check(result, thigh, false); if (az > 0.0) { double te = -by / (2.0*az) + start_time; if ((tlow < te) && (te < thigh)) result = check(result, te, false); } return result; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/prop/000077500000000000000000000000001323754603300213205ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/source/jugglinglab/prop/Prop.java000077500000000000000000000054151323754603300231130ustar00rootroot00000000000000// Prop.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.prop; import java.awt.*; import java.util.*; import java.text.MessageFormat; import jugglinglab.util.*; import jugglinglab.renderer.*; public abstract class Prop { static ResourceBundle guistrings; static ResourceBundle errorstrings; static { guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } protected String initString; public static final String[] builtinProps = { "Ball", "Image", "Ring" }; public static Prop getProp(String name) throws JuggleExceptionUser { try { Object obj = Class.forName("jugglinglab.prop."+name.toLowerCase()+"Prop").newInstance(); if (obj instanceof Prop) return (Prop)obj; } catch (ClassNotFoundException cnfe) { } catch (IllegalAccessException iae) { } catch (InstantiationException ie) { } String template = errorstrings.getString("Error_prop_type"); Object[] arguments = { name }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } public abstract String getName(); public abstract Color getEditorColor(); public abstract ParameterDescriptor[] getParameterDescriptors(); public void initProp(String st) throws JuggleExceptionUser { initString = st; this.init(st); } protected abstract void init(String st) throws JuggleExceptionUser; public abstract Coordinate getMax(); public abstract Coordinate getMin(); public abstract Image getProp2DImage(Component comp, double zoom, double[] camangle); public abstract Dimension getProp2DSize(Component comp, double zoom); public abstract Dimension getProp2DCenter(Component comp, double zoom); public abstract Dimension getProp2DGrip(Component comp, double zoom); /* public abstract Object getPropIDX3D(); public abstract Coordinate getPropIDX3DGrip(); */ } jugglinglab-0.6.2+ds.1/source/jugglinglab/prop/ballProp.java000077500000000000000000000254611323754603300237510ustar00rootroot00000000000000// ballProp.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.prop; import java.util.*; import java.awt.*; import java.awt.image.*; import java.lang.reflect.*; import java.text.MessageFormat; import jugglinglab.core.*; import jugglinglab.util.*; import jugglinglab.renderer.*; public class ballProp extends Prop { static String[] colornames = {"black", "blue", "cyan", "gray", "green", "magenta", "orange", "pink", "red", "white", "yellow"}; static Color[] colorvals = {Color.black, Color.blue, Color.cyan, Color.gray, Color.green, Color.magenta, Color.orange, Color.pink, Color.red, Color.white, Color.yellow}; protected static final int colornum_def = 8; // red protected static final double diam_def = 10.0; // in cm protected static final boolean highlight_def = false; protected double diam = diam_def; // diameter, in cm protected int colornum = colornum_def; protected Color color; protected boolean highlight = highlight_def; // protected int ball_pixel_size; protected Image ballimage; protected double lastzoom = 0.0; // protected int offsetx, offsety; protected Dimension size = null; protected Dimension center = null; protected Dimension grip = null; public String getName() { return "Ball"; } public Color getEditorColor() { return color; } public ParameterDescriptor[] getParameterDescriptors() { ParameterDescriptor[] result = new ParameterDescriptor[3]; Vector range = new Vector(); for (int i = 0; i < colornames.length; i++) range.add(colornames[i]); result[0] = new ParameterDescriptor("color", ParameterDescriptor.TYPE_CHOICE, range, colornames[colornum_def], colornames[colornum]); result[1] = new ParameterDescriptor("diam", ParameterDescriptor.TYPE_FLOAT, null, new Double(diam_def), new Double(diam)); result[2] = new ParameterDescriptor("highlight", ParameterDescriptor.TYPE_BOOLEAN, null, new Boolean(highlight_def), new Boolean(highlight)); return result; } protected void init(String st) throws JuggleExceptionUser { color = Color.red; if (st == null) return; ParameterList pl = new ParameterList(st); String colorstr = pl.getParameter("color"); if (colorstr != null) { Color temp = null; if (colorstr.indexOf((int)',') == -1) { // color name for (int i = 0; i < colornames.length; i++) { if (colornames[i].equalsIgnoreCase(colorstr)) { temp = colorvals[i]; colornum = i; break; } } } else { // RGB triplet // delete the '{' and '}' characters first String str = colorstr; int pos; while ((pos = str.indexOf('{')) >= 0) { str = str.substring(0,pos) + str.substring(pos+1,str.length()); } while ((pos = str.indexOf('}')) >= 0) { str = str.substring(0,pos) + str.substring(pos+1,str.length()); } StringTokenizer st2 = new StringTokenizer(str, ",", false); if (st2.countTokens() == 3) { int red = 0, green = 0, blue = 0; String token = null; try { token = st2.nextToken(); red = Integer.valueOf(token).intValue(); token = st2.nextToken(); green = Integer.valueOf(token).intValue(); token = st2.nextToken(); blue = Integer.valueOf(token).intValue(); } catch (NumberFormatException nfe) { String template = errorstrings.getString("Error_number_format"); Object[] arguments = { token }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } temp = new Color(red, green, blue); } else throw new JuggleExceptionUser(errorstrings.getString("Error_token_count")); } if (temp != null) color = temp; else { String template = errorstrings.getString("Error_prop_color"); Object[] arguments = { colorstr }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } } String diamstr = pl.getParameter("diam"); if (diamstr != null) { try { Double ddiam = Double.valueOf(diamstr); double temp = ddiam.doubleValue(); if (temp > 0.0) diam = temp; else throw new JuggleExceptionUser(errorstrings.getString("Error_prop_diameter")); } catch (NumberFormatException nfe) { String template = errorstrings.getString("Error_number_format"); Object[] arguments = { "diam" }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } } String highlightstr = pl.getParameter("highlight"); if (highlightstr != null) { Boolean bhighlight = Boolean.valueOf(highlightstr); highlight = bhighlight.booleanValue(); } } public Coordinate getMax() { return new Coordinate(diam/2,0,diam/2); } public Coordinate getMin() { return new Coordinate(-diam/2,0,-diam/2); } public Image getProp2DImage(Component comp, double zoom, double[] camangle) { if ((ballimage == null) || (zoom != lastzoom)) // first call or display resized? recalc2D(comp, zoom); return ballimage; } public Dimension getProp2DSize(Component comp, double zoom) { if ((size == null) || (zoom != lastzoom)) // first call or display resized? recalc2D(comp, zoom); return size; } public Dimension getProp2DCenter(Component comp, double zoom) { if ((center == null) || (zoom != lastzoom)) recalc2D(comp, zoom); return center; } public Dimension getProp2DGrip(Component comp, double zoom) { if ((grip == null) || (zoom != lastzoom)) // first call or display resized? recalc2D(comp, zoom); return grip; } protected void recalc2D(Component comp, double zoom) { int ball_pixel_size = (int)(0.5 + zoom * diam); if (ball_pixel_size < 1) ball_pixel_size = 1; int offsetx = -ball_pixel_size / 2; int offsety = -ball_pixel_size; // Now we should create a ball image of diameter ball_pixel_size // pixels and put it in the variable ballimage. First try making a // ball with a transparent background. ballimage = VersionSpecific.getVersionSpecific().makeImage(comp, ball_pixel_size+1, ball_pixel_size+1); Graphics ballg = ballimage.getGraphics(); VersionSpecific.getVersionSpecific().setAntialias(ballg); if (this.highlight) { float highlightOvals = ball_pixel_size / 1.2f; // Number of concentric circles to draw. float[] rgb = new float[3]; rgb[0] = (float)color.getRed() / 255f; rgb[1] = (float)color.getGreen() / 255f; rgb[2] = (float)color.getBlue() / 255f; // Make the color a little darker so that there is some contrast. for (int i = 0; i < rgb.length; i++) { rgb[i] = rgb[i] / 2.5f; } ballg.setColor(new Color(rgb[0], rgb[1], rgb[2])); ballg.fillOval(0, 0, ball_pixel_size, ball_pixel_size); // Full sized ellipse. // Now draw the highlight on the ball. for (int i = 0; i < highlightOvals; i++) { // Calculate the new color for (int j = 0; j < rgb.length; j++) { rgb[j] = Math.min(rgb[j] + (1f / highlightOvals), 1f); } ballg.setColor(new Color(rgb[0], rgb[1], rgb[2])); ballg.fillOval((int)(i/1.1), (int)(i/2.5), // Literals control how fast highlight // moves right and down respectively. ball_pixel_size - (int)(i*1.3), // These control how fast the ball_pixel_size - (int)(i*1.3)); // highlight converges to a point. } } else { ballg.setColor(color); ballg.fillOval(0, 0, ball_pixel_size, ball_pixel_size); } size = new Dimension(ball_pixel_size, ball_pixel_size); center = new Dimension(ball_pixel_size/2, ball_pixel_size/2); grip = new Dimension(ball_pixel_size/2, ball_pixel_size/2); lastzoom = zoom; } /* public Object getPropIDX3D() { Object result = null; try { Class ob = Class.forName("idx3d.idx3d_Object"); Class of = Class.forName("idx3d.idx3d_ObjectFactory"); Class mat = Class.forName("idx3d.idx3d_Material"); Method sphere = of.getMethod("SPHERE", new Class[] {Float.TYPE, Integer.TYPE}); result = sphere.invoke(null, new Object[] {new Float((float)diam/2), new Integer(10)}); Method setcolor = mat.getMethod("setColor", new Class[] {Integer.TYPE}); Object surf = mat.newInstance(); setcolor.invoke(surf, new Object[] {new Integer(color.getRGB())}); Method setmaterial = ob.getMethod("setMaterial", new Class[] {mat}); setmaterial.invoke(result, new Object[] {surf}); } catch (ClassNotFoundException e) { return null; } catch (NoSuchMethodException e) { return null; } catch (SecurityException e) { return null; } catch (IllegalAccessException e) { return null; } catch (InstantiationException e) { return null; } catch (InvocationTargetException e) { return null; } return result; } public Coordinate getPropIDX3DGrip() { return new Coordinate(0.0, 0.0, -diam/2); // bottom of ball } */ } jugglinglab-0.6.2+ds.1/source/jugglinglab/prop/imageProp.java000066400000000000000000000210171323754603300241070ustar00rootroot00000000000000// imageProp.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.prop; import java.awt.*; import java.util.*; import javax.swing.*; import java.awt.image.*; import java.awt.image.ImageObserver.*; import java.net.*; import java.io.*; import java.lang.reflect.*; import java.text.MessageFormat; import jugglinglab.util.*; import jugglinglab.renderer.*; import jugglinglab.core.*; public class imageProp extends Prop { private URL url_def; private URL url; private Image image; private Image scaled_image; private final float width_def = 10f; // in cm private float height_def; // The default height is whatever preserves the proper aspect // We have to load the image to determine it private float width; private float height; private Dimension size = null; private Dimension center = null; private Dimension grip = null; private double last_zoom = 0; public imageProp() throws JuggleExceptionUser { VersionSpecific vs = VersionSpecific.getVersionSpecific(); url_def = vs.getDefaultPropImage(); url = url_def; loadImage(); rescaleImage(1.0); } private void loadImage() throws JuggleExceptionUser { // We should probably get the real component that this image wants to be // drawn on, but it doesn't really seem to matter much. try { MediaTracker mt = new MediaTracker(new JPanel()); image = Toolkit.getDefaultToolkit().getImage(url); mt.addImage(image, 0); // Try to laod the image try { mt.waitForAll(); } catch (InterruptedException ex) {} if (mt.isErrorAny()) { image = null; // This could also be bad image data, but it is usually a nonexistent file. throw new JuggleExceptionUser(errorstrings.getString("Error_bad_file")); } float aspectRatio = ((float)image.getHeight(null))/((float)image.getWidth(null)); this.height_def = this.width_def * aspectRatio; this.width = width_def; this.height = height_def; } catch (SecurityException se) { throw new JuggleExceptionUser(errorstrings.getString("Error_security_restriction")); } } private void rescaleImage(double zoom) { int image_pixel_width = (int)(0.5 + zoom * width); if (image_pixel_width < 1) image_pixel_width = 1; int image_pixel_height = (int)(0.5 + zoom * height); if (image_pixel_height < 1) image_pixel_height = 1; size = new Dimension(image_pixel_width, image_pixel_height); center = new Dimension(image_pixel_width/2, image_pixel_height/2); int offsetx = image_pixel_width / 2; int offsety = image_pixel_height; grip = new Dimension(offsetx, offsety); last_zoom = zoom; scaled_image = image.getScaledInstance(image_pixel_width, image_pixel_height, Image.SCALE_SMOOTH); } public String getName() { return "Image"; } public Color getEditorColor() { // The color that shows up in the visual editor // We could try to get an average color for the image return Color.white; } public ParameterDescriptor[] getParameterDescriptors() { ParameterDescriptor[] result = new ParameterDescriptor[2]; result[0] = new ParameterDescriptor("image", ParameterDescriptor.TYPE_ICON, null, url_def, url); result[1] = new ParameterDescriptor("width", ParameterDescriptor.TYPE_FLOAT, null, new Double(width_def), new Double(width)); //result[2] = new ParameterDescriptor("height", ParameterDescriptor.TYPE_INT, // null, new Integer(height_def), new Integer(height)); return result; } protected void init(String st) throws JuggleExceptionUser { if (st == null) return; ParameterList pl = new ParameterList(st); String sourcestr = pl.getParameter("image"); if (sourcestr != null) { try { this.url = new URL(sourcestr); loadImage(); } catch (MalformedURLException ex) { throw new JuggleExceptionUser(errorstrings.getString("Error_malformed_URL")); } } String widthstr = pl.getParameter("width"); if (widthstr != null) { try { Float width = Float.valueOf(widthstr); float temp = width.floatValue(); if (temp > 0) { this.width = temp; float aspectRatio = ((float)image.getHeight(null))/((float)image.getWidth(null)); this.height = this.width * aspectRatio; } else throw new NumberFormatException(); } catch (NumberFormatException nfe) { String template = errorstrings.getString("Error_number_format"); Object[] arguments = { "width" }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } } /*String heightstr = pl.getParameter("height"); if (heightstr != null) { try { Integer height = Integer.valueOf(heightstr); int temp = height.intValue(); if (temp > 0) this.height = temp; else throw new NumberFormatException(); } catch (NumberFormatException nfe) { String template = errorstrings.getString("Error_number_format"); Object[] arguments = { "height" }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } }*/ } public Image getProp2DImage(Component comp, double zoom, double[] camangle) { if (zoom != last_zoom) rescaleImage(zoom); return scaled_image; } // Copied from ball public Coordinate getMax() { return new Coordinate(width/2, 0.0, width); } public Coordinate getMin() { return new Coordinate(-width/2, 0.0, 0.0); } public Dimension getProp2DSize(Component comp, double zoom) { if ((size == null) || (zoom != last_zoom)) rescaleImage(zoom); return size; } public Dimension getProp2DCenter(Component comp, double zoom) { if ((center == null) || (zoom != last_zoom)) rescaleImage(zoom); return center; } public Dimension getProp2DGrip(Component comp, double zoom) { if ((grip == null) || (zoom != last_zoom)) rescaleImage(zoom); return grip; } /* public Object getPropIDX3D() { Object result = null; try { Class ob = Class.forName("idx3d.idx3d_Object"); Class of = Class.forName("idx3d.idx3d_ObjectFactory"); Class mat = Class.forName("idx3d.idx3d_Material"); Class tex = Class.forName("idx3d.idx3d_Texture"); Method sphere = of.getMethod("CUBE", new Class[] {Float.TYPE}); result = sphere.invoke(null, new Object[] {new Float((float)Math.max(width, height))}); Constructor texcons = tex.getConstructor(new Class[] {Class.forName("java.awt.Image")}); Object texture = texcons.newInstance(new Object[] {image}); Object surf = mat.newInstance(); Method settexture = mat.getMethod("setTexture", new Class[] {tex}); settexture.invoke(surf, new Object[] {texture}); Method setmaterial = ob.getMethod("setMaterial", new Class[] {mat}); setmaterial.invoke(result, new Object[] {surf}); } catch (ClassNotFoundException e) { System.err.println("ClassNotFound"); return null; } catch (NoSuchMethodException e) { System.err.println("NoSuchMethod"); return null; } catch (SecurityException e) { return null; } catch (IllegalAccessException e) { return null; } catch (InstantiationException e) { System.err.println("Instantiation"); return null; } catch (InvocationTargetException e) { System.err.println("InvocationTarget"); return null; } return result; } public Coordinate getPropIDX3DGrip() { return new Coordinate(0.0, 0.0, -height/2); // bottom of cube } */ }jugglinglab-0.6.2+ds.1/source/jugglinglab/prop/ringProp.java000077500000000000000000000302351323754603300237710ustar00rootroot00000000000000// ringProp.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.prop; import java.util.*; import java.awt.*; import java.awt.image.*; import java.lang.reflect.*; import java.text.MessageFormat; import jugglinglab.core.*; import jugglinglab.util.*; import jugglinglab.renderer.*; public class ringProp extends Prop { static String[] colornames = {"black", "blue", "cyan", "gray", "green", "magenta", "orange", "pink", "red", "white", "yellow"}; static Color[] colorvals = {Color.black, Color.blue, Color.cyan, Color.gray, Color.green, Color.magenta, Color.orange, Color.pink, Color.red, Color.white, Color.yellow}; protected static final int colornum_def = 8; // red protected static final double outside_diam_def = 25.0; // in cm protected static final double inside_diam_def = 20.0; // in cm protected double outside_diam = outside_diam_def; protected double inside_diam = inside_diam_def; protected int colornum = colornum_def; protected Color color; protected Image image; protected double lastzoom = 0.0; protected double[] lastcamangle = {0.0, 0.0}; protected Dimension size = null; protected Dimension center = null; protected Dimension grip = null; int polysides = 200; int[] px, py; public String getName() { return "Ring"; } public Color getEditorColor() { return color; } public ParameterDescriptor[] getParameterDescriptors() { ParameterDescriptor[] result = new ParameterDescriptor[3]; Vector range = new Vector(); for (int i = 0; i < colornames.length; i++) range.add(colornames[i]); result[0] = new ParameterDescriptor("color", ParameterDescriptor.TYPE_CHOICE, range, colornames[colornum_def], colornames[colornum]); result[1] = new ParameterDescriptor("outside", ParameterDescriptor.TYPE_FLOAT, null, new Double(outside_diam_def), new Double(outside_diam)); result[2] = new ParameterDescriptor("inside", ParameterDescriptor.TYPE_FLOAT, null, new Double(inside_diam_def), new Double(inside_diam)); return result; } protected void init(String st) throws JuggleExceptionUser { px = new int[polysides]; py = new int[polysides]; color = Color.red; if (st == null) return; ParameterList pl = new ParameterList(st); String colorstr = pl.getParameter("color"); if (colorstr != null) { Color temp = null; if (colorstr.indexOf((int)',') == -1) { // color name for (int i = 0; i < colornames.length; i++) { if (colornames[i].equalsIgnoreCase(colorstr)) { temp = colorvals[i]; colornum = i; break; } } } else { // RGB triplet // delete the '{' and '}' characters first String str = colorstr; int pos; while ((pos = str.indexOf('{')) >= 0) { str = str.substring(0,pos) + str.substring(pos+1,str.length()); } while ((pos = str.indexOf('}')) >= 0) { str = str.substring(0,pos) + str.substring(pos+1,str.length()); } int red = 0, green = 0, blue = 0; StringTokenizer st2 = new StringTokenizer(str, ",", false); if (st2.hasMoreTokens()) red = Integer.valueOf(st2.nextToken()).intValue(); if (st2.hasMoreTokens()) green = Integer.valueOf(st2.nextToken()).intValue(); if (st2.hasMoreTokens()) blue = Integer.valueOf(st2.nextToken()).intValue(); temp = new Color(red, green, blue); } if (temp != null) color = temp; else { String template = errorstrings.getString("Error_prop_color"); Object[] arguments = { colorstr }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } } String outsidestr = pl.getParameter("outside"); if (outsidestr != null) { try { Double ddiam = Double.valueOf(outsidestr); double temp = ddiam.doubleValue(); if (temp > 0.0) outside_diam = temp; else throw new JuggleExceptionUser(errorstrings.getString("Error_prop_diameter")); } catch (NumberFormatException nfe) { String template = errorstrings.getString("Error_number_format"); Object[] arguments = { "diam" }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } } String insidestr = pl.getParameter("inside"); if (insidestr != null) { try { Double ddiam = Double.valueOf(insidestr); double temp = ddiam.doubleValue(); if (temp > 0.0) inside_diam = temp; else throw new JuggleExceptionUser(errorstrings.getString("Error_prop_diameter")); } catch (NumberFormatException nfe) { String template = errorstrings.getString("Error_number_format"); Object[] arguments = { "diam" }; throw new JuggleExceptionUser(MessageFormat.format(template, arguments)); } } } public Coordinate getMax() { return new Coordinate(outside_diam/2, 0, outside_diam/2); } public Coordinate getMin() { return new Coordinate(-outside_diam/2, 0, -outside_diam/2); } public Image getProp2DImage(Component comp, double zoom, double[] camangle) { if ((image == null) || (zoom != lastzoom) || (camangle[0] != lastcamangle[0]) || (camangle[1] != lastcamangle[1])) // first call or display resized? redrawImage(comp, zoom, camangle); return image; } public Dimension getProp2DSize(Component comp, double zoom) { if ((size == null) || (zoom != lastzoom)) // first call or display resized? redrawImage(comp, zoom, lastcamangle); return size; } public Dimension getProp2DCenter(Component comp, double zoom) { if ((center == null) || (zoom != lastzoom)) // first call or display resized? redrawImage(comp, zoom, lastcamangle); return center; } public Dimension getProp2DGrip(Component comp, double zoom) { if ((grip == null) || (zoom != lastzoom)) // first call or display resized? redrawImage(comp, zoom, lastcamangle); return grip; } private void redrawImage(Component comp, double zoom, double[] camangle) { int outside_pixel_diam = (int)(0.5 + zoom * outside_diam); int inside_pixel_diam = (int)(0.5 + zoom * inside_diam); double c0 = Math.cos(camangle[0]); double s0 = Math.sin(camangle[0]); double s1 = Math.sin(camangle[1]); int width = (int)(outside_pixel_diam * Math.abs(s0*s1)); if (width < 2) width = 2; int height = outside_pixel_diam; if (height < 2) height = 2; int inside_width = (int)(inside_pixel_diam * Math.abs(s0*s1)); if (inside_width == width) inside_width -= 2; int inside_height = inside_pixel_diam; if (inside_height == height) inside_height -= 2; // The angle of rotation of the ring. double term1 = Math.sqrt(c0*c0 / (1.0 - s0*s0*s1*s1)); double angle = (term1 < 1.0) ? Math.acos(term1) : 0.0; if (c0*s0 > 0.0) angle = -angle; double sa = Math.sin(angle); double ca = Math.cos(angle); int pxmin=0, pxmax=0, pymin=0, pymax=0; for (int i = 0; i < polysides; i++) { double theta = (double)i * 2.0 * JLMath.pi / (double)polysides; double x = (double)width * Math.cos(theta) * 0.5; double y = (double)height * Math.sin(theta) * 0.5; px[i] = (int)(ca*x - sa*y + 0.5); py[i] = (int)(ca*y + sa*x + 0.5); if ((i == 0) || (px[i] < pxmin)) pxmin = px[i]; if ((i == 0) || (px[i] > pxmax)) pxmax = px[i]; if ((i == 0) || (py[i] < pymin)) pymin = py[i]; if ((i == 0) || (py[i] > pymax)) pymax = py[i]; } int bbwidth = pxmax - pxmin + 1; int bbheight = pymax - pymin + 1; size = new Dimension(bbwidth, bbheight); image = VersionSpecific.getVersionSpecific().makeImage(comp, bbwidth, bbheight); Graphics g = image.getGraphics(); VersionSpecific.getVersionSpecific().setAntialias(g); g.setColor(color); for (int i = 0; i < polysides; i++) { px[i] -= pxmin; py[i] -= pymin; } g.fillPolygon(px, py, polysides); VersionSpecific.getVersionSpecific().setColorTransparent(g); for (int i = 0; i < polysides; i++) { double theta = (double)i * 2.0 * JLMath.pi / (double)polysides; double x = (double)inside_width * Math.cos(theta) * 0.5; double y = (double)inside_height * Math.sin(theta) * 0.5; px[i] = (int)(ca*x - sa*y + 0.5) - pxmin; py[i] = (int)(ca*y + sa*x + 0.5) - pymin; } g.fillPolygon(px, py, polysides); center = new Dimension(bbwidth/2, bbheight/2); int gripx = (s0 < 0) ? (bbwidth - 1) : 0; double bbw = sa*sa + ca*ca*Math.abs(s0*s1); double dsq = s0*s0*s1*s1*ca*ca + sa*sa - bbw*bbw; double d = (dsq > 0.0) ? Math.sqrt(dsq) : 0.0; if (c0 > 0) d = -d; int gripy = (int)((double)outside_pixel_diam * d) + bbheight/2; grip = new Dimension(gripx, gripy); lastzoom = zoom; lastcamangle = new double[] {camangle[0], camangle[1]}; } /* public Object getPropIDX3D() { Object result = null; try { Class ob = Class.forName("idx3d.idx3d_Object"); Class of = Class.forName("idx3d.idx3d_ObjectFactory"); Class mat = Class.forName("idx3d.idx3d_Material"); Method spiral = of.getMethod("SPIRAL", new Class[] {Float.TYPE, Float.TYPE, Float.TYPE, Float.TYPE, Float.TYPE, Float.TYPE, Integer.TYPE, Integer.TYPE}); result = spiral.invoke(null, new Object[] {new Float(0f), new Float((float)outside_diam/2), new Float(0f), new Float((float)(outside_diam-inside_diam)/2), new Float(1.02f), new Float(0f), new Integer(10), new Integer(10)}); Method rotate = ob.getMethod("rotate", new Class[] {Float.TYPE, Float.TYPE, Float.TYPE}); Method scale = ob.getMethod("scale", new Class[] {Float.TYPE, Float.TYPE, Float.TYPE}); rotate.invoke(result, new Object[] {new Float(0f), new Float(JLMath.pi/2), new Float(0f)}); scale.invoke(result, new Object[] {new Float(0.1f), new Float(1f), new Float(1f)}); Method setcolor = mat.getMethod("setColor", new Class[] {Integer.TYPE}); Object surf = mat.newInstance(); setcolor.invoke(surf, new Object[] {new Integer(color.getRGB())}); Method setmaterial = ob.getMethod("setMaterial", new Class[] {mat}); setmaterial.invoke(result, new Object[] {surf}); } catch (ClassNotFoundException e) { return null; } catch (NoSuchMethodException e) { return null; } catch (SecurityException e) { return null; } catch (IllegalAccessException e) { return null; } catch (InstantiationException e) { return null; } catch (InvocationTargetException e) { return null; } return result; } public Coordinate getPropIDX3DGrip() { return new Coordinate(0.0, -outside_diam/2, 0.0); } */ } jugglinglab-0.6.2+ds.1/source/jugglinglab/renderer/000077500000000000000000000000001323754603300221465ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/source/jugglinglab/renderer/JLMatrix.java000066400000000000000000000122511323754603300245040ustar00rootroot00000000000000// JLMatrix.java // // Copyright 2011 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.renderer; public class JLMatrix { public double m00 = 1.0, m01 = 0.0, m02 = 0.0, m03 = 0.0; public double m10 = 0.0, m11 = 1.0, m12 = 0.0, m13 = 0.0; public double m20 = 0.0, m21 = 0.0, m22 = 1.0, m23 = 0.0; public double m30 = 0.0, m31 = 0.0, m32 = 0.0, m33 = 1.0; public JLMatrix() { } public JLMatrix(JLVector right, JLVector up, JLVector forward) { m00 = right.x; m10 = right.y; m20 = right.z; m01 = up.x; m11 = up.y; m21 = up.z; m02 = forward.x; m12 = forward.y; m22 = forward.z; } public static JLMatrix shiftMatrix(double dx, double dy, double dz) { JLMatrix m = new JLMatrix(); m.m03 = dx; m.m13 = dy; m.m23 = dz; return m; } public static JLMatrix scaleMatrix(double dx, double dy, double dz) { JLMatrix m = new JLMatrix(); m.m00 = dx; m.m11 = dy; m.m22 = dz; return m; } public static JLMatrix scaleMatrix(double d) { return JLMatrix.scaleMatrix(d,d,d); } public static JLMatrix rotateMatrix(double dx, double dy, double dz) { JLMatrix out = new JLMatrix(); double SIN; double COS; if (dx != 0.0) { JLMatrix m = new JLMatrix(); SIN = Math.sin(dx); COS = Math.cos(dx); m.m11 = COS; m.m12 = SIN; m.m21 = -SIN; m.m22 = COS; out.transform(m); } if (dy != 0) { JLMatrix m = new JLMatrix(); SIN = Math.sin(dy); COS = Math.cos(dy); m.m00 = COS; m.m02 = SIN; m.m20 = -SIN; m.m22 = COS; out.transform(m); } if (dz != 0) { JLMatrix m = new JLMatrix(); SIN = Math.sin(dz); COS = Math.cos(dz); m.m00 = COS; m.m01 = SIN; m.m10 = -SIN; m.m11 = COS; out.transform(m); } return out; } public void shift(double dx, double dy, double dz) { transform(shiftMatrix(dx,dy,dz)); } public void scale(double dx, double dy, double dz) { transform(scaleMatrix(dx,dy,dz)); } public void scale(double d) { transform(scaleMatrix(d)); } public void rotate(double dx, double dy, double dz) { transform(rotateMatrix(dx,dy,dz)); } public void transform(JLMatrix n) { JLMatrix m = this.getClone(); m00 = n.m00*m.m00 + n.m01*m.m10 + n.m02*m.m20; m01 = n.m00*m.m01 + n.m01*m.m11 + n.m02*m.m21; m02 = n.m00*m.m02 + n.m01*m.m12 + n.m02*m.m22; m03 = n.m00*m.m03 + n.m01*m.m13 + n.m02*m.m23 + n.m03; m10 = n.m10*m.m00 + n.m11*m.m10 + n.m12*m.m20; m11 = n.m10*m.m01 + n.m11*m.m11 + n.m12*m.m21; m12 = n.m10*m.m02 + n.m11*m.m12 + n.m12*m.m22; m13 = n.m10*m.m03 + n.m11*m.m13 + n.m12*m.m23 + n.m13; m20 = n.m20*m.m00 + n.m21*m.m10 + n.m22*m.m20; m21 = n.m20*m.m01 + n.m21*m.m11 + n.m22*m.m21; m22 = n.m20*m.m02 + n.m21*m.m12 + n.m22*m.m22; m23 = n.m20*m.m03 + n.m21*m.m13 + n.m22*m.m23 + n.m23; } public JLMatrix getClone() { JLMatrix m = new JLMatrix(); m.m00=m00; m.m01=m01; m.m02=m02; m.m03=m03; m.m10=m10; m.m11=m11; m.m12=m12; m.m13=m13; m.m20=m20; m.m21=m21; m.m22=m22; m.m23=m23; m.m30=m30; m.m31=m31; m.m32=m32; m.m33=m33; return m; } public JLMatrix inverse() { JLMatrix m = new JLMatrix(); double q1 = m12; double q6 = m10*m01; double q7 = m10*m21; double q8 = m02; double q13 = m20*m01; double q14 = m20*m11; double q21 = m02*m21; double q22 = m03*m21; double q25 = m01*m12; double q26 = m01*m13; double q27 = m02*m11; double q28 = m03*m11; double q29 = m10*m22; double q30 = m10*m23; double q31 = m20*m12; double q32 = m20*m13; double q35 = m00*m22; double q36 = m00*m23; double q37 = m20*m02; double q38 = m20*m03; double q41 = m00*m12; double q42 = m00*m13; double q43 = m10*m02; double q44 = m10*m03; double q45 = m00*m11; double q48 = m00*m21; double q49 = q45*m22-q48*q1-q6*m22+q7*q8; double q50 = q13*q1-q14*q8; double q51 = 1.0/(q49+q50); m.m00 = (m11*m22*m33-m11*m23*m32-m21*m12*m33+m21*m13*m32+m31*m12*m23-m31*m13*m22)*q51; m.m01 = -(m01*m22*m33-m01*m23*m32-q21*m33+q22*m32)*q51; m.m02 = (q25*m33-q26*m32-q27*m33+q28*m32)*q51; m.m03 = -(q25*m23-q26*m22-q27*m23+q28*m22+q21*m13-q22*m12)*q51; m.m10 = -(q29*m33-q30*m32-q31*m33+q32*m32)*q51; m.m11 = (q35*m33-q36*m32-q37*m33+q38*m32)*q51; m.m12 = -(q41*m33-q42*m32-q43*m33+q44*m32)*q51; m.m13 = (q41*m23-q42*m22-q43*m23+q44*m22+q37*m13-q38*m12)*q51; m.m20 = (q7*m33-q30*m31-q14*m33+q32*m31)*q51; m.m21 = -(q48*m33-q36*m31-q13*m33+q38*m31)*q51; m.m22 = (q45*m33-q42*m31-q6*m33+q44*m31)*q51; m.m23 = -(q45*m23-q42*m21-q6*m23+q44*m21+q13*m13-q38*m11)*q51; return m; } }jugglinglab-0.6.2+ds.1/source/jugglinglab/renderer/JLVector.java000066400000000000000000000032451323754603300245050ustar00rootroot00000000000000// JLVector.java // // Copyright 2011 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.renderer; public class JLVector { public double x = 0.0, y = 0.0, z = 0.0; public JLVector() { } public JLVector(double xpos, double ypos, double zpos) { x = xpos; y = ypos; z = zpos; } public double length() { return Math.sqrt(x*x+y*y+z*z); } public JLVector transform(JLMatrix m) { double newx = x*m.m00 + y*m.m01 + z*m.m02 + m.m03; double newy = x*m.m10 + y*m.m11 + z*m.m12 + m.m13; double newz = x*m.m20 + y*m.m21 + z*m.m22 + m.m23; return new JLVector(newx, newy, newz); } public static JLVector add(JLVector a, JLVector b) { return new JLVector(a.x + b.x, a.y + b.y, a.z + b.z); } public static JLVector sub(JLVector a, JLVector b) { return new JLVector(a.x - b.x, a.y - b.y, a.z - b.z); } public static JLVector scale(double f, JLVector a) { return new JLVector(f * a.x, f * a.y, f * a.z); } }jugglinglab-0.6.2+ds.1/source/jugglinglab/renderer/Juggler.java000066400000000000000000000162171323754603300244170ustar00rootroot00000000000000// Juggler.java // // Copyright 2003 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.renderer; import jugglinglab.util.*; import jugglinglab.jml.*; // This class calculates the coordinates of the juggler elbows, shoulders, etc. public class Juggler { // juggler dimensions, in cm public final static double shoulder_hw = 23.0; // shoulder half-width (m) public final static double shoulder_h = 40.0; // throw pos. to shoulder public final static double waist_hw = 17.0; // waist half-width public final static double waist_h = -5.0; public final static double elbow_hw = 30.0; // elbow "home" public final static double elbow_h = 6.0; public final static double elbow_slop = 12.0; public final static double hand_out = 5.0; // outside width of hand public final static double hand_in = 5.0; public final static double head_hw = 10.0; // head half-width public final static double head_h = 26.0; // head height public final static double neck_h = 5.0; // neck height public final static double shoulder_y = 0.0; public final static double pattern_y = 30.0; public final static double upper_length = 41.0; public final static double lower_length = 40.0; public final static double lower_gap_wrist = 1.0; public final static double lower_gap_elbow = 0.0; public final static double lower_hand_height = 0.0; public final static double upper_gap_elbow = 0.0; public final static double upper_gap_shoulder = 0.0; protected final static double lower_total = lower_length + lower_gap_wrist + lower_gap_elbow; protected final static double upper_total = upper_length + upper_gap_elbow + upper_gap_shoulder; // the remaining are used only for the 3d display public final static double shoulder_radius = 6; public final static double elbow_radius = 4; public final static double wrist_radius = 2; public static void findJugglerCoordinates(JMLPattern pat, double time, JLVector[][] result) throws JuggleExceptionInternal { for (int juggler = 1; juggler <= pat.getNumberOfJugglers(); juggler++) { JLVector lefthand, righthand; JLVector leftshoulder, rightshoulder; JLVector leftelbow, rightelbow; JLVector leftwaist, rightwaist; JLVector leftheadbottom, leftheadtop; JLVector rightheadbottom, rightheadtop; Coordinate coord0 = new Coordinate(); Coordinate coord1 = new Coordinate(); Coordinate coord2 = new Coordinate(); pat.getHandCoordinate(juggler, HandLink.LEFT_HAND, time, coord0); pat.getHandCoordinate(juggler, HandLink.RIGHT_HAND, time, coord1); lefthand = new JLVector(coord0.x, coord0.z + lower_hand_height, coord0.y); righthand = new JLVector(coord1.x, coord1.z + lower_hand_height, coord1.y); pat.getJugglerPosition(juggler, time, coord2); double angle = JLMath.toRad(pat.getJugglerAngle(juggler, time)); double s = Math.sin(angle); double c = Math.cos(angle); leftshoulder = new JLVector( coord2.x - shoulder_hw * c - shoulder_y * s, coord2.z + shoulder_h, coord2.y - shoulder_hw * s + shoulder_y * c); rightshoulder = new JLVector( coord2.x + shoulder_hw * c - shoulder_y * s, coord2.z + shoulder_h, coord2.y + shoulder_hw * s + shoulder_y * c); leftwaist = new JLVector( coord2.x - waist_hw * c - shoulder_y * s, coord2.z + waist_h, coord2.y - waist_hw * s + shoulder_y * c); rightwaist = new JLVector( coord2.x + waist_hw * c - shoulder_y * s, coord2.z + waist_h, coord2.y + waist_hw * s + shoulder_y * c); leftheadbottom = new JLVector( coord2.x - head_hw * c - shoulder_y * s, coord2.z + shoulder_h + neck_h, coord2.y - head_hw * s + shoulder_y * c); leftheadtop = new JLVector( coord2.x - head_hw * c - shoulder_y * s, coord2.z + shoulder_h + neck_h + head_h, coord2.y - head_hw * s + shoulder_y * c); rightheadbottom = new JLVector( coord2.x + head_hw * c - shoulder_y * s, coord2.z + shoulder_h + neck_h, coord2.y + head_hw * s + shoulder_y * c); rightheadtop = new JLVector( coord2.x + head_hw * c - shoulder_y * s, coord2.z + shoulder_h + neck_h + head_h, coord2.y + head_hw * s + shoulder_y * c); double L = lower_total; double U = upper_total; JLVector deltaL = JLVector.sub(lefthand, leftshoulder); double D = deltaL.length(); if (D <= (L+U)) { // Calculate the coordinates of the elbows double Lr = Math.sqrt((4.0*U*U*L*L-(U*U+L*L-D*D)*(U*U+L*L-D*D))/(4.0*D*D)); if (Double.isNaN(Lr)) throw new JuggleExceptionInternal("NaN in renderer 1"); double factor = Math.sqrt(U*U-Lr*Lr)/D; if (Double.isNaN(factor)) throw new JuggleExceptionInternal("NaN in renderer 2"); JLVector Lxsc = JLVector.scale(factor, deltaL); double Lalpha = Math.asin(deltaL.y / D); if (Double.isNaN(Lalpha)) throw new JuggleExceptionInternal("NaN in renderer 3"); factor = 1.0 + Lr*Math.tan(Lalpha)/(factor*D); leftelbow = new JLVector( leftshoulder.x + Lxsc.x * factor, leftshoulder.y + Lxsc.y - Lr*Math.cos(Lalpha), leftshoulder.z + Lxsc.z * factor); } else { leftelbow = null; } JLVector deltaR = JLVector.sub(righthand, rightshoulder); D = deltaR.length(); if (D <= (L+U)) { // Calculate the coordinates of the elbows double Rr = Math.sqrt((4.0*U*U*L*L-(U*U+L*L-D*D)*(U*U+L*L-D*D))/(4.0*D*D)); if (Double.isNaN(Rr)) throw new JuggleExceptionInternal("NaN in renderer 4"); double factor = Math.sqrt(U*U-Rr*Rr)/D; if (Double.isNaN(factor)) throw new JuggleExceptionInternal("NaN in renderer 5"); JLVector Rxsc = JLVector.scale(factor, deltaR); double Ralpha = Math.asin(deltaR.y / D); if (Double.isNaN(Ralpha)) throw new JuggleExceptionInternal("NaN in renderer 6"); factor = 1.0 + Rr*Math.tan(Ralpha)/(factor*D); rightelbow = new JLVector( rightshoulder.x + Rxsc.x * factor, rightshoulder.y + Rxsc.y - Rr*Math.cos(Ralpha), rightshoulder.z + Rxsc.z * factor); } else { rightelbow = null; } result[juggler-1][0] = lefthand; result[juggler-1][1] = righthand; result[juggler-1][2] = leftshoulder; result[juggler-1][3] = rightshoulder; result[juggler-1][4] = leftelbow; result[juggler-1][5] = rightelbow; result[juggler-1][6] = leftwaist; result[juggler-1][7] = rightwaist; result[juggler-1][8] = leftheadbottom; result[juggler-1][9] = leftheadtop; result[juggler-1][10] = rightheadbottom; result[juggler-1][11] = rightheadtop; } } } jugglinglab-0.6.2+ds.1/source/jugglinglab/renderer/Renderer.java000066400000000000000000000040611323754603300245600ustar00rootroot00000000000000// Renderer.java // // Copyright 2003 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.renderer; import java.awt.*; import javax.swing.*; import jugglinglab.jml.*; import jugglinglab.util.*; public abstract class Renderer { public abstract void setPattern(JMLPattern pat); public abstract void initDisplay(Dimension dim, int border, Coordinate overallmax, Coordinate overallmin); public abstract void setCameraAngle(double[] angle); public abstract double[] getCameraAngle(); // the following return results in local coordinates public abstract Coordinate getHandWindowMax(); public abstract Coordinate getHandWindowMin(); // the following return results in global coordinates public abstract Coordinate getJugglerWindowMax(); public abstract Coordinate getJugglerWindowMin(); public abstract int[] getXY(Coordinate coord); // pixel coordinates public abstract Coordinate getScreenTranslatedCoordinate(Coordinate coord, int dx, int dy); public abstract void drawFrame(double time, int[] pnum, Graphics g, JPanel pan) throws JuggleExceptionInternal; public abstract Color getBackground(); protected static JLVector toVector(Coordinate c, JLVector result) { result.x = c.x; result.y = c.z; result.z = c.y; return result; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/renderer/Renderer2D.java000066400000000000000000000663561323754603300247650ustar00rootroot00000000000000// Renderer2D.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.renderer; import java.awt.*; import java.awt.geom.*; import java.util.*; import java.lang.reflect.*; import javax.swing.*; import jugglinglab.core.*; import jugglinglab.jml.*; import jugglinglab.util.*; import jugglinglab.prop.*; public class Renderer2D extends Renderer { public static final int RENDER_POINT_FIELD = 0; public static final int RENDER_WIRE_FRAME = 1; public static final int RENDER_FLAT_SOLID = 2; protected int render_type = RENDER_FLAT_SOLID; // One of the above protected Color background = null; protected Coordinate left = null, right = null; protected JLVector cameracenter; protected double[] cameraangle; protected double cameradistance; protected JLMatrix m; protected int width, height; protected JMLPattern pat = null; protected double zoom; protected int originx, originz; protected int polysides; // # sides in polygon for head protected double[] headcos, headsin; protected int[] headx, heady; protected DrawObject2D[] obj = null, obj2 = null; protected JLVector[][] jugglervec = null; protected Coordinate tempc = null; protected JLVector tempv = null; public Renderer2D() { this.background = Color.white; this.cameraangle = new double[2]; this.polysides = 40; headcos = new double[polysides]; headsin = new double[polysides]; headx = new int[polysides]; heady = new int[polysides]; for (int i = 0; i < polysides; i++) { headcos[i] = Math.cos((double)i * JLMath.toRad(360.0) / polysides); headsin[i] = Math.sin((double)i * JLMath.toRad(360.0) / polysides); } this.tempc = new Coordinate(); this.tempv = new JLVector(); } public void setPattern(JMLPattern pat) { this.pat = pat; int numobjects = 5*pat.getNumberOfJugglers() + pat.getNumberOfPaths(); this.obj = new DrawObject2D[numobjects]; for (int i = 0; i < numobjects; i++) obj[i] = new DrawObject2D(numobjects); this.obj2 = new DrawObject2D[numobjects]; this.jugglervec = new JLVector[pat.getNumberOfJugglers()][12]; } public Color getBackground() { return this.background; } public void initDisplay(Dimension dim, int border, Coordinate overallmax, Coordinate overallmin) { this.width = dim.width; this.height = dim.height; Rectangle r = new Rectangle(border, border, width-2*border, height-2*border); calcScaling(r, overallmax, overallmin); this.cameradistance = 1000.0; this.cameracenter = new JLVector(0.5*(overallmax.x+overallmin.x), 0.5*(overallmax.z+overallmin.z), 0.5*(overallmax.y+overallmin.y)); setCameraAngle(this.cameraangle); // sets camera position } public void setCameraAngle(double[] camangle) { this.cameraangle[0] = camangle[0]; this.cameraangle[1] = camangle[1]; if (cameracenter == null) return; m = JLMatrix.shiftMatrix(-cameracenter.x, -cameracenter.y, -cameracenter.z); m.transform(JLMatrix.rotateMatrix(0.0, JLMath.toRad(180.0) - cameraangle[0], 0.0)); m.transform(JLMatrix.rotateMatrix(JLMath.toRad(90.0) - cameraangle[1], 0.0, 0.0)); m.transform(JLMatrix.shiftMatrix(cameracenter.x, cameracenter.y, cameracenter.z)); m.transform(JLMatrix.scaleMatrix(1.0, -1.0, 1.0)); // larger y values -> smaller y pixel coord m.transform(JLMatrix.scaleMatrix(this.zoom)); m.transform(JLMatrix.shiftMatrix(this.originx, this.originz, 0.0)); } public double[] getCameraAngle() { double[] ca = new double[2]; ca[0] = cameraangle[0]; ca[1] = cameraangle[1]; return ca; } public int[] getXY(Coordinate c) { return getXY(new JLVector(c.x, c.z, c.y)); } protected int[] getXY(JLVector vec) { JLVector v = vec.transform(m); // apply camera rotation int[] val = new int[2]; val[0] = (int)(v.x + 0.5f); val[1] = (int)(v.y + 0.5f); return val; } protected JLVector getXYZ(JLVector vec, JLVector result) { result.x = vec.x*m.m00 + vec.y*m.m01 + vec.z*m.m02 + m.m03; result.y = vec.x*m.m10 + vec.y*m.m11 + vec.z*m.m12 + m.m13; result.z = vec.x*m.m20 + vec.y*m.m21 + vec.z*m.m22 + m.m23; return result; } public Coordinate getScreenTranslatedCoordinate(Coordinate c, int dx, int dy) { JLVector v = new JLVector(c.x, c.z, c.y); JLVector s = v.transform(m); JLVector news = JLVector.add(s, new JLVector(dx, dy, 0.0)); JLVector newv = news.transform(m.inverse()); return new Coordinate(newv.x, newv.z, newv.y); } public void drawFrame(double time, int[] pnum, Graphics g, JPanel pan) throws JuggleExceptionInternal { // try to turn on antialiased rendering VersionSpecific.getVersionSpecific().setAntialias(g); int numobjects = 5*pat.getNumberOfJugglers() + pat.getNumberOfPaths(); // first reset the objects in the object pool for (int i = 0; i < numobjects; i++) obj[i].covering.removeAllElements(); // first create a list of objects in the display int index = 0; for (int i = 1; i <= pat.getNumberOfPaths(); i++) { obj[index].type = DrawObject2D.TYPE_PROP; obj[index].number = i; pat.getPathCoordinate(i, time, tempc); if (!tempc.isValid()) tempc.setCoordinate(0.0,0.0,0.0); getXYZ(Renderer.toVector(tempc, tempv), obj[index].coord[0]); int x = (int)(0.5f + obj[index].coord[0].x); int y = (int)(0.5f + obj[index].coord[0].y); Prop pr = pat.getProp(pnum[i-1]); if (pr.getProp2DImage(pan, this.zoom, this.cameraangle) != null) { Dimension center = pr.getProp2DCenter(pan, this.zoom); Dimension size = pr.getProp2DSize(pan, this.zoom); obj[index].boundingbox.x = x - center.width; obj[index].boundingbox.y = y - center.height; obj[index].boundingbox.width = size.width; obj[index].boundingbox.height = size.height; } index++; } Juggler.findJugglerCoordinates(pat, time, jugglervec); for (int i = 1; i <= pat.getNumberOfJugglers(); i++) { obj[index].type = DrawObject2D.TYPE_BODY; obj[index].number = i; getXYZ(jugglervec[i-1][2], obj[index].coord[0]); // left shoulder getXYZ(jugglervec[i-1][3], obj[index].coord[1]); // right shoulder getXYZ(jugglervec[i-1][7], obj[index].coord[2]); // right waist getXYZ(jugglervec[i-1][6], obj[index].coord[3]); // left waist getXYZ(jugglervec[i-1][8], obj[index].coord[4]); // left head bottom getXYZ(jugglervec[i-1][9], obj[index].coord[5]); // left head top getXYZ(jugglervec[i-1][10], obj[index].coord[6]); // right head bottom getXYZ(jugglervec[i-1][11], obj[index].coord[7]); // right head top int xmin, xmax, ymin, ymax; xmin = xmax = (int)(0.5f + obj[index].coord[0].x); ymin = ymax = (int)(0.5f + obj[index].coord[0].y); for (int j = 1; j < 8; j++) { int x = (int)(0.5f + obj[index].coord[j].x); int y = (int)(0.5f + obj[index].coord[j].y); if (x < xmin) xmin = x; if (x > xmax) xmax = x; if (y < ymin) ymin = y; if (y > ymax) ymax = y; } // inset bb by one pixel to avoid intersection at shoulder: obj[index].boundingbox.x = xmin+1; obj[index].boundingbox.y = ymin+1; obj[index].boundingbox.width = xmax-xmin-1; obj[index].boundingbox.height = ymax-ymin-1; index++; // the lines for each arm, starting with the left: for (int j = 0; j < 2; j++) { if (jugglervec[i-1][4+j] == null) { obj[index].type = DrawObject2D.TYPE_LINE; obj[index].number = i; getXYZ(jugglervec[i-1][2+j], obj[index].coord[0]); // entire arm getXYZ(jugglervec[i-1][0+j], obj[index].coord[1]); int x = Math.min((int)(0.5f + obj[index].coord[0].x), (int)(0.5f + obj[index].coord[1].x)); int y = Math.min((int)(0.5f + obj[index].coord[0].y), (int)(0.5f + obj[index].coord[1].y)); int width = Math.abs((int)(0.5f + obj[index].coord[0].x) - (int)(0.5f + obj[index].coord[1].x)) + 1; int height = Math.abs((int)(0.5f + obj[index].coord[0].y) - (int)(0.5f + obj[index].coord[1].y)) + 1; obj[index].boundingbox.x = x; obj[index].boundingbox.y = y; obj[index].boundingbox.width = width; obj[index].boundingbox.height = height; index++; } else { obj[index].type = DrawObject2D.TYPE_LINE; obj[index].number = i; getXYZ(jugglervec[i-1][2+j], obj[index].coord[0]); // upper arm getXYZ(jugglervec[i-1][4+j], obj[index].coord[1]); int x = Math.min((int)(0.5f + obj[index].coord[0].x), (int)(0.5f + obj[index].coord[1].x)); int y = Math.min((int)(0.5f + obj[index].coord[0].y), (int)(0.5f + obj[index].coord[1].y)); int width = Math.abs((int)(0.5f + obj[index].coord[0].x) - (int)(0.5f + obj[index].coord[1].x)) + 1; int height = Math.abs((int)(0.5f + obj[index].coord[0].y) - (int)(0.5f + obj[index].coord[1].y)) + 1; obj[index].boundingbox.x = x; obj[index].boundingbox.y = y; obj[index].boundingbox.width = width; obj[index].boundingbox.height = height; index++; obj[index].type = DrawObject2D.TYPE_LINE; obj[index].number = i; getXYZ(jugglervec[i-1][4+j], obj[index].coord[0]); // lower arm getXYZ(jugglervec[i-1][0+j], obj[index].coord[1]); x = Math.min((int)(0.5f + obj[index].coord[0].x), (int)(0.5f + obj[index].coord[1].x)); y = Math.min((int)(0.5f + obj[index].coord[0].y), (int)(0.5f + obj[index].coord[1].y)); width = Math.abs((int)(0.5f + obj[index].coord[0].x) - (int)(0.5f + obj[index].coord[1].x)) + 1; height = Math.abs((int)(0.5f + obj[index].coord[0].y) - (int)(0.5f + obj[index].coord[1].y)) + 1; obj[index].boundingbox.x = x; obj[index].boundingbox.y = y; obj[index].boundingbox.width = width; obj[index].boundingbox.height = height; index++; } } } numobjects = index; // figure out which display elements are covering which other elements for (int i = 0; i < numobjects; i++) { for (int j = 0; j < numobjects; j++) { if (j == i) continue; if (obj[i].isCovering(obj[j])) obj[i].covering.addElement(obj[j]); } obj[i].drawn = false; } // now figure out a drawing order index = 0; boolean changed = true; while (changed) { changed = false; for (int i = 0; i < numobjects; i++) { if (obj[i].drawn) continue; boolean candraw = true; for (int j = 0; j < obj[i].covering.size(); j++) { DrawObject2D temp = (DrawObject2D)(obj[i].covering.elementAt(j)); if (!temp.drawn) { candraw = false; break; } } if (candraw) { obj2[index] = obj[i]; obj[i].drawn = true; index++; changed = true; } } } // just in case there were some that couldn't be drawn: for (int i = 0; i < numobjects; i++) { if (obj[i].drawn) continue; obj2[index] = obj[i]; obj[i].drawn = true; index++; // System.out.println("got undrawable item, type "+obj[i].type); } // draw the objects in the sorted order g.setColor(this.background); g.fillRect(0, 0, width, height); for (int i = 0; i < numobjects; i++) { DrawObject2D ob = obj2[i]; switch (ob.type) { case DrawObject2D.TYPE_PROP: Prop pr = pat.getProp(pnum[ob.number-1]); int x = (int)(0.5f + ob.coord[0].x); int y = (int)(0.5f + ob.coord[0].y); Image propimage = pr.getProp2DImage(pan, this.zoom, this.cameraangle); if (propimage != null) { Dimension grip = pr.getProp2DGrip(pan, this.zoom); g.drawImage(propimage, x-grip.width, y-grip.height, pan); } /* else { g.setColor(pr.getEditorColor()); draw3DProp(ob.object, g); } */ // g.setColor(Color.black); // g.drawLine(ob.boundingbox.x, ob.boundingbox.y, ob.boundingbox.x + ob.boundingbox.width, ob.boundingbox.y); // g.drawLine(ob.boundingbox.x + ob.boundingbox.width, ob.boundingbox.y, ob.boundingbox.x + ob.boundingbox.width, ob.boundingbox.y + ob.boundingbox.height); // g.drawLine(ob.boundingbox.x + ob.boundingbox.width, ob.boundingbox.y + ob.boundingbox.height, ob.boundingbox.x, ob.boundingbox.y + ob.boundingbox.height); // g.drawLine(ob.boundingbox.x, ob.boundingbox.y + ob.boundingbox.height, ob.boundingbox.x, ob.boundingbox.y); break; case DrawObject2D.TYPE_BODY: int[] bodyx = new int[4]; int[] bodyy = new int[4]; for (int j = 0; j < 4; j++) { bodyx[j] = (int)(0.5f + ob.coord[j].x); bodyy[j] = (int)(0.5f + ob.coord[j].y); } g.setColor(this.background); g.fillPolygon(bodyx, bodyy, 4); g.setColor(Color.black); g.drawPolygon(bodyx, bodyy, 4); double LheadBx = ob.coord[4].x; double LheadBy = ob.coord[4].y; double LheadTx = ob.coord[5].x; double LheadTy = ob.coord[5].y; double RheadBx = ob.coord[6].x; double RheadBy = ob.coord[6].y; double RheadTx = ob.coord[7].x; double RheadTy = ob.coord[7].y; for (int j = 0; j < polysides; j++) { headx[j] = (int)(0.5f + 0.5f*(LheadBx + RheadBx + headcos[j]*(RheadBx-LheadBx))); heady[j] = (int)(0.5f + 0.5f*(LheadBy + LheadTy + headsin[j]*(LheadBy-LheadTy)) + (headx[j]-LheadBx)*(RheadBy-LheadBy) / (RheadBx-LheadBx)); } g.setColor(this.background); g.fillPolygon(headx, heady, polysides); g.setColor(Color.black); g.drawPolygon(headx, heady, polysides); break; case DrawObject2D.TYPE_LINE: g.setColor(Color.black); int x1 = (int)(0.5f + ob.coord[0].x); int y1 = (int)(0.5f + ob.coord[0].y); int x2 = (int)(0.5f + ob.coord[1].x); int y2 = (int)(0.5f + ob.coord[1].y); g.drawLine(x1, y1, x2, y2); break; } // g.setColor(Color.black); // g.drawLine(ob.boundingbox.x, ob.boundingbox.y, ob.boundingbox.x+ob.boundingbox.width-1, ob.boundingbox.y); // g.drawLine(ob.boundingbox.x+ob.boundingbox.width-1, ob.boundingbox.y, ob.boundingbox.x+ob.boundingbox.width-1, ob.boundingbox.y+ob.boundingbox.height-1); // g.drawLine(ob.boundingbox.x+ob.boundingbox.width-1, ob.boundingbox.y+ob.boundingbox.height-1, ob.boundingbox.x, ob.boundingbox.y+ob.boundingbox.height-1); // g.drawLine(ob.boundingbox.x, ob.boundingbox.y+ob.boundingbox.height-1, ob.boundingbox.x, ob.boundingbox.y); } } public Coordinate getHandWindowMax() { return new Coordinate(Juggler.hand_out, 0, 1); } public Coordinate getHandWindowMin() { return new Coordinate(-Juggler.hand_in, 0, -1); } public Coordinate getJugglerWindowMax() { Coordinate max = pat.getJugglerMax(1); for (int i = 2; i <= pat.getNumberOfJugglers(); i++) max = Coordinate.max(max, pat.getJugglerMax(i)); max = Coordinate.add(max, new Coordinate(Juggler.shoulder_hw, Juggler.shoulder_hw, // Juggler.head_hw, Juggler.shoulder_h + Juggler.neck_h + Juggler.head_h)); return max; // return new Coordinate(Math.max(max.x, max.y), Math.max(max.x, max.y), max.z); } public Coordinate getJugglerWindowMin() { Coordinate min = pat.getJugglerMin(1); for (int i = 2; i <= pat.getNumberOfJugglers(); i++) min = Coordinate.min(min, pat.getJugglerMin(i)); min = Coordinate.add(min, new Coordinate(-Juggler.shoulder_hw, -Juggler.shoulder_hw, // -Juggler.head_hw, Juggler.shoulder_h)); return min; // return new Coordinate(Math.min(min.x, min.y), Math.min(min.x, min.y), min.z); } protected void calcScaling(Rectangle r, Coordinate coordmax, Coordinate coordmin) { // double frame_width = 2.0 * Math.max(Math.abs(coordmax.x), Math.abs(coordmin.x)); double frame_width = coordmax.x - coordmin.x; double frame_height = coordmax.z - coordmin.z; zoom = Math.min((double)(r.width) / frame_width, (double)(r.height) / frame_height); originx = r.x + (int)(0.5 + 0.5 * (r.width - zoom*(coordmax.x+coordmin.x))); // r.x + r.width / 2; originz = r.y + (int)(0.5 + 0.5 * (r.height + zoom*(coordmax.z+coordmin.z))); } class DrawObject2D { public static final int TYPE_PROP = 1; public static final int TYPE_BODY = 2; public static final int TYPE_LINE = 3; protected static final double slop = 3.0; public int type; public int number; // either path or juggler number public JLVector[] coord = null; public Rectangle boundingbox = null; public Vector covering = null; public boolean drawn = false; public JLVector tempv = null; public DrawObject2D(int numobjects) { this.coord = new JLVector[8]; for (int i = 0; i < 8; i++) this.coord[i] = new JLVector(); this.boundingbox = new Rectangle(); this.covering = new Vector(numobjects); this.tempv = new JLVector(); } public boolean isCovering(DrawObject2D obj) { if (!boundingbox.intersects(obj.boundingbox)) return false; switch (this.type) { case TYPE_PROP: switch (obj.type) { case TYPE_PROP: return (this.coord[0].z < obj.coord[0].z); case TYPE_BODY: { vectorProduct(obj.coord[0], obj.coord[1], obj.coord[2], tempv); if (tempv.z == 0f) return false; double z = obj.coord[0].z - (tempv.x * (this.coord[0].x - obj.coord[0].x) + tempv.y * (this.coord[0].y - obj.coord[0].y)) / tempv.z; return (this.coord[0].z < z); } case TYPE_LINE: return (isBoxCoveringLine(this, obj) == 1); } break; case TYPE_BODY: switch (obj.type) { case TYPE_PROP: { vectorProduct(this.coord[0], this.coord[1], this.coord[2], tempv); if (tempv.z == 0f) return false; double z = this.coord[0].z - (tempv.x * (obj.coord[0].x - this.coord[0].x) + tempv.y * (obj.coord[0].y - this.coord[0].y)) / tempv.z; return (z < obj.coord[0].z); } case TYPE_BODY: { double d = 0.0; for (int i = 0; i < 4; i++) d += (this.coord[i].z - obj.coord[i].z); return (d < 0.0); } case TYPE_LINE: return (isBoxCoveringLine(this, obj) == 1); } break; case TYPE_LINE: switch (obj.type) { case TYPE_PROP: case TYPE_BODY: return (isBoxCoveringLine(obj, this) == -1); case TYPE_LINE: return false; } break; } return false; } // returns 1 if box covers line, -1 if line covers box, 0 otherwise protected int isBoxCoveringLine(DrawObject2D box, DrawObject2D line) { // If at least one end of the line is inside the box's boundingbox, then return // 1 if all such ends are behind the box, and -1 otherwise. // If neither end is inside the boundingbox, then find intersections between the // line and the boundingbox. If no points of intersection, return 0. If the // line is behind the bb at all points of intersection, return 1. Otherwise // return -1; // System.out.println("starting..."); if (box.type == TYPE_BODY) vectorProduct(box.coord[0], box.coord[1], box.coord[2], tempv); else { tempv.x = 0f; tempv.y = 0f; tempv.z = 1f; } if (tempv.z == 0f) return 0; // box is exactly sideways boolean endinbb = false; for (int i = 0; i < 2; i++) { double x = line.coord[i].x; double y = line.coord[i].y; if (box.boundingbox.contains((int)(x+0.5f), (int)(y+0.5f))) { double zb = box.coord[0].z - (tempv.x * (x - box.coord[0].x) + tempv.y * (y - box.coord[0].y)) / tempv.z; if (line.coord[i].z < (zb-slop)) { // System.out.println(" exit 1"); return -1; } endinbb = true; } } if (endinbb) { // System.out.println(" exit 2"); return 1; // know that end wasn't in front of body } boolean intersection = false; for (int i = 0; i < 2; i++) { int x = ((i == 0) ? box.boundingbox.x : (box.boundingbox.x+box.boundingbox.width-1)); if ((x < Math.min(line.coord[0].x, line.coord[1].x)) || (x > Math.max(line.coord[0].x, line.coord[1].x))) continue; if (line.coord[1].x == line.coord[0].x) continue; double y = line.coord[0].y + (line.coord[1].y-line.coord[0].y)*((double)x - line.coord[0].x) / (line.coord[1].x - line.coord[0].x); if ((y < box.boundingbox.y) || (y > (box.boundingbox.y + box.boundingbox.height - 1))) continue; intersection = true; double zb = box.coord[0].z - (tempv.x * (x - box.coord[0].x) + tempv.y * (y - box.coord[0].y)) / tempv.z; double zl = line.coord[0].z + (line.coord[1].z-line.coord[0].z)*((double)x-line.coord[0].x) / (line.coord[1].x - line.coord[0].x); if (zl < (zb-slop)) { // System.out.println(" exit 3, i = "+i); return -1; } } for (int i = 0; i < 2; i++) { int y = ((i == 0) ? box.boundingbox.y : (box.boundingbox.y+box.boundingbox.height-1)); if ((y < Math.min(line.coord[0].y, line.coord[1].y)) || (y > Math.max(line.coord[0].y, line.coord[1].y))) continue; if (line.coord[1].y == line.coord[0].y) continue; double x = line.coord[0].x + (line.coord[1].x-line.coord[0].x)*((double)y - line.coord[0].y) / (line.coord[1].y - line.coord[0].y); if ((x < box.boundingbox.x) || (x > (box.boundingbox.x + box.boundingbox.width - 1))) continue; intersection = true; double zb = box.coord[0].z - (tempv.x * (x - box.coord[0].x) + tempv.y * ((double)y - box.coord[0].y)) / tempv.z; double zl = line.coord[0].z + (line.coord[1].z-line.coord[0].z)*(x-line.coord[0].x) / (line.coord[1].x - line.coord[0].x); if (zl < (zb-slop)) { // System.out.println(" exit 4, i = "+i); return -1; } } // System.out.println(" exit 5"); return (intersection ? 1 : 0); } public JLVector vectorProduct(JLVector v1, JLVector v2, JLVector v3, JLVector result) { double ax = v2.x - v1.x; double ay = v2.y - v1.y; double az = v2.z - v1.z; double bx = v3.x - v1.x; double by = v3.y - v1.y; double bz = v3.z - v1.z; result.x = ay * bz - by * az; result.y = az * bx - bz * ax; result.z = ax * by - bx * ay; return result; } } } jugglinglab-0.6.2+ds.1/source/jugglinglab/util/000077500000000000000000000000001323754603300213155ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/source/jugglinglab/util/Coordinate.java000077500000000000000000000054131323754603300242550ustar00rootroot00000000000000// Coordinate.java // // Copyright 2002 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.util; // Simple container class public class Coordinate { public double x, y, z; public Coordinate() { this(0.0,0.0,0.0); } public Coordinate(double x, double y) { this(x,y,0.0); } public Coordinate(double x, double y, double z) { this.x = x; this.y = y; this.z = z; } public Coordinate(Coordinate c) { this.x = c.x; this.y = c.y; this.z = c.z; } public void setCoordinate(double x, double y, double z) { this.x = x; this.y = y; this.z = z; } public double getIndex(int index) { if (index == 0) return x; else if (index == 1) return y; else return z; } public static Coordinate max(Coordinate coord1, Coordinate coord2) { if (coord1 == null) return coord2; if (coord2 == null) return coord1; return new Coordinate(Math.max(coord1.x, coord2.x), Math.max(coord1.y, coord2.y), Math.max(coord1.z, coord2.z)); } public static Coordinate min(Coordinate coord1, Coordinate coord2) { if (coord1 == null) return coord2; if (coord2 == null) return coord1; return new Coordinate(Math.min(coord1.x, coord2.x), Math.min(coord1.y, coord2.y), Math.min(coord1.z, coord2.z)); } public static Coordinate add(Coordinate coord1, Coordinate coord2) { if (coord1 == null) return coord2; if (coord2 == null) return coord1; return new Coordinate(coord1.x+coord2.x, coord1.y+coord2.y, coord1.z+coord2.z); } public static Coordinate sub(Coordinate coord1, Coordinate coord2) { if (coord1 == null) return coord2; if (coord2 == null) return coord1; return new Coordinate(coord1.x-coord2.x, coord1.y-coord2.y, coord1.z-coord2.z); } public boolean isValid() { if (Double.isNaN(this.x) || Double.isInfinite(this.x) || Double.isNaN(this.y) || Double.isInfinite(this.y) || Double.isNaN(this.z) || Double.isInfinite(this.z)) return false; return true; } public String toString() { return ("("+x+","+y+","+z+")"); } } jugglinglab-0.6.2+ds.1/source/jugglinglab/util/ErrorDialog.java000077500000000000000000000142041323754603300243750ustar00rootroot00000000000000// ErrorDialog.java // // Copyright 2002 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.util; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*; import jugglinglab.core.*; public class ErrorDialog implements Runnable { static ResourceBundle guistrings; static ResourceBundle errorstrings; static { guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } Component parent = null; String msg = null; public ErrorDialog(Component parent, String msg) { this.parent = parent; this.msg = msg; SwingUtilities.invokeLater(this); } public void run() { JOptionPane.showMessageDialog(parent, msg, "Error", JOptionPane.ERROR_MESSAGE); } public static void handleException(Exception e) { String exmsg1 = errorstrings.getString("Error_internal_part1"); String exmsg2 = errorstrings.getString("Error_internal_part2"); String exmsg3 = errorstrings.getString("Error_internal_part3"); String exmsg4 = errorstrings.getString("Error_internal_part4"); String exmsg5 = errorstrings.getString("Error_internal_part5"); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); sw.write(errorstrings.getString("Error_internal_msg_part1")+"\n\n"); sw.write(errorstrings.getString("Error_internal_msg_part2")+"\n"+ errorstrings.getString("Error_internal_msg_part3")+"\n\n"); sw.write("Juggling Lab version: "+Constants.version+"\n\n"); e.printStackTrace(pw); sw.write("\n"); // System.getProperties().list(pw); final JFrame exframe = new JFrame(errorstrings.getString("Error_internal_title")); exframe.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); exframe.getContentPane().setLayout(new BorderLayout()); JPanel exp = new JPanel(); exframe.getContentPane().add(exp, BorderLayout.PAGE_START); GridBagLayout gb = new GridBagLayout(); exp.setLayout(gb); JLabel text1 = new JLabel(exmsg1); text1.setFont(new Font("SansSerif", Font.BOLD, 12)); exp.add(text1); gb.setConstraints(text1, make_constraints(GridBagConstraints.LINE_START,0,0, new Insets(10,10,0,10))); JLabel text2 = new JLabel(exmsg2); text2.setFont(new Font("SansSerif", Font.PLAIN, 12)); exp.add(text2); gb.setConstraints(text2, make_constraints(GridBagConstraints.LINE_START,0,1, new Insets(10,10,0,10))); JLabel text3 = new JLabel(exmsg3); text3.setFont(new Font("SansSerif", Font.PLAIN, 12)); exp.add(text3); gb.setConstraints(text3, make_constraints(GridBagConstraints.LINE_START,0,2, new Insets(0,10,0,10))); JLabel text4 = new JLabel(exmsg4); text4.setFont(new Font("SansSerif", Font.PLAIN, 12)); exp.add(text4); gb.setConstraints(text4, make_constraints(GridBagConstraints.LINE_START,0,3, new Insets(0,10,0,10))); JLabel text5 = new JLabel(exmsg5); text5.setFont(new Font("SansSerif", Font.BOLD, 12)); exp.add(text5); gb.setConstraints(text5, make_constraints(GridBagConstraints.LINE_START,0,4, new Insets(10,10,10,10))); JTextArea dumpta = new JTextArea(); dumpta.setText(sw.toString()); dumpta.setCaretPosition(0); JScrollPane jsp = new JScrollPane(dumpta); jsp.setPreferredSize(new Dimension(400,200)); exp.add(jsp); gb.setConstraints(jsp, make_constraints(GridBagConstraints.CENTER,0,5, new Insets(10,10,10,10))); JPanel butp = new JPanel(); butp.setLayout(new FlowLayout(FlowLayout.LEADING)); JButton quitbutton = new JButton(guistrings.getString("Quit")); quitbutton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); } }); butp.add(quitbutton); JButton okbutton = new JButton(guistrings.getString("Continue")); okbutton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { exframe.setVisible(false); exframe.dispose(); } }); butp.add(okbutton); exp.add(butp); gb.setConstraints(butp, make_constraints(GridBagConstraints.LINE_END,0,6, new Insets(10,10,10,10))); Locale loc = JLLocale.getLocale(); exframe.applyComponentOrientation(ComponentOrientation.getOrientation(loc)); exframe.pack(); exframe.setResizable(false); exframe.setVisible(true); } protected static GridBagConstraints make_constraints(int location, int gridx, int gridy, Insets ins) { GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = location; gbc.fill = GridBagConstraints.NONE; gbc.gridheight = gbc.gridwidth = 1; gbc.gridx = gridx; gbc.gridy = gridy; gbc.insets = ins; gbc.weightx = gbc.weighty = 0.0; return gbc; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/util/JLLocale.java000066400000000000000000000045321323754603300236110ustar00rootroot00000000000000// JLLocale.java // // Copyright 2011 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.util; import java.io.UnsupportedEncodingException; import java.util.Enumeration; import java.util.Locale; import java.util.PropertyResourceBundle; import java.util.ResourceBundle; public class JLLocale { static Locale locale; // convenience functions for managing locale public static void setLocale(Locale loc) { JLLocale.locale = loc; } public static Locale getLocale() { if (JLLocale.locale != null) return JLLocale.locale; return Locale.getDefault(); } public static ResourceBundle getBundle(String baseName) { ResourceBundle bundle = null; Locale loc = JLLocale.getLocale(); if (loc == null) bundle = ResourceBundle.getBundle(baseName); // use default else bundle = ResourceBundle.getBundle(baseName, loc); if (!(bundle instanceof PropertyResourceBundle)) return bundle; return new Utf8PropertyResourceBundle((PropertyResourceBundle)bundle); } private static class Utf8PropertyResourceBundle extends ResourceBundle { PropertyResourceBundle bundle; private Utf8PropertyResourceBundle(PropertyResourceBundle bundle) { this.bundle = bundle; } public Enumeration getKeys() { return bundle.getKeys(); } protected Object handleGetObject(String key) { String value = (String)bundle.handleGetObject(key); try { return new String (value.getBytes("ISO-8859-1"),"UTF-8") ; } catch (UnsupportedEncodingException e) { // Shouldn't fail - but should we still add logging message? return null; } } } }jugglinglab-0.6.2+ds.1/source/jugglinglab/util/JLMath.java000066400000000000000000000023471323754603300233050ustar00rootroot00000000000000// JLMath.java // // Copyright 2003 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.util; // Random math functions public class JLMath { public static final double pi = 3.141592653589793238; public static double toRad(double deg) { return (deg * pi / 180.0); } // a choose b public static int choose(int a, int b) { int result = 1; for (int i = 0; i < b; i++) { result *= (a - i); result /= (i + 1); } return result; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/util/JuggleException.java000077500000000000000000000021651323754603300252630ustar00rootroot00000000000000// JuggleException.java // // Copyright 2002 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.util; // This is our own exception class, which we use to handle juggling-related // problems that occur. public class JuggleException extends Exception { public JuggleException() { super(); } public JuggleException(String s) { super(s); } } jugglinglab-0.6.2+ds.1/source/jugglinglab/util/JuggleExceptionDone.java000077500000000000000000000022171323754603300260670ustar00rootroot00000000000000// JuggleExceptionDone.java // // Copyright 2002 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.util; // This is our own exception class, which we use to handle juggling-related // problems that occur. public class JuggleExceptionDone extends JuggleExceptionUser { public JuggleExceptionDone() { super(); } public JuggleExceptionDone(String s) { super(s); } } jugglinglab-0.6.2+ds.1/source/jugglinglab/util/JuggleExceptionInternal.java000077500000000000000000000022331323754603300267540ustar00rootroot00000000000000// JuggleExceptionInternal.java // // Copyright 2002 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.util; // This is our own exception class, which we use to handle juggling-related // problems that occur. public class JuggleExceptionInternal extends JuggleException { public JuggleExceptionInternal() { super(); } public JuggleExceptionInternal(String s) { super(s); } } jugglinglab-0.6.2+ds.1/source/jugglinglab/util/JuggleExceptionUser.java000077500000000000000000000022131323754603300261140ustar00rootroot00000000000000// JuggleExceptionUser.java // // Copyright 2002 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.util; // This is our own exception class, which we use to handle juggling-related // problems that occur. public class JuggleExceptionUser extends JuggleException { public JuggleExceptionUser() { super(); } public JuggleExceptionUser(String s) { super(s); } } jugglinglab-0.6.2+ds.1/source/jugglinglab/util/LabelDialog.java000077500000000000000000000052401323754603300243230ustar00rootroot00000000000000// LabelDialog.java // // Copyright 2002 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.util; import javax.swing.*; import java.awt.*; // import java.awt.event.*; public class LabelDialog implements Runnable { Component parent = null; String title = null; String msg = null; public LabelDialog(Component parent, String title, String msg) { this.parent = parent; this.title = title; this.msg = msg; SwingUtilities.invokeLater(this); } public void run() { JOptionPane.showMessageDialog(parent, msg, title, JOptionPane.INFORMATION_MESSAGE); } } /* public class LabelDialog extends JDialog { Button okbutton; protected final static int border = 10; public LabelDialog(Frame parent, String title, String text) { super(parent, title, true); this.setResizable(false); GridBagLayout gb = new GridBagLayout(); this.setLayout(gb); int pbtopborder = 0; if (text != null) { Label lab = new Label(text); this.add(lab); gb.setConstraints(lab, make_constraints(GridBagConstraints.LINE_START,0,0, new Insets(border,border,10,border))); } else pbtopborder = border; okbutton = new Button("OK"); okbutton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { setVisible(false); dispose(); } }); this.add(okbutton); gb.setConstraints(okbutton, make_constraints(GridBagConstraints.LINE_END,0,2, new Insets(0,border,border,border))); this.pack(); this.show(); } protected GridBagConstraints make_constraints(int location, int gridx, int gridy, Insets ins) { GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = location; gbc.fill = GridBagConstraints.NONE; gbc.gridheight = gbc.gridwidth = 1; gbc.gridx = gridx; gbc.gridy = gridy; gbc.insets = ins; gbc.weightx = gbc.weighty = 0.0; return gbc; } } */ jugglinglab-0.6.2+ds.1/source/jugglinglab/util/ParameterDescriptor.java000066400000000000000000000030061323754603300261360ustar00rootroot00000000000000// ParameterDescriptor.java // // Copyright 2002 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.util; import java.util.*; import javax.swing.*; public class ParameterDescriptor { public static final int TYPE_BOOLEAN = 1; public static final int TYPE_FLOAT = 2; public static final int TYPE_CHOICE = 3; public static final int TYPE_INT = 4; public static final int TYPE_ICON = 5; public String name; public int type; public Vector range; public Object default_value; public Object value; public ParameterDescriptor(String name, int type, Vector range, Object default_value, Object value) { this.name = name; this.type = type; this.range = range; this.default_value = default_value; this.value = value; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/util/ParameterList.java000077500000000000000000000053371323754603300247470ustar00rootroot00000000000000// ParameterList.java // // Copyright 2002 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.util; import java.util.*; public class ParameterList { protected int size; protected Vector names; protected Vector values; public ParameterList() { size = 0; } public ParameterList(String source) { this(); this.readParameters(source); } public void addParameter(String name, String value) { if (size == 0) { names = new Vector(); values = new Vector(); } names.addElement(name); values.addElement(value); size++; } public String getParameter(String name) { for (int i = size-1; i >= 0; i--) if (name.equalsIgnoreCase(getParameterName(i))) return getParameterValue(i); return null; } public String getParameterName(int index) { return (String)names.elementAt(index); } public String getParameterValue(int index) { return (String)values.elementAt(index); } public int getNumberOfParameters() { return size; } public void readParameters(String source) { if (source == null) return; StringTokenizer st1 = new StringTokenizer(source, ";"); while (st1.hasMoreTokens()) { String str = st1.nextToken(); int index = str.indexOf("="); if (index > 0) { String name = str.substring(0, index).trim(); String value = str.substring(index + 1).trim(); if ((name.length() != 0) && (value.length() != 0)) addParameter(name, value); } } } public String toString() { String result = ""; for (int i = 0; i < size; i++) { if (i != 0) result += ";"; result += getParameterName(i) + "=" + getParameterValue(i); } return result; } }jugglinglab-0.6.2+ds.1/source/jugglinglab/util/Permutation.java000077500000000000000000000231251323754603300244750ustar00rootroot00000000000000// Permutation.java // // Copyright 2002 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.util; import java.util.*; public class Permutation { protected int size; protected int[] mapping; protected boolean reverses; public Permutation(int n, boolean reverses) { // identity permutation this.size = n; this.reverses = reverses; if (reverses) { mapping = new int[size*2+1]; for (int i = 0; i < (size*2+1); i++) mapping[i] = i-size; } else { mapping = new int[size]; for (int i = 0; i < n; i++) mapping[i] = i+1; } } public Permutation(int n, int[] mapping, boolean reverses) { this.size = n; this.reverses = reverses; this.mapping = mapping; } public Permutation(int n, String perm, boolean reverses) throws JuggleException { int i; boolean[] used; this.size = n; this.reverses = reverses; if (reverses) { mapping = new int[size*2+1]; used = new boolean[size*2+1]; for (i = 0; i < (size*2+1); i++) { mapping[i] = 0; used[i] = false; } } else { mapping = new int[size]; used = new boolean[size]; for (i = 0; i < n; i++) { mapping[i] = 0; used[i] = false; } } // two ways to specify permutation: cycle notation (parenthesis) // and an explicit mapping (comma-separated integers) if (perm.indexOf('(') == -1) { // explicit mapping int num; StringTokenizer st = new StringTokenizer(perm, ","); if (st.countTokens() != size) throw new JuggleException("Permutation init error: must have "+n+ " elements in mapping"); for (i = 0; i < size; i++) { String s = st.nextToken().trim(); try { num = Integer.parseInt(s); } catch (NumberFormatException nfe) { throw new JuggleException("Permutation init error: number format"); } if ((num < 1) || (num > size)) throw new JuggleException("Permutation init error: out of range"); if (used[num-1]) throw new JuggleException("Permutation init error: not one-to-one"); used[num-1] = true; mapping[i] = num; } } else { // cycle notation StringTokenizer st1 = new StringTokenizer(perm, ")"); while (st1.hasMoreTokens()) { String s1 = st1.nextToken().trim(); if (s1.charAt(0) != '(') throw new JuggleException("Permutation init error: parenthesis not grouped"); s1 = s1.substring(1); int num = 0, lastnum = -(size+1); StringTokenizer st2 = new StringTokenizer(s1, ","); while (st2.hasMoreTokens()) { String s2 = st2.nextToken().trim(); try { if (reverses) { boolean negate = false; if (s2.endsWith("*")) { negate = true; s2 = s2.replace('*',' ').trim(); } num = Integer.parseInt(s2); if (negate) num = -num; } else num = Integer.parseInt(s2); } catch (NumberFormatException nfe) { throw new JuggleException("Permutation init error: number format"); } if (reverses) { if ((num < -size) || (num > size) || (num == 0)) throw new JuggleException("Permutation init error: out of range"); if (used[num+size]) throw new JuggleException("Permutation init error: not one-to-one"); used[num+size] = true; if (lastnum == -(size+1)) mapping[num+size] = num; else { mapping[num+size] = mapping[lastnum+size]; mapping[lastnum+size] = num; if (used[-lastnum+size] && (mapping[-lastnum+size] != -num)) throw new JuggleException("Permutation init error: input not reversible"); } } else { if ((num < 1) || (num > size)) throw new JuggleException("Permutation init error: out of range"); if (used[num-1]) throw new JuggleException("Permutation init error: not one-to-one"); used[num-1] = true; if (lastnum == -(size+1)) mapping[num-1] = num; else { mapping[num-1] = mapping[lastnum-1]; mapping[lastnum-1] = num; } } lastnum = num; } } } if (reverses) { for (i = 1; i <= size; i++) { if (used[i+size] && !used[-i+size]) mapping[-i+size] = -mapping[i+size]; else if (!used[i+size] && used[-i+size]) mapping[i+size] = -mapping[-i+size]; else if (!used[i+size] && !used[-i+size]) { mapping[-i+size] = 0; mapping[i+size] = 0; } } } else { for (i = 0; i < size; i++) if (!used[i]) mapping[i] = i+1; } // if (reverses) { // for (i = -size; i <= size; i++) // System.out.println("mapping["+i+"] = "+mapping[i+size]); // } } public String toString() { return this.toString(true); } public String toString(boolean cyclenotation) { int i; String s; if (cyclenotation) { if (reverses) { int start, current; boolean[] printed = new boolean[size]; for (i = 0; i < size; i++) printed[i] = false; s = ""; for (i = 0; i < size; i++) { if (printed[i] == false) { start = i+1; printed[i] = true; current = mapping[start+size]; if (current != 0) { s += "(" + convertReverse(start); while (current != start) { if (current > 0) printed[current-1] = true; else if (current < 0) printed[-current-1] = true; s += "," + convertReverse(current); current = mapping[current+size]; } s += ")"; } } } } else { int start, current, left = size; boolean[] printed = new boolean[size]; for (i = 0; i < size; i++) printed[i] = false; s = ""; while (left > 0) { for (i = 0; i < size; i++) if (printed[i] == false) break; start = i+1; printed[i] = true; s = s + "(" + start; left--; current = mapping[i]; while (current != start) { s = s + "," + current; printed[current-1] = true; left--; current = mapping[current-1]; } s = s + ")"; } } } else { if (reverses) { s = convertReverse(mapping[size+1]); for (i = 1; i < size; i++) s = s + "," + convertReverse(mapping[size+1+i]); } else { s = "" + mapping[0]; for (i = 1; i < size; i++) s = s + "," + mapping[i]; } } return s; } protected String convertReverse(int num) { if (num >= 0) return (""+num); else return ((-num)+"*"); } public int getSize() { return size; } public boolean hasReverses() { return reverses; } public boolean equals(Permutation p) { if (p == null) return false; if (reverses != p.hasReverses()) return false; if (getSize() != p.getSize()) return false; for (int i = 0; i < getSize(); i++) if (getMapping(i+1) != p.getMapping(i+1)) return false; return true; } public int getMapping(int elem) { if (reverses) return mapping[elem+size]; else return mapping[elem-1]; } public int getMapping(int elem, int power) { if (power > 0) { for (int i = 0; i < power; i++) elem = getMapping(elem); } else if (power < 0) { for (int i = power; i < 0; i++) elem = getInverseMapping(elem); } return elem; } public Permutation apply(Permutation firstp) { if (this.getSize() != firstp.getSize()) return null; if (this.hasReverses() || firstp.hasReverses()) return null; int[] res = new int[this.getSize()]; for (int i = 0; i < this.getSize(); i++) res[i] = this.getMapping(firstp.getMapping(i+1)); return new Permutation(this.getSize(), res, false); } public int getInverseMapping(int elem) { if (reverses) { for (int i = 0; i < (2*size+1); i++) if (mapping[i] == elem) return (i-size); } else { for (int i = 0; i < size; i++) { if (mapping[i] == elem) return (i+1); } } return 0; } public Permutation getInverse() { int[] invmapping = null; if (reverses) { invmapping = new int[size*2+1]; for (int i = 0; i < (size*2+1); i++) invmapping[mapping[i]+size] = i-size; } else { invmapping = new int[size]; for (int i = 0; i < size; i++) invmapping[mapping[i]-1] = i+1; } return new Permutation(size, invmapping, reverses); } public static int lcm(int x, int y) { // Euclid's GCD algorithm (x>0, y>0) int x0 = x; int y0 = y; int g = y; while (x > 0) { g = x; x = y % x; y = g; } return (x0*y0)/g; } public int getOrder() { int ord = 1; for (int elem = 1; elem <= size; elem++) if (getMapping(elem) != 0) ord = lcm(ord, getOrder(elem)); return ord; } public int getOrder(int elem) { int index; int ord = 1; index = (reverses ? elem+size : elem-1); while (mapping[index] != elem) { ord++; index = mapping[index] + (reverses ? size : -1); } return ord; } public int[] getCycle(int elem) { int ord = getOrder(elem); int[] result = new int[ord]; int term = elem; for (int i = 0; i < ord; i++) { result[i] = term; term = mapping[(reverses ? term+size : term-1)]; } return result; } }jugglinglab-0.6.2+ds.1/source/jugglinglab/view/000077500000000000000000000000001323754603300213125ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/source/jugglinglab/view/EditView.java000077500000000000000000000071241323754603300237040ustar00rootroot00000000000000// EditView.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.view; import java.awt.*; import java.util.*; import javax.swing.*; import javax.swing.border.*; import jugglinglab.core.*; import jugglinglab.jml.*; import jugglinglab.util.*; public class EditView extends View { protected AnimatorEdit jae = null; protected JPanel ladder = null; static protected int ladder_width = 150; static protected int ladder_min_width = 80; public EditView(Dimension dim) { this.setLayout(new BorderLayout()); this.jae = new AnimatorEdit(); jae.setJAPreferredSize(dim); this.ladder = new JPanel(); ladder.setLayout(new BorderLayout()); ladder.setPreferredSize(new Dimension(ladder_width, 1)); ladder.setMinimumSize(new Dimension(ladder_min_width, 1)); ladder.setBackground(Color.white); JSplitPane jsp = null; Locale loc = JLLocale.getLocale(); if (ComponentOrientation.getOrientation(loc) == ComponentOrientation.LEFT_TO_RIGHT) { jsp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, jae, ladder); jsp.setResizeWeight(1.0); } else { jsp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, ladder, jae); jsp.setResizeWeight(0.0); } jsp.setBorder(new EmptyBorder(0,0,0,0)); jsp.setBackground(Color.white); this.setBackground(Color.white); this.add(jsp, BorderLayout.CENTER); } public void restartView() throws JuggleExceptionUser, JuggleExceptionInternal { jae.restartJuggle(); } public void restartView(JMLPattern p, AnimatorPrefs c) throws JuggleExceptionUser, JuggleExceptionInternal { jae.restartJuggle(p, c); if (p != null) { LadderDiagram new_ladder; /* if (pat.getNumberOfJugglers() > 1) { new_ladder = new PassLadderDiagram(pat, parent); ((PassLadderDiagram)new_ladder).setAnimator(jae); } else {*/ new_ladder = new EditLadderDiagram(p, parent); ((EditLadderDiagram)new_ladder).setAnimator(jae); // } jae.setLadderDiagram(new_ladder); jae.deactivateEvent(); new_ladder.setPreferredSize(new Dimension(ladder_width, 1)); new_ladder.setMinimumSize(new Dimension(ladder_min_width, 1)); this.ladder.removeAll(); this.ladder.add(new_ladder, BorderLayout.CENTER); this.ladder.validate(); } } public Dimension getAnimatorSize() { return jae.getSize(new Dimension()); } public void dispose() { jae.dispose(); } public JMLPattern getPattern() { return jae.getPattern(); } public boolean getPaused() { return jae.getPaused(); } public void setPaused(boolean pause) { if (jae.message == null) jae.setPaused(pause); } } jugglinglab-0.6.2+ds.1/source/jugglinglab/view/JMLView.java000077500000000000000000000157711323754603300234500ustar00rootroot00000000000000// JMLView.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.view; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*; import java.text.MessageFormat; import javax.swing.*; import javax.swing.event.*; import org.xml.sax.*; import jugglinglab.core.*; import jugglinglab.jml.*; import jugglinglab.util.*; public class JMLView extends View { protected boolean isdirty = false; protected Animator ja = null; protected JTextArea ta = null; protected JButton compile = null; protected JButton revert = null; // protected JLabel dirty = null; protected JLabel lab = null; public JMLView(Dimension dim) { this.setLayout(new BorderLayout()); this.ja = new Animator(); //ja.setPreferredSize(dim); ja.setJAPreferredSize(dim); //ja.setMinimumSize(dim); this.ta = new JTextArea(); // ta.setPreferredSize(new Dimension(400,1)); ChangeListener myListener = new ChangeListener(); this.ta.getDocument().addDocumentListener(myListener); JScrollPane jscroll = new JScrollPane(ta); jscroll.setPreferredSize(new Dimension(400,1)); if (true /*PlatformSpecific.getPlatformSpecific().isMacOS()*/) { jscroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); jscroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); } JSplitPane jsp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, ja, jscroll); this.add(jsp, BorderLayout.CENTER); JPanel lower = new JPanel(); lower.setLayout(new FlowLayout(FlowLayout.LEADING)); this.compile = new JButton(guistrings.getString("JMLView_compile_button")); compile.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { try { JMLView.this.compilePattern(); } catch (Exception e) { jugglinglab.util.ErrorDialog.handleException(e); } } }); lower.add(compile); this.revert = new JButton(guistrings.getString("JMLView_revert_button")); revert.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { try { JMLView.this.revertPattern(); } catch (Exception e) { jugglinglab.util.ErrorDialog.handleException(e); } } }); lower.add(revert); /* java.net.URL url = this.getClass().getResource("/images/ball.gif"); if (url != null) { ImageIcon aboutPicture = new ImageIcon(url); if (aboutPicture != null) this.dirty = new JLabel(aboutPicture); } lower.add(dirty);*/ this.lab = new JLabel(""); lower.add(lab); this.add(lower, BorderLayout.PAGE_END); } public void restartView() { try { ja.restartJuggle(); } catch (JuggleException je) { lab.setText(je.getMessage()); } } public void restartView(JMLPattern p, AnimatorPrefs c) { try { ja.restartJuggle(p, c); updateTextArea(); lab.setText(""); setDirty(false); if (p != null) parent.setTitle(p.getTitle()); } catch (JuggleException je) { lab.setText(je.getMessage()); setDirty(true); } catch (IOException ioe) { lab.setText(ioe.getMessage()); setDirty(true); } } public Dimension getAnimatorSize() { return ja.getSize(new Dimension()); } public void dispose() { ja.dispose(); } public JMLPattern getPattern() { return ja.getPattern(); } public boolean getPaused() { return ja.getPaused(); } public void setPaused(boolean pause) { if (ja.message == null) ja.setPaused(pause); } protected void compilePattern() { if (isdirty) { try { JMLPattern newpat = new JMLPattern(new StringReader(ta.getText())); ja.restartJuggle(newpat, null); lab.setText(""); parent.setTitle(newpat.getTitle()); updateTextArea(); setDirty(false); } catch (JuggleExceptionUser jeu) { lab.setText(jeu.getMessage()); setDirty(true); } catch (JuggleExceptionInternal jei) { ErrorDialog.handleException(jei); setDirty(true); } catch (SAXParseException spe) { String template = errorstrings.getString("Error_parsing"); Object[] arguments = { new Integer(spe.getLineNumber()) }; lab.setText(MessageFormat.format(template, arguments)); setDirty(true); } catch (SAXException se) { lab.setText(se.getMessage()); setDirty(true); } catch (IOException ioe) { ErrorDialog.handleException(ioe); setDirty(true); } } } protected void revertPattern() { if (isdirty) { try { updateTextArea(); lab.setText(""); setDirty(false); } catch (IOException ioe) { lab.setText(ioe.getMessage()); } } } protected void updateTextArea() throws IOException { StringWriter sw = new StringWriter(); ja.getPattern().writeJML(sw, true); sw.close(); ta.setText(sw.toString()); ta.setCaretPosition(0); } protected void setDirty(boolean dirty) { this.isdirty = dirty; // this.dirty.setVisible(dirty); this.compile.setEnabled(dirty); this.revert.setEnabled(dirty); } class ChangeListener implements DocumentListener { public void insertUpdate(DocumentEvent e) { JMLView.this.setDirty(true); } public void removeUpdate(DocumentEvent e) { JMLView.this.setDirty(true); } public void changedUpdate(DocumentEvent e) { JMLView.this.setDirty(true); } } } jugglinglab-0.6.2+ds.1/source/jugglinglab/view/Mutator.java000077500000000000000000000030311323754603300236100ustar00rootroot00000000000000// Mutator.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.view; import javax.swing.*; import jugglinglab.jml.*; /* Possible mutations: 1) Change positions of events (in-plane) 2) Change positions of events (out of plane) 3) Change times of events 4) Add new events 5) Remove events 6) Change throw types 7) Add throw/catch pair */ public class Mutator { protected JPanel controls = null; public Mutator() { } public JMLPattern mutatePattern(JMLPattern pat) { return pat; } public JPanel getControlPanel() { if (controls == null) controls = makeControlPanel(); return controls; } protected JPanel makeControlPanel() { JPanel p = new JPanel(); p.add(new JButton("Hello")); return p; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/view/NormalView.java000077500000000000000000000040411323754603300242420ustar00rootroot00000000000000// NormalView.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.view; import java.awt.*; import javax.swing.*; import jugglinglab.core.*; import jugglinglab.jml.*; import jugglinglab.util.*; public class NormalView extends View { protected Animator ja = null; public NormalView(Dimension dim) { this.ja = new Animator(); // ja.setPreferredSize(dim); ja.setJAPreferredSize(dim); this.setLayout(new BorderLayout()); this.add(ja, BorderLayout.CENTER); } public void restartView() throws JuggleExceptionUser, JuggleExceptionInternal { ja.restartJuggle(); } public void restartView(JMLPattern p, AnimatorPrefs c) throws JuggleExceptionUser, JuggleExceptionInternal { ja.restartJuggle(p, c); } public Dimension getAnimatorSize() { return ja.getSize(new Dimension()); } public void dispose() { ja.dispose(); } public JMLPattern getPattern() { return ja.getPattern(); } public boolean getPaused() { return ja.getPaused(); } public void setPaused(boolean pause) { if (ja.message == null) ja.setPaused(pause); } // The following is needed by the GIF saver public Animator getAnimator() { return ja; } } jugglinglab-0.6.2+ds.1/source/jugglinglab/view/SelectionView.java000077500000000000000000000117641323754603300247510ustar00rootroot00000000000000// SelectionView.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.view; import javax.swing.*; import java.awt.*; import java.awt.event.*; import jugglinglab.core.*; import jugglinglab.jml.*; import jugglinglab.util.*; public class SelectionView extends View { protected Animator[] ja = null; protected Mutator mutator = null; protected Dimension dtemp = null; public SelectionView(Dimension dim) { this.dtemp = new Dimension(); final JPanel pleft = new JPanel() { public void paint(Graphics g) { super.paint(g); ja[0].getSize(dtemp); int vline1x = dtemp.width; int vline2x = 2 * vline1x; int hline1y = dtemp.height; int hline2y = 2 * hline1y; int w = 3 * vline1x; int h = 3 * hline1y; g.setColor(Color.black); g.drawLine(vline1x, hline1y, vline1x, hline2y); g.drawLine(vline1x, hline2y, vline2x, hline2y); g.drawLine(vline2x, hline2y, vline2x, hline1y); g.drawLine(vline2x, hline1y, vline1x, hline1y); int x, y, width; Dimension appdim = this.getSize(); int appWidth = appdim.width; int appHeight = appdim.height; FontMetrics fm = g.getFontMetrics(); String message = "Selection view isn't working yet"; width = fm.stringWidth(message); x = (appWidth > width) ? (appWidth-width)/2 : 0; y = (appHeight + fm.getHeight()) / 2; g.setColor(this.getBackground()); g.fillRect(x-10, appHeight/2 - fm.getHeight(), width+20, 2*fm.getHeight()); g.setColor(Color.black); g.drawString(message, x, y); } }; pleft.setLayout(new GridLayout(3,3)); this.ja = new Animator[9]; for (int i = 0; i < 9; i++) { ja[i] = new Animator(); ja[i].setJAPreferredSize(dim); pleft.add(ja[i]); } pleft.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent me) { } public void mouseReleased(MouseEvent me) { Component c = me.getComponent(); int num; for (num = 0; num < 9; num++) { if (c == SelectionView.this.ja[num]) break; } if (num == 9) return; try { SelectionView.this.restartView(ja[num].getPattern(), null); } catch (final JuggleExceptionUser jeu) { SwingUtilities.invokeLater(new Runnable() { public void run() { new ErrorDialog(SelectionView.this, jeu.getMessage()); } }); } catch (final JuggleExceptionInternal jei) { ErrorDialog.handleException(jei); } } }); this.mutator = new Mutator(); final JPanel pright = mutator.getControlPanel(); GridBagLayout gb = new GridBagLayout(); this.setLayout(gb); this.add(pleft); GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = GridBagConstraints.LINE_START; gbc.fill = GridBagConstraints.BOTH; gbc.gridheight = gbc.gridwidth = 1; gbc.gridx = 0; gbc.gridy = 0; gbc.weightx = gbc.weighty = 1.0; gb.setConstraints(pleft, gbc); this.add(pright); gbc = new GridBagConstraints(); gbc.anchor = GridBagConstraints.FIRST_LINE_START; gbc.fill = GridBagConstraints.NONE; gbc.gridheight = gbc.gridwidth = 1; gbc.gridx = 1; gbc.gridy = 0; gbc.weightx = 0.0; gbc.weighty = 1.0; gb.setConstraints(pright, gbc); } public void restartView() throws JuggleExceptionUser, JuggleExceptionInternal { for (int i = 0; i < 9; i++) ja[i].restartJuggle(); } public void restartView(JMLPattern p, AnimatorPrefs c) throws JuggleExceptionUser, JuggleExceptionInternal { ja[4].restartJuggle(p, c); for (int i = 0; i < 9; i++) { if (i != 4) { JMLPattern newpat = mutator.mutatePattern(p); ja[i].restartJuggle(newpat, c); } } } public Dimension getAnimatorSize() { return ja[4].getSize(new Dimension()); } public void dispose() { for (int i = 0; i < 9; i++) ja[i].dispose(); } public JMLPattern getPattern() { return ja[4].getPattern(); } public boolean getPaused() { return ja[4].getPaused(); } public void setPaused(boolean pause) { /* if (ja[4].message == null) for (int i = 0; i < 9; i++) ja[i].setPaused(pause); */ } } jugglinglab-0.6.2+ds.1/source/jugglinglab/view/View.java000077500000000000000000000413171323754603300231000ustar00rootroot00000000000000// View.java // // Copyright 2004 by Jack Boyce (jboyce@users.sourceforge.net) and others /* This file is part of Juggling Lab. Juggling Lab is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Juggling Lab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Juggling Lab; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package jugglinglab.view; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*; import javax.swing.*; import jugglinglab.core.*; import jugglinglab.jml.*; import jugglinglab.util.*; public class View extends JPanel implements ActionListener { static ResourceBundle guistrings; static ResourceBundle errorstrings; static { guistrings = JLLocale.getBundle("GUIStrings"); errorstrings = JLLocale.getBundle("ErrorStrings"); } protected JFrame parent = null; protected Dimension animsize = null; protected AnimatorPrefs jc = null; protected JMLPattern pat = null; protected View subview = null; public View() {} public View(JFrame p, Dimension animsize) { setParent(p); this.animsize = animsize; this.jc = new AnimatorPrefs(); } protected void setParent(JFrame p) { this.parent = p; } public void restartView() throws JuggleExceptionUser, JuggleExceptionInternal { if (subview != null) subview.restartView(); } // In the following, a null argument means no update for that item public void restartView(JMLPattern p, AnimatorPrefs c) throws JuggleExceptionUser, JuggleExceptionInternal { if (p != null) this.pat = p; if (c != null) this.jc = c; if (subview != null) subview.restartView(p, c); } public Dimension getAnimatorSize() { if (subview != null) return subview.getAnimatorSize(); return null; } public void dispose() { if (subview != null) subview.dispose(); subview = null; } public JMLPattern getPattern() { return pat; } public boolean getPaused() { if (subview != null) return subview.getPaused(); return false; } public void setPaused(boolean pause) { if (subview != null) subview.setPaused(pause); } protected static final String[] fileItems = new String[] { "Close", null, "Save JML As...", "Save Animated GIF As...", "Save HTML As..." }; protected static final String[] fileCommands = new String[] { "close", null, "saveas", "savegifanim", "savehtml" }; protected static final char[] fileShortcuts = { 'W', ' ', 'S', ' ', ' ' }; public JMenu createFileMenu() { JMenu filemenu = new JMenu(guistrings.getString("File")); for (int i = 0; i < fileItems.length; i++) { if (fileItems[i] == null) filemenu.addSeparator(); else { JMenuItem fileitem = new JMenuItem(guistrings.getString(fileItems[i].replace(' ', '_'))); if (fileShortcuts[i] != ' ') fileitem.setAccelerator(KeyStroke.getKeyStroke(fileShortcuts[i], Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); fileitem.setActionCommand(fileCommands[i]); fileitem.addActionListener(this); filemenu.add(fileitem); } } return filemenu; } protected static final String[] viewItems = new String[] { "Simple", "Visual editor", /*"Selection editor",*/ "JML editor", null, "Restart", "Animation Preferences..." }; protected static final String[] viewCommands = new String[] { "simple", "edit", /*"selection",*/ "jml", null, "restart", "prefs" }; protected static final char[] viewShortcuts = { '1', '2', '3', /*'4',*/ ' ', ' ', 'P' }; public JMenu createViewMenu() { JMenu viewmenu = new JMenu(guistrings.getString("View")); ButtonGroup buttonGroup = new ButtonGroup(); boolean addingviews = true; for (int i = 0; i < viewItems.length; i++) { if (viewItems[i] == null) { viewmenu.addSeparator(); addingviews = false; } else if (addingviews) { JRadioButtonMenuItem viewitem = new JRadioButtonMenuItem(guistrings.getString(viewItems[i].replace(' ', '_'))); if (viewShortcuts[i] != ' ') viewitem.setAccelerator(KeyStroke.getKeyStroke(viewShortcuts[i], Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); viewitem.setActionCommand(viewCommands[i]); viewitem.addActionListener(this); viewmenu.add(viewitem); buttonGroup.add(viewitem); } else { JMenuItem viewitem = new JMenuItem(guistrings.getString(viewItems[i].replace(' ', '_'))); if (viewShortcuts[i] != ' ') viewitem.setAccelerator(KeyStroke.getKeyStroke(viewShortcuts[i], Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); viewitem.setActionCommand(viewCommands[i]); viewitem.addActionListener(this); viewmenu.add(viewitem); } } // viewmenu.getItem(0).setSelected(true); // start in Normal view return viewmenu; } public void actionPerformed(ActionEvent ae) { String command = ae.getActionCommand(); try { if (command.equals("close")) doMenuCommand(FILE_CLOSE); else if (command.equals("saveas")) doMenuCommand(FILE_SAVE); else if (command.equals("savegifanim")) { if (jugglinglab.core.Constants.INCLUDE_GIF_SAVE) doMenuCommand(FILE_GIFSAVE); } else if (command.equals("savehtml")) doMenuCommand(FILE_HTMLSAVE); else if (command.equals("restart")) doMenuCommand(VIEW_RESTART); else if (command.equals("prefs")) doMenuCommand(VIEW_ANIMPREFS); else if (command.equals("simple")) { if (getViewMode() != VIEW_SIMPLE) { setViewMode(VIEW_SIMPLE); if (parent != null) parent.pack(); restartView(pat, jc); } } else if (command.equals("edit")) { if (getViewMode() != VIEW_EDIT) { setViewMode(VIEW_EDIT); if (parent != null) parent.pack(); restartView(pat, jc); } } else if (command.equals("jml")) { if (getViewMode() != VIEW_JML) { setViewMode(VIEW_JML); if (parent != null) parent.pack(); restartView(pat, jc); } } else if (command.equals("selection")) { if (getViewMode() != VIEW_SELECTION) { setViewMode(VIEW_SELECTION); if (parent != null) parent.pack(); restartView(pat, jc); } } } catch (JuggleExceptionUser je) { new ErrorDialog(this, je.getMessage()); } catch (Exception e) { jugglinglab.util.ErrorDialog.handleException(e); } } public static final int FILE_NONE = 0; public static final int FILE_CLOSE = 1; public static final int FILE_SAVE = 2; public static final int FILE_GIFSAVE = 3; public static final int FILE_HTMLSAVE = 4; public static final int VIEW_RESTART = 5; public static final int VIEW_ANIMPREFS = 6; public void doMenuCommand(int action) throws JuggleExceptionInternal { switch (action) { case FILE_NONE: break; case FILE_CLOSE: parent.dispose(); break; case FILE_SAVE: if (getPattern().isValid()) { try { int option = PlatformSpecific.getPlatformSpecific().showSaveDialog(this); if (option == JFileChooser.APPROVE_OPTION) { if (PlatformSpecific.getPlatformSpecific().getSelectedFile() != null) { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); FileWriter fw = new FileWriter(PlatformSpecific.getPlatformSpecific().getSelectedFile()); PrintWriter write = new PrintWriter(fw); getPattern().writeJML(fw, true); fw.close(); } } } catch (FileNotFoundException fnfe) { throw new JuggleExceptionInternal("FileNotFound: "+fnfe.getMessage()); } catch (IOException ioe) { throw new JuggleExceptionInternal("IOException: "+ioe.getMessage()); } finally { setCursor(Cursor.getDefaultCursor()); } } else { new ErrorDialog(this, "Could not save: pattern is not valid"); } break; case FILE_GIFSAVE: if (jugglinglab.core.Constants.INCLUDE_GIF_SAVE) { if (getViewMode() == VIEW_SIMPLE) { NormalView nv = (NormalView)subview; Animator ja = nv.getAnimator(); if (!ja.isAnimInited()) break; ja.writeGIFAnim(); } else { new LabelDialog(this, "Not available", "Switch to Simple view to save an animated GIF"); } } break; case FILE_HTMLSAVE: if (getPattern().isValid()) { try { int option = PlatformSpecific.getPlatformSpecific().showSaveDialog(this); if (option == JFileChooser.APPROVE_OPTION) { if (PlatformSpecific.getPlatformSpecific().getSelectedFile() != null) { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); FileWriter fw = new FileWriter(PlatformSpecific.getPlatformSpecific().getSelectedFile()); PrintWriter pw = new PrintWriter(fw); String config = null; Dimension dim = null; if (this.getViewMode() == VIEW_EDIT) { config = "entry=none;view=edit"; dim = getSize(); } else { config = "entry=none;view=simple"; dim = getAnimatorSize(); } String prefs = this.jc.toString(); int w = dim.width; int h = dim.height; JMLPattern pat = getPattern(); pw.println(""); pw.println(""); pw.println(""); pw.println(""); pw.println(""+JMLNode.xmlescape(pat.getTitle())+""); pw.println(""); pw.println(""); pw.println(""); pw.println(""); if (prefs.length() != 0) pw.println(""); pw.println(""); pw.println(""); pw.println("Java not available"); pw.println(""); pw.println(""); pw.println(""); pw.flush(); fw.close(); } } } catch (FileNotFoundException fnfe) { throw new JuggleExceptionInternal("FileNotFound: "+fnfe.getMessage()); } catch (IOException ioe) { throw new JuggleExceptionInternal("IOException: "+ioe.getMessage()); } finally { setCursor(Cursor.getDefaultCursor()); } } else { new ErrorDialog(this, "Could not save: pattern is not valid"); } break; case VIEW_RESTART: try { restartView(); } catch (JuggleExceptionUser je) { new ErrorDialog(this, je.getMessage()); } catch (JuggleException je) { throw new JuggleExceptionInternal(je.getMessage()); } break; case VIEW_ANIMPREFS: AnimatorPrefsDialog japd = new AnimatorPrefsDialog(parent); // AnimatorPrefs oldjc = this.getAnimator().getAnimatorPrefs(); AnimatorPrefs newjc = japd.getPrefs(this.jc); if (newjc != jc) { // user made change? setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); this.jc = newjc; try { restartView(null, newjc); } catch (JuggleExceptionUser je) { new ErrorDialog(this, je.getMessage()); } catch (JuggleException je) { throw new JuggleExceptionInternal(je.getMessage()); } finally { setCursor(Cursor.getDefaultCursor()); } } break; } } // these should be in the same order as in the View menu public static final int VIEW_NONE = 0; public static final int VIEW_SIMPLE = 1; public static final int VIEW_EDIT = 2; public static final int VIEW_SELECTION = 3; public static final int VIEW_JML = 4; public void setViewMode(int mode) throws JuggleExceptionUser, JuggleExceptionInternal { View newview = null; boolean paused = false; if (subview != null) { animsize = subview.getAnimatorSize(); pat = subview.getPattern(); // retrieve possibly edited pattern from old view paused = subview.getPaused(); remove(subview); } switch (mode) { case VIEW_NONE: break; case VIEW_SIMPLE: newview = new NormalView(animsize); break; case VIEW_EDIT: newview = new EditView(animsize); break; case VIEW_JML: newview = new JMLView(animsize); break; case VIEW_SELECTION: newview = new SelectionView(animsize); break; } if (newview == null) return; GridBagLayout gb = new GridBagLayout(); this.setLayout(gb); this.add(newview); GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = GridBagConstraints.LINE_START; gbc.fill = GridBagConstraints.BOTH; gbc.gridwidth = gbc.gridheight = 1; gbc.gridx = 0; gbc.gridy = 0; gbc.insets = new Insets(0,0,0,0); gbc.weightx = 1.0; gbc.weighty = 1.0; gb.setConstraints(newview, gbc); newview.setParent(parent); newview.setPaused(paused); if (subview != null) subview.dispose(); subview = newview; } protected int getViewMode() { if (subview == null) return VIEW_NONE; if (subview instanceof NormalView) return VIEW_SIMPLE; if (subview instanceof EditView) return VIEW_EDIT; if (subview instanceof JMLView) return VIEW_JML; if (subview instanceof SelectionView) return VIEW_SELECTION; return VIEW_NONE; } } jugglinglab-0.6.2+ds.1/source/resources/000077500000000000000000000000001323754603300200655ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/source/resources/ErrorStrings.properties000066400000000000000000000205741323754603300246560ustar00rootroot00000000000000# ErrorStrings.properties # # This properties file defines language-specific text visible in the # Juggling Lab user error messages # # Language for this file = United States English # Error_config_syntax = Syntax error in 'config' Error_config_option = Unrecognized option in 'config' Error_URL_syntax = Syntax error in pattern file URL Error_reading_pattern = Problem reading pattern file Error_parsing_pattern = Problem parsing pattern file Error_reading_JML = Problem reading JML pattern Error_parsing_JML = Problem parsing JML pattern Error_no_pattern = No pattern specified Error_number_format = Number format error in ''{0}'' value Error_parsing = Parsing error at line {0,number,integer} Error_invalid_JML = File not valid JML Error_file_not_found = File not found Error_IO = IO error Error_internal_part1 = Juggling Lab had an internal error that should not have occurred. Error_internal_part2 = Please help us make Juggling Lab better by emailing the debugging Error_internal_part3 = information below to jboyce@users.sourceforge.net, along with a Error_internal_part4 = detailed description of the user actions that led to the error. Error_internal_part5 = You may want to restart Juggling Lab to avoid erratic behavior. Error_internal_msg_part1 = Juggling Lab internal error report Error_internal_msg_part2 = Please email to jboyce@users.sourceforge.net, along with a detailed Error_internal_msg_part3 = description of the user actions that led to the error. Error_internal_title = Juggling Lab internal error Error_missing_JML_tag = Missing or misplaced tag Error_missing_patternlist_tag = Missing or misplaced tag Error_illegal_tag = Illegal tag in pattern list XML Error_generator_insufficient_input = Must specify number of balls, max throw, and period Error_generator_too_few_balls = Must have at least 1 object Error_generator_must_be_prime_mode = Must specify max period if not in prime mode Error_generator_underspecified = Either max throw or period must be specified Error_generator_height_too_small = Maximum throw must be at least 1 Error_generator_period_problem = Syntax error in period Error_passing_leader_number = passing leader number Error_excluded_throws = Format error in excluded throws Error_excluded_passes = Format error in excluded passes Error_included_throws = Format error in included throws Error_unrecognized_option = Unrecognized option ''{0}'' Error_included_excluded_clash = Included and excluded throws clash Error_period_multiple = Pattern period must be a multiple of {0,number,integer} Error_juggler_permutations = Must include juggler permutations when generating only ground or excited state patterns Error = Error Error_hand_name = Unrecognized hand name Error_event_coordinate = Number format error in coordinate value Error_unspecified_hand = Must specify hand in event Error_juggler_out_of_range = Juggler number is out of range Error_no_path = Must specify path attribute in tag Error_path_out_of_range = Path number is out of range Error_event_subtag = Tags within cannot have subtags Error_juggler_outofrange = Juggler number is out of range Error_no_left_events = No events for left hand of juggler {0,number,integer} Error_no_right_events = No events for right hand of juggler {0,number,integer} Error_no_path_events = No events for path {0,number,integer} Error_successive_throws = Successive throws on path {0,number,integer} Error_juggler_changed = Juggler number changed during carry on path {0,number,integer} Error_hand_changed = Hand changed during carry on path {0,number,integer} Error_successive_catches = Successive catches on path {0,number,integer} Error_setup_tag = Error in tag Error_prop_assignments = Wrong number of prop assignments in tag Error_prop_number = Prop number out of range in tag Error_prop_format = Number format error prop assignment in tag Error_unknown_tag = Unknown tag ''{0}'' Error_position_coordinate = Number format error in coordinate value Error_position_nojuggler = Must specify juggler in tag Error_position_subtag = tag cannot have subtags Error_symmetry_format = Number format error in tag Error_symmetry_notype = No symmetry type specified in tag Error_symmetry_type = Unrecognized symmetry type in tag Error_body_noparen = Missing ')' in body coordinate Error_body_coordinate = Number format error in body coordinate Error_body_character = Unknown character ''{0}'' in body specifier Error_body_badending = Body specifier must end with '.' Error_hands_toofewcoords = Must have at least 2 coordinates per throw in \"hands\" Error_hands_nothrow = Must specify throw coordinate Error_hands_nocatch = Must specify catch coordinate Error_hands_Tnotstart = 'T' must be first coordinate Error_hands_toomanycoords = Can only specify one throw coordinate Error_hands_Catstart = First coordinate in \"hands\" must be a throw Error_hands_toomanycatches = Can only specify one catch coordinate Error_hands_noparen = Missing ')' in hands coordinate Error_hands_coordinate = Number format error in hand coordinate Error_hands_character = Unknown character ''{0}'' in hands specifier Error_hands_badending = Hands specifier must end with '.' Error_badpattern = Pattern is not valid Error_badpattern_paths = Pattern is not valid (discontinuous paths) Error_badpattern_delay = Pattern is not valid (delay symmetry not valid) Error_badpattern_switchdelay = Pattern is not valid (switchdelay symmetry not valid) Error_unknown_symmetry = Unrecognized symmetry type Error_bps_value = Number format error in 'bps' value Error_dwell_value = Number format error in 'dwell' value Error_color_format = Error in color format Error_notation_bad = Notation type bad Error_notation_notfound = Notation type not found Error_notation_cantaccess = Cannot access notation (security restricted) Error_notation_cantcreate = Cannot create notation Error_jugglers_body = Too few jugglers in 'body' setting Error_siteswap_nobraces = Must use braces with multiple throws Error_siteswap_nozero = Cannot have 0 in multiplexed throw Error_siteswap_target = Target juggler not valid Error_siteswap_canthold = Cannot hold a throw going to another hand Error_siteswap_badmod = Misplaced throw modifier in pattern Error_siteswap_braces_mismatched = Mismatched braces in pattern Error_siteswap_passing_brackets = '>' with no corresponding '<' Error_siteswap_jugglers = Inconsistent number of jugglers across throws Error_siteswap_badchar = Bad character in solo pattern Error_siteswap_bad_average = Invalid pattern average Error_siteswap_syntax = Syntax error in pattern Error_siteswap_badchar_parens = Unknown character outside parenthesis Error_siteswap_oddthrow = Throw values must be even Error_siteswap_parens_mismatched = Mismatched parenthesis in pattern Error_siteswap_comma = Misplaced comma in pattern Error_siteswap_commas = Too many commas in pattern Error_siteswap_braces_parens = Braces must be inside parenthesis Error_siteswap_parens_brackets = Parenthesis must be inside '<' and '>' Error_siteswap_braces_brackets = Braces must be inside '<' and '>' Error_siteswap_brackets_mismatched = '>' with no corresponding '<' Error_siteswap_parens_bar = Parenthesis must be inside '|' Error_siteswap_braces_bar = Braces must be inside '|' Error_siteswap_nobar = Cannot have '|' in solo pattern Error_path_badmod = Unknown throw modifier Error_prop_color = Prop color ''{0}'' not recognized Error_prop_diameter = Prop diameter value must be positive Error_JML_filename = JML file name cannot contain '.' Error_JML_extension = JML file name must have '.jml' extension Error_no_JML_specified = No JML file name specified Error_JML_is_pattern_list = JML file is a pattern list Error_could_not_launch_editor = Could not launch editor Error_no_pattern_specified = No pattern specified Error_malformed_URL = Malformed URL Error_bad_file = Unable to open file Error_security_restriction = Java security manager will not allow Juggling Lab to access the remote file Error_pattern_syntax = Cannot parse character ''{0}'' at position {1,number,integer} in the pattern Error_prop_type = Prop type ''{0}'' not recognized Error_token_count = Must have three values in color specification Error_missing_pattern = JML pattern expected inside line tag {0,number,integer} Error_reading_file = Could not read file ''{0}'' Error_writing_file = Count not write file ''{0}'' Error_already_12 = JML file is already version 1.2 Error_already_exists = Output file ''{0}'' already exists jugglinglab-0.6.2+ds.1/source/resources/ErrorStrings_he.properties000066400000000000000000000335511323754603300253310ustar00rootroot00000000000000# ErrorStrings.properties # # This properties file defines language-specific text visible in the # Juggling Lab user error messages # # Language for this file = Hebrew # Error_config_syntax = ����� ������ ������� Error_config_option = ������ ���� ����� ������� Error_URL_syntax = ����� ������ ������ ����� ������� Error_reading_pattern = ����� ������ ���� ������� Error_parsing_pattern = ����� ������ ���� ������� Error_reading_JML =����� ������ ���� �JML Error_parsing_JML = ����� ������ ���� �JML Error_no_pattern = �� ����� �� ������ Error_number_format = ����� ����� ������ ������ ''{0}'' Error_parsing = ����� ���� �{0} Error_invalid_JML = ����� ���� JML ���� Error_file_not_found = ���� �� ���� Error_IO = ����� ������ ����� Error_internal_part1 = Juggling Lab ���� ������ ����� ��� ����� ����� ����� Error_internal_part2 = ��� ���� ��� ����� �� Juggling Lab ���� ���� ��� ����� ��� �� ����������� �� ������ Error_internal_part3 = ������ jboyce@users.sourceforge.net, ��� �� ����� ����� �� Error_internal_part4 = ������� ������ ������� ������ Error_internal_part5 = ��� ���� ����� ����� ���� �� Juggling Lab �� ��� ������ �������� ���� ����� Error_internal_msg_part1 = ��� ����� ������ �� Juggling Lab Error_internal_msg_part2 = ��� ��� � jboyce@users.sourceforge.net, ������ ����� Error_internal_msg_part3 =�� ������� ����� ������ ��� �����. Error_internal_title = ��� ����� ������ �� Juggling Lab Error_creating_pattern =����� ������ ������ Error_missing_JML_tag = �� ��� �� ����� ��� ���� Error_missing_patternlist_tag = �� ��� �� ����� ��� ���� Error_illegal_tag = �� ���� ���� ����� ����� ������� Error_generator_insufficient_input =���� ���� ����� ���� ������, ����� �������� ���� Error_generator_too_few_balls = ���� ����� ����� ������� ��� Error_generator_must_be_prime_mode = ���� ����� ��� ������� �� �� ���� ���� Error_generator_underspecified = ���� ����� ����� �������� �� ��� Error_generator_height_too_small = ����� �������� ����� ����� ����� 1 Error_generator_period_problem = ����� ����� ���� Error_passing_leader_number = ���� ����� ������ Error_excluded_throws = ����� ����� ������� ����� Error_excluded_passes = ����� ����� ������� ����� Error_included_throws =����� ����� ������� ����� Error_unrecognized_option = ������ ���� ����� ''{0}'' Error_included_excluded_clash = �� ������� ��� ������� ����� �������� ����� Error_period_multiple = ��� ������ ���� ����� ����� �� {0,number,integer} Error_juggler_permutations = ���� ����� ������ �'������ �������� �� ������ ���� ����� ����� ���� Error = ����� Error_hand_name = �� �� ���� ����� Error_event_coordinate = ����� ������ ����� ����������� Error_unspecified_hand = ���� ����� �� ����� ������ Error_juggler_out_of_range = ���� ��'������ ���� ����� Error_no_path = ���� ����� ������ ��� Error_path_out_of_range =���� ����� ���� ����� Error_event_subtag = ���� ���� �� ������ ����� ��-���� Error_juggler_outofrange = ���� ��'������ ���� ����� Error_no_left_events =��� ������� ��� ���� �� ��'����{0,number,integer} Error_no_right_events =��� ������� ��� ���� �� ��'���� {0,number,integer} Error_no_path_events = ��� ������� ������ {0,number,integer} Error_successive_throws =������ ������ ������ {0,number,integer} Error_juggler_changed = ���� ������� ����� ������ {0,number,integer} Error_hand_changed = ��� ������ ������{0,number,integer} Error_successive_catches = ������ ������ ������ {0,number,integer} Error_setup_tag =����� ��� Error_prop_assignments =����� �� ����� �� ���� ������ ��� Error_prop_number = ���� ����� ���� ����� ��� Error_prop_format = ����� ������ ������ �� ����� ��� Error_unknown_tag = �� ���� ���� ''{0}'' Error_position_coordinate = ����� ������ ����� ����������� � Error_position_nojuggler = ���� ����� �'���� ��� Error_position_subtag = ��� �� ���� ����� ��� ���� Error_symmetry_format = ����� ������ ����� ��� Error_symmetry_notype = �� ����� ��� ������� ��� Error_symmetry_type =��� ������� ���� ����� ��� Error_body_noparen = ����� � ')' ������������ �� ���� Error_body_coordinate = ����� ������ ����� ������������ �� ���� Error_body_character = �� ���� ����� ''{0}'' ������ ���� Error_body_badending = ����� ���� ���� ������� � '.' Error_hands_toofewcoords = ���� ����� ��� ���������� ����� �� ����� � \"�����\" Error_hands_nothrow =���� ����� ���������� ������ Error_hands_nocatch = ���� ����� ���������� ������ Error_hands_Tnotstart = 'T' ���� ����� ���������� ������� Error_hands_toomanycoords = ���� ����� �� ��������� ��� �� ����� Error_hands_Catstart = ���������� ������� � \"�����\" ����� ����� ����� Error_hands_toomanycatches = ���� ����� �� ��������� ��� �� ����� Error_hands_noparen =����� � ')' ����������� �� ������ Error_hands_coordinate = ����� ������ ����� ����������� �� ������ Error_hands_character = �� ���� �����''{0}'' ������ ������ Error_hands_badending = ����� ������ ���� ������� � '.' Error_badpattern = ������ �� ����� Error_badpattern_paths = ������ �� ����� (����� �����) Error_badpattern_delay = ������ �� ����� (������ �������� �� �����) Error_badpattern_switchdelay = ������ �� ����� (����� ������ �������� �� �����) Error_unknown_symmetry = ��� ������� �� ���� Error_bps_value = ����� ������ ���� ���� �� 'bps' Error_dwell_value = ����� ������ ���� ���� �� '����� ���' Error_color_format = ����� ������ ������ Error_notation_bad = ����� ���� ������ Error_notation_notfound = ��� ����� �� ���� Error_notation_cantaccess = �� ���� ����� ���� ������ (����� ��������) Error_notation_cantcreate = �� ���� ����� ���� ������ Error_matstyle_number = ���� ������ �� ���������� � 'mat_style' Error_matstyle_format =����� ������ ����� ����������� �� 'mat_style' Error_matstyle_coords = �� ����� ���������� � 'mat_style' Error_jugglers_body = ��� �� �'������ ������� 'body' Error_siteswap_nobraces =���� ������ �������� ������� ������ Error_siteswap_nozero = ����� ���������� �� ����� ����� 0 Error_siteswap_target = �'���� ����� ���� ���� Error_siteswap_canthold =�� ���� ������ ����� ����� ��� ������ Error_siteswap_badmod =���� ����� ���� ������ ����� ���� ���� Error_siteswap_braces_mismatched = ������� ���� ������� ������ Error_siteswap_passing_brackets = '>' ��� '<' Error_siteswap_jugglers = ���� ���� ���� �� �'������ ������� Error_siteswap_badchar = �� ���� ���� ������ ���� Error_siteswap_bad_average = ����� ����� ���� ���� Error_siteswap_syntax = ����� ����� ������ Error_siteswap_badchar_parens = �� ���� ���� ���� �������� Error_siteswap_oddthrow =���� ������� ������ ����� ������ Error_siteswap_parens_mismatched = ������� ���� ������ ������ Error_siteswap_comma = ���� �� ����� ������ Error_siteswap_commas = ���� ��� ������ ������ Error_siteswap_braces_parens =������� �������� ������ ����� ���� ������� Error_siteswap_parens_brackets = ������� ������ ����� ���� '<' � '>' Error_siteswap_braces_brackets =������� �������� ������ ����� ���� '<' � '>' Error_siteswap_brackets_mismatched = '>' ��� '<' Error_siteswap_parens_bar = ������� ������ ����� ���� '|' Error_siteswap_braces_bar = ������� �������� ������ ����� ���� '|' Error_siteswap_nobar = �� ���� ���� '|' ������� ���� Error_path_badmod = ���� ����� ���� ���� Error_prop_color = ��� ���� ''{0}'' �� ����� Error_prop_diameter = ���� ���� ���� ����� ��� ��� ����� Error_JML_filename = �� ���� �JML �� ���� ����� '.' Error_JML_extension = ���� �JML ���� ����� ��� ����� '.jml' Error_no_JML_specified = �� ���� �� ���� JML Error_JML_is_pattern_list = ���� JML ��� ����� �� ������ Error_could_not_launch_editor = �� ���� ����� �� ����� Error_no_pattern_specified = �� ������ ����� Error_malformed_URL = ����� ����� Error_bad_file = �� ���� ����� ���� Error_security_restriction =���� ������ �� �'���� �� ����� ���� ����� ����� Error_pattern_syntax = �� ���� ���� �� ��� ''{0}'' ������ {1,number,integer} ������ Error_prop_type = ����� ���� ''{0}'' ��������� Error_token_count =���� ����� ����� ����� ������� ���� jugglinglab-0.6.2+ds.1/source/resources/GUIStrings.properties000066400000000000000000000145041323754603300242050ustar00rootroot00000000000000# GUIStrings.properties # # This properties file defines language-specific text visible in the # Juggling Lab GUI # # Language for this file = United States English # Processing = processing... Click_Edit = Click Edit to create pattern Edit = Edit Pattern_entry = Pattern entry Defaults = Defaults Juggle = Juggle Pattern = Pattern Dwell_beats = Dwell beats Beats_per_second = Beats per second Hand_movement = Hand movement Body_movement = Body movement Manual_settings = Manual settings Generator = Generator Run = Run balls = Balls max._throw = Max. throw period = Period Jugglers = Jugglers Rhythm = Rhythm asynch = asynch synch = synch Compositions = Compositions all = all non-obvious = non-obvious none_(prime_only) = none (prime only) Find = Find ground_state_patterns = ground state patterns excited_state_patterns = excited state patterns transition_throws = transition throws pattern_rotations = pattern rotations juggler_permutations = juggler permutations connected_patterns = connected patterns only Multiplexing = Multiplexing enable = enable simultaneous_throws = simultaneous throws no_simultaneous_catches = no simultaneous catches no_clustered_throws = no clustered throws true_multiplexing = true multiplexing only Exclude_these_throws = Exclude these expressions Include_these_throws = Include these expressions Passing_communication_delay = Passing communication delay File = File Notation = Notation Help = Help New_Pattern = New Pattern New_Pattern_List = New Pattern List Open_JML... = Open JML... # Open_Animator_Pattern_List... = Open Animator Pattern List... Convert_JML... = Convert JML to version 1.2... Quit = Quit About_Juggling_Lab = About Juggling Lab Close = Close Save_JML_As... = Save JML As... Save_Text_As... = Save Text As... Patterns = Patterns View = View Save_Animated_GIF_As... = Save Animated GIF As... Save_HTML_As... = Save HTML As... Save_to_Server = Save to Server Restart = Restart Animation_Preferences... = Animation Preferences... Simple = Simple Visual_editor = Visual editor Selection_editor = Selection editor JML_editor = JML editor Animation_Preferences = Animation Preferences Solid_3D_display = Solid 3D display Frames_per_second = Frames per second Slowdown_factor = Slowdown factor Border_(pixels) = Border (pixels) Double-buffered_animation = Double-buffered animation Start_paused = Start paused Pause_on_mouse_away = Pause on mouse away Stereo_display = Stereo display Catch_sounds = Catch sounds Bounce_sounds = Bounce sounds Cancel = Cancel OK = OK Change_title... = Change title... Change_title = Change title Change_overall_timing... = Change overall timing... Change_timing = Change timing Rescale_percentage = Rescale percentage Add_event_to_L_hand = Add event to L hand Add_event_to_R_hand = Add event to R hand Remove_event = Remove event Define_prop... = Define prop... Make_last_in_event = Make last in event Define_throw... = Define throw... Change_to_catch = Change to catch Change_to_softcatch = Change to softcatch Define_prop = Define prop Prop_type = Prop type Define_throw = Define throw Throw_type = Throw type Message_click_to_start = Click to start Saving_animated_GIF = Saving Animated GIF Message_GIFsave_color_map = Building color map Message_GIFsave_writing_frame = Writing frame JMLView_compile_button = Compile JMLView_revert_button = Revert Pattern_List = Pattern List Version = Version {0} Copyright_message = Copyright (C) 2002-{0} Jack Boyce and others GPL_message = This program is released under the GNU General Public License. Continue = Continue Patterns = patterns Generator_stopped_title = Generator stopped Generator_timeout = Limit of {0,number,integer} seconds exceeded Generator_spacelimit = Limit of {0,number,integer} patterns exceeded Generator_patterns_1 = 1 pattern Generator_patterns_ne1 = {0,number,integer} patterns Pattern_list_tab = Pattern list Prop_type = Prop type Generator_intro = This is the siteswap generator component of Juggling Lab, derived from the\n\ program J2 v2.3, written by Jack Boyce in Feb 1992. It finds juggling\n\ patterns in a generalized form of siteswap notation. For a full\n\ description of this notation and the program's operation, consult the accom-\n\ panying documentation files. All patterns satisfying the given constraints\n\ are listed by the program. Solo asynchronous juggling is the default mode.\n\n\ Usage: j2 [-options]\n\n\ where options include:\n \ -n show number of patterns\n \ -no print number only\n \ -se hide starting/ending sequences for excited state patterns\n\n \ -x .. exclude listed regular expressions\n \ -i .. must include listed regular expressions\n \ -lame remove '11' sequence in asynch mode\n\n \ -g ground state patterns only\n \ -ng excited state patterns only\n \ -f full listing (including composite patterns)\n \ -prime prime patterns only\n \ -rot show all rotated versions of patterns (e.g., 645 and 564)\n\n \ -m multiplexing with at most simultaneous throws\n \ -mf allow simultaneous nontrivial catches (squeeze patterns)\n \ -mc disallow multiplex clustered throws (e.g., [33])\n \ -mt require at least one multiplexed throw with no holds\n\n \ -s find synchronous siteswaps\n\n \ -j set number of jugglers\n \ -cp show only connected passing patterns\n \ -d passing communication delay (see docs)\n \ -l passing leader person number (for use with -d)\n \ -jp show patterns with all juggler permutations\n\n\ Examples:\n \ j2 5 7 5\n \ j2 5 7 5 -x 2 3\n \ j2 5 7 18 -prime\n \ j2 4 6 6 -s -g\n \ j2 5 6 4 -m 2 -g -mt\n \ j2 6 4 2 -j 2 -g -jp -m 2 -d 1 -l 1 Prop_name_ball = ball Prop_name_ring = ring Prop_name_image = image MHNHands_name_default = default MHNHands_name_inside = inside throws MHNHands_name_outside = outside throws MHNHands_name_half = half shower MHNHands_name_Mills = Mills Mess MHNHands_name_custom = custom MHNBody_name_default = default MHNBody_name_line = line MHNBody_name_feed = feed MHNBody_name_backtoback = back to back MHNBody_name_sidetoside = side to side MHNBody_name_circles = circles MHNBody_name_custom = custom jugglinglab-0.6.2+ds.1/source/resources/GUIStrings_es.properties000066400000000000000000000112111323754603300246640ustar00rootroot00000000000000# GUIStrings_es.properties # # This properties file defines language-specific text visible in the # Juggling Lab GUI # # Language for this file = Spanish # Processing = procesando... Click_Edit = Hacer clique en Editar para crear nuevo patrón Edit = Editar Pattern_entry = Entrar patrón Defaults = Restaurar Juggle = Comenzar Pattern = Patrón Dwell_beats = Cociente de detención Beats_per_second = Tiros por segundo Hand_movement = Movimiento de las manos Body_movement = Movimiento del cuerpo Manual_settings = Ajustes manuales Generator = Generedor Run = Comenzar balls = Pelotas max._throw = Tiro max. period = Período Jugglers = Malabaristas Rhythm = Ritmo asynch = asynch synch = synch Compositions = Composiciones all = todas non-obvious = no obvias none_(prime_only) = primas solamente Find = Buscar ground_state_patterns = patrones terrados excited_state_patterns = patrones exitados transition_throws = tiros transitorios pattern_rotations = permutaciones del patrón juggler_permutations = permutaciónes de los malabaristas connected_patterns = patrones conectados solamente Multiplexing = Multiplexación enable = permitir simultaneous_throws = tiros simultáneos no_simultaneous_catches = sin capturas simultáneas no_clustered_throws = sin tiros agrupados true_multiplexing = multilpexación verdadero solamente Exclude_these_throws = Excluir estas expresiones Include_these_throws = Incluir estas expresiones Passing_communication_delay = Retraso de comunicación al pasar File = Archivo Notation = Notación Help = Ayuda New_Pattern = Nuevo Patrón New_Pattern_List = Nueva Lista de Patrones Open_JML... = Abrir Archivo JML... # Open_Animator_Pattern_List... = Abrir Lista de Patrones... Convert_JML... = Convert JML to version 1.2... Quit = Salir About_Juggling_Lab = Acerca de Juggling Lab Close = Cerrar Save_JML_As... = Guardar JML Como... Save_Text_As... = Guardar Texto Como... Patterns = Patrones View = Aspecto Save_Animated_GIF_As... = Guardar GIF Animado Como... Save_HTML_As... = Guardar HTML Como... Save_to_Server = Guardar en Servidor Restart = Recomenzar Animation_Preferences... = Preferéncias de Animación... Simple = Simples Visual_editor = Editor visual Selection_editor = Editor de seleccíon JML_editor = Editor de JML Animation_Preferences = Preferéncias de Animación Solid_3D_display = Animación 3D sólida Frames_per_second = Frecuencia de refresco Slowdown_factor = Velocidad Border_(pixels) = Beira (pixeles) Double-buffered_animation = Animación doble-protegida Start_paused = Comenzar pausado Pause_on_mouse_away = Hacer pausa al afastar el mouse Stereo_display = Ver en estéreo Catch_sounds = Dar son al pegar con las manos Bounce_sounds = Dar son al bater con la tierra Cancel = Cancelar OK = Aceptar Change_title... = Cambiar título... Change_title = Cambiar título Change_overall_timing... = Cambiar tiempo... Change_timing = Cambiar tiempo Rescale_percentage = Nueva escala (porcentaje) Add_event_to_L_hand = Añadir evento a la mano izquierda Add_event_to_R_hand = Añadir evento a la mano derecha Remove_event = Remover evento Define_prop... = Ajustar objeto... Make_last_in_event = Cambiar para último en evento Define_throw... = Ajustar tiro... Change_to_catch = Cambiar para captura Change_to_softcatch = Cambiar para captura leve Define_prop = Ajustar objeto Prop_type = Tipo de objeto Define_throw = Ajustar tiro Throw_type = Tipo de tiro Message_click_to_start = Hacer click para comenzar Saving_animated_GIF = Guardando GIF animado Message_GIFsave_color_map = Construyendo mapa de color Message_GIFsave_writing_frame = Gravando image JMLView_compile_button = Compilar JMLView_revert_button = Volver Pattern_List = Lista de Patrones Version = Versión {0} Copyright_message = Copyright (C) 2002-{0} Jack Boyce and others GPL_message = Este programa es encuentran bajo el Licencia Pública General GNU(GPL). Continue = Continuar Patterns = patrónes Generator_stopped_title = Generador terminado Generator_timeout = Limite de {0,number,integer} segundos excedido Generator_spacelimit = Limite de {0,number,integer} patrones excedido Generator_patterns_1 = 1 patrón Generator_patterns_ne1 = {0,number,integer} patrones Pattern_list_tab = Lista de patrones Prop_type = Tipo de objeto Prop_name_ball = ball Prop_name_ring = ring Prop_name_image = image MHNHands_name_default = default MHNHands_name_inside = inside throws MHNHands_name_outside = outside throws MHNHands_name_half = half shower MHNHands_name_Mills = Mills Mess MHNHands_name_custom = custom MHNBody_name_default = default MHNBody_name_line = line MHNBody_name_feed = feed MHNBody_name_backtoback = back to back MHNBody_name_sidetoside = side to side MHNBody_name_circles = circles MHNBody_name_custom = customjugglinglab-0.6.2+ds.1/source/resources/GUIStrings_fr.properties000066400000000000000000000144031323754603300246720ustar00rootroot00000000000000# GUIStrings_fr.properties # # This properties file defines language-specific text visible in the # Juggling Lab GUI # # Language for this file = French (France) # Processing = processing...* Click_Edit = Click Edit to create pattern* Edit = Edit* Pattern_entry = Edition Defaults = Restaurer Juggle = Jongler Pattern = Figure Dwell_beats = Ratio de temps de repos Beats_per_second = Lancers par seconde Hand_movement = Mouvement de la main Body_movement = Mouvement du corps Manual_settings = Paramètres manuels Generator = Générateur Run = Générer balls = Balles max._throw = Lancer max period = Periode Jugglers = Jongleurs Rhythm = Rythme asynch = asynchrone synch = synchrone Compositions = Composés all = Tous non-obvious = Non évidents none_(prime_only) = premiers seulement Find = Trouver ground_state_patterns = figures fondamentales excited_state_patterns = figures excitées transition_throws = lancers de transitions pattern_rotations = permutations circulaires juggler_permutations = juggler permutations* connected_patterns = connected patterns only* Multiplexing = Multiplex enable = activer simultaneous_throws = lancers simultanés no_simultaneous_catches = pas de récéptions simultanées no_clustered_throws = pas de lancers en grappe true_multiplexing = true multiplexing only* Exclude_these_throws = Exclure ces expressions* Include_these_throws = Inclure ces expressions* Passing_communication_delay = Délai de communication (passing) File = Fichier Notation = Notation Help = Aide New_Pattern = Nouvelle figure New_Pattern_List = Nouvelle liste de figures Open_JML... = Ouvrir JML... # Open_Animator_Pattern_List... = Ouvrir liste de figures pour animation... Convert_JML... = Convert JML to version 1.2... Quit = Quitter About_Juggling_Lab = A propos de Juggling Lab Close = Fermer Save_JML_As... = Enregistrer JML sous... Save_Text_As... = Enregistrer texte sous... Patterns = Figures View = Voir Save_Animated_GIF_As... = Enregistrer le gif animé sous... Save_HTML_As... = Enregistrer le HTML sous... Save_to_Server = Save to Server* Restart = Redémarrer Animation_Preferences... = Préférences d'animation... Simple = Simple* Visual_editor = Editeur visuel Selection_editor = Editeur de sélection JML_editor = Editeur JML Animation_Preferences = Préférences d'animation Solid_3D_display = Affichage 3D pleine Frames_per_second = Images par secondes Slowdown_factor = Facteur de ralentissement Border_(pixels) = Bordure (pixels) Double-buffered_animation = animation avec mémoire tampon doublée Start_paused = Redémarrer Pause_on_mouse_away = Pause on mouse away* Stereo_display = Affichage Stereo Catch_sounds = Réceptions sonores Bounce_sounds = Rebonds sonores Cancel = Annuler OK = OK Change_title... = Changer le titre... Change_title = Changer le titre Change_overall_timing... = Changer le timing global... Change_timing = Changer le timing Rescale_percentage = pourcentage Add_event_to_L_hand = Ajouter évenement à la main gauche Add_event_to_R_hand = Ajouter évenement à la main droite Remove_event = Supprimer l'évenement Define_prop... = Définir l'objet... Make_last_in_event = Transformer dernier en évenement Define_throw... = Définir le lancer... Change_to_catch = Changer pour réception Change_to_softcatch = Changer pour réception douce Define_prop = Définir l'objet Prop_type = Type d'objet Define_throw = Définir le lancer Throw_type = Type de lancer Message_click_to_start = Cliquer pour commencer Saving_animated_GIF = GIF animé en cours de sauvegarde Message_GIFsave_color_map = Construction de la table des couleurs Message_GIFsave_writing_frame = Ecriture de la frame JMLView_compile_button = Compiler JMLView_revert_button = Restaurer Pattern_List = Liste des figures Version = Version {0} Copyright_message = Copyright (C) 2002-{0} Jack Boyce and others GPL_message = Ce programme est publiées sous licence GPL (GNU General Public License). Continue = Continuer Patterns = figures Generator_stopped_title = Générateur arrêté Generator_timeout = Limite de {0,number,integer} secondes dépassée Generator_spacelimit = Limite de {0,number,integer} figures dépassée Generator_patterns_1 = 1 figure Generator_patterns_ne1 = {0,number,integer} figures Pattern_list_tab = Liste des figures Prop_type = Prop type* Generator_intro = Ceci est le générateur de siteswap de Juggling Lab, dérivé du programme J2\n\ v2.3, écrit par Jack Boyce en février 1992. Il génère des figures de jonglage\n\ dans le cadre d'une notation siteswap généralisée. Pour une description\n\ complète de cette notation et du déroulement du programme, consulter la\n\ documentation l'accompagnant. Les figures satisfaisant aux contraintes\n\ définies sont générées en totalité. Le jonglage solo et asynchrone est le\n\ mode par défaut.\n\n\ Usage : j2 nombre_objets lancer_max periode [options]\n\n\ les options incluent :\n \ -s mode synchrone -j définit le nombre de jongleurs\n \ -n donne le nombre d'objets -m multiplex avec au moins le\n \ -no imprime juste les nombres nombre donné de lancers simultanés\n \ -g figures fondamentales -mf permet les réceptions multiples\n \ -ng figures excitées -mc empêche les lancers multiplex par lots\n \ -f liste complète (avec -mt true multiplexing patterns*\n \ les figures composées) -d retard de communication (passing)\n \ -se disable starting/ending -l passing leader person number\n \ -prime premiers seulement -x .. exclure les lancers pour soi\n \ -rot avec permutations -i .. inclure les lancers pour soi\n \ des figures -lame supprimer les '11' en mode asynchrone\n \ -cp connected patterns only -jp show all juggler permutations* Prop_name_ball = ball Prop_name_ring = ring Prop_name_image = image MHNHands_name_default = défaut MHNHands_name_inside = inside throws MHNHands_name_outside = outside throws MHNHands_name_half = half shower MHNHands_name_Mills = Mills Mess MHNHands_name_custom = personnalisé MHNBody_name_default = défaut MHNBody_name_line = line MHNBody_name_feed = feed MHNBody_name_backtoback = back to back MHNBody_name_sidetoside = side to side MHNBody_name_circles = circles MHNBody_name_custom = personnalisé jugglinglab-0.6.2+ds.1/source/resources/GUIStrings_he.properties000066400000000000000000000140631323754603300246610ustar00rootroot00000000000000# GUIStrings.properties # # This properties file defines language-specific text visible in the # Juggling Lab GUI # # Language for this file = Hebrew # Processing = ����... Click_Edit = ��� "�����" ��� ����� ����� Edit = ����� Pattern_entry = ���� ����� Defaults = ����� ���� Juggle = ���� Pattern = ����� Dwell_beats = ��� ��� Beats_per_second = ����� ������ Hand_movement = ����� ��� Body_movement = ����� ���� Manual_settings = ������ ����� default = ����� ���� custom = ����� ����� Generator = ����� ������ Run = ��� balls = ������ max._throw =����� �������� period = ��� Jugglers = �������� Rhythm = ��� asynch = ��������� synch = �������� Compositions = ����������� all = ��� non-obvious = ������� none_(prime_only) = ��� (���� ����) Find = ��� ground_state_patterns = ������ ���� ����� excited_state_patterns = ������ ���� "����" transition_throws = ������ ���� pattern_rotations = ��� ������ juggler_permutations = juggler permutations connected_patterns = ������ ������� ���� Multiplexing = ��������� enable = ����� simultaneous_throws =������ ���������� no_simultaneous_catches = ��� ������ ���������� no_clustered_throws = no clustered throws true_multiplexing = ��������� ����� ���� Exclude_these_throws = ���� �� �������� ����� Include_these_throws = ���� �� �������� ���� Passing_communication_delay = Passing communication delay File = ���� Notation = ��� ����� Help =���� New_Pattern = ����� ���� New_Pattern_List = ����� ������ ���� Open_JML... = ��� JML... Open_Animator_Pattern_List... = Open Animator Pattern List... Quit = �� About_Juggling_Lab = ����� Juggling Lab Close = ���� Save_JML_As... = Save JML As... Save_Text_As... = Save Text As... Patterns = Patterns View = View Save_Animated_GIF_As... = Save Animated GIF As... Save_HTML_As... = Save HTML As... Save_to_Server = Save to Server Restart = Restart Animation_Preferences... = Animation Preferences... Simple = Simple Visual_editor = Visual editor Selection_editor = Selection editor JML_editor = JML editor Animation_Preferences = Animation Preferences Solid_3D_display = Solid 3D display Frames_per_second = Frames per second Slowdown_factor = Slowdown factor Border_(pixels) = Border (pixels) Double-buffered_animation = Double-buffered animation Start_paused = Start paused Pause_on_mouse_away = Pause on mouse away Stereo_display = Stereo display Catch_sounds = Catch sounds Bounce_sounds = Bounce sounds Cancel = Cancel OK = OK Change_title... = Change title... Change_title = Change title Change_overall_timing... = Change overall timing... Change_timing = Change timing Rescale_percentage = Rescale percentage Add_event_to_L_hand = Add event to L hand Add_event_to_R_hand = Add event to R hand Remove_event = Remove event Define_prop... = Define prop... Make_last_in_event = Make last in event Define_throw... = Define throw... Change_to_catch = Change to catch Change_to_softcatch = Change to softcatch Define_prop = Define prop Prop_type = Prop type Define_throw = Define throw Throw_type = Throw type Message_click_to_start = Click to start Saving_animated_GIF = Saving Animated GIF Message_GIFsave_color_map = Building color map Message_GIFsave_writing_frame = Writing frame JMLView_compile_button = Compile JMLView_revert_button = Revert Pattern_List = Pattern List Version = Version GPL_part1 = This program is free for non-commercial use only. Portions are released GPL_part2 = under the GNU General Public License. Continue = Continue Patterns = patterns Generator_stopped_title = Generator stopped Generator_timeout = Limit of {0,number,integer} seconds exceeded Generator_spacelimit = Limit of {0,number,integer} patterns exceeded Generator_patterns_1 = 1 pattern Generator_patterns_ne1 = {0,number,integer} patterns Pattern_list_tab = Pattern list Prop_type = Prop type Generator_intro = This is the siteswap generator component of Juggling Lab, derived from the\n\ program J2 v2.3, written by Jack Boyce in Feb 1992. It finds juggling\n\ patterns in a generalized form of siteswap notation. For a full\n\ description of this notation and the program's operation, consult the accom-\n\ panying documentation files. All patterns satisfying the given constraints\n\ are listed by the program. Solo asynchronous juggling is the default mode.\n\n\ Usage: j2 number_of_objects max_throw pattern_period [options]\n\n\ where options include:\n \ -s synchronous mode -j set number of jugglers\n \ -n show number of patterns -m multiplexing with at most the\n \ -no print number only given number of simultaneous throws\n \ -g ground state patterns -mf allow simultaneous catches\n \ -ng excited state patterns -mc disallow multiplex clustered throws\n \ -f full listing (including -mt true multiplexing patterns\n \ composite patterns) -d passing communication delay\n \ -se disable starting/ending -l passing leader person number\n \ -prime only prime patterns -x .. exclude listed self-throws\n \ -rot show all rotated -i .. must include listed self-throws\n \ versions of patterns -lame remove '11' sequence in asynch mode\n \ -cp connected patterns only -jp show all juggler permutationsjugglinglab-0.6.2+ds.1/source/resources/GUIStrings_pt.properties000066400000000000000000000111371323754603300247070ustar00rootroot00000000000000# GUIStrings_pt.properties # # This properties file defines language-specific text visible in the # Juggling Lab GUI # # Language for this file = Portuguese # Processing = processando... Click_Edit = Fazer clique em Editar para criar novo padrão Edit = Editar Pattern_entry = Entrar padrão Defaults = Restaurar Juggle = Começar Pattern = Padrão Dwell_beats = Quociente de detencão Beats_per_second = Tiros por segundo Hand_movement = Movimento das mãos Body_movement = Movimento do corpo Manual_settings = Ajustes manuais Generator = Gerador Run = Começar balls = Bolas max._throw = Tiro max. period = Período Jugglers = Malabaristas Rhythm = Ritmo asynch = asynch synch = synch Compositions = Composições all = todas non-obvious = não óbvias none_(prime_only) = primas somente Find = Procurar ground_state_patterns = padrões aterrados excited_state_patterns = padrões exitados transition_throws = tiros de transição pattern_rotations = permutações do padrão juggler_permutations = permutacões de malabarista connected_patterns = padrões conectados somente Multiplexing = Multiplexação enable = permitir simultaneous_throws = tiros simultâneos no_simultaneous_catches = sem capturas simultâneas no_clustered_throws = sem tiros agrupados true_multiplexing = multiplexação verdadeiro somente Exclude_these_throws = Excluir estas expressões Include_these_throws = Incluir estas expressões Passing_communication_delay = Retraso de comunicação ao passar File = Arquivo Notation = Notação Help = Ajuda New_Pattern = Novo Padrão New_Pattern_List = Nova Lista de Padrões Open_JML... = Abrir Arquivo JML... # Open_Animator_Pattern_List... = Abrir Lista de Padrões... Convert_JML... = Convert JML to version 1.2... Quit = Sair About_Juggling_Lab = Acerca de Juggling Lab Close = Fechar Save_JML_As... = Guardar JML Como... Save_Text_As... = Guardar Texto Como... Patterns = Padrões View = Aspecto Save_Animated_GIF_As... = Guardar GIF Animado Como... Save_HTML_As... = Guardar HTML Como... Save_to_Server = Guardar em Servidor Restart = Recomeçar Animation_Preferences... = Preferéncias de Animação... Simple = Simples Visual_editor = Editor visual Selection_editor = Editor de seleção JML_editor = Editor de JML Animation_Preferences = Preferéncias de Animação Solid_3D_display = Animação 3D sólida Frames_per_second = Freqüência de renovação Slowdown_factor = Velocidade Border_(pixels) = Beira (pixels) Double-buffered_animation = Animação dobro-protegida Start_paused = Começar pausado Pause_on_mouse_away = Fazer pausa ao afastar o mouse Stereo_display = Ver em estéreo Catch_sounds = Dar som ao pegar com as mãos Bounce_sounds = Dar som ao bater com o chão Cancel = Cancelar OK = OK Change_title... = Modificar título... Change_title = Modificar título Change_overall_timing... = Modificar tempo... Change_timing = Modificar tempo Rescale_percentage = Nova escala (porcentagem) Add_event_to_L_hand = Adicionar evento à mão esquerda Add_event_to_R_hand = Adicionar evento à mão direita Remove_event = Tirar evento Define_prop... = Ajustar objeto... Make_last_in_event = Mudar para último neste evento Define_throw... = Ajustar tiro... Change_to_catch = Mudar para captura Change_to_softcatch = Mudar para captura leve Define_prop = Ajustar objeto Prop_type = Tipo de objeto Define_throw = Ajustar tiro Throw_type = Tipo de tiro Message_click_to_start = Começar Saving_animated_GIF = Guardando GIF animado Message_GIFsave_color_map = Construindo mapa de cor Message_GIFsave_writing_frame = Gravando imagem JMLView_compile_button = Compilar JMLView_revert_button = Restaurar Pattern_List = Lista de padrões Version = Versão {0} Copyright_message = Copyright (C) 2002-{0} Jack Boyce and others GPL_message = Este programa é encontram sob a Licença Pública Geral do GNU(GPL). Continue = Continuar Patterns = padrões Generator_stopped_title = Gerador terminado Generator_timeout = Limite de {0,number,integer} segundos excedido Generator_spacelimit = Limite de {0,number,integer} padrões excedido Generator_patterns_1 = 1 padrão Generator_patterns_ne1 = {0,number,integer} padrões Pattern_list_tab = Lista de padrões Prop_type = Tipo de objeto Prop_name_ball = ball Prop_name_ring = ring Prop_name_image = image MHNHands_name_default = default MHNHands_name_inside = inside throws MHNHands_name_outside = outside throws MHNHands_name_half = half shower MHNHands_name_Mills = Mills Mess MHNHands_name_custom = custom MHNBody_name_default = default MHNBody_name_line = line MHNBody_name_feed = feed MHNBody_name_backtoback = back to back MHNBody_name_sidetoside = side to side MHNBody_name_circles = circles MHNBody_name_custom = custom jugglinglab-0.6.2+ds.1/source/resources/about.gif000077500000000000000000000673311323754603300217030ustar00rootroot00000000000000GIF89a1޵֥ƥJ޽ƌ罄sZZ9޵֥޽{޵ޜJޜ1cƽƵֽ֌1{)޽ƽcεεέsΥΥΥRΔRΌR{Bތ֥kƵƥsƜsƜJ{Zk1kc)νεֽƥƌk{)kJZRJ{kZ9JcZJss1skkcZkRR{Rk)c1cZJJ!JJ1kZ){)JBkJ{ZBcB{ZsBkZc9c1cZcRRJ)1kZ{1cBB9BB9k{s{9{)sBkRkc9c1c)ZBBZ))BRB1B)9!9{B{Z{B{{{sk{ZR{9)s)s{cs{Rsc9sc1sc)scs)k9k)k{)ksRksBkkkkkkkBkcRkcBkR1kJBkJ1kJkB1kBk9k11k1!k)cBckkc)ZkRZcRZc1Zc!ZRcZRRZJBZJR{)Rs!Rc{RcBRRRRBBRJc1JRkJJ9JJ1JJ)JJ!JJJ9)J1J)1J)J!!J!Bc!BRBBJBBBRB99B1c)1Z191191!1!11)J1)J!!!9)9!!,mSNt] שWNEIUDU ZR+#.\-n(SSM\ʔҢ" ׶`ptٲ˟>_ rΕH$o8q~F}Ԝ>sY=UxV9}ᾆmx;o=~׏x񜑌n…NIt'#GzEU_+JsJɑ M4<4kf:cBA?mMlSVUj){ji]\΋ѯ7o9j~˕=Ks9ۆ5 sI;wF$!D|DPF Ju9H؛*L:77V1\sʍQ%wUYU[Ot9XZWsycyxcpWK6Ne,OGmrƕq0Y*<).SR%d?"7`gt#Jw:P TT~`"ӐP&V'dC>m@ d6R .vX.3\\#$ȣ \a׫_$ 0̡$#ExT.`Yf~X67pfZ@5Ow3h#\1)")80rkoOzw 2ottFw%$t` K@ fGgVy~9HVpփoxmPy֘f /ZOu6y"o#3SKF<ӡ<=t  rGM'vƇfY@F7(8֦n&m80كFX[` eݠe!7 D6I1ZB,POV1zw#! B$qG!7ow__A afgh:sfx؍(#fZ  +fM04"2JNt7ꑔ35Hw(%3A5t5Y'vunuQhywmoWWPlxf'I~~&E AAH6XYR3]r?8!c( i_@+FP ({{/ df6:G%ɍyf()(~0` `mF~xWpy7m7>mhzP @8 >s?4yY*M2cQl1Pb5l!J˱!b)fggmt)Yms 2h)X觃4gl)@Z}("F2+桢(Xש%XZG5s<gsHlOb#MbE\XW1[@fphs: *BGisiuٟ=Ǜrsws=(g @ `` MIGvz?(%(,I,"$  nm+r1t0="AeF\ ѐKp0im[ʛwV1r`)`* @ pg꩛*~Zʩ<~C8P| '3#3+ %tڢĺ1 $X+O4)gazcp#ɍ'9tfٮf,'t `,P,0f0pzgP)Is 6f+Z°,U=cߙsJ; G0 x+1+tUPTڅb! v)ЮK,"pfFPQJYghV7z` R<s7/Tk*ED Ͳj5 vߡCt!Jؔ#k&b  |yj&t`'`˺BBw FFK/k1VC{ pxxU jyX[sGU n$UI890I*q2@& F~W<Н#w>ne)PK^ZG[?:˒%YjΝXgcY>(+X XXa0 +,L؂ K` 2zĩ"+3'KyA 0@5TN8aVp`8H4x!N'',/G(gim =;x,Z, 0x*Z,XFAdΉUc ȋ/ KBP͂"UU'acUpC`Q*.[h Jyx:ofi b mX@i 8HKwy1Gl/4lGFiӷ_Y۸vǜnF; X =rg˩yYVP BTU^t6b >aKcΑVf5ǥ'u^A-!Na PΊzB =x g\I)ܮ?K3{x' ^4&G}X`TQdQ(,z%S;ZhA1DL59\yl *XPG, aP P+:26xЮV88Q_;9 hdp h@p*XBB۸A+{h?Q|.H7}fS>MG4 QR( #Lt fZѦ`@Q|P! Y( V½1{/qx dgj6>b SYɊ IZ @`&`9=y[?&$GLr }[M|߃"V5 96q4T#0be1 QD0,$"!* "@І҂R0l(J#-*za_6UpVf0 /|c*DZJ-%XJ&tVTEM]s$R&J!_V(Sm]8exK\ޢLM"X T@$"⊛V K^ju /8q-P@wHR :NK9@ZvpM$ SOS%\-"l7 _ jC(؁`mJP \Gv,Rc[ OR Tn@](r(LAƝ+`Bsu$BB~tC`:3'A:ٗBAߘhU_\k"OɕBQmQWےs(US+6Ȁ ۀHa t*<3!'汩_x,+\ A* TxAP%J +[YBZ pQ=s3? p $ pyGo9GzщL ׶x>v4zq0(\I )@A6ήg-ZCT+,<ՆU-sj6, \HEe JWIPבkZ_Tnh&bPB H `<\⒎#6[Pr$!ɖ(goӊV` r܃N8^cr|NsM0:rw !2B% dHy)8꣋^!~ M8B p  ؤ<n-J薞ѭnHܠ-6}Ԗ #F/ o NW6h3+z!ggےX(BaKx];7&/"/j@ )ksx!G e(C GD"fGHuܫR0CL#iEq{:" H <$<9|cAǬp+Fuk)?H[ iue![Y؛#! @ G@84@p&˰/3":&pc s؇!x!X;6: 1h <=UyژZz-PEX$Z[!!%ЀӀ%JT ҫD"!i*`5,S9 @B6+4@h*s_r;7q:@[oIe*f 1i(&qAQ!21Jpp[Ao0@EȂ[$DP2۸*0aB r$:-@?a hFi2Q@=50xjAi_z D v@ s"MKح q6t>@ELycx1KqU[L,))FFcD+?Td{*8 8p@:|3W;ْЊ,)zD:怢qӇٛЙnHx *hh<`=pHY2QXU2NUXFx )W?:BƓB Xɔ\ caaB(Hƙl!k³T k,1k?(40+j&7~\e됞 hhH(Y; =<PhHL YFſdKOKW-HzĜÌXŴab9n& TFZ#G(GX5`3xx^!II$ 鈖؛Dqxy0  X1 1hIJDH?t^KV{?äk{IOBIF\̴M @)O/4Èe@PGx=Pfj zx:@Dd u=Geف}ג_P(L6 -1؃HJI0R#X= t+*b:]l)+acFR 35 G ܀81+5P,x̀D:{E.rJ~yPAoH=XSK >>=SNJЄT }UU?WIEE))8PUtI .  m$S 2 4uATʂĐS.=l4(^J~PYx-fZ1{KL1PQ?ĄSUtۃ=X]RǩH*)XXsHF$X%n4SY )d+S#0863573WhACf}ǽnJ{\ @*XE!ń!"Tu>[m㲄HH[qB qU^ҍC\H6m (P@C Pe\r:M3Y30#0@GXk.xӇ["]XAD;??LFņF8UJ^띄?$J2>HDU[1,LDTbDH:RD\ /<2 aC Ŀ%jØ>`?08`5moJ5,B}d}y2fQU"UUIQƄQD_ bOIUkЅ(b]1bS*(T8ـfGMЄ2,#0(^)yxiʢZv$3Hx2paa SSNU-hYgVJL>Ӏ]]|bI؅]hnhnT5tI.?O cec" 9@pQ(?8)#X\8>p-x"m" d,y]]j }*B؄QdVNNFES-ha}H ;(]u rvvinB{GVR޹ BG0Ho`&ӧ{-2Qsp(J>1=Į)1;H{F]-QQi(`2UX8UOքKP(IiuPv ~)0`.6lUD5\ced23ViU-bB0 8;x`e/c-CjdAD[JN3>ean$EJS!%efX8T؅r8ABvЈ'͐h؅“lxϩl4@lVUb1aM#/8mi8DD 64x۞a~}M;%RhraF\!^XTe LU8Dw &B&\ EPXL_/ss ¸ $ NbB02 jX=v5NCkC ~x =TeLHX 05 qqdІKJR&҇|HUD*UPx(WȤ'PЇWkXЂ=_/2liΦlAb qhG2,˂Wo߆%gh@WJt&!gn-h|_RhRXe@L LnRQ>hk쒗S hA%{-$J| ) *2`lvI=Ap` ' Tu` Xxd@4HG(ZmІikLP[R$-Ua 1٤Q2$R 1Id9ՀWd/"2-Hc*XQpsl86ηm ?|D ÃB\8!>sӧ/H/.X@4EkcLTOEPU9I&`T$K_>P7|>}uyEeϘ,YPI1e[PV.]()H1d,lha +8dK!33aȖV6B iҪh%(4a49zLSJה%1J|Xm^?Q vk֨sUI"; u]1d`,ءE 1+dq(=qe1p |YD(Mψ>x>B( - 3 &W (|L(TTPA+zX8[E%WuՔ]'UK/0Zda|Mt_mD v -iE ` ,`b3aV,` |P<#UdB A4)h| ,CIV#--S Ph#<,`ܭЭ+PfOxyՏSiy/ӍA UߚmW^TDCԹBPg /(hF30r 14p")A4o!OA)Dp7р ̀kj) # LRSY%2pH4ӝ?NmO9WP12zdQZt'g|s^P@B,EZ!,Q!C f84d?UJkc>*0I#,U\qBܬP=U9+]͔s9f%c\ PyE+`PDQg 4a{2 +ph{!k:A&7ؑ4KRJ0l\}E^SCixtK7e<`N3`fC,,>% ѢK|Rq`vt]\L0Q}(8 B4"!i;Hv)aCR HHBT"> cx"pEiHJ SSdGXPGy#ydDшF2 [B HkZ|BЂ(1 碂I 1A Md88` $EJ!mPRE/@M#Gh΁C%`P }VTܒeVl"Va9vsXz8eA /(Ѥ-;8Mv '(30,P22t` $!D#kF"RJz(?xt+XlFa%$sd18U.zd.6 72iv%+4!}#,чN #0*O/CZp<1!\J{:&Am0&zI?\3PDQ8*#zh_*+66CCq1ȪE%@k?L,ɦ8Qo;.S"FRЇ11-fr :uUB@-VC @n`im)C 9'Xע,`P(R)G<DŽ,Hp('cD$ƹq00rre¦F7,Q2ٖRyzn-LgPWZ8nr6`Qh8O8 GL +Dx7ݸ X(yzE3Jzyo8` 8=@B() BP830!CJ)`ͼm4*Ve+V,ݎZ01-B`E L0B]b}nL1,xAPѴ!3ƚZW)7eL041aO`܊\6[=p0ۇSD⃁{\$4!ր~>aNc6Y*hH˫SŠ==NnX@@|pBA9\l#!!z4,GTTؒw(x8 a%E(q1Xg <ߜOSv s#rAx,BHM>l\z؃KAzXڠ< |,¨70BK1`+P, ǵ^˯x)_@KlvQs z0PW0L1A*LT.TiyR7ꝃP̕L [81 I WM A0BH u0 4 p\/Bi\ɕh8ayF*!^{ك)=Ad Ȁ(Xs1LAQ"(LyB.<,EVp rdṼN9b!Z9vj]UVx,`#"8=Z  U*ģul@`B/%Z-l٢ơ\♟->L.Z*)޽Āe #`b0P#m5 6>`%c`y7zXxE:# jE=6=;$<#>SI]U"8TBu`Mt΍Q&$AF($ A%|=M,ZEb>/C`}$-7BdA* ,B0C%L%LcOB633Ccbi94(&,b[c\եE?Z*Ytqm[0%P(pT6>e_ƒ-]`[~F.6A (@ #&(\/@#LBMNBhƔd8^xXN&;)zK_<)@t}J,&((,%i1Ŋg$di ' ꩡ8:(4AUC91RU8Aqr)Bmq9&&W Фz'Ռ,|* faiGG=;H~dBmC*$}be~jBp ,u- /Of9Ckcb;6|X # )_E1@;l &0z@p#dRI 6~f)KQ&,ci"O4,Y 4,kZfk^QC8T RMֳ gXRCj<1e0gAZ Ar!(I='g݆'߆om<i@^C ,A΀uU[be%mP0B+ADzR&y/̂M\mC""о"ZOE ,t+m%fʦ[%`@/&88b*lzƭm~/`߮]i/(ub?],@`1}.7Oe.hC< =:!e뱞M+NA/1&;CՍ ظet0JAM/lH_f*V$-&zZlC$ @"l**У4.@`–#j\-=g2=m,qiŢ'̗$hF +(<7‮>ͅC2lb :(z.SMDp39CC{!W\@ pokl^564&L,@ijo8`+1,I_MVqڹqʕcdȐ΍,IR۹sڐ;w1QV1 `7/ܼ\Mc􁃩8̴y|dg ;O7iu˶-xgۧpxg췼UKݯ\w: /24k۷o^@@1\H1XEs G\촁TdmKԦpdDĈQ+:6'=v`F-q T8bbIq =F$ }78.[qɋ@ϺG+}<BQJфI`˶F0" P(H{ )&6tyK 7~dX).K#Cb #`gؾad +(2cJ .b4Ha L~D>8:"&3 /rA) -wspf "t=a4C @` V0Q *!X9#f$iGc7rXVcctraGs 1P!+Z;8p 8̈l@-P#^@ kk?[N{܁wP6S8ТQJ@`N6}/@ȁ"F}>&rV'YVs1ǗLF\4?A-fd]RsRZ1dX 0=h!04w10e>\ Hq=⫰v='w*>0)Ma C;Rh 6gء|4QO>ƜN6'HM/tVr)8 48f2~>qVIJE)3(VBRQ`D 0T ҳ߶<]=So Ǚ6CV ; <@A=C((2X +Hi3i&b/Avf``sF%9qhK4 8a Ok X`.4a-,`pn+A[֖}0T\ 5٧}F%"Q0a\h1H `Wd7p`0ؐ>asCv 0J$H3E!q0CF:sR:#Z ;Nư;y)0\042HAP(`|5 &@z/`Xcf>EB=Hj\xPq̨26exW0'=)`B8}GC)`|g48,CqC̀D+ +(4d@HG7/mh RM*^`JEb>؆;y^ PS^T@80)_V H{onE,`RUXEZ@GcrqDYlX`f ,L{ 4;lnGIx =hIlpR 'I P>E_ *RXv4a$sQS''# PEb㨇\: cPo0f \ȃj ?'xUCYh:fW S̀1pvxV ab,|ki.4"aڀXġJA2DZ`cA(I\4oH D+H (0 J:A"fFZ`T Z"L>`fj@j0  ^/B+ Svz/NiZ@a/0Ald` `4'd\> M0f8!f`AД@- z@@_iƍ 6` ,P0cR0"V@zD F407a_N -D~퐐#%!E0Ʀ0 f Qj!e` `~(ܐfbKE`, -ag4 2⇶@e램PPX,!3:D./\6aDPDM`ʀ@2/A`o) Aɘlo 0+em"p .d+YHzhC6 2r "Z 0 Bq(5@P,, p!0f0b֢-j`r?k_!)Ȋ>AlZd.D6* A!RRt~@b&0)FJMVHvd&`M 9kH6HY`Z '@#),:Rze*/0{"!OeP #ڢ%N|P?=%%.,SA ThA0hx-3b`f c Oa U-9<_'SM Sld%Tb@`6 ;,`x ^X@CW/`#)Alg.BĆM%7L=m%״n N!A+A 4AMc@'!C ԍb*J" aR X(f ̨ Du ABdRa Ȫ Ƀ<@Ų4HmN0k3]@N ?j@{Z([I '* Z6A Bd%DRdi$DaDLARӔ8ųMT@,w%mU:o pVSX`lZ3=k~pP>bmh3Bw}@IYg[ªfhai+GQmz `@tZL,A&rNFe898^ !in vw\#bUmɖ 8 ;:@[ S'0O/a@~0->w3atXPƔΚdQQe@K4 ڀZ2f4K&'HH~AEDu8!Dz! 9o`A ~VV<9@mL@rX &mĨ/-aС݁Aa3Au^4\4` A.VM g)ZZ !aUa"jE-j45d\(#dE(Z2 H t  tul`iJeN es,Xٙe3ZG}ԕY@ A~0W Z,l(jRaaE`E7reG` %OzN`^@^;!d4!`nHcfL 1 0 ,*ao!  ;;,cI`6#*dAvvaYϢNNXGI4Ʃ5!x&Y*`)9xE]+vjr;÷:HZZ~_`T28~@=Q{@mbs0`ھ!!!rG72dj~KAR~!/QY wx `04Nx!(A)5!EE fv+[+k ;h6 THHk)+Uy,W;zDDVMs{g+[_*.aY0 ^` g5ovL *-- fb.uAdzqL aRaA9*0|[o*Z`R-<ov| ;>%/k|t!tEW3agd1/.&` >w;&aG 0af c; *úƀHF*i`Rcc ~ ysb؇#{̘\2wQ<&Aab~^+Y߻\öL^f&9]gk]nE:H4pk[0Չ4W`">`MlL؊ke|O@N_Ŵ墾IޱmXѡ%wqn!hM;.D`!75K9" ݡ::驾1 8@r8AZ8Hli~G] sr.@Nz>z[k >Ӵ"aןY@]nF B  -mbPϘ>&iDIӤOcuLFQA'NDAh"若Af/>mZXQ" QnhI /nb!8HƂ'RHX KP@aBv={ѵϮVV+poE ]9v6wa ϝ{ٻ|/޷^Bi+mڈقp25Q%Ϟ1 I-p2i2Ο }ϠUIf/FVZxg)x&m  Vd`` ^ D )PP@ aG$t\u`"X2;)abe~N8\|=|X6@@wXE m$LCPbTor\#h( !I |ќ_"'c 0dIwExCQE9 -B ԹU)dX\uc 5T0@'ԁK:gsiY`"}bb=C 5Q Mv=="^`G"-dclc C}HIVIo'G }Gǥd%H)}c9c ,dtfC/nRTP'V`eb]_ZЖ*\N-@xnNbXPs;DV0”7ۨvG XamȠ|a$0˲ qD)FWK^%݊3%m5RLɩޝp|Z`}W apB$|OpEBpu'}ð +8݋I]1I0FT=p46b0B,\JipvvnjMGV i%@ns!i!wKGWKovB.Cpucki| P"tAt ae3$hPlKd&VP@[tIh5v'px+gma'6#L J 8s y uU J!~,ftQ*Ԑ o] |+H 4 @ ,uZ0 -I 7 0 h` _0ZaDrCȖCӳ<aab!~9w\P$`h )*h 0 p p QЅC.uŀc  + 3Y@ 0 0 P i 0 Zeq[Aw*JIrṘ[}t=ubᗕ9xB`(#6LJ s b@nbSrrb&&!!*`Wj '{ BҀ (f0, pY Y 9 @ @:) #m-Tg50gRbOFCq}tUIDb69QQuC@` Yh&}0 S p p BP|]w^ & @W 3``ez QhbA[HRC+`r'$PJ񘕕566Lُ)ӥ @ qٖ` r`D7Qi`L6 '){ȋ7B !2pU*jebc`121K1b|ͪ@E gʶ.L9'lwx(j1ǵD)  Cy7ue j AH DC[z 6; (\бkdx0W2K!q\.7- [`vCuZ/aU/b!f6p3b{i+ ] [ۏ<l0l #GhD@6D|R2}#1j1\ do`v;&ƳWC2;ͺWRݲ :ƎV? ; (:ǍJd!" ]J4p *ݝѤ(N jx@6橑w׬d-m$j2@{0~;p^>=yڂj.CGԮÊk!JԐLu1D/u"z"(C@p( b]D - ̉R;>h̭˻JЉޭ/N10 f@3}[;΂[ڲC2 408Pna fxaxCCr>,/ \&(IĪ . &b4@r .`@*r@̡ l@ޜJ@aPY `} {-V0P^귮|+L.z@{W5)0C?Ku=~~隉5@"] >~ݏ`Xl`#VU9v@n FJfj&{Ʈ"Y끻Qɺvkմm摌͔>UuREѮu.?dAX,^j6Dе>@b;˙4I/4u9vp>J. MJjokC=ڤ.4V]N5P0$7C`,6^x@GRP? <:Ҝ_J@a@d)~&eqG";ZG1m1ƕVbÊ11*"̛>\pّJEl`B,Xlhb-6PcƀCƎbv\" UiTk(UWlbsH!@RAm… D* ^ 25g9`Jć6h( RTch-vڴG1[E+-.RcI3&Mi˗nR@5O>} "Q;zg,h,`8 ,VH*DXmblYhQ`+N5j̵A+LGs0x/6p (Tp,8 0 ; =jH6$jmʨ+:mI ,X ^&T@'瘃A-)ȢHҦh02nl 1d"5:  ;j@h+ ;jugglinglab-0.6.2+ds.1/source/resources/ball.gif000066400000000000000000000024111323754603300214640ustar00rootroot00000000000000GIF89a1(86E?MFTP]UahsjuyՂ؄ّܓޚߜᢩ⪰宴歳崹躿꺿2 1 2!3!4#5$6$5$6%6&7'8'8(9):*;+<,=,=->->.?.?/@1A2C1B3E2C3D4D6G5E7H9I:I:I:J;L;JM?NAQ@OAQBQCRDSETFUGVGVHVIXK[KYKZLZL[M\N\O^O]P^RaTaTbUcVcWdXeWdYfZhZg\i]k^l^k_l`mancpcoeseqgtfrhtgtivkxjvjwmynynyozo{q}p{q|r}tttvuvyxzz{|~ׁ؁؀ׂ؂ׇچهىڈٌ܋ۊڍ܍ێ܏ܑݒݔޓݕޔݖޗߙߙߚߛߡ⣪⦭䥭㦭㨯䧮㩰䨯㩰㭴歴寶段屸籷糺贺賹綼鴺繿긾ർ鳺!, Hߜ@ *\D ;:Z%Vi O"Oni̙2bd BR"֬õkՖmX(,pPu n$ʕ+-[MAV„J|U@%`*!. n;F>RZ  XazKp >~*[&,JIdnڱ/:t"a0}Cl7l#0]{/jԩ\ XlN| ;L1LFdCmo"y 抔1r0piHR*]4A59)Ҝs2qwb)K1r,Triء'J-)4eȁ#p &Hk(J<nԱ|QGitq@I6EHEiQFP^6`OLqT< ) 7CJ(EOz) 44*C )-sb9"i;jugglinglab-0.6.2+ds.1/source/resources/ball.png000066400000000000000000000031641323754603300215110ustar00rootroot00000000000000PNG  IHDRc pHYs  gAMA cHRMmsϩ3n4)HK2IDATxḺ 0 Q;vCO,)XBx_׍B R@Q-qXyS|&]$hQВ21^| v?1Ɋh ;c aP: n@aX,3cH.ff../xyXx03p13pXY8.w f%j sYYm@ n<@xٙ0?[pc dKdx33 ++(> p1'PN @pd?~Ü/_D-zY -@l VFE GL@׳||@p|g÷?[->IҿfG| J% ˀ.;`jb8x&P _z  ?~q? kh/;‚ 00XƬ\ .P\17'$hAa7 PO.Rvl ĦL?$3" &bPP1\ bf0"@qK< 0owrJbO>$*J$H8s7+M14dL *PaZ4R1a N, OqY'5zN@  T 9jɟ<78Ud`B @0C7R G~o,eТd 8#z:KA (@0KPJb=_H-aca#@! N@lQ-gT61KP`x N@{|iLY8 `k gXOE_`P-& h-XĄ P# #x`~@EB=FW@.4VP -LšE ǠJ06ǝq'IENDB`jugglinglab-0.6.2+ds.1/source/resources/bounce.au000066400000000000000000000477371323754603300217110ustar00rootroot00000000000000.sndWOD/Users/jack/Documents/JugglingLab/sounds/gauche_bass_vince.wav               $    "                                                    !!!'$"(&$#%$!" %' ")(($'$&*#$&,&"0"*.&,-)++,++.,.1.,0,0)7,14/1&:'54(9.2.20202:,97/:8876;;3=44>695=74=5;5:?1D45>399@5;<8;>89?<8@=8:9959?/9A/>;>97C59E7:J5<B7>:B7<>:<>@8D8:=<A6?::>@==A==9A=?A@>E=?E6H:EA=B;F5DAA@;H8K;BG>HADC?BE<G=D@DE@@HCCI=FDBDECBEDC@CK@GEECCF@EI@ICEGAN=O?IGFMEMANMJQLMOLLGQNQQKOJMMHRLKXFURIWMXKSTLZRXVT[OSYTW[UVXXSXWW]V\[\`Zg\afdjacfZhf[nabbheendpkhmofpionjonmirdvjiofnmlqqljpkkuostqoror{rquuqp|qyvoxpnssuunyrqvqulzesqeoiggjhkalahemcilcqbhdceYaWV^Q]ZSWUSXVRTRYNTUNTRKUJOIHJAIAB8>;+@5094-45(4-).$/&%+!,#"$&     ~}suxv|wuzsyyxrrs}q{tyr~ovlxwi}hyjvofqooqvcslq|n|xizsmzywtrttoskqivplxourzz|{{|x~   !$'"8('6-3707.873;=8CGBKLTVOT^LXb\cZlliwis}twyu~ruszvpztyzytmnggkqqpxvhvfcm[bUUM>H49@7@6:=H5*.$1/$&(}~xhsddp[Sl^@XoC3^:==-bEP& $\zK?A 2   : A  >  % n   l j h  S 3  7 s M  2 E P@T'T9?Yl n&e./w(4\ ;wy$=#%TI*p$LRc8LUelpFCkEB~@U#rWRH$KG~SF9YHnc?Pn Ei m q r  s[ qZkcc3dz ?[MlV gmlCm`E V  N  = p _  e "3 tzlX|y6P^Bs   U':Oi[oQ"Wg3\:U    r T ! 8 t 3 % 6 V Y . w  ( , t j\xz^?Rty=|_Q.  W B % z  : ! F ' ! c     n z \ H lC#=oRLrq=:~IS^Qa9OIb,fb7K mu]3R~j=-/Y=2l(G6=Y)23[Fr <!I+}zXZ6=cH9\oa 9Bzxa9v G!*+9w = T  x ' 1 _ O D O > > 9 " ~ d Q 5  e # Z - 8    ! H Q =ZY *O a+a|y!ygG` @P\Ms(YFMh$ E(mAGj1^b}X+"i)M(p3U?? HZd L1O}\a* 2v>M{&l 8*] #ZB_R*&FN u\aF@Y<L.:E~J~7VRt$@ T j {   i b d _ H H  , 0  "uld7Zc7h/{#b9 k. a3 jw}v5 =~&dvdc5Xa>Agz"_jh6Ul~ZWDT]T_byk:  v I  a  W  01?9 R_b&02N%Pe%vr Kd'EOufrCIDS+8 F[Kd=T]MN+ Z$ 2  p u M $~l^bNN+%)ZYNFxQu;78$&8?GPk}ii# {>0O:"$GYD  R~j^_H-q}O158;s," .!YD7^ 97Jti EgQ$i'*,do=i8/Vlj$YXi[v~ga%MmE )&SP^ @+vQpG X%P<3$   ou|^yA >.b>b6j7 5ZM|0),ugp8[jrGLTJ7@]TA<6St,G>IFW5L ;bt3r&u Rq_w\)DYz{-Ukd] &Ps:pu{_z\m>_J >lxrGISks" $&)Sts]~rz}FCSQB A#y7Pb6!7/\5\"Q>H@xza%tIl&!e~}fpzjNKNn0:@EQ8=-x(IdPIwz X)>r Iyl6"\qt7JMlkLLDMFo  S c  n n k   $ ( K A G x y j t z F 6     j [ N >  7 ,  iTVJ4,t>^P=*wyE bEqL,5fW6zVtVSC*y; \% \%b\dSI8% 'DKTFLc\wt%'OUz(OvEKNV^t  m@A%>3HEuC.HI+whR\WB90vloXKqZ2xxXObq:";B3(. # tke|{]A40<$4;0$-.:;?;/5inBao"!0Ud)PjZl7`oW~5Pf *=[*D}-Uz6JTw%L~*9TS-T|0 Fz)Jb  H l   / I s  0 - A M O ^ Y a w y y c f P = 4 V U  { a 8 v D ]/ ^2"\)dNcS#]|i,}cCLLJ=n=pPB*$ vwhhJ8I7qe_OS?@4'96'=Mp6BH* Fy*;& D_ZOj#DONXi {pw}} !3Qf"9^jCiv/Nk9dFz<c 05v.cB^ D  5 P X |  " G T Z | r l o e B ; 4 3  t P '   h Z ; ^+d@#qS: {T-X6Fb:urM,FG]: X:vKyM?pIZHF=R\bbYP<+-)!",,$  +)!'43NN7B:ctVev !8VR_it|@:Ee''.?Yz8C`x >Mjql57GL8  ,L<-<^`}vu"187<7AF,)1.('"  #*-+$ :+$d_C$#7*.0);9+'$ irvkR5twdsfblWH>0 *'$4S_]i[j %9Gm~)A54KQG\e ,1>KPMKw -(.EY 'OGMof{ld}0@l/BQ^pv,$&BNQVkpoq ->Elqxos$%&BQats{tzrV>8&*{oQ&j`R,rl]j[D(!> rbNMJ?:pbPC:- }o|w^IRB;  ~}oa_V[Q>>BESb[_gLOL@AD89CE\3ue1+omb^d__WKE;)ul\F9"qP {`[E594204DOC2(3RUn~H^vma`yn 1E?UTL|{16Jaax%6D\o4Xap +9NZf(J_v+F[b %HR^ &A<IUb~u\SSQMIMJN2/  vl\U82,}|pZh|wc_RKI,,)&,(kf^aM60)& weXP[DG42<<7+)0&.4'66#$1###6AONiZXNTf}{uprxw{psyZdqp}}yspnpy}vkfe[[HHSTU?; z_U?*% {oafZQ-6}wseS@=E0/ u}rhgZ_EW\QORGOYhipklke`hsf2JBG?K=8O9KI==/+%<,DE19*3:2D=8G8B:NYV]LXXcgk}z !67EKE^or| +,&+>3P]piuwwrjfoyyp\NKI>LK7N676<?4E/5),+!61**-)4**" $ wswsdqdKZIH>@$'('      &).6'*۫120M@&?L,-AӬK;6>_S0.-*MǮ4/gMo_GI__뾷MU_63,/gñK:3IͳSCMǼS@AQӹgC36>oŽSBWӿ?8>SβɺY>?AQ۾MMWȾSI=>K[;[QKOüg[WS[_ͽOI;6;M_ž_IKEK翻SMMQȼ[Y[g_[[N[wƽÿcWNIH>:<=AN¾cSMEFGHS[E<<6=OwS][Y]MHGOSNWc[kgIEJOkMLMQcWSM;gMOSgʿogkgKEEIWocSJ>;==AQgwggoSMMDCEIN[oMG><<;AEM[WNIJMJMNW[SK?>>BGOSSWUIDCEIU[U[c[U[YWcc_wg[QIBEQc[[c_w[S[]ogYSSS_gYSNMNSYSWKIEFKQgog[MKLS]og_MC><>DM]ogYMIIKOQ[YOMMMMQ[[_g[SSY[]gg[YSNMNSNS[WSS[[cwgw[gojugglinglab-0.6.2+ds.1/source/resources/jml.dtd000077500000000000000000000033101323754603300213440ustar00rootroot00000000000000 jugglinglab-0.6.2+ds.1/source/resources_osx/000077500000000000000000000000001323754603300207565ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/source/resources_osx/Info.plist000066400000000000000000000030131323754603300227230ustar00rootroot00000000000000 CFBundleDevelopmentRegion English CFBundleDocumentTypes CFBundleTypeExtensions jml CFBundleTypeIconFile JML_document.icns CFBundleTypeName Juggling Markup Language CFBundleTypeRole Editor CFBundleExecutable Juggling Lab CFBundleGetInfoString CFBundleIconFile Juggling Lab.icns CFBundleIdentifier net.sourceforge.jugglinglab CFBundleInfoDictionaryVersion 6.0 CFBundleName Juggling Lab CFBundlePackageType APPL CFBundleShortVersionString 0.6.0 CFBundleSignature ???? Java ClassPath $JAVAROOT/JugglingLab.jar JVMVersion 1.5+ MainClass JugglingLab Properties apple.laf.useScreenMenuBar true jugglinglab.macosxapp true jugglinglab-0.6.2+ds.1/source/resources_osx/JML_document.icns000066400000000000000000001246621323754603300241670ustar00rootroot00000000000000icnsics#H????????????????????????????is32byuqla<:οa ̈K נ} 礭ǰn òƌ fyW/m bZ}f'q~ C~22OY n!$e YR Jױ Cq [Mmw` -%(&%#*+byuqla<:οa ̈K נ} Tpǰn 3ƌ P "T{9B} S $ 7ʌ O8B`i o&3k YT Nر Cq [Mmw` -%(&%#*+byuqla<:οa ̈K נ} Tpǰn 3ƌ P "Uys͙ S *uР ?Si§ K$Qj 5{JTwٱ ,= LMoFw -%(&%#*+s8mkw߇\yn ')U{ܸ WEl(dB[xiZn>Sb} BMQbz {:NR\n~ v>@FKQ} v² ©Ҍ ʷϋ Ͽۊ ţˉʟȈͧɇ Ӷʇe]jʲćz$;Mbsyź#4Fzʪ|‡$-I,3G[ҭۇ !+' ,>Pڈ߇&(4$4C^x|c4h(7CQ\bj]F)4?HPf|p$.58U{ܹ[El*eB[xiZn>Sb} BMQbz {:NR\n~ v>@FKQ} v² ©Ҍ ʷϋ Ͽۊ ţˉʟȈͧɇ Ӷʇe]jʲćz$;Mbsyź#4Fzʪ|‡$-EIۇ $-'J߇&%Ksc )FX\]b]#8Kby{ol{"3CuԺ}fj* +9gfTcv!/Amg]IKRW~ $/:ENL\bu",4CHMU\hw|{{|yݤQČ]AGQNMO\fnv{~(!&*/48;AFLT^m~{{z{|ޤYBERNHU`iqw~E  %).27:?DKS_rع}zyxxߤYDASN2OYclry] #'+049=BHQ]rܳywvvs‹[D?PN2MQ\fmtzn6 "&)-17;?ENZoƜyustsȐ_D>LON2MU`gov{zW  $(,048FN^vɠvponlgקpJC?QNFMOYbiot{qQ+ #'+/36:AHTg}ֶrlkjifߴ|QB?LONDQZcipv{bE "%)-048=CLXhynhggfdŏ]DBARNDMQ[bioty~xR: #&*.159=CMXfwxngdccb`vդlLA?JQN;RZahmrw|~fE0 !$'+.159=DKU_iqutoica_^_^[m 㹁WDB?OON?O  "%'*,/2468;<>?AABB@=IཕoRE=<:x߇ "$'),.02578:;<==<;7qU@4eԀՀv !#%(+-.12467876=FƜqJW}X  !$')*-.01233210t ޴Ppzրۿ  "$%()+,-,+*GۯnXqzv  "$%&()(('%gMapz(  !"#"!0ց΢dM^ox$| ݴMS]nw%ӻ MɘeIQ\ku~ЀL ?CᲀRLOYhr{z E0ԞnINNVfnwҕ  K&njaDQNSblu}ʀͪ g'}WBSMO]hqyȀʷ   :%߯rPBSNMWcmu|ƂǸ2k#٥jLBSNMR_iqx~‚ŵF5$  'Cc&ӜdKATNNOYcltzKGEC@>>@EN[mИ`J@RNR]gou}c^WVVW\bjx ϗ_I?OONWbjqx}қaI?NON/PZdksyעgJ?IPNMR]emsz ݪoMCCSNU_hnu{ɀySD?ONWbgnu{Ŋ]E@FQNPYahoty~ӛiJC?ONPXahnty} zSAADRNMPXagmsw|ǓcGB@NPNMOV^ekpuy} ڭxQBCAOONMNT[dinrv{· ȔcIACCRON QZafkotx{~ ෂ\GABCQON PU\afkorvx{}~zըzWEAABOQNMNPU[aeikoqstuuvn ʠtSEAC@JSPNOTY]adfhikfh ʠuYIACACLSPN MNPRTVYVVuˣaMDBC@BLOSQPO QQLMbͭjWJCBC@@DGLLMMKLJIK[xٽjYOHEEDA@AABEJRaxѻwi_XTSTUX]frҾ~yy{߂݀ ր¿b߂܀Հ43ހہ¿qfހہ¿cyހہ|d߀ۀրb߀ۀրÿd߀ۀրúb߀ہʺd߀ۀľʺdۀʺbր¼ʺbހ րžʸbހۀʸaހۀúʸa߀!ſʸa߀!ʸa߀ۀ¹ʸa߀ۀ»ʸa߀ۀ ûʸaļʸbƽʸbʸbʸb¸ʹd!ùvnnʹd$Ļ{slifddegimptʺb$Ƽxsnljjklnqsvzdzwts ttvy|~dú~|} 3ž pº} Þoffiq~рƿ/٘V9;BHMRW[_bdj+;.5;@FKPUZ^bfilnnB#,17>FKQV\afkotvy}ԤQԦq: !%(,048DHMRW]eo}ʺޤYBH  #%),/258;?ACEE?4#(-37=BGKPU\dpéߤYD1 !#%)+.2469;>?:1# "',16:@DINSYbo⽟‹[D*1  "%(+-0257971& !%*/49=AGLPV_kΩȐ_D71  "%(*,/2440(  $(-27;@DIMR[fx׮ϚfE?E !$'(+./.( "'+/49=AFJOW_oѭ}xקpJC'D  "$')*'   $)-269?CFKRYew}|{zwߴ|QB8C !#%%!  "'+/48<@DHNT]iyɿ~yxxwuŏ]DB C    $(,158=AEJNT^iw~xuttsqդlLA<    # !%*.159=BEINU]fpzztrpopol{㹁WDB-;(Oe||fE "'+/26:>BEJOS[bimqrqomlkklkipϛlM@B!/&[˻O !$(+037;?BFJNRX\`eefgfeo㺋_F@@4*u׺j !%),037;>AEHLPSVY[^_``b_pӪySCA=5Q߯6 "&)-047:=ADGKOQSVXZ[\]\YtCɝmPBA?pk  #&*-036:=@CGJLNQRTVWXWU~NĕmQCAA) ! "&),/268;?ADGILMOPRRSSRO?ཕoRE=<5u߈#%(,/258;=@BEGIKLNMLFqU@4gԀՀw "%(+.1469<>@CDFGIGFHFƜqJW}Z !$'*-/2579;>?ABCCBA@y ޴Ppzրڿ  #&(*-02468:;<;;7?ۯnXqzw "%&),.02356754lMapz* !"%')+-//0/9ց΢dM^ox}  "$&'()*(&ݴMS]nwӻ  ""$%$"RɘeIQ\ku~ЀN D9ᲀRLOYhr{{ I0ԞnINNVfnwҖ M&njaDQNSblu}ʀͫ  g'}WBSMO]hqyȀʷ ;%߯rPBSNMWcmu|ƂǸ!3k#٥jLBSNMR_iqx~‚ŵE5%  )Cc&ӜdKATNNOYcltzKGEC@>>@EN[mИ`J@RNR]gou}c^WVVW\bjx ϗ_I?OONWbjqx}қaI?NON/PZdksyעgJ?IPNMR]emsz ݪoMCCSNU_hnu{ɀySD?ONWbgnu{Ŋ]E@FQNPYahoty~ӛiJC?ONPXahnty}zSAADRNMPXagmsw|ǓcGB@NPNMOV^ekpuy} ڭxQBCAOONMNT[dinrv{· ȔcIACCRON QZafkotx{~ ෂ\GABCQON PU\afkorvx{}~zէzWEAABOQNMNPU[aeikoqstuuvn  ʠtSEAC@JSPNOTY]adfhikfh ʠuYIACACLSPN MNPRTVYVVuˣaMDBC@BLOSQPO QQLMbͭjWJCBC@@DGLLMMKLJIK[xٽjYOHEEDA@AABEJRaxѻwi_XTSTUX]frҾ~yy{߂݀ ր¿b߁ ׀Ԁ43ހہ¿qfހہ¿cyހہ|d߀ۀրb߀ۀրÿd߀ۀրúb߀ہʺd߀ۀľʺdۀʺbր¼ʺbހ րžʸbހۀʸaހۀúʸa߀!ſʸa߀!ʸa߀ۀ¹ʸa߀ۀ»ʸa߀ۀ ûʸaļʸbƽʸbʸbʸb¸ʹd!ùvnnʹd$Ļ{slifddegimptʺb$Ƽxsnljjklnqsvzdzwts ttvy|~dú~|} 3ž pº} Þoffiq~рƿ/٘V9;BHMRW[_bdj+;.5;@FKPUZ^bfilnnB#,17?:0#Ecq{‹[D*1  "%(+-0257971#)PaqyȐ_D70  "%(*,/2440':S`oxрϚfE?E !$'(+./.(GP^lv~קpJC'D  "$')*'  MO[is|ߴ|QB87 !#%%!'PNYgpỳŏ]DB 6   -RMUclu}ˁդlLA< :  5RMQ_hqyȀ㹁WDB-2 (27;><4%3RNNYdnv|ǀϛlM@B!- *7AGMRW\acb\EJQLMS`iqyÀ㺋_F@@0*3:>DINTY]behmrpj]NMYdmtzӪySCA=?!)/5:@FKOTY^bejmpruvkTP^hnu}JɝmPBA?&+17;@FKOUY^cfjmqsvwzu`Wajqy~IĕmQCAA)  &,17;AEKOTY^bfknqswxy|{iYclsyIཕoSE=<"!&+17;@DKNSZ^djosuwwxy{|{h[emtzEqU@*!&+17:?CIMSZaiqy~}|{{|}zg]hot{=ƜqH !&+059>BGLS[er|{{|xc_hntz:޴/  &*-37<@EKS\j}¼{{zzpY`hnty~?ۯh $)-16:?DJR\nԷ}zyywaVaimsy}B# #',048EN]uӧyqoomiTMMQY`ejnswz}|,ᲀK  #'+/36:@HTe|࿝unkkjhXMN SZ`ejmqtwy{}z/Ԟn9 !%)-048DLUaktyytlfb`_\VPON MNNPRTXQ[߯rP !$(+.259>CJRY^ccb`]\[YQFLRSQO PQSLKPp٥jL "%(+/26:=AGLPTVWWVVWWVM@BDFGHIIGGJқaI5.  "%(+-03479;=?@ABCCABaעgJ= + !$'),.03579:;==>=<;ݪoMC !#&(+-/135689873€ySD2  "%')+-/013431KŊ]E@  #$&(*,-.,)ӛiJC. !"$&')('=zSAA  !"##$#""ǓcGB7 ]ڭxQBC( (ˇȔcIAC ෂ\GAA $ ըzWEAA$  ( ʠtSEAC. > ʠuYIAC<" g ˣaMDBC:! RͭjWJCBC=.  1TxٽjYOHEED@=7358EPaxѻwi_XTSTUX]frҾ~yy{t8mk@    N   I#  ,~A  %6V  *>B .EC 1IB 3KC 3LB 3LB 3MC 3MC 3MC 3MD 3MD 3MD 3MD 3MD 3MD 3MD 3MC 3MC 3MC 3MC 3MB 3MB 3MC 3MB 3MB 3M( 3M3Mv 3Ml% 3M< 3MO3MW# 3M]( 3M^, 3M^/3M^13M[23MY33MX33MV33MS33MR33MQ33MP33MN33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33MM33LL33LL33KK31II1.EE. *>>*  %6I[itz~~zti[I6%  ,;IU]befffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeb]UI;,   ,6>EIKLLMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMLLKIE>6,  %*.133333333333333333333333333333333333333333333333333333333333333333333333333333331.*%    jugglinglab-0.6.2+ds.1/source/resources_osx/Juggling Lab.icns000066400000000000000000001741231323754603300240710ustar00rootroot00000000000000icnsSics#H??????is32ϡfܿUI4SfzvNp/7P{B[xQ-C򌇨:RWz7#3T}igoJXp}{BMO`t &0:FY嵂{ԢCHNShx;",5?SutMBRMXkyn '09Gnpmd:PONYkwB "*2PSizsJ=>PyԂڅ>NNZo~ڄAHPO_rO?SMQar~l;IQMQ_nzȋLPSizsJ>>QyԂڅ>NNZo~ڄAHPO_rO?SMQar~l;IQMQ_nzȋLFO]v~{}f=MON\jvq '-5tIOMRanx4 $+18?I\ߞ}uvylBEQNMUepy[ !(.4:CSt~rqmyG>RNXfoyu; %*16>I_ѝymkjِORNNMNXdmtzzC #(-39AM[ktsjb__^k΀H>CSNNMNS]tA $).4:@HPWYYXWXW`ϫaC=ISNNIWϗ6  %*/48=CHLNOQQP`ґUA>HPGcGx   $)-27:>BEGIIHjLjRC>:h  $(-047;>@AA@~'Ŏ[=N #'+-14696+ʉJyp  $'*-/110<$ρ[{8  #&('*Ugxݏ  ! 6&xHdu  )ԣUM_rW )чDQZmz~ ̻lARTguϓ8ԭ\ARO_ozʙ3mԄ'U@SMWgt~ǖE?723>Rqڅ&ؗR?TMP_lwÐqfeitѶ$֚RLQN T^gouzĀLA>ISON PV_glqtw{o̖ԼyLA=CMRPONMNSY]cb^֘VE?=AIORSSQOIKeښȚrUHC>?@DK`֜}i]YY_iy̟ ̽З ̷qchsԡ ֊I5?IPY`ejl̞<)19BKRY`glquv"*2:BJQY`gmquy}՘"*2:AHPYdox|zz|ۖԟ!)/7>FOZn}|ڸ5  '.5BEA, %.5=ELT^p辘f9 "&*/26::.#+29AIPZm䫍lA, !$)-03.!(/6=EKTe𵎂~yG", "'**!%,29@GOZpت~|{ِO7+    !(.5DINTY]_`bbapґUA4 >x #(.37=CGKOSVXZZYwLjRC9O #(-27;@DHLOQR,Ŏ[=P #',059=@DGIJIF&ʉJyr!%*.259Rqڅ&ؗR?TMP_lwÐqfeitѶ$֚RLQN T^gouzĀLA>ISON PV_glqtw{o̖ԼyLA=CMRPONMNSY]cb^֘VE?=AIORSSQOIKeښȚrUHC>?@DK`֜}i]YY_iy̟ ̽З ̷qchsԡ ֊I5?IPY`ejl̞<)19BKRY`glquv"*2:BJQY`gmquy}՘"*2:AHPYdox|zz|ۖԟ!)/7>FOZn}|ڸ5  '.5BE?.Rwf9 "&*/26::*0^tlA, !$)-03-=^qyG", "'**IYm|ِO7+ "  MUhwԯ`C"+ "PPar}΀H=* 0>IQTO:8OLYkwϫaC5-;DLT[cipneTPbq{ґUA4  +4H[zrrkPQ]hov})ԣE !'-39APiҙwnmjVLOXaipvz~})ч+#)/5;EUooggfWMNNQX`fkoruj)̻l  %+06=FTgz}neaa_VQPONNPTY]U^ԭ\ !&+17BEHJKLMJqfeitѶ֚R( "'*.37:=@CDnɸضڪX5 !%),0368;<;8dA  "&*-013;yG+  #&(*++)ҙT?  !"8ԒpE7  ٗUA- ĀLA.  }̖ԼyLA7"֘VE?-UښȚrUHC9-"'8[֜}i]YY_iy̟ ̽Зh8mk  GΩt6xPMi+o[A^, +=?6[G Vˊ06["WM"r[1?< Ar@ 9S,j J*{O"i.t 1mU,q zH0OVq'wn<\ N͎B\ʿ^/cۋuY;`+AD?4$TUB,bBFHIOUUWX\\_q˗/ҹgJPTajpu|ҁ{P6;;?CFIMOQUXZ]_badfezԓ0ȪtVOOTainu{҂ˁܔ\-269;?CFIKPSUX[^_adegijlmj1ͺzeGPNS_gmsy~с*׫5'-037:=ADHKMPTWY]^aceghklnoqqp~3̭pYJPMR]elsx}с+ήX '*-158:?BEIMOQTVY]^acegjlnpprssts݌q}dQJPNQ\djqw{ȴz #(+.379@CGJLOSVY^cglquz} }||{{||}~|{لѽ}aMAERN)MQYaglqvz~Ń4þ9!$&*./378;>@CFILOSVZ_ejqx~}{{|{|Ϻw_J?ERN*MNV]einsw{‚4Q !$&*-/267:=?BEHKOSVZbhox~|{y{Ӷt[H?DRN)MRZbfkqux}6]  #'*+.1479<>ADHKNQV\clu}{yβqXG?DQNeMOW^dinsvz~q  "%)*-0369;=@CFIMRV\foyĻ}{ý̲pVEAASNlS[`ekqsw|~vB  #%(*-0257:=?BEIMQV]hr~ɶ|{zzyyxṷmVECBTNfOV\bglpty}u\ "$'*-/1479;>ADGLPU]huκ}zyxwvyڀ̭lVEA?PN%RY_dimruy}-vg6 !$&)+.02689<@BEJOT\huȵ~zxvtr ѯlVEA>MONVOS[afjotvz~gW  #%'*,/0479:>BDHMT[fuªzxwvuttroѲpXE??JPN#OV]bfkptx|.nZ< "$'),.0368:=@CGLQYer ϳ{wuutqpεrYG??ERMNTPX^bhmptx|u_I !#%'*-/1469<=@DINVam{׺{vutssrpowиv\H?A@SONTOSZ_eilquy|{hS9 "$'),.03479OQNUOOU[afinrux}p\K% !#%(+-/1369:=AEJOWbn ջzsqpomkjŸeMA?>GPNUPU\bfjnqty|xbQ?  "$')+.01478;>BGLS\fu ˴xrpomlih}ħjTE?CBSNcMPV^afjmqux|~lVG5  !#&(),/03579LONuQX]bfjmruy|zcNA-  "$&'+-/13679=@DKQWbnzʼzrnkihhihge_Ͷy\JA?AASN`OSX^bfjnrux|~qZG<"  #%')+-/2569JPN&ORX^bfjnqtwz}|hQ@85 !$%(*+.03579;?BGKRZbkv|upjgfedcc`]ȯmXH??AASN&MLQX]afimptvy|u`J:35  "$&(*,/02679<@BFKRX`hpwzsnjfddbcb`_\Ѻv]MA?A?KPN%MOSY^bfjmpsuy|~}nYE7. 5 !#$')*-/1368:=?CHMQW]djqwxyzxuqmiecba`_^]Y̧iUG??A@QN#ORV\aehknqux{|}}p`O=3+ 4  "$%')+-/1478:   "$%(),./14679JPNPMORSZkȕF  !#$&(*-/02467:<=?CFGJNPQQSTUVUUVUSQPtpXJA??C@QPNSIJbַh  #%&(*,./13579:?@BCDEFGGIJKIGFA ҾpYLE?mC=GQMKIBXٍ !##%()*,./1356799;=?@ABCDDEFEFGGFDDC= ̵kYME?,A>?MH>SӁ/  !"#%')*+-/1235789:<=>?@AACDCBA?;σ ĵi[LEA=';89L|ҀӀ0 !"#&')*+,/00256789:;<=>?@A@?=>==;::q1ʶt`RG=52;wԂՁԀ-  ""#&''*+,./0124567889:998731ǶsaP?70b}؀׀Ԁ8  "$%&')+,-//02334567887887743/ʇ/ɼt\G5Ow|܀փ$H  "#$%'(*++-.0123454331/T7йiOGnu~ׂ*6 !!#$%'()*+,-./0010/.-*8̨sMdnv~Ճ&ݵ   "#$%''(*++,-.-,+*T̋:ŨkQhmwՂ$Z  !"#$%&(()*+*)($:ϽS^gpw~Հ&ؾ  !"#$%%&'(&%$L̋-ĭdL_hpx~ ԁ%j  !"##$$%$$"!.ɵ}NT^how}Ղָ   ! e.ӾfKQ^hov|+D &ċ/ȨvQRR^iou{Ӂת  /ѵ}_JQQ^gmtz~ҁрM 1̪rNNPR]flsy}҂}  Z̊2κxfGQMP[ekrw}ѯ  6ƪ4īkYFRMPZcipv{ ρ-  _AӾzaQHQNOXagmsx}΁T   n̋@ɵq[JJONNW`fmrw|΄n  aƪAfRBKONNU]dkquz~́Ѝ*~̋ Ϲ}_OBPN3QZahnsx|̂ʀ͢ LԪ7вuYLBRNNMOX_flrv{րɃȹh ɬpUJBSN)OU]djotx}΂Ȅǵ  Qᶪ ŪiRG@SN)PY`glrvz~ɁɀDŽŹ  *Rv dOCATN)MU]djosw|ÄŀĶI7$,C]vԪ ݾ|aLC@SN*MR[bgkqvy}ñEAA?;*  +CRajx̐ кw]JA@SN+MOW_diotw{EA?AA==9;?EJRY_iȗ Ͷt[GC?RN)S[`flpsw| QLHGEGHJLORX_fmxڿ εrYGC?QON*OW]bhlquy}b_YXURUX[]aimv̔ βqYGA>OON)SZ`einrw{~{vplifiilpt{̕ βqYGAHPN1OW]chmqtx} ͻ ж ӵw\H??DRN*RZ_dinruy} ́ ƪ Ϲx_J?C?SMN+U\afjnrvz}ӿп }aLAAFQN,ONPV]cgkosvz} ǨlRE?ACRN"QY`dhlpswz~IJ ̱tXG?A=MON)MNS[_dhloswz} к|_LC?ADRN&OTY^dhkosvy}ɴ fPE?A>KPN%PUZ_cgkoruy|~ DzmVH??ACSN/OU[_chkosvy{~μx_OA?A>MPON LNU[_dgjnruwz| ŨiVG??ABQN OTY^bfjmpsvx|~̷̴t_JA?KRNMOSX]aeilosvx{}¡iTE??A@LPN MMNRX]`dilortwy|~̸αx]LC??C?OONMMQUY_cgjloruwz}~̸kUHA??AARNRY^aehjmprtxz{~ ɳx_OE?HTNQX\`cfikmptvwz|}̺ Ĭp\LC?>DRONPUY]`cfiloprtwyz|}~x϶ӿmYJC??A@ASONMNQUY\`cfiklnqstvwxyz{| {{z|u̪ ʹfRGA?>ASPNORUY]`cfhkkmpqsstuuwvvuttlϪ ŮzaRHA?@?JSN ORVY]_bdfhiklmo ponpmiƪ xdUHA?ACHOSRONOQTQKGLZsʷl_ULECA? AA>=@ELQPQSSTSQPQPHEFO_l{μwi]RMHCAA?AA><=?>??A@ABDELU]fsķwkaYTMJGCACCEEGGJMPU[aitڶĶ~tkd_XUROLORRX\air|){wmfd`_]\\]]_dflszڿ%Ĺ|xvuuvx{!׿ ā ƪŹ߶̠rUAACFJMOSW\`fms{~|z|4̼3 !$')-/157:=@CEHLNSW\airz~|zy|6ѽi  $'*,/1579@CFJNRX^fq}ʿ}{yyxyۻ:ª@  "$'+-0258:ADHLPV_hv й}zyxwuq׸.̺B !$&)+-0368:=@CFJNV^gvȲ}zxwxxvtr.ҽ^  #%'*,/1479:>BEHMU\euzxwvuutsv֊Ī߶/Įx3 !$')+.0369:=@CFLR[drʴ{wutsqntiQOSWYZ`fghimloҗ/ҹe !#%(*-/1579;>ADIOW`n й{vutrpp~ZELLPTWZ^`cfikmpsruwuٓ0ȪtQ "%'),/02589<@BFMS\hxҼ{urqpnlmܗc:BFIMPSWZ\`dgilopruvxz{|}zŪ2ͺze.  #%'+-/0368:=@EKPVbn}7Ϲyspoponmkm?7AHMR]htƳwqon$llign^-58AEKQXamw{tmigfeb_\G',159=@DGJNQSVZ^`bfhjmpsuwy|~Έй}_R$i !$&()+./2589BGLPU[bhmrtuvtqnjgda]XTN:#'+.159=@DGJNQRUY\^`dgjoruz}˅fOC)  "#%')*-/13678BEIMQTX[]_5^][XTNG@ #'+.159=?CGHLOQTWZ]`dgkpv{Ϻw_J?*  "$&(*+.014679;?ACFJMORTVW4VTQKC='  $'+.158<>BFGKNPSVY\`dgksyӶt[H?c !#$%(*,.014689;=?BEFILNOOQRQPMH@9* $&*.058:=@DGJMORUX\_bgmt}βqXG?c !"$&(*,./03678:<>ACDGIJLMNMJF@8/  $&*.0479ABCEFHIIHD>70  #&*-0369@,>;5-' "%(+.0479=@BFIJMQTV[`fmyѯlVEA3$  "##%()*-./2356899;=+95.&  !$'*.0468@CFHKNQTX]bjv ־εrYG??S !"$&'()+,./02457762-'    #%(+.0368;>ADFJMNQUZ_gq~Įиv\H?A$S  "#%&'*+,-/012342.(" "$')-0257;=@CDHKMPSW]cmx ů~~zջz_JAA3! !"$%&(*+-./0/-)#  #&)+.147:<>ACFIKNRV[`hs~ į|{ŸeMA?; T !"$%&()+,-.-,*$  #%(+-/258:=@ADHILOSW]dnw ӿ~|zyħjTE?C"u  !"$%%()**)(% !$'),.1467;>@CEGJMPSX_ho{Ƕ}||{zywtɭqXG?A3`  !#$%&'('%!   #%'*-/2469=?ACEHKNQU\bisƻ|zyxvpͶy\JA?A &  "#$%%$" 6 "$'),.1468;@BEHJMQSW\ciqy~zwuustsqpmѺv]MA?A8  5 "%'),.13579<>ADFHKNPTX^cinu{}yvtsrqponj̧iUG??A(   %*#$% *  #%'*-/14679ACEHJMPSUY^beilmopoommlklkjhgkkUEA??; 9jȦT$)  "$&*+-/1477:>@ADFHJMPRTX\^adfhihihhfeu̳y_LC??A3M$UǔH   #%')+.02569;>@BDFHKMNPTWX[_abcdefgffgfecapXJA??C+R0vַj  #&'*,./2568;@BEGHKMNQSTVWYZ[\]^^__`a`_\Y~ ijw`PE?A( @Ѐ@ܥ"  "$&(*-/02578:<>@CDFGJKNPQSTVWXXZ[[\\^^]]^]\YX r\LC?A*#`р2M !"$&)+,/12577:<>ABDEHJKMOPQSTUVWXXZ[ZXWR ҾpYLE?C2^1َ "$&)+-/024589;>?ADEFHJKMNPQRSTUUVWVWUUTN ̵kYME?,A;-Ӂ/ !"#&)+-.014678:<>ABCEGHJKMNOPQRRTUTSRPLՃ ĵi[LEA='; ${ҀӀ0  "$&(*,.014678:<>?@CEFGHJKLMNOPQRQPNMTЄ4̴p\OGA;775B|ҀӁԁ,ݫ! !"%'(),-/234789;=?@BCDEGHIJKLMNOONNLJKx1ʶt`RG=52;xԂՁԀ-  "$%')+-00135789<=?@ABDEFGHIIKJJHGC1ǶsaP?70b}؀׀Ԁ8  "$%'(+-./235679:<>?@BCCDEFGHHGHHGGDB>ʇ/ɼt\G5Ow|܀փ+J  "#%')*+-/1236779;<>?@@ABCDEDCC@?]7йiOGnu~ׂ)8 !#%&()+,./02456889;<=>?@A@?><:8̨sMdnv~Ճ&ݶ   "#&'(*+,.012456789:;<=<;:9[̋:ŨkQhmwՂ%[  !#%&()*,-/0124557899:9762:ϽS^gpw~Հ2ؾ !"$%&()*,-./0224556776776432T̋-ĭdL_hpx~ ԁ k !"$%'((*+,-.0122322//+.ɵ}NT^how}Ղ ָ   !#$%&'()*+-./.,,+i.ӾfKQ^hov|0F  !#$%%'())**+,+((1ɋ/ȨvQRR^iou{Ӂ ת   !"#$$%&'('%%$/ѵ}_JQQ^gmtz~ҁр!N  !!"#$$#$"!1̪rNNPR]flsy}҂-~  !! !!^̊2κxfGQMP[ekrw}Ѱ  ;ƪ4īkYFRMPZcipv{ ρ.  bAӾzaQHQNOXagmsx}΁V p̋@ɵq[JJONNW`fmrw|΄p  cƪAfRBKONNU]dkquz~́Ѝ    .̋ Ϲ}_OBPN3QZahnsx|̂ʀͣ   MԪ7вuYLBRNNMOX_flrv{րɃȹh ɬpUJBSN)OU]djotx}΂Ȅǵ Qᶪ ŪiRG@SN)PY`glrvz~ɁɀDŽŹ  +Uv dOCATN)MU]djosw|ÄŀĶI7%,D]vԪ ݾ|aLC@SN*MR[bgkqvy}ñEAA?;,,CRajx̐ кw]JA@SN+MOW_diotw{EA?AA==9:OON)SZ`einrw{~{vplifiilpt{̕ βqYGAHPN1OW]chmqtx} ͻ ж ӵw\H??DRN*RZ_dinruy} ́ ƪ Ϲx_J?C?SMN+U\afjnrvz}ӿп }aLAAFQN,ONPV]cgkosvz} ǨlRE?ACRN"QY`dhlpswz~IJ ̱tXG?A=MON)MNS[_dhloswz} к|_LC?ADRN&OTY^dhkosvy}ɴ fPE?A>KPN%PUZ_cgkoruy|~ DzmVH??ACSN/OU[_chkosvy{~μx_OA?A>MPON LNU[_dgjnruwz| ŨiVG??ABQN OTY^bfjmpsvx|~̷̴t_JA?KRNMOSX]aeilosvx{}¡iTE??A@LPN MMNRX]`dilortwy|~̸αx]LC??C?OONMMQUY_cgjloruwz}~̸kUHA??AARNRY^aehjmprtxz{~ ɳx_OE?HTNQX\`cfikmptvwz|}̺ Ĭp\LC?>DRONPUY]`cfiloprtwyz|}~x϶ӿmYJC??A@ASONMNQUY\`cfiklnqstvwxyz{| {{z|u̪ ʹfRGA?>ASPNORUY]`cfhkkmpqsstuuwvvuttlϪ ŮzaRHA?@?JSN ORVY]_bdfhiklmo ponpmiƪ xdUHA?ACHOSRONOQTQKGLZsʷl_ULECA? AA>=@ELQPQSSTSQPQPHEFO_l{μwi]RMHCAA?AA><=?>??A@ABDELU]fsķwkaYTMJGCACCEEGGJMPU[aitڶĶ~tkd_XUROLORRX\air|){wmfd`_]\\]]_dflszڿ%Ĺ|xvuuvx{!׿ ā ƪŹ߶̠rUAACFJMOSW\`fms{~|z|4̼3 !$')-/157:=@CEHLNSW\airz~|zy|6ѽi  $'*,/1579@CFJNRX^fq}ʿ}{yyxyۻ:ª@  "$'+-0258:ADHLPV_hv й}zyxwuq׸.̺B !$&)+-0368:=@CFJNV^gvȲ}zxwxxvtr.ҽ^  #%'*,/1479:>BEHMU\euzxwvuutsv֊߶/Įx3 !$')+.0369:=@CFLR[drʴ{wutsqn /ҹe !#%(*-/1579;>ADIOW`n й{vutrppʞ0ȪtQ "%'),/02589<@BFMS\hxҼ{urqpnlmܪ窐2ͺze.  #%'+-/0368:=@EKPVbn}0Ϲyspoponmkmς@̭pY  "$&),./1479<>AHMR]htƳwqon$llihm͐ЀB}dO  !$&(*,/1367:AEKQXamw{tmigfeb_W[|ҀӁй}_R$^ !$&()+./2589BGLPU[bhmrtuvtqnjgda]XTJKmӆԁfOC)  "#%')*-/13678BEIMQTX[]_+^][XTNGACDGIJLMNMJF@8-Ihoxփ̲́pVEAd  !"$&(*+./13579:<>ABCEFHIIHD>7-4[gqyՂ߁̭mVEC!e  #$&(**,/024678:=?@ACDDCB<5-'J`iry~ԃ̭lVEA*&  #$%')*,.0234789;=>@,>;5-#/Tairy~ՂѯlVEA3$  "##%()*-./2356899;=+95.&@V`hqx}ԀҀ ѲpXE?;T  !"%%')*+-/1235779:983.'$NU`iqw| ҀεrYG??S !"$&'()+,./02457762-'>OT`hpu{ҁиv\H?A$S  "#%&'*+,-/012342.("OOT`gouz рջz_JAA3! !"$%&(*+-./0/-)#(OOS_fmtx}ҁŸeMA?; S !"$%&()+,-.-,*$=PMR]dlrw} ЀЪħjTE?C"b  !"$%%()**)(%FPNQ[bjqv{΁ɭqXG?A3`  !#$%&'('%!NONPZaiosy~͂Ͷy\JA?A _  "#$%%$" !NONOX_gmrw}͂ѿePE??9&  !"#  +QN(T\ejpuy~߁˂ݶȯmXH??A!\  0SNNMPZcinsx}ʂѺv]MA?A8P  :QNNMPW`glqwz~ҀɃϪ̧iUG??A(!   BEHJLPSWYZabddaO)ACGJNQTVY\^_bcehkme\VNLMNNS[aglquz~pXJA??C+N (.269<@CEIMPRVY[^`bdfgiknopnh]PLMOW]cjnswz~ ʀ кfUGA??A%P")-/379=ADGKMPSVY\^acegikmopqrstkZMLSY_fjosw{~ŀ ijw`PE?A(U #&*-169;>BEHLOQSVY\^acehjlnpqrttuvsdPMV\bgkpuy} ρ r\LC?A*V #'+.269;?BDILMPTWY\^adfhjlnpqttvvxyypYOX`dhnruz~ҁ ҾpYLE?C2'"%),/269;?BDILMPTWY\^adfhjlnpqttvwy0{xbTZ`ekpsv{~ۂ ̵kYME?`A;"&*-0269ACFKLNRVY]afimsvy{|{|.}|zn\`einrty}:ǶsaP?7'  $&)-0268;>@CFILNRVY]chmrx|~}{z|&}|zygZbfjnruy|Ї9ɼt\G5  #%)-/158:=@CEHLOQVY`fls{}}|${yva\bgjnrvy}7йiO  #&)+/0479BDHMSZcr2׿{xxwwvusiNQW\`dhkortwz}.Ӿ^ "$&)+.0268:<@CFLRYbq ˶{xvu"roSLQW\`dhkortwy|~ɋ/Ȩv8 !#%(*-/1479<>ADIOV_m|ս}wvt"sqpcMLPV[^afknpruwz}1ѵ}_ !$'),.02589@DJNWcp¨|urpnmkZLNPU\`cfilnptvx{|~ ̊2κxf.  #%&*,-02579ADHOUZaiov}{vqlhfcba``ba_^\SMNLMOPPRSTVXYWXTOr ɬpUJ4  "#%(*,.02578:=@DINRW]dhmpqrqolifcb`_^__]\XTQONMOON OQTNLaᶪ ŪiRG* !"$&'*,./2567;>?CFKOTX[_bcdba_]^\[\ZYWPGLRRONOQRNKN\x dOC,  #%&'*,./24689;?BEILORUWZZ[[Z.YYXXYXXYXWVUI;?@EJOTRQNOOPOMPRSSJFHO`vԪ ݾ|aLC* !#%')*,/024789<>ADGJLOQSTU)VWVVWVUSRI?AA?<=AEFHIIKIHGGDDJUajx̐ кw]JA*  "#%'(*-//2468:<=@CEFJLNOPQR STSSTTRQOEAA?AA=>@CEJRY_iȗ Ͷt[GC-  !#%&(*,.013579;=>ACDFGIJMMNO PQPPQPONKCLLHGEGHJLORX_fmxڿ εrYGC(@  !#%&)*,.012679:<>?ACDEGIJJKLKMNNMMNMMJIB__YXURUX[]aimv̔ βqYGA./  "#%')*+.013568:;<>@ACEEFGHIJK LKJGGK{vplifiilpt{̕ βqYGA7=  !#%''*+-/124589:;=>?ABBDEFFGGHIIHGFDDW̗ δs[GA; .  "#$%()+,.02356799;<>??ABBCD EEDCCA?vͻ ж ӵw\H??= !#$&()*+./0235789:<==?@@ABBABCBA@>9́ ƪ Ϲx_J?C"-  !"%&')+,./01246789::<=>>?><:9Ϳп }aLAA5,  "#$&()*,./013456789:;;< ;;:87[̪ ȤfOC?=-  !#$%'(),-.//124456778988652 ǨlRE?A # !"%%&(**,-./12456776530+ ̱tXG?A3(  "#$&'()*,,.//011232110/e к|_LC?A%  "#$%&'))+--../0/.,,*ɴ fPE?A7  "#$%&'()*++,-,,+*)(Z DzmVH??A#  !"#$%%'())*)('&" μx_OA?A5  !!"$ %%''&''&$""P ŨiVG??A!  !"#""!"·̴t_JA??;   o¡iTE??A+ L̸ αx]LC??C+ $̸kUHA??A"  ɳx_OE?;  k̺ Ĭp\LC?8 w϶ӿmYJC??A?  ̪ ʹfRGA?=   Ϫ ŮzaRHA?"  6ƪ xdUHA?A3 TȮziVJEA??A?' 1x ª|fVMEA?A; T ӿj]PGC?A2 @pת ȵueXMGC?AA;%  ,Psʷl_ULECA?AA;.!  -K_l{μwi]RMHCAA?AA=5+**07HU]fsķwkaYTMJGCACCEEGGJMPU[aitڶĶ~tkd_XUROLORRX\air|){wmfd`_]\\]]_dflszڿ%Ĺ|xvuuvx{!׿ ā ƪt8mk@CQ~~wT7(fԙafg! u\ dO 9  R RI #kc  &M #,jF (5c7)=` (=T ':NP$]w1Ԉ0 /QqTlb$?bqd -Kp."9Y~i,Fh) 6RuI !>\~>(HfZ/PpJ5Xx):^~ ?e#Cji%Fm (Iq{(Kr(Krw'Jr&'Ip%El !AgH[vd 2Pl 1Pj] :[t 0NjC +Bb~#;Ur0 3Pka'Ed~w 2Tt %?c1  0Ot7 #;\++Eg<%  5Qt}>)  >\~\@/ &Fd[E1+Mlw]F/ 1TuԫhUB, 6[{ҹvdM9(  ;`»Ӻq_K5# !?ezgRB0 $CjteVE2%%ElynbRD7( %Fmـyqg[PD7+! %FmVahmpssssplhc[SLB8/% %Dl)d)  9^~ 3Ww.Pp=(Hg !?]0 6Su.Il]%=^ 1Pv7(Dh7Zz *Hh4 9WsY +Gb  4Mn"#8Wwl  )Db|y)1Leh8" 5KgU8' "3LiΈO9(  "7QjhT?(  #8Od|㽌dS?)  !3E]uҬraK5% ,@Wi|ѳm[F1   *=NavǴ|hSA/  #0@TftyiZG4& $4CQbq}tfVF9)  *5DS_kwynaVH9,")4>IT^fnu{|xph_WK@6,    (19@HOTX]_``_^ZUQJB;4*"   %*-14666642.+'! jugglinglab-0.6.2+ds.1/source/resources_osx/PkgInfo000066400000000000000000000000101323754603300222250ustar00rootroot00000000000000APPL????jugglinglab-0.6.2+ds.1/source/resources_win/000077500000000000000000000000001323754603300207425ustar00rootroot00000000000000jugglinglab-0.6.2+ds.1/source/resources_win/Juggling Lab.ico000066400000000000000000003025361323754603300236740ustar00rootroot00000000000000 (V@@ (B~00 %J  Np h(   %*-14666642.+'!   (19@HOTX]_``_^ZUQJB;4*" )4>IT^fnu{|||xxxvvvuuuuuuvvvxxx{{{|xph_WK@6,   *5DS_kw{{{wwwmmmfffddd```___]]]\\\\\\]]]]]]___dddffflllssszzzynaVH9," $4CQbq~~~}tttkkkddd___XXXUUURRROOOLLLLLLLLLLLLLLLLLLOOORRRRRRXXX\\\aaaiiirrr|||tfVF9)  #0@TftwwwkkkaaaYYYTTTMMMJJJGGGCCCCCCCCCAAAAAAAAACCCCCCEEEEEEGGGGGGJJJMMMPPPUUU[[[aaaiiitttyiZG4& *=Navwwwiii]]]RRRMMMHHHCCCAAAAAA?????????AAAAAA=>>5<<+==*??>>????AA@@AA*BB0DD7EEHLLUUU]]]fffsss|hSA/ ,@Wi|lll___UUULLLEEECCCAAA?????????AAAAAA;>>.==!@@ EELLQQPPQQSSSSTTSSQQPPQQPP HHEE-FFKOO___lll{{{m[F1   !3E]uuuueeeXXXMMMGGGCCC?????????AAAAAA;<<%>>CC HHOOSSRROOOOOONNNNNNNNNNNNNNNNOOQQTTQQKKGG,LLPZZsssraK5%  #8Od|jjj]]]PPPGGGCCC????????????AAA2==AAGGRRSSPPOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNPPSSTTMMKK@WWpttdS?)  "7Qj|||fffVVVMMMEEEAAA?????????AAA;==BBKKTTQQNNNNNNNNNNNNNNNNNNNNNNNNNNNNMMNNOONNMMNNOOPPPPQQSSTTSS LLTffhT?( "3LizzziiiVVVJJJEEEAAA??????AAA?@@'@@ GGRRPPNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMMNNPPRRTTVVWWYYYY[[]]\\[[\\UU1ZZx{{O9( 5KgxxxdddUUUHHHAAA?????????AAA3<<DDQQQQNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMMPPTTWWYY\\^^``bbccddffggggggffffhh ]]TnnU8' 1LezzzaaaRRRHHHAAA??????????@@"??JJSSNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOORRVVYY]]__bbddffhhii kk ll mm oo oo oo pp oo nn ppmm6ii˓h8"  )Db|fffRRRGGGAAA?????????=>>AASSPPNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOORRUUYY]]``ccffhhkkkk mm pp qq ss ss tt uu uu ww vv vv uu tt ttll􄑑y)#8WwmmmYYYJJJCCC??????AAA?@@AASSOONNNNNNNNNNNNNNNNNNNNNNNNNNMMNNQQUUYY\\``ccffiikk ll nn qq ss tt vv ww xx yyzz{{||||||{{{{zz ||uu鐛l  4Mnppp\\\LLLCCC?????????8>>DDRROONNNNNNNNNNNNNNNNNNNNNNNNNNNNPPUUYY]]``ccffii ll oo pp rr tt ww yy zz||}}~~xxw" +Gbxxx___OOOEEE?????????;??HHTTNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNQQXX\\``ccffiikk mm pp tt vv wwzz||}}k  9WskkkUUUHHHAAA??????AAA"AARRNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNRRYY^^aaeehhjjmm pp rr tt xx zz{{~~Y *Hhxxx]]]LLLCCC??????CCC+??OOOONNNNNNNNNNNNNNNNNNNNNNMMMMQQUUYY__ccggjj ll oo rr uu wwzz}}~~$47ZziiiTTTEEE??????AAA+@@LLPPNNNNNNNNNNNNNNNNNNNNMMMMNNRRXX]]``ddiill oo rr tt ww yy||~~L(Dhttt___JJJAAA??????;?? KKRRNNNNNNNNNNNNNNNNNNNNNNMMOOSSXX]]aaeeiill oo ss vv xx{{}} o 1PviiiVVVGGG??????AAA!BBQQNNNNNNNNNNNNNNNNNNNNNNNNOOTTYY^^bbffjj mm pp ss vv xx||~~ !!!"""###""!"7%=^xxx___OOOAAA???AAA5>>MMPPOONNNNNNNNNNNNNNNNNNLLNNUU[[__ddggjj nn rr uu wwzz|| !!"$$$%%''&''&$""P.IlmmmVVVHHH??????AAACCSSNNNNNNNNNNNNNNNNNNNNNNOOUU[[__cchhkk oo ss vv yy{{~~ !"#$%%'())*****)('&"] 6SufffPPPEEE???AAA7>>KKPPNNNNNNNNNNNNNNNNNNNNPPUUZZ__ccggkk oo rr uu yy||~~ "#$%&'()*++,---,,+*)(Z !?]|||___LLLCCC???AAADDRRNNNNNNNNNNNNNNNNNNNNOOTTYY^^ddhhkk oo ss vv yy}} "#$%&'))+--../////0/.,,*0(HgtttXXXGGG???AAA3==MMOONNNNNNNNNNNNNNNNMMNNSS[[__ddhh ll oo ss wwzz}} "#$&'()*,,.//011233332110/e.PplllRRREEE???AAA CCRRNNNNNNNNNNNNNNNNNNNNQQYY``ddhhll pp ss wwzz~~!"%%&(**,-./1222456776666530+= 3WwfffOOOCCC???=>>FFQQNNNNNNNNNNNNNNOONNPPVV]]ccggkk oo ss vvzz}} !#$%'(),-.//124456778999988652 9^}}}~aaaLLLAAAAAA5<<LLQQNNNNNNNNNNNNNNNNPPVV\\bbggjj nn ss vv yy~~ "#$&()*,./013456789:;;<<<<;;:87[ >dxxx___JJJ???CCC"??SSMMNNNNNNNNNNNNNNNNUU\\aaffjj nn rr vv zz}} !"%&')+,./01246789::<=>>??????><:9) #Biwww\\\HHH??????DDRRNNNNNNNNNNNNNNNNRRZZ__ddii nn rr uu yy}}!#$&()*+./0235789:<==?@@ABBABCBA@>9^$'*-////-*'$ %Dlsss[[[GGGAAA;>> HHPPNNNNNNNNNNNNNNOOWW]]cchhmm qq tt xx}} "#$%()+,.02356799;<>??ABBCDDDEEDCCA?v)?ABBDEFFGGHIIHGFDDWVahmpssssplhc[SLB8/% %FmqqqYYYGGGAAA.>>OOOONNNNNNNNNNNNSSZZ``eeii nn rr ww{{~~ "#%')*+.013568:;<>@ACEEFGHIJKKKKKLKJGGK{{{vvvpppllliiifffffffffiiiiiilllpppttt{{{yqg[PD7+! %ElrrrYYYGGGCCC(??QQOONNNNNNNNNNOOWW]]bbhh ll qq uu yy}} !#%&)*,.012679:<>?ACDEGIJJKLKMNNMMNMMJIB_bb___YYYXXXUUURRRRRRRRRRRRUUUXXX[[[]]]aaaiiimmmvvvynbRD7( $Cjttt[[[GGGCCC??RRNNNNNNNNNNNNSS[[``ff ll pp ss ww|| !#%&(*,.013579;=>ACDFGIJMMNOOOOPQPPQPONKCLQQLLLHHHGGGEEEEEEEEEEEEEEEGGGHHHJJJLLLOOORRRXXX___fffmmmxxxteVE2%!?ewww]]]JJJAAA@@SSNNNNNNNNMMOOWW__ddii oo tt ww{{ "#%'(*-//2468:<=@CEFJLNOPPPQRRRRSTSSTTRQOEAEEAAA?????????AAAAAA===>==>99>99>99>:9@<;C??EEEJJJRRRYYY___iiiuuuzgRB0  ;`|||aaaLLLCCC@@SSNNNNNNNNMMRR[[bbggkk qq vv yy}}!#%')*,/024789<>ADGJLOQSTUUUUUUUUVWVVWVUSRI?EEAAAAAA???<;;=,*AEF HIIKIHG GDD,+JCCURRaaajjjxxxq_K5#  6[{dddOOOCCCAATTNNNNNNNNMMUU]]ddjj oo ss ww|| #%&'*,./24689;?BEILORUWZZ[[ZZZYYXXYXXYXWVUI;II?77@%$EJOTRQNOOPOMPRSSJFH,,ODC`]]vvvvdM9(  1TuiiiRRRGGG@@SSNNNNNNNNPPYY``ggll rr vvzz~~!"$&'*,./2567;>?CFKOTX[_bcdddba_]^\[\\\\\ZYWPGLRRONNNNNNNNNNNNNNOQRNK N+*\URxvvhUB,+MlpppUUUJJJBBSSNNNNNNOOUU]]ddjj oo tt xx}} "#%(*,.02578:=@DINRW]dhmpqrqolifcb`_^^^__]\XTQ ONNNNNNNNNNNNMOONNNNNOQTNLaQQw]F/&FduuuYYYLLL'BBRRNNNNMMOOXX__ffll rr vv{{!#%'*+-/1368:>ADHOUZaiov}{vqlhfcba``ba_^\SMNNNNNNNNNNNNNLMOPPRSTVXYWXTOrhh[E1 >\}}}~___OOO.BBPPNNNNNNQQZZaahh nn ss xx||"$&)*-/03689<@DHMT[clvyrmjfdcccccb_^UM NNNNNNNNNNNMNPRUXZ\ ^ ^ _ a c b a _ b Y fML\@/  5QtfffRRR8BBKKOONNNNUU]]ddkk qq uu zz~~ !$&(*,/1368:) +Egqqq[[[GJJJJOONNNNWW``ff mm rr ww||!#%'),/02579@DJNWcp|urppppnmkZ~}LNNNPU\ ` c f il n p t v x {|~ !! !!^Z 'Ed}}}~___JJQQQQ^^gg mm tt zz~~!$'),.02589ADIOV_m|}wvtttsqpcM LPV[ ^ a f kn p r u w z} !"#$$%&'''(((('%%$a#;Ur^ffKKQQ^^hh oo vv||"$&)+.0268:<@CFLRYbq{xvuuuuroSFDLQW\` d h ko r t w y |~ !#$%%'())**+,,,+++((1&0 +Bb}}}~.NNTT^^hh oo ww}} #%'*,/2479;>BDHMSZcr{xxwwvusiN QW\ ` d h ko r t w z } !#$%&'()*+-- - .!/!/!/!/!/!. ,,+ie0Nj_ddLL__hh pp xx~~!#&(+.1258:[viiiOOOGGnn uu~~ #&)+/0479/?0@0@1@1A1A1A1@0?/>.<-:*d+=Vrttt\\\GGG555OO ww|| #%)-/158:=@CEHLOQVY`fls{}}|||||{yvaJH\b g jn r v y } "#%')*+- /"1#2$3%6'7(7*9+;+<->.?0@0@0A1B2C3D4E5E5E5E5D4C3C3@1?/]T.CWqsssaaaPPP???777'00 bb}} $&)-0268;>@CFILNRVY]chmrx|~}{z|||}|zygZb f jn r u y | "$%'(+-. /"2$3%5&6'7)9+:,<->/?/@0B2C3C3D4E5F6G7H8H8G7H8H8G7G7D4B3>/,,C[pttt```RRRGGG===555222;; xw #&)-0269;>ACFKLNRVY]afimsvy{||||{{{{{|||}|zn\`e in r t y } "$%')+- 0"0"1#3&5'7'8*9+<,=.?/@0A1B2D4E5F6G7H8I8I9K:K:K:K:K:J9J9H8G7C3d-D`yppp\\\OOOGGGAAA;;;777777555BF|| #&)-0269O>N=N=L;J:K:xq 0E_|iii[[[LLLEEEAAA=========;;;! 89$L{|#&*-0269/?0@0C2E5F6G7H8J9K:L;MP?Q@Q@Q@RARARAQ@P?N=M?MH>-S"&*-0269/A1B2C3E5G7H8J9K:MP?Q@RARATCTCTCUDUDUDTCSBRAP?L;+";XqpppYYYLLLEEE?????????CCC22=GQMKIB1X"%),/269;?BDILMPTWY\^adfhjlnpqttvwyyy{xbTZ` e kp s v {~"$&)+-/!0#2#4%5(8)9*;,>.?/A1D3E5F6H7J9K9M;N=P?Q@RASBTCUDUDVEWFVEWFWGWGWFUDUDTCN=ۼP 5Rqrrr\\\LLLCCC?????????AAA**?KSONNMKEO`t #'+.269;?BDILMPTWY\^adfhjlnpqttvvxyypYMKOX` d h n r u z~!"$&)+,/!1#2%5&7(7*:+<->/A0B2D4E5H7J9K:MP?Q@SBTCUDVEWFXGXGZIZIZI[J[J[J[KZIXGWFRAҟ~ 0Ggwww```PPPEEE?????????AAA((=RQNNNNNMMHF @d#&*-169;>BEHLOQSVY\^acehjlnpqrttuvsdP" MV\ b g kp u y } "$&(*-/!0"2$5'7)8*:+<->/@0C3D4F6G7J9K:N=P?Q@SBTCVEWFXGXHZI[J[J\K\L^M^M]L]L^M]L\KYHXGϚ&?YzfffUUUGGGAAA??????AAA%%?OPNNNNNNNNMLG)\o")-/379=ADGKMPSVY\^acegikmopqrstkZ\ZM LSY_ f jo s w {~!$%(+,. 0#2$3%5(8):+<->/@0B2E5G6H7K:MJPNNNNNNNNNNNNMORSZ $kU'27:>ACGJNQTVY\^_bcehkme\VHFN LMNNS[ a g lq u z ~ #%')+.!0#2$5&6(9*;->/@0B2D4F6H7K:MBEHJLPSWYZabddaO)Tj$>< QNNNMMV^ d io s w | "$&*+- /"1$4%7(7):,>.@/A1D4F6H7J9M/A1C4E6H8J9M/A1D3F6H8K:N=P?TCXH^McQiWn]ud{jтq҇wԈxԉyԊzӈx҅uсq}myivetcsbraq`q`q`q`p_o^n]jYϋ/JlmmmXXXHHH??????AAA!!ASNNNNNNNNNNMLQX]afi m p t v y| u`J: 30SNNMPZc in s x } #&(*- 0"2$4&7(8*;,>/@0B2E6H7J9MJPNNNNNNNNNNORX^bfj n q t wz} !!""## |hQ@ 8+ QNNNT\ e jp u y~ "%(),.!1$3%7(8*:+=.@0C3E5H7J9L;P?SBXG\KdRkZrb|kӇvבۙߢ⨛⫝⫞⩜गݞڕ֌|҅uЁp{jxgvfueueueudtctcq`n]ݭ$Cayyy\\\JJJAAA???AAA ASNNNNNNNNNNOSX^bfj n r u x|~ ""##$$%%%%$$""qZG LONNNNNNNNNNQX]bfj m r u y| !!##$$%%&&''((''%%!!zcNA -NONPZa i o s y ~ #%'*- /"2$4&6'9+=-?/A1C3E6H7K9N=Q@UD\KbQiWsbnԊzۘ⪜躮ŻƼ黯㭠ޟٔԊzтrn|kzizhzhziyhxgvep_G0RrjjjTTTEEE???CCC""BSNNNNNNNNNMPV^afj m q u x|~ !!""$$%%%%(())****))((%%lVG5F PNQ[b jq v {!$'),.!1#4&6(7);,>/@0C3E5G7J9M GPNNNNNNNNNPU\bfj n q t y|!!""$$%%&&(())++,,--..--,,**$$xbQ?=PMR] d l r w } #%(+- /"2$5'8):+=.@0A1D4H7I8L;O>SBWG]LdSn\wf҅uږॗ蹮꿴㫟ݞؒӈxуrЁpooo~m|lziyhЋ}ǪOQNNNNNNNOOU[afi n r u x}!!""$$%%&&((**++--..//000000--))##p\K(%OOS_ f m t x } #&)+.!1#4%7(:+<->/A1C3F6I9K:N=RAVE[J`OhWsb~n׏ߣ浨Ļ䯢ޠٔԉz҄sЂqЀpЀpЀpom|k{jצ!Agvvv\\\HHH???AAA$$@SONNNNNNNOSZ_ei l q u y| ""##%%&&''**++,,--//001122334422..(({""hS9OOT` g o u z"$')-0"2$5'7);,=.@0C3D4H7K9M OT` hp u { #%(+.!0#3%6'8*;->/A1D4F6J9M.@0C3F6H8K:N=Q@TCXG]LbQjYveЂrאߣ軰꾳⪝ݝؒՋ{Ӈwӆu҅uфtфtфtЁqтpף'JrlllVVVEEEAAA33>MONNNNNNOS[afj o t v z~ ""####%%(())**--..//22335566889999;;======9955..&&g W@ V` h q x }!$'*. 0#4%6'8*<,?/A0D4G7I9K:O>SBUDYH_MeTl[wf҅uؒक़輰綪ߤۙ׏ԊzӈxӇwӇv҆uхtхtуr~o&(KrlllVVVEEEAAA**?PNNNNNNNRY_dim r u y} ##$$%%''))**,,..00223344778899;;==>>@@@@@@>>;;55--v#'g/6Ta ir y ~"%(+.!0$4&7)9+=.@0B2F6I8J9MRAUDXG]LaPfUn]yh҅uבߢ綪Ǿĺ洨खۙבՌ}ԊzӉyӈxӈxӈxӇwӇvЇy(IqpppVVVEEEAAAASNNNNNNS[`ek q s w|~ !!""$$&&((**++..//1133557799::<<>>AABBCCEEFFHHIIIIHHDD>>77-0v4B[g q y  #&*- 0#3%6(9*<-?0B2D5H7L:M=P?SBVEYI]MbQgVn]yhтr֎~ݝ䯢꽲岥ঘܚؔ֎Ռ|ԋ{ԊzԊzԉyԉyӈx҆uߴ{%FmqqqXXXGGG???DQNNNNMOW^di n s v z~!!""$$&&((**,,..//0033667788::<<>>AACCDDGGIIJJLLMMNNMMJJFF@@88-/qI h o x  $&*. 0"4%7)9*<-?0C3F6I9L;N=Q@TCWF[I^McRgVm\wfЀoՉyڗग尤꾳ȿŻ鼱寣ߤܜٔא֌}ԋ{ԋ{ԋ{ԋ{ԉyԉyӉyԑ #Cjttt[[[HHH???DRNNNNMRZbfk q u x}!!##$$%%((**,,..001144668899;;==??BBEEFFIILLNNOOOOQQRRQQPPMMHH@@695*]Ypw ~ $&*. 0#5'8*:+=.@1D4G7J9MRAUDXH\K_NbQgVm\tc}l҅uאܜॗ寣踬齲꿵꾳蹮注㬠ߢܜٕא֍}ԋ{ԋ{ԋ{ԋ{ԋ{ԉyԉyԉyỳi ?ewww___JJJ???ERNNNMNV]ei n s w{ ""$$&&((**++..001144667799;;??AACCFFJJMMOORRTTVVWWWWWWWWVVTTQQKKCC8=A'Qk w } $'+.!1$5&8*<->/B2F6G7K:N=P?SBVEYH\K`OdSgVkZsbyhЀoԈxؒۙޠᥘᩜ᪝ᩜक़ߢݝڗؒא֍~Ռ|Ռ|Ռ|Ռ|Ռ|ԋ{ԉy֌{Ԝ:^}}}~aaaMMMAAAERNNNMQYag l q v z~ ""$$%%((**++--//11445577::==>>BBEEIIMMQQTTXX[[]]________^^]][[XXTTNNGG<@R 9u|#'+.!1$5&9*=.?/C3G7H8L;O>Q@TCWFZI]L`OdSgVkZp_ve{jтqԈx֍~ؒږۚۚۙڗٕؒ׏֍}Ռ{ԋ{Ռ|Ռ|Ռ|Ռ|Ռ|Ջ{Ռ|֛5XxfffOOOCCCDQNNNNT\cj o s w| ""##%%''))**--//1133667788<Q@TCXG[J]L`OdSgVjYo^tcwg|lЁq҅uԊzՍ}֏אאא֎֍}Ԍ|Ռ|Ջ{ԋ{Ռ|Ռ|֍}֍~Ռ|Ջ{ד)/PplllUUUGGGDQNNMPY_fl q vz~!!##$$&&))**,,//0033557799<<>>BBGGLLPPUU[[bbhhmmrrttuuvvttqqnnjjggddaa]]XXTTJNK:vm #'+.!1$5'9+=-@0D4G7J:N=Q@RAUDYH\K^M`OdSgVjYo^raudzi}lЁpуs҆vӇwԉxԉyԉyԉyԊzԊzԊzԋ{ԋ{Ռ|Ռ|Ռ|Ռ|֌|΅vJ(HfwwwYYYLLLCTNNMQ[ch o s w}""$$&&((++--//00336677::<<@@CCGGKKRRZZ``ggppxx~~zzsslliiffbb``]\WWOSOCp# "&*. 1$5'9+=-@0D4G7J:N=Q@SBVEYI\L_NaPeTgVjYn]p_sbvezi}lnЁpуr҅t҅u҆v҇vӇwԈxԉyԊzԋ{Ռ|Ռ|Ռ|Ռ}σsZ !>\}}}~___RRR$$CSNNNU]dj p u y~!!$$&&(())++..//22558899< 6RufffUUU22FOONOXaf l r v{ ##%%''))++--0022447799;;>>AAEEKKQQXXaammww{{ttmmiiggffeebb__W\[G| ',1#5'9*=-@0D4G7J:N=Q@SBVEZJ^M`ObQfUhWjYm\p_sbudwfyh|k~moЁpЂr҄tӆvӇwӈxԉyԉyԋ{ԋ{Պzъ|I,Fhqqq[[[@@HMONPZch o t y~ ""$$&&((++--0011336688::==AAEEJJQQWW``llzzxxrrmmjjiihhggffcc\aYLr+?$+/!3%8);,?/C3G7J9M>AAHHMMRR]]hhttwwqqoonnnnnnlllliihgmn.^X- 5'8*<-A1E5I8L:P?SBVEZI^M`OcQeTgVjYn]o^ratcvexg{j}lnЀpЁpуrуsуs҄tфsՙ$?bzzzeee..GPNS_gm s y~ ##%%''++--//00336688::==@@EEKKPPVVbbnn}}yyssppooppoonnmmkkmmq?57'<-?0C3G7K:N=RAUDYH\K^MbPfTgWjYn]o^ratcvexgzh{k|lnoЁqЁqЀpЋ~ļd /QqtttQQVOOTai n u{""%%'')),,//0022558899<<@@BBFFMMSS\\hhxx{{uurrqqqqqqppnnllmmTlc\:-B2F6I9M;P?SCWFZI\K`PdSgUiXl[o^p_raudvexgzi{j|l}mzjяŽb">]weegJPTaj p u|!!##%%((**--//11557799;;>>AADDIIOOWW``nn{{vvuuttrrrrrrppppҽ1~{ZPȫE6L;L;P?TCWFZI^M`OcQfUiXkZm]p_sbraudwfueΉzᮦ0 0Lhxxx33RSTbk q w}!!$$''))++..00336699::==@@CCFFLLRR[[ddrr{{wwuuttttttssqqnnaFtmi^ȱQBO>SBWFYHZI`OfUgUhWiXm\l\o_ˁqқE":Ts^^cMUaj q x~ ##%%''**,,//11447799::>>BBEEHHMMUU\\eeuuzzxxwwvvuuuuttssvvDJժuפڨҝ̕ڪݭ٪{ýV7(?^yBBXVbk r y!!$$&&))++--00336688::==@@CCFFJJNNVV^^ggvv}}zzxxwwxxxxvvttrr߀ -IguuyQbj r y""$$&&**,,//11447799<<>>AADDHHLLPPVV__hhvv}}zzyyxxxxxxwwuuqq 7Ti@@^`j q x ""$$''++--00225588::<>@@CCFFJJNNRRXX^^ffqq}}}}{{{{{{{{yyyyxxyy ':Niiw c o w $$''**,,//11557799<>AACCFFJJMMOOSSWW\\``ffmmss{{~~||||||||||||||zz|| (5c p!!$$''++..11447799<frrrXYYGIICBBD>>A==7>>&BBGGHHIIJJIIKK*KKIUUplle? A77PPP #Jx```IJJ@AAD==>B>>)CC LLPPPPNNNNNNNNNNMMMMPPQQTTVVVVTT6ddZ! KxxxSSS@BBB>>8??IIOOOONNNNNNNNNNNNOOSSYY__ccffii llkkggiiot \KK?zUUU@AAC>>3@@MMOONNNNNNNNNNMMNNSSZZbbggll oo ss vv ww yyzz wwttV D /h^^^CDDC>>/BBNNOONNNNNNNNNNMMQQZZbbggmm rr vv zz}}FPqppIII@??;@@ LLPPNNNNNNNNMMNNTT^^ff ll qq vv{{~~Ub}} 0qXXX@@@@>>KKOONNNNNNNNMMOOWWaaii oo uu zz(n/]GqqqHIIC==$EEPPNNNNNNNNMMPPZZccjj qq vv|| !#$%%%7||#`]^^CBB>>> LLOONNNNNNNNPPZZcckk rr zz~~ #$&)*+++(+^JW 3tPQQD>>"FFPPNNNNNNMMOOYYddll ss zz"%'*,./1111-@BwwwIII?== KKOONNNNNNNNWWddll sszz!$'*-.1346787576qNlmmHEE2@@NNNNNNNNNNUUaajj rrzz"%(+.1368:<=>=<:Qw  wwwVeggHBB#DDPPNNNNMMQQ^^ii qq yy #&),0368;=?ABCDC=S 7;=;6-!  YbddHAAFFOONNNNOOZZee oo ww~~ #'*-148;=@CDGIIJJFLp|wwwvuuyww||}rcP9#dccWeffFBBIIPPNNNNUUbb ll tt}} #&*.159<@DGJLMNOOOMGRWWOMMKNNIOOJQRNVVT\\^ffnvvw]?" wxxEEEOkllEDD IIPPMMOO\\hh rr zz $'*.26:>CHMQRSTSTTUSK=MM=>>?65B'&CDEF! J-,PCBaddyT2DuuuIHHJJPPMMSScc nn ww"&*.26:?FNU[__^\ZZZZYQE-+K MPOOONOLKP&$cQOh7 8{RNNKKPPNNZZhh ss||"%*-16;@IT_luyvogb__`^WOOONNNMMNPRSRUoWV>)i_WWHHNNPP__mm ww $(-16:@HTezsjdddcYM NNNNNPV[_ b e h e b n84ItqmmmRrii$KKNNSSdd ppzz#',049>FSeqjihhZLNNMQW_ e im q t t w w rt$㢙ITN9w:QQMMUUgg tt~~!&*.37CM\uzuttdLV_ g n s x }!$%(()*+$9/ ŽCXggUUmmzz"&,16:@GQ_yywvuYMMUb i o u z"%')+. /!0#1#1#0"- RIx(^$[[jj{{#(.38=CJR`u}zzzlXc k q w }!$'*-/"1#4&6'7(8*8*9*4%=1ꦛWWW +_SZZ `` ||$*.5;?ELS^n{{{w^?>ak r x ~#&),.!2#5&7(9+<,>.?0?0?0>/;,XN+VsvvPJJ&;; tt$+173W$,17>CIOT[`ekortxy{}hYi p x  $)- /!3%7):+?/B1E4H8J:M=P>Q@RASBSCRAO>\M!UqqqLLL??@DD>((DNOE3[$*07=CJOU[`eimqsv{x`mlXe o v ~ $(-1#4&7);-?0C3G6K:N!!EPONPHPo'17''DONNNNOLJ -ho/;BHNTZ_djojcYNMMM] hr z #'+0"4&8*=.A1E5J9N=SBWF\K_NaPbQcRcRdSdSeTaOk\hhhMqqqHHIAA>11ANNNNNNMP[_e tO,8BHNSQK6l&ACOMS c nv "'+/"4%8)=.A2E6K9P?UD]LcRiXl[l[l[kZjYiYjYkZgVk\ +kYYYAAA??? LONNNNMS\f m s w z#%%m B(D QMYh s { %)/"3%7);-B1F6K:P?WGaPl[wfoЂrЀozjucq`o^o^p_l[tf@yyyJJKCC=&&DPNNNNNQ]f m tz! [ := QN_ mv #(-2$7(;,@1F5J9P?WFcRsaфsٔޠߡܚՌ|πoxgudtdudp_~oUffgDDD==? LONNNNR^f n u{ ##$%''$$i E4 RSd q {!&+0"5':+?/D4I8N=VEbQtcԊ{᧙꿴躮ߡ֌|nyiygyhsb΃u&fYYZEE?''CONNNNP\f m t|!!$$''**++++%$|V+ #RVh t ~#)- 3%8)=.B3G7M;SC^Mo^Ӈwᨚ岥ٕ҄tn~m|kyi̓u0sQQRCC=IPNNNPZf m u| ##&&((,,..1122.. #n;NY kv  %+0#5'<-@1E5K:P?YHfU{jݝƼ躯ۙӇwЂqЁp~no٧>7|OON;;> LONNNWbl t|!!$$(())--0033669977.. ]= ]l y "'- 3%8*>/C3I8O=UD]Ln]҇w⫟涪ۘԉy҅tфtЁqІv:{{|OOL33@NNNNS`i rz""$$''**..225588::==??;:+/~+?\n {#)/!5';,A0F6K:R@XGbQraՋ|䰣⩛ؒӉyӇw҇uфt՗c:{{}QQL++CPNNO[g p x!!$$((++//336699==AADDFFFF>=,.sMp{$+1#7)=.C3I8N=TCZJdSsbԊz⩛峧ۚ֍~ӉyԉyӇwӌ}5{UUO$$BPNMTc m v}!!$$((,,//3377;;??DDHHLLOOPPLK>B7'Zh |%,3%9*?/E5K:Q?VE]LeTq`҂rۙ層ù꿵䭡ۛאԋ{ԋ{ԉyԋ{؜T֗.qZZS$$CPNN[h qz $$((++//3388<TD[KaPfUl[raxg}lЁpуt҆uԈwԊzԋ{Ԋzԏܶء=|}BBNMO]k v %%))--1166;;AAJJXXllrrjjhfdfZZt/E)1";+B2I9O>TD\KaPgVkZq`vezj~nЁq҅uӈwԈwԊzܻ֒؝'d[[\ KP` oz##'',,0044::??HHUUiizzoommmlhiahRLs9-5'>.G7O>UD\KbPgVl[q`vezi~nЁpуr҄tӋ|כ`3ԑ~~~IvNQd q| %%**//3388==CCNN__{{~~rrppppllzy˳x#RGF9F7J9Q@XH^MeSjYo^tbxfyioЄuԑ޸ zg֙+]>>[Pf t""((--1166;;@@GGUUii~~vvttssrrOve]Z[NUFWF_OdTkZo_rawf΅uԔZᾸԄwӊ~୤uuv<}|Te v$$))..4499>>DDLLXXnn{{wwxxsszzjt"ȟў.јDϒIϔIנFר.˞rfܨʺGGGgb v!!&&++0066;;@@FFNN[[nn{{yyyyvvjnnztZQ 0щ{ۨ99: &Sgr""((--2288==BBIIPPZZjj}}{{{{xxrg͎̎͊΍ԗԜ̌~"ssqr""))//4499>>DDKKQQYYddss}}||||{{0aaU``{}""))0055;;AAFFLLQQYY``hhqqyy}}}}||{{{{||||}}\pp MM##))0055<>->>">>??@@'DD8KK[``p9=yVVVEEE???-==AAIIOORRSSSSQQOOIIKKUeeQ =yyyLLLAAA7==CCMMRRPPOONNMMNNSSYY]]ccbb"^^ލn0{LLLAAA.>>IISSOONNNNNNPPVV__ggll qq tt ww {{oo} cUUUAAA->>LLQQNNNNNNNNTT^^gg oo uu zzzBEHJKLMJqqqfffeeeiiitttuY;\UUU@@SSMMWWgg tt~~"'+15:@FKOPQRSTBEEEB???87A22B33I>>YRRqqq^/ N\\\AARROO__ oo zz!&+17H[zrrkP" Q] h o v } "$%%"OH8UUgg xx&-4;BMcyvvdS` kt { !$'*,. /!. =6 { [[ {{!)07=FPdzyu\:8`mu } $'+. 1#4&6(7(7(6'z,q.JJ yy#*2:@HR`u||{frp_mv ~!%*. 2$5'9*<-?/@1@1@0G< 1m[[[===PN#,4;CKR\ht|~|z|~m` k v #',0#5'9+=-@1D4G6I9J9I9F6U.tRRRCCC99>: Oh#,4Q@RARAR@~"iUUUAAA44> HPG >c+4SBVEXGZIZIYHwjOaaaCCC55=ISNNIWf-;DLT[cipneT86Pbq {!'- 3%8*>/D4I8N=TCYH]L_N`ObQbQaPp`*{HHH==>CSNNMNS] #t `0>IQTO:{86AOLYkw  &,2$7)=.D4J:Q@XHaPhWjYjYiXiWiXhWo` J```CCC"">RNNMNXd m t z"%$zC"PPa r }$*1#6(=-C3J9RA^Ml[|k҅tфs{jsbp_p_o^zkjOOO77<HPNMOYe p x" \ &MUh w !(.!5&<-C2I8Q@^Mtc֐⫞縬㬟ؔowfveudϊ~,yyyGGG"">RNNNXf o y""''****!u;IYm |%,2%9*@1G6O>ZIp_ٔ¸⪝ԉy~m|k{jأ9lllAABEQNMUe p y!!$$))--0033-.[=^q !(/!6(=.E4K:TCeSфt縬浩֎~тrЁq~mľS@fff99>IOMRa n x""&&**//2266::::*.04^t #+2$9+A1I8P?ZIm\ב⫞֍}҆uӇvψy Afff00=MON\j v""&&++004499>>BBEE?A.,qR w%. 5'=-E5LWF`On]҆vߤ鼱ĺ洧ܜ֍~ԋ{Ս}Ҏ 1vvv..BPN[l x %%**//55;;CCMMWW__aa__XYGJ\!8&0"9*B1J:Q@YIaPkZyiӉxٖؓؑՌ|ԋ{֍}ԍ}?"r88HMQc r~$$))//44;;DDRRgg{{uuhh^`RPo'7!0"9*B3L;SB[JcRkZsb{jЀpфs҆vԉy֍}ӊ{[WOOUJUi x""''..33::BBRRlluuiieh^[t3I*9)B3K:SB\KdRkZraxg}lЂq҆uՉyԑM6qqq E[ m|%%++2277??LLddoonnor[NDЬ?/M;SB[JcRkZrawg}lЁpЄuۨ"[00O_ q""((//55<>FFOOZZnn}}||ӵo}""**22::AAHHPPYYddooxx||zzzz||i""**22::BBJJQQYY``ggmmqquuyy}}+M<<))1199BBKKRRYY``ggllqquuvvڨxII55??IIPPYY``eejjllվP GƇqqƹcchhss΍ԩt6?????( @ "F_hdR4YlllOOO?CC3??(@@.DDEUUy}}8#wMMM5::==GGNNPPPPOOLL3YY˙dyEEE*<<IISSPPNNRR\\ff nn uull|XLLL*<<MMQQMMNNYYhh ss||x%lll4;;IIQQMMQQ__ nn zz !"8KOOO??SSMMQQaa rr~~#(,-.Vg=AAHHPPOO__ rr!&+159:4.v.>>NNNNZZ oo~~#)/5;@DFF{HWK2 r%>>PPSSii zz"*18@GMOQTCssKJJE>=I>>WQP{yyC _(BBQQ\\ tt!(09EWee^\\IhgEJLKH Q+*Ԉ{B[JiXЁpۙݟבՍ}ԋ{K2NNWL_ w$$,,55??SSxxqq]bc@v'8'E5RA^MiXtc}m҃sԉyӋ|㽸exxzGh~ ))22< gui ../../bin/JugglingLab.jar ../../Juggling Lab.exe JugglingLab . Juggling Lab.ico 1.5.0 jugglinglab-0.6.2+ds.1/source/resources_win/j2.xml000066400000000000000000000007051323754603300220010ustar00rootroot00000000000000 console ../../bin/JugglingLab.jar true ../../bin/j2.exe j2 Siteswap Generator . 1.5.0 jugglinglab/generator/siteswapGenerator JugglingLab.jar