pax_global_header00006660000000000000000000000064140103273510014506gustar00rootroot0000000000000052 comment=c5758ded5e93bc6ff83b46fd041549c43e1e37a5 jigsaw-generator-0.2.7/000077500000000000000000000000001401032735100147645ustar00rootroot00000000000000jigsaw-generator-0.2.7/.gitignore000066400000000000000000000001251401032735100167520ustar00rootroot00000000000000*.log *.aux *.pdf puzzle*.tex puzzle*.md auto Makefile config.status jigsaw-generate jigsaw-generator-0.2.7/AUTHORS000066400000000000000000000007601401032735100160370ustar00rootroot00000000000000AUTHORS for jigsaw ================== This software was written by Julian Gilbey . It is inspired by the Windows software Tarsia Formulator, and was initially written to create jigsaw puzzles and card sort activities for Underground Mathematics (https://undergroundmathematics.org/). Though it is no longer directly used for that site (as the ideas have been incorporated directly into the site's software), it remains useful as a standalone tool for those who wish to use it. jigsaw-generator-0.2.7/COPYING000066400000000000000000001036571401032735100160330ustar00rootroot00000000000000The file appdirs.py is under a separate license; see below. The file goose.png is out of copyright; see below. jigsaw-generator: Jigsaw generator software Copyright (C) 2014, 2015 Julian Gilbey 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 3 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, see . GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. 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 them 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 prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. 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. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey 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; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If 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 convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. 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. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 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. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS ======== Copyright and license information for appdirs.py # This is the MIT (Expat) license Copyright (c) 2010 ActiveState Software Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ======== goose.png was downloaded from https://openclipart.org/detail/124243/goose That page reads: By papapishu Created 2011-02-28 Description This image comes from the 4th edition of Meyers Konversationslexikon (1885-90), it is therefore Public Domain. jigsaw-generator-0.2.7/ChangeLog000066400000000000000000000016061401032735100165410ustar00rootroot000000000000002021-02-08 Julian Gilbey * Fix regex substitutions for stricter Python 3.6 behaviour 2021-01-28 Julian Gilbey * Update appdirs.py to latest upstream version 2018-10-18 Julian Gilbey * Remove old email address (J.Gilbey@maths.cam.ac.uk will cease working at some point) 2016-12-15 Julian Gilbey * Finish writing (and fixing) documentation. (version 0.2.4) 2016-10-26 Julian Gilbey * The git log has a full changelog. Prepare for first Debian release version. (0.2.3) 2015-11-13 Julian Gilbey * Lots of improvements to template handling, configuration file handling and so on. See the git log for the full details. 2015-08-26 Julian Gilbey * First version of jigsaw software jigsaw-generator-0.2.7/INSTALL.md000066400000000000000000000015511401032735100164160ustar00rootroot00000000000000### Installing the software If you are using a Debian or Ubuntu system, you should be able to install this software using a command such as: ``` sudo apt install jigsaw-generator ``` which will also install all prerequisites, and you need read no further. To install this software on other Linux or macOS systems, run the three commands: ``` ./configure make sudo make install ``` More configuration options can be found by running `./configure --help` This software installs a number of supporting data files, and the locations of these can be controlled using configuration options. To uninstall this software, run ``` sudo make uninstall ``` You will need to have Python 3.x and a TeX distribution installed in order to use this software. You will also need the PyYAML module. The latter can be installed with the command ``` sudo -H pip3 install PyYAML ``` jigsaw-generator-0.2.7/Makefile.in000066400000000000000000000031431401032735100170320ustar00rootroot00000000000000# Use a handwritten Makefile rather than an automake mess for such # a simple package. But stick to familiar autoconf variable names. PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ prefix = @prefix@ datarootdir = @datarootdir@ datadir = @datadir@ pkgdatadir = @datadir@/${PACKAGE_NAME} docdir = @docdir@ mandir = @mandir@ exec_prefix = @exec_prefix@ bindir = @bindir@ MKDIR_P = @MKDIR_P@ build: sed -e 's|@pkgdatadir[@]|$(pkgdatadir)|; s|@PACKAGE_VERSION[@]|$(PACKAGE_VERSION)|;' jigsaw-generate.in > jigsaw-generate chmod a+x jigsaw-generate $(MAKE) -C doc build install: $(MKDIR_P) ${DESTDIR}${bindir} cp jigsaw-generate ${DESTDIR}${bindir} chmod 755 ${DESTDIR}${bindir}/jigsaw-generate $(MKDIR_P) ${DESTDIR}${pkgdatadir} cp -R jigsaw templates ${DESTDIR}${pkgdatadir} if [ -d filters ]; then cp -R filters ${DESTDIR}${pkgdatadir}; fi chmod -R a+rX ${DESTDIR}${pkgdatadir} $(MKDIR_P) ${DESTDIR}${docdir} cp README.md COPYING ChangeLog AUTHORS ${DESTDIR}${docdir} cp -R examples ${DESTDIR}${docdir} cp doc/jigsaw-generator.pdf ${DESTDIR}${docdir} chmod -R a+rX ${DESTDIR}${docdir} $(MKDIR_P) ${DESTDIR}${mandir}/man1 cp jigsaw-generate.1 ${DESTDIR}${mandir}/man1 chmod 644 ${DESTDIR}${mandir}/man1/jigsaw-generate.1 uninstall: rm -rf ${DESTDIR}${pkgdatadir} rm -rf ${DESTDIR}${docdir} rm -f ${DESTDIR}${bindir}/jigsaw-generate rm -f ${DESTDIR}${mandir}/man1/jigsaw-generate.1 clean: rm -f jigsaw-generate $(MAKE) -C doc clean distclean: clean rm -f Makefile doc/Makefile config.log config.status .PHONY: build install uninstall clean distclean jigsaw-generator-0.2.7/README.md000066400000000000000000000013571401032735100162510ustar00rootroot00000000000000### Mathematical Jigsaw creation software This software is designed to create Tarsia Formulator type mathematical jigsaws using LaTeX. The puzzle data is stored in a YAML file, and the software turns it into a printable jigsaw. This software makes it reasonably straightforward to create multiple jigsaw-style puzzles. If you are using a Debian or Ubuntu system, you should be able to install this software using a command such as: ``` sudo apt install jigsaw-generator ``` which will also install all prerequisites. If you are installing on a different system, see the `INSTALL.md` file for more information. At present, this software does not work well on Windows. If you would like to help make it work on Windows, please do get in touch! jigsaw-generator-0.2.7/TODO000066400000000000000000000006171401032735100154600ustar00rootroot00000000000000* There's probably a bug, in that things may well break if we don't try to create TeX files. Go through and check for this. * Create GUI front-end for editing jigsaw files * Change "sys.exit" in generate-jigsaw.py to exception-throwing - this will be needed for when we have a GUI, and it's also more pythonic * Handle longer text entries by automatically wrapping for jigsaws, perhaps jigsaw-generator-0.2.7/configure000077500000000000000000002512131401032735100166770ustar00rootroot00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for jigsaw-generator 0.2.7. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and jdg@debian.org $0: about your system, including any error possibly output $0: before this message. Then install a modern shell, or $0: manually run the script under such a shell if you do $0: have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='jigsaw-generator' PACKAGE_TARNAME='jigsaw-generator' PACKAGE_VERSION='0.2.7' PACKAGE_STRING='jigsaw-generator 0.2.7' PACKAGE_BUGREPORT='jdg@debian.org' PACKAGE_URL='' ac_subst_vars='LTLIBOBJS LIBOBJS MKDIR_P target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking ' ac_precious_vars='build_alias host_alias target_alias' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures jigsaw-generator 0.2.7 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/jigsaw-generator] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of jigsaw-generator 0.2.7:";; esac cat <<\_ACEOF Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF jigsaw-generator configure 0.2.7 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by jigsaw-generator $as_me 0.2.7, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } ac_config_files="$ac_config_files Makefile doc/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by jigsaw-generator $as_me 0.2.7, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ jigsaw-generator config.status 0.2.7 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' MKDIR_P='$MKDIR_P' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi jigsaw-generator-0.2.7/configure.ac000066400000000000000000000001741401032735100172540ustar00rootroot00000000000000AC_INIT([jigsaw-generator], [0.2.7], [jdg@debian.org]) AC_PROG_MKDIR_P AC_CONFIG_FILES([Makefile doc/Makefile]) AC_OUTPUT jigsaw-generator-0.2.7/doc/000077500000000000000000000000001401032735100155315ustar00rootroot00000000000000jigsaw-generator-0.2.7/doc/Makefile.in000066400000000000000000000005221401032735100175750ustar00rootroot00000000000000build: pdflatex jigsaw-generator bibtex jigsaw-generator pdflatex jigsaw-generator pdflatex jigsaw-generator clean: rm -f jigsaw-generator.aux jigsaw-generator.bbl jigsaw-generator.blg rm -f jigsaw-generator.log jigsaw-generator.out jigsaw-generator.pdf rm -f jigsaw-generator.toc .PHONY: build install uninstall clean distclean jigsaw-generator-0.2.7/doc/jigsaw-generator.tex000066400000000000000000000542071401032735100215330ustar00rootroot00000000000000% Documentation for jigsaw-generator % Copyright (C) 2015 Julian Gilbey % This is free software, and you are welcome to redistribute it % under certain conditions; see the COPYING file for details. \documentclass{article} \usepackage{graphicx} \usepackage{hyperref} \usepackage{calc} \usepackage{tikz}[2013/12/13 v3.0.0] \usetikzlibrary{calc} \usepackage{amsmath} \usepackage{upquote} % to get straight quote marks for code examples \def\YAML{{\small YAML}} \def\JSON{{\small JSON}} \def\PDF{{\small PDF}} \def\HTML{{\small HTML}} \def\XML{{\small XML}} \def\MathML{Math{\small ML}} \def\MacOSX{Mac\,{\small OS\,X}} \def\GNU{{\small GNU}} \def\WYSIWYG{{\small WYSIWYG}} \def\PGF{{\small PGF}} \def\TikZ{Ti\emph{k}Z} \def\CSS{{\small CSS}} \def\CTAN{{\small CTAN}} \def\TUG{{\small TUG}} \usepackage{shortvrb} \MakeShortVerb{\|} \def\gobble#1{} %%%%%%%%%%%%%% The following are macros required for typesetting the %%%%%%%%%%%%%% jigsaw example. They are reduced from the full macros %%%%%%%%%%%%%% which come with the jigsaw software. \tikzset{regular/.style={sloped, above}} \newlength\sidelength % side length \newlength\trad % triangle circumradius \newcommand{\setshapesize}[1]{% \pgfmathsetlength\sidelength{#1*72.27/2.54} \pgfmathsetlength\trad{(#1*72.27/2.54) / sqrt(3)} } \newcommand{\makestyles}[3]{% % split #3 into {style}{text} \makestylesa#1#2#3 } \newcommand{\makestylesa}[4]{% \def#1{#3} \def#2{#4} } \newcommand{\tiltedtriangle}[7]{% \coordinate (a) at ($ #1 +({#2-150}:\trad) $); \coordinate (b) at ($ #1 +({#2-30}:\trad) $); \coordinate (c) at ($ #1 +({#2+90}:\trad) $); \makestyles\stylea\contenta{#3} \makestyles\styleb\contentb{#4} \makestyles\stylec\contentc{#5} \draw[allow upside down] (a) -- node[\stylea] {\contenta} (b) -- node[\styleb] {\contentb} (c) -- node[\stylec] {\contentc} cycle; % If card number is empty, don't draw circle around number \def\templabel{#6} \ifx\templabel\empty \else \node[circle,draw,thin,inner sep=1pt,rotate=#7] at ($ #1 $) {#6}; \fi } \newcommand{\uptriangle}[6]{% \tiltedtriangle{#1}{0}{#2}{#3}{#4}{#5}{#6} } \newcommand{\downtriangle}[6]{% \tiltedtriangle{#1}{180}{#2}{#3}{#4}{#5}{#6} } \newcommand{\lefttriangle}[6]{% \tiltedtriangle{#1}{90}{#2}{#3}{#4}{#5}{#6} } \newcommand{\righttriangle}[6]{% \tiltedtriangle{#1}{270}{#2}{#3}{#4}{#5}{#6} } %%%%%%%%%%%%%% end jigsaw macros \begin{document} \title{Creating (mathematical) jigsaw puzzles using jigsaw-generator} \author{Julian Gilbey} \date{December 2015} \maketitle \begin{abstract} \noindent The jigsaw puzzles described here are constructed from shapes such as triangles, squares and so on, with questions and answers written along their edges. The aim is to match them up correctly. Related puzzle varieties are card sorts and dominoes. This package provides a \TeX- and Python-based system designed to author such puzzles. The input is a text-based \YAML\ file; the output can include both printable \PDF s for cutting up and Markdown files for potential conversion to \HTML. \end{abstract} \tableofcontents \section{Introduction} For a general background to this software and its history, see my \TUG boat article~\cite{JGtugboat}. This documentation describes the usage of the software; some details have changed since the \TUG boat article, and so all of the relevant material will be repeated here. \subsection{Usage overview} The most important files from a user's perspective are the data input files. These specify the type of puzzle (a hexagonal jigsaw or a card sort, for example), any options for the jigsaw (such as whether to number the cards or not) and the text to appear on the puzzle. Sensible defaults are provided for all of the options if they are not specified. These input files are written in \YAML. For example, here is a data file for creating a small hexagonal puzzle: \begin{verbatim} format: 1 type: smallhexagon title: An example puzzle note: 'You will have to work out the missing number shown as `?''' pairs: - ['$10^6\div10^3$', '$1000$'] - ['$10^{23}\div10^{21}$', '$100$'] - ['$9^4\times9^5$', '$9^9$'] - - '$(3^2)^2$' - puzzletext: '?' solutiontext: '$81$' - ['$6\times6^2$', '$216$'] - ['$2^4\div2^6$', '$\dfrac{1}{4}$'] edges: - '$-1$' - '$10$' - '$13^2\times13$' - '$39$' - '$13^3$' - '$108$' \end{verbatim} The solution to the resulting puzzle looks like this: \begin{center} \tikzset{above/.default=2pt} \setshapesize{3.7} \begin{tikzpicture}[line width=1.5pt, rounded corners=0.7pt] \righttriangle{(60:\trad)} {{regular}{\normalsize $1000$}}{{regular}{\normalsize $10^{23}\div10^{21}$}}{{regular}{\normalsize $108$}}{\scriptsize 1}{150} % {A1}{Q2}{E1}{1}{270} \lefttriangle {(0:\trad)} {{regular}{\normalsize $13^3$}}{{regular}{\normalsize $100$}}{{regular}{\normalsize $9^4\times9^5$}}{\scriptsize 3}{-150} % {E2}{A2}{Q3}{2}{90} \righttriangle{(-60:\trad)} {{regular}{\normalsize $(3^2)^2$}}{{regular}{\normalsize $39$}}{{regular}{\normalsize $9^9$}}{\scriptsize 2}{150} % {Q4}{E3}{A3}{3}{270} \lefttriangle {(-120:\trad)}{{regular}{\normalsize $81$}}{{regular}{\normalsize $6\times6^2$}}{{regular}{\normalsize $13^2\times13$}}{\scriptsize \underline{6}}{-30} % {A4}{Q5}{E4}{4}{90} \righttriangle{(180:\trad)} {{regular}{\normalsize $10$}}{{regular}{\normalsize $216$}}{{regular}{\normalsize $2^4\div2^6$}}{\scriptsize 5}{150} % {E5}{A5}{Q6}{5}{270} \lefttriangle {(120:\trad)} {{regular}{\normalsize $10^6\div10^3$}}{{regular}{\normalsize $-1$}}{{regular}{\normalsize $\frac{1}{4}$}}{\scriptsize 4}{-150} % {Q1}{E6}{A6}{6}{90} \end{tikzpicture} \end{center} If the puzzle is stored in the file |hexpuzzle.yaml|, then the command: \begin{verbatim} jigsaw-generate hexpuzzle \end{verbatim} will produce several \PDF\ files: |hexpuzzle-puzzle.pdf| (containing the puzzle), |hexpuzzle-solution.pdf| (the solution) and |hexpuzzle-table.pdf| (with the puzzle content laid out in a tabular form), along with Markdown versions |hexpuzzle-puzzle.md| and |hexpuzzle-solution.md| containing the puzzle and solution respectively; these can be used to create \HTML\ versions of the puzzle via pandoc or some such system. The command-line command |jigsaw-generate| offers a number of command line switches; run the command \begin{verbatim} jigsaw-generate --help \end{verbatim} to obtain information about this. \bigskip In the following sections, the data files are described in detail, and then the other supporting files (configuration files, templates and so on) and command line options are described. In many cases, it is adequate to simply copy and edit the example input files, which will be found in \nolinkurl{/usr/local/share/doc/jigsaw-generator/examples} or \nolinkurl{/usr/share/doc/jigsaw-generator/examples}, depending on your specific installation of the package. \section{Data input files} The data input files consist of layout information (the type of puzzle, whether to produce a solution and so forth) and content information. Being a \YAML\ mapping, these can appear in any order in the data file; will will describe them in these two separate sections for simplicity. \subsection{Available layouts} There are four jigsaw puzzle layouts currently available: \begin{itemize} \item smallhexagon, which consists of 6 triangles as shown above; \item hexagon, which consists of 24 triangles; \item triangle, which consists of 16 smaller triangles; \item parquet, which consists of 4 squares and 8 triangles. \end{itemize} There are also three card sort layouts currently available: \begin{itemize} \item cards, which consists of an arbitrary number of rectangular cards; no solution is produced, and this is intended for classification activities or suchlike, where there is no ``correct'' answer expected; these cards are not shuffled by default; \item cardsort, which is like cards, except that there is a correct order, so the cards are shuffled and a solution is produced; \item dominoes, which consists of an arbitrary number of domino cards; a solution is produced. \end{itemize} More details are given in the following sections. \subsection{Layout information} Each of these options must be followed by a colon and a space, followed by the option value, as demonstrated in the example above. All of these options are optional unless stated otherwise. The most common options are given first in each of the following three lists. \subsubsection*{Options applicable to all puzzle types} \begin{itemize} \item |format:| The version of the file format. It is currently ignored, but the format version of the current software is 1. Future changes to the software will use the format version where relevant to produce backward-compatible behaviour for older format files. \item |type:| (required) The type of jigsaw being created. The current recognised standard types are those listed above, namely |smallhexagon|, and so on. \item |title:| The title of the activity, printed at the top of the page. \item |note:| A note printed at the top of the page. \item |produceSolution:| Whether to produce a solution \PDF\ and Markdown file; the default is |true| except for cards, where the default is |false|. \item |numberCards:| Do we number the cards for ease of identification? (Default: |true|) \item |textSize:| How large the text should be on the cards; this is a number from 0 to 9, with 0 being the smallest. (Default:~5) \item |makepdf:| Whether to produce \PDF\ output files. (Default: |True|) \item |makemd:| Whether to produce Markdown output files. (Default: |True|) \item |latex:| Which \LaTeX\ engine to use to produce the \PDF\ files. (Default: |pdflatex|) \item |texfilter:| If specified, this is a filter to pass the \LaTeX\ files through prior to running \LaTeX. See the later section on filters (\ref{sec:filters}) for more information on filters. \item |mdfilter:| If specified, this is a filter to pass the Markdown files through to produce the final Markdown files. \item |clean:| If true, then intermediate files will be deleted. This includes the \LaTeX\ files and related aux files and so on. (Default: |true|) \item |puzzleHeaderTeX:| This specifies the header file to use to produce the \LaTeX\ puzzle file. See the later section on templates (\ref{sec:templates}) for more information on header and template files. \item |puzzleTemplateTeX:| This specifies the template file to use to produce the \LaTeX\ puzzle file. \item |solutionHeaderTeX:| This specifies the header file to use to produce the \LaTeX\ solution file. \item |solutionTemplateTeX:| This specifies the template file to use to produce the \LaTeX\ solution file. \item |tableHeaderTeX:| This specifies the header file to use to produce the \LaTeX\ table file. \item |tableTemplateTeX:| This specifies the template file to use to produce the \LaTeX\ table file. \item |puzzleHeaderMarkdown:| This specifies the header file to use to produce the Markdown puzzle file. \item |puzzleTemplateMarkdown:| This specifies the template file to use to produce the Markdown puzzle file. \item |solutionHeaderMarkdown:| This specifies the header file to use to produce the Markdown solution file. \item |solutionTemplateMarkdown:| This specifies the template file to use to produce the Markdown solution file. \item |hiddennote:| If any entries are hidden, the note to include at the top of the \PDF\ solution output file. (Default: |'|\texttt{Entries that are hidden in the puzzle are highlighted in yellow.}|'|) \item |hiddennotemd:| If any entries are hidden, the note to include at the top of the Markdown solution output file. (Default: |'|\texttt{Entries that are hidden in the puzzle are indicated with (*).}|'|) \item |hiddennotetable:| If any entries are hidden, the note to include at the top of the \PDF\ table output file. (Default: |'|\texttt{Entries that are hidden in the puzzle are indicated with (*).}|'|) \end{itemize} \subsubsection*{Options applicable to card sorts and dominoes only} \begin{itemize} \item |rows:| (required) How many rows of cards to produce per page. \item |columns:| (required) How many columns of cards to produce per page. \item |shuffleCards:| (card sorts only) Are the cards shuffled? This is by default |true| for cardsort, and |false| for cards. \item |shufflePairs:| (dominoes only) Are the order of the pairs shuffled from the order given in the data file? This is by default |false|. \item |flip:| (dominoes only) Are the order of the entries in each pair presented in a random order? This is by default |false|. \item |cardTitle:| The title to write on each card. \item |cardTitleSize:| How large the title should be on the cards, a number from 0 to 9 (like the |textSize|). By default, this is 1~less than the label size (see below). \item |label:| The default label to write on each card. This is like a subtitle, and appears at the bottom of the card. (This can be useful if the cards are of two or more types, and the type of card is important.) This is not used for dominoes. \item |labelSize:| How large the labels should be on the cards, again a number from 0 to 9; by default, this is 2~less than the text size. (This can be overridden for individual cards.) This is not used for dominoes (though setting it will have an impact on the size of the title if |cardTitleSize| is not set). \item |cardsep:| How much space to leave between adjacent cards. By default this is 12pt. It should be a \TeX\ length. \item |cardsepHorizontal:| How much space to leave between horizontally adjacent cards. By default, this is |cardsep|. \item |cardsepVertical:| How much space to leave between vertically adjacent cards. By default, this is |cardsep|. \item |loop:| (dominoes only) Do we have a domino loop, with there being no start and end? The default is |true|. \item |start:| (dominoes only) If we do not have a loop, then the text to write on the start of the chain. The default is |'Start'|. \item |finish:| (dominoes only) If we do not have a loop, then the text to write on the end of the chain. The default is |'Finish'|. % \item \textbf{WILL WANT SOMETHING HERE ABOUT \% DIVIDER ON DOMINOES} \end{itemize} \subsubsection*{Options applicable to jigsaws only} \begin{itemize} \item |shufflePairs:| Are the order of the pairs shuffled from the order given in the data file? This is by default |false|. \item |flip:| Are the order of the entries in each pair presented in a random order? This is by default |true|. \item |shuffleEdges:| Are the order of the edges shuffled from the order given in the data file? This is by default |false|. \end{itemize} \subsection{Card content} The content of the cards is given in a final one or two \YAML\ key--value pairs, depending on the type of material being produced. The keys are |cards| (for card sorts), |pairs| (for dominoes and jigsaws) and |edges| (for jigsaws). Each of these takes as a value a \YAML\ sequence of card content. For |cards| and |edges|, each of these is a single entry, while for |pairs|, each one is a sequence of two entries, as in the example above. The number of cards, edges or pairs depends upon the type of puzzle being produced. Each entry can have exactly one of the following types of content: \begin{itemize} \item A string. This will be the content of the relevant card, edge or half of a pair. This will be inserted verbatim into the Markdown and \LaTeX\ output files, so should be written in \LaTeX. (Images are handled specially; see below.) \item A \YAML\ mapping. This uses the following keys: \begin{itemize} \item |text:| This contains the text to be used as content for this entry (card, edge or half of a pair). \item |size:| This will be added to the |defaultsize|, so a size of |1| will produce larger text in the \PDF\, while a size of |-1| will produce smaller text. \item |hidden:| If this is set to |true|, the entry will not be shown on the puzzle, only on the solution. \item |label:| This overrides the current label. \item |puzzletext:|, |puzzlesize:| These override the |text| and |size| settings for the puzzle. Specifying |puzzletext| overrides any |hidden| setting. \item |solutiontext:|, |solutionsize:| These override the |text| and |size| settings for the solution. If |solutiontext| is specified, then |hidden| is assumed to be |true|. \end{itemize} Either |text| or both |puzzletext| and |solutiontext| must be present. \item Special \YAML\ content. \begin{itemize} \item |newpage: true| This produces a new page in the \PDF\ output file for card sort activities, but has no effect on the table or Markdown outputs. \item |newlabel:| This contains the text to be used as the default label for all following cards. \item |newlabelsize:| This specifies the label size to be used as the default for all following cards. \end{itemize} \end{itemize} \section{Puzzle templates} \label{sec:templates} The puzzle templates are \LaTeX\ files with templating marks. For the supplied templates, \PGF/\TikZ\ has been used for the graphics and to place the text items. Version 3.0.0 or higher of \PGF/\TikZ\ is required for the current templates. Alternative templates can be written if this is desired. For example, someone might prefer to use Asymptote or another graphical package, or they may wish to modify the existing templates in various ways. There is also a layout file (written in \YAML) for each puzzle type: this specifies various parameters required to create the puzzle. \textbf{TODO: Write a description of the template and layout files} In the meantime, please look at the template and layout files in the distributed package to see how they are written, and modify them appropriately if you wish to create your own. You can also email me if you have questions. These files can be specified in the puzzle files as described above (with the template description file specified by the |type| option, and the templates defined within the layout file or overridden by the corresponding options in the puzzle file). These files are looked for in the current directory, in the user config directory (typically \nolinkurl{~/.config/jigsaw-generator/templates/}) and in the package templates directory (typically \nolinkurl{/usr/share/jigsaw-generator/templates/} or \nolinkurl{/usr/local/share/jigsaw-generator/templates/}). \section{Filters} \label{sec:filters} There may be occasions on which you need to systematically modify the \LaTeX\ file prior to running \LaTeX, or to modify the Markdown output in some way. Filters offer this facility. They are programs (scripts or other executables) which read in the \LaTeX\ or Markdown on standard input and write the filtered version to standard output. For example, you might have reason to change the standard Markdown or \LaTeX\ syntax for images to meet some local need. Filters can been specified either on the command line or within the puzzle files or within the template description files. Filters are looked for in the current directory, in the user config directory (typically \nolinkurl{~/.config/jigsaw-generator/filters/}) and in the package filters directory (typically \nolinkurl{/usr/share/jigsaw-generator/filters/} or \nolinkurl{/usr/local/share/jigsaw-generator/filters/}; this assumes that all supplied filters are system-independent scripts). \section{Configuration files} The |jigsaw-generate| program reads a configuration file, found at \nolinkurl{~/.config/jigsaw-generator/config.ini}, which is in an {\small INI} format. The default configuration file can be found in \nolinkurl{/usr/share/jigsaw-generator/templates/default_config.ini} (or \nolinkurl{/usr/local/share/...}, depending on where is has been installed). The default file is effectively as follows: \begin{verbatim} [jigsaw-generate] makepdf = yes makemd = yes latex = pdflatex clean = yes texfilter = mdfilter = \end{verbatim} and these correspond to the identically-named command-line options. \section{Some notes on \texorpdfstring{\YAML}{YAML} syntax} For a full, precise description of \YAML\ syntax, see the \YAML\ Specification~\cite{YAML}. What follows is a very brief summary of some of the basic parts of the specification which should be sufficient for most people's needs when using this software. Although \YAML\ allows unquoted strings in general, there are a number of restrictions on what is permitted in them. For this reason, it may be simplest to single-quote all value strings. (\YAML\ also offers double-quoted strings, but these interpolate backslash-escapes; this is probably undesirable in this context, since many \TeX\ expressions include backslashes.) Within a single-quoted string, a single quote is written as a doubled quote mark (|''|), hence the three quote marks in a row at the end of the note field in the above example (two to indicate a quote, and the third to end the string). For collections (`sequences' and `mappings' in \YAML's terminology, each of which consists of a number of `entries'), \YAML\ allows two different notations: either a flow style, which is similar to \JSON\ notation, or a block style. With the flow style, the entries of a sequence, such as a question--answer pair or the list of edges, are enclosed in square brackets and separated by commas; for the block style, each entry appears on a new line preceded by a vertically-aligned hyphen. Similarly, for a mapping the entries consist of key--value pairs, with the key and value separated by a colon. They can be written either using a flow style as a comma-separated list enclosed in braces, or with a block style by writing each key--value pair on an identically-indented new line. Both of the sequence styles appear in the example here, though only the block style is used for mappings. Note also that the top-level structure of the file is itself a mapping. This means that the entries (type, title, pairs, and so on) can appear in any order. However, for the benefit of the human reader, it is wise to maintain a meaningful order to these entries. \section*{Acknowledgements} I thank those who offered very useful ideas and feedback at the \TUG\ conference; these have helped me to solve some of the thorny issues I had been facing. \smallskip \bibliographystyle{plain} \bibliography{jigsawrefs} \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: jigsaw-generator-0.2.7/doc/jigsawrefs.bib000066400000000000000000000026561401032735100203640ustar00rootroot00000000000000@Misc{CMEP, author = {\gobble{Underground} {M}athematics}, howpublished = {\url{https://undergroundmathematics.org/}} } @Misc{formulator, author = {\gobble{Hermitech}Hermitech Laboratory}, title = {Formulator {T}arsia}, howpublished = {Available from \url{http://www.mmlsoft.com/index.php/products/tarsia}} } @Misc{pandoc, author = {\gobble{Macfarlane}John MacFarlane}, title = {The {P}andoc universal document converter}, howpublished = {Available from \url{http://johnmacfarlane.net/pandoc/index.html}} } @Misc{MathJax, author = {\gobble{Mathjax}MathJax Consortium}, title = {Math{J}ax}, howpublished = {Available from \url{http://www.mathjax.org/}} } @Misc{latexmk, author = {David J. Musliner and Evan McLean and John Collins}, title = {Latexmk}, howpublished = {Available from \url{http://www.phys.psu.edu/~collins/software/latexmk-jcc/}} } @Misc{YAML, author = {Oren Ben-Kiki and Clark Evans and Ingy d\"ot Net}, title = {{\YAML} {S}pecification}, howpublished = {Available from \url{http://www.yaml.org/spec/1.2/spec.html}} } @Article{JGtugboat, author = {Julian Gilbey}, title = {Creating (mathematical) jigsaw puzzles using {\TeX} and~friends}, journal = {TUGboat}, year = {2014}, volume = {35}, number = {2}, pages = {168--172}, howpublished = {Available from \url{https://www.tug.org/TUGboat/tb35-2/tb110gilbey.pdf}} } jigsaw-generator-0.2.7/examples/000077500000000000000000000000001401032735100166025ustar00rootroot00000000000000jigsaw-generator-0.2.7/examples/Makefile000066400000000000000000000001241401032735100202370ustar00rootroot00000000000000all: clean: rm -f puzzle-*.pdf puzzle-*.tex puzzle-*.aux puzzle-*.log puzzle-*.md jigsaw-generator-0.2.7/examples/goose.png000066400000000000000000000453241401032735100204340ustar00rootroot00000000000000‰PNG  IHDRÿ, Õeÿ IDATxœí½}˜–e~ßýÉ}Lç˜g:™L&vJgÂJYÂC aYÂC\KYc±ÖZCŒa1ÄXãZk}k­¥ëC‰¥ÔXC\cX×5®K]òÄu•õ…u]tPÞ_…aæùã{9Ï뺯·ûýž™ó{¿cæ¾ïëå¼^~çù{ÿ‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡G}ðc@•ÐLºj ¾?œöï1@fÃHeþ‰À€ùÀ4 #ç~ç€w€W×€ï?ªÅ=<<ª‹à!`Ž¡À2ààtÂ6QÚì3­Ž×ááá‘-ÀíÀI’™x'ÐêìÓ\<ìOÙÏ¥µÀÜš_‡‡G.ÌÞ$̤Ç'åH|ÿ©ih þN@“Âj’'“GÎj^„‡‡G~´!æÂ2åQà¬A¯RtK½O»‹«tœ¸ØB˜ß@†¾Z  ¸bI`I· jtn$šßM±Ao'ÐcÿVàr$¶o^¾LÉyþ‰À:âUÓÀÔœÇñðð(Q¬Ûº!cßàF$ªÇí?„¼í9ÆQîJ8ÎK¥\‡‡G:ÚÐêœä¾æ¥ì?x;eߨ[oVÎq]›0¦kò^˜‡‡G2®&~µÞ lr>ÏHØ.0³ ×çß51ûï&ŸáááƒÀâó6$ưŒÝŸpœÅÈíW óº+çX—Åì{wÎ}=<<ô!cœë¾3t‰ð³±úz–ko*ðlÌ1³èòcnAÆCw¿“(ÚÐÃÃ#½À ’EôŠõú5Áoo—pž;‰ŸXŽ7‹Ûn.ùs¦Q¬ÿûÕßÃ#“•ý é+ð~`œ³ßT,³­)ñœó€ÍÁ¾{x_h½‡)–T¼îïáÁ\àiâWá$+¼í[PÈn©ºy]ÈnP-L¡xÜ7Wñø#mÈŠþ¥éÝg[óü~e}†Ÿ Û(¶ü·¤îáá1ŠÑŠté¸Ì¹-H\^ŠÜf ‘5ߵпy;ÒË£Çh¦T[×ýhèꆎÈãAXì Ì /¢™q)û­¶½YÍS¼ªªVO%¸xŠøñ­oà¸<<ꎬ5Þ¥ûsì»kõ?sŒ(5í(±'m|CÈ…éá1ê1“ø¨¼·I7°ÍžÙ/‹•Wß¼sŒK4FºaÉn»U1Û·  NWÎKy²ùª*–wŒk0FºaéuñnŒl?ʘÞP#òè,qŒÛ0Fº bÞK¯Pl˜‹ºìÊ¥{jwY±¸¼Œ1ž©ó=<ꆥ¿ð;€•ˆYâ|ÝY†²¼´±FׇNòûŒ’õ÷•Ø@øE¿žtã^7Õù åÍÁ¯÷V0Ƥ´c¦DÞè4w»CÀWQç› ¨Ï/ÓQ¬^Ò}üåà!àWQÓZbqû6Â0éáQs¬$¼Ê ^C¿ôé“Õ\ò¥è¦!+)Vxn¦D'šâJ\ד^CLfšsŒCõýÜ2^¦JOp *Ʊ rsI/%–EWeÞE&B9½úZñHäos¨€2éÀfÔýdð·y Æ#µ`¼³m9¸|Lr>þ¡àœ­1¿t*Øn•«*ÿør…Çðð¨ÊÉH;ì ¨´¡I %ï| Ù ¦’]d£±Mšå½ Ù&ªÝ oaLF™‚ÏP~¾zÓ­5¹c-HW_ÚuU›i?ÊøýMT²k9É™‡ÃÀµºÙ¯EiÃÕbþ%$7û&ìþ[•²g~:a.ÅUuË¡¨!gÒï§QI²¬ %ÏüuÆ’c6“`ôFpœµÎwÏ ^w‘¿)ˆg~` ñú¸é­·$æ7CCÈíx™óÝCα¯HÙ×3¿‡G ‡ââ¡CÈ}˜ÆüÈÁÛ°)Ë["ÇÎccðÌï1¢PÍÒÖÆ!àóÀ‡Îwd¤ûldÛ€×ÏŸCÁ?ß>O!Ü"l4Ý'Q‹…d¯ÒQDŸqî ö½ÓÙÆTå]œãx~å÷ðhl QM廜ï&¡n?®Ñ/šÐ”F·×üª<<<2q=éŒjŒ|ÝØdž›‚ïò2{”¢eÌ<<š£U—ýFÆïÔøð½à»ÏÇíÀÃcÔc´2ÿ²™Øü‡B‰ß >“°ñ0 §JØÖãá­ÌðVÆï—Ï;Q¤ß®às/ð%œïB Ûzx4£™ùßÏø}:ª»ç–ÿgÈ J-~²„ó-a[†c43ÿ‘Û¼†Ò‡ .öÿ›B [sžÏ3¿ÇˆÂhfþÃ9¶‰3™A¸Hèàk9ÏçÅ~…ÑÌüÇÊØ§üSçógu9÷õ?…ÑÌüç³7‰Å4çÿ9ÀËX‘þòÄáã2ÏçáÑŒfæÏ‹×#Ÿ§cEøq¨ÖßwmW&ǯü# žùáK„'€Â÷e! U N*ê™ßãIp3ùÂrWR\ÉçYî;„j\|¥ûƧ³>—åáá‘7C/Œkïyç;ãû_|¾(Çq<¤‡‡G½1p¶^&Û_† *•Úª7|ú`4Šý&t7IäÂDû}X^ÆùŽá+÷zŒ@ŒFæÿåàoÞxûÏ $×çuŠCœ+Ñãé1™Nð7ïÊßüíG>âªþþ!ð­„ý=ó{ŒHŒ6æïÀºêò2¿ÙMlÀ»‘ßÿø³”ý=ó{ŒHŒ6æ¿]Ó.ò»ß¾ü5Ìï6çt?é^yæ÷‘mÌ?;ø›wÕUï=ütðÙèöÑßt±;á{¦Æh‹ð3Æ»WJØçGÀ/`ïŇċú“‰Ç; ß{xxÔ lY®yÇ­Ëß‹¼neß(M¨à\UÀtÄŒCÈðW ¹‘ïçÜs²‚ñzxxT 7!†|»Œ}·û>ù~éÌÿF¹ƒõðh4F“Áïׂ¿Ii¼I˜ˆÍÿfôey ¼¾ï1b1Z˜¿€­ÌSбÂFÏÖÈoYÍ8<ó{ŒXŒ柅uÅý]‰ûîÂúD}öYY[J<—‡GÓ`´0¿é­÷!°µÄ}/üÿíàoêÏwiƾ?*ñ\UÆ‹È÷D™û€Ë±^‚‡É—Ê›·^€‡‡G ÐÜ{ÃÀ’*óò1ÔFàááQG¸ýô’¢ðJÅŠý#ì$cÈÃãXƒqo…ÇÜ,¥˜ñŸBõý—E¾÷|<<„lHïÊŒmÓЉ ô‰ÒF¬xßKxõï­àœ`>–dl›†/ÏøÃ(MØÅ‹ÎoYÞa9bÂÔŸ¡XÀ6õŒR\ºîÎï÷•yN ±1á£cÉ«~œëp.áÉa´ÄJxxŒ¸Í8Upœ^âñM>;#Û]³‡‡G aÄï¨Üß~=Òå_B>‹H_Ñb™/š<<<ê„—ó-kÀ¹·^ýŸÆ‹ÿuër«V`O)ØM±šP‰«ÑÃÃ#'– †[߀sO¤8ÒÏÐÃx Àã¦x1ÛÕÎw$~ßTãs?Kz¼ÿZ”èááQetÈ7ïúDÌww Ï=‹| ?Ûƒm=<<ªˆ«)öí_Œe¼ëjxîGÉÇüÃH5X‰Ô*À$òÜâ|÷–éfÔè¼í¨Zo^æw'€;Q•à~|BG`¤5íhE ¶³Îô%Ç:„T¥uÀ7 ·'÷ðh<@úªvIÏßÄg·˜G5hÕ%¨¥Kp >ÈË&¤&L©áX<ã1‚W2ëÖ†Žhl£€ê¸L¾:¼™âçeè%jWkÁc”¡âȳƒ”—SïQ]Ì%œåø$p?ÉŒohMÞà‘ŠK)~yjYŸÏ£4Ì@A?qL>€ì~ßïtä‘‚hçÜ“ø£Ù`JªEéæà÷‰¤—>{šø–hcѨ¾/5v8\Jq“MØ2kiíÏW`q]FìB³æów#ýÞÍAÿµ«Ï瑎””4øedÙoCeÄ~ˆ˜þuT Š^Tb,Ëå÷5à ¨Æ€ÇÆ„W‡z¦ìz(´úbT+áâàs9~û•d- Öu<š÷~)lìp<*ÄDò×;0ÏÛQ œïOÒ<*L=ð0’Ü./cßš4ö£ôߤ‰Ö¥„ï½Ç€«/G©™ÚI»mÂÓÈm¼ymä·ê8ÞF¡µßBõ:ü\M~)à^Ɔ‡eT ­þ[ZàH½±›Ò™?šÕv´Žã­ZJs²‹ ¢ˆÌ8cÜTöë¤M!›Q[§È¯ £À _é9ÍÂTí$¯î€óuK¯öL”ï>¸2òÛ‡ÕT q#ð;ÀV`Á/ ¦þ±7‰Ú­Áo_~7Ø'/¿‚Ô9㯿€ê¼ ŽßM@RD?¥¯ä“QìÈ__DÏãÉ0‹äÙû‰Ž+OoÕ1­¸OÇüöbÝG] à¤¬A´Úß…˜5/ HZ¸ ¹Mß$¹.`z,eŒgPÇäö’¯Þ£¦ˆ«Ï?ŒjÄE#Àh­rèù¢£Ž ô `¦ëPé­+„Sí¤›>4á,–!qÿ ŠƒDõü.â[Œ»´¸ïh¸3†ŽÓœ³tšK2/íD•ˆ}¦Z阇ÍÄzL׿¼’ÙÁ±<ŒµŒœÕ±ƒôüƒRè5š'x©ÙÑG±Xò& cÝÁqïR­¥¹¼IcoRüPhèˆÒ±ê0ÿ0Êx‰"h;Å’Ùµ(éæ.T‹¯¥ÖûQo´ Ø+ØöíG±RT^oŒKƒ(±· ãõ()~ w:¿OEÑ[Í‚¨ó#½v¤ uÝ9Mqë´k)–Šv ‘üAä9˜Œ‚i^7r>åo/²·˜ocŸƒÉ£˜Jö½^G²Ëð( 6k/بG+ñÂ4~èGeˆæ™™;É_Š* QY&\©h£ô¼ ùæ÷â9â]oS¡î$l#¾ç bèMˆ!×!Á–˜mŸÇºÆfHš‰Àùx(ø¼9á8æ½* •+éy¼‰¨ &ÿ–¿?ê|güå`‹i4 ÷RÝÕõÑÿïB“Í b̧‘î<‹øÕx\ð» kDRY)ªJ Jܺ=·{Ðs]‡mG@{ƒólGîЇ(NÛ]…t#Àìàº6£Ém1ñ÷y’âšÀFi5ͳàŒJ˜Œ7C;ƒ¿W¿ït~»=Œ!ôÐé èD/k5'€‡ê0î‡cm¤X>Žê܉îõÚÈ6hžRZ°ãº MȱAªÉ0 ¥^A¼j™‡Ž"õƇ ׳ ßìY„ƒE\ßî“„]m.9›ÒêÑgÑõÍúëDñòO®Æl¦¼ÄœrqÙµ.!~¬ô[Áì`ûU ÛÇÑR¤Ö¸ßm§¾÷`L ê7õls~Û† B+Í.Á®:åPÔÓ±¾¾Ãÿ{t Qùi¤/oA‰9è ³â¤!) t-vÁØlÛŠ 8LúDgÒÇoMø}#ñ[=Ê€[¶i æ÷G߇þ9ŒDn Ñá²=Ä»£òÐLdÀr¿[Pßá7&!£bÆvIÌéÒCHX|Þ„ —·§ìótÎ㿬×`oèñ˜ß£nµ§ƒ¿'‘±ÐnfÇì[oŒGñR$~ô¹…+Ÿ‰¸Iqš|§Téx¡ú¶œÛfå¼DX|_„¤S&lKpœ¨ño ùí9Û‘Ää݃eÀeþƒ1¿w~ÈI"[ÔçÜH´£d•$w“KÆn1{ƒTn`OiE-ڱ̔ÏʳïXÝú š˜oEn²¼ÆØv¬OÿLp̼hERß02g5E8üwšxã‚Ì\ZŒ3Ín°y¨¼a°¸Ì¿;a›‡I8ÃØ¸€fÃÅè¥Iš´\ÿþýÎ÷•¥4:ñsšhº‘d:2ö­@>o×ÿ4ùݎ󑎽®A$¯Eeº—9ô böMˆá‡Ðj;9áW#Q}a°MWp—`­ø3Ñê›wÅ ¶Ö \¤·\ÛA4™^–ã¸;‘]ÊK9‡ù'(âR³¸ ’` jnÐadÓ0p#Ôž¢²ÄŸEd¿¨†Ž#&½“òEø H X…Ò÷§œï4šC’ÆøŒc· U5-tw;нHšd߯æŽ+N2[œ3jPÜ\—ùüR’*;D‹Ö|qÑD˜Ò×ä—·ºä?ŒªÆ¼H¾òØYƤZc&bz#æ?‡,ëÑu{s˜I`Z•¿„õgÇ¡EÅ™ã¼^ü›Ñªv%ZEç øøZ­º±Å8ú¨,6£€Œ¡SZÞ¿©š<ˬiÿåwŠvÉÔ`¼‚°¤7˜Ek/z ñÙœy„W $´Q\97Ž¢Us¢˜c›z¡4דž)x:Øfgäû=h¹­0KÑjc Žëi~‰¨\t¢ëÍcWùáUûŽ`ÿ<ûÆQO°¿ûÌÌ„­9°I·®Ô2„TžÈƱ€ÚOÂEø±zž,Ó°­­>þaʶ³P”YÚêñï€ÿâ|n!\ìadYÿß%´¶èF«ùtà“HüžAüµþGôòL~éò.| ø!šþ²Ì±LN RZµÂäà<ߪ±®Dî¼ïM(fa-2¶UË‚ÝDðÝ(l6šŸ1]Ûµ”ÞÝhöþd©¯!«¹ÁYDZ‡›±+¶ëV< ×Q|ÿ&¡wðiª"n$ŠÓÆ,šÕ—dñu±˜d`”ù¯ÇVl1¥Ÿï®pÌÀMØI¯aÀó±±{ˆ]޾n’lŒØ½Ùâ¼ dt<žï†à¼YSg`ó=®D+°™ž#,Š&ÝY*™€,×võ,ÙFL½ˆaïö­4c4ÎeÞ´p‹\.̹Ï<â“5îˆlw+Ö hŒ`&%4ÏDÓLpkn¡>‰M‹ !&Z…ì&i®¬4y<„e¼ýḥ׎CF719„&ÅËŒî>„]ñLÆ¥‘,.>Eºõͯ˜å0™QW'cßÅjÔfh!Üvå»ÌAÝdÇH›$FLä¡élǼiè£8ãêÈ6·£ÉôŽFâØTl(çH‚[ˆâ)ê÷{‘¨ú v"x­î@ ÷22F^OR^UŸîàœîûq]÷­ˆ¹7aW[Zh& SÆLšŸrŽeŒ¿·ßmBïF7éd†‘«r’ŒÐ俢/¸öÍØ´eC›Ð½\‡ÞÃ'z‘ðÂfÞé™ÁuOÏtâ¥Ó"}DÀ„ìcûÞ—‚¹Èà³b]ñôb¸ñܛРÔ蜀r0ðƒ^Cý»Ôv¡ÕtbÌ´•³Z‘—Óƒ®'>‡â4á$0wu6*âa ¿™0¢Á>ƒ”&zo'¹+QV¤_œó5¤ëgÅ® ϨH`ïµ)8Ò‰&Èçƒq¼D} ÃT 7²m˜êþRô‚º«‡¡ršG6¢-¬7ÑX—^š€oÃРX 3˜|õËÑä<ƒÒ$˜v¤.G/{%:üAâ{+¸tIqjæ**S¿z‘p&R§4“ø”õvlÜĨˆ"4:™¡Ø²M•¢›ä•isÊ~ÍŒ»(¾–!$Î6ªpZ™Ž£`—´ ¼=Øv#VE8ˆ¤˜)¯šn2 ÎBvŠÅHÚ{‰çë {† ñÍ=íB¡ÄîJýéVµFâ‘~䞉$ˆŸ2‰šÁÏòQï‰|÷*ðäÓ¬oÿB½|ª ǯ7ú8'îüðµŒc<€˜e!üù”KÁ\ౕ—¾ ü1ò;çŤ`ÿßÁ†~€Z~mƶ û€òÛ·u#Uo*ðŸÐjÞ‰Dæh‰ß¾<ËÐJûªrô×(V Æaƒ:ãvÔ ü„ó›¡6l…äÖà÷–ào)é(N ÍÂü }-j}ÿ3ôbUŠeÄWÿ©Ìb–Ï£ûö¯BüÉÌ<M ±ÅP.`+§÷!F8üÞ…˜õ3Á¾ýÁo_A«ì{^×<4y,$^¬½Œg €9œÿ0 J:‡ ~1h~M,—‘m#9ü*º/Ë‘Zò*²qüñL?­¸¿ü?ËôÕÏßB“á6t½&Ø4|k,¿üƒ„q6%âºö SÑꢄc«h7Åñ# Ñì´a$ñä©Ä31ÛHôÞLrÌñà¸OÛÏ!~%štØ~ÊÓ‰»QXì ¤×W»^bDH‡‘NŸ§Å¸ñ:T“¶¡E+KžCئµ?Çx›j埇¬õQüàŸWáøÛ)6 œ@"×ÝH”û$êÛ옌^ˆïžÝŸ!¾ÄÔV¤l@bl^‘¼@؆p–üᣳ€ôï~´š¾Ðöàï»Áß¼ªF+RU&"Éå_ Å¡€VÁ¢g:òmF[o#Ãåß’_ÅèE×úI4™ŽC÷Έì.LhîYtíÇÐý9„×Ü—])çkGû(Žèû’RÑLÌ_@†¾h4×YÄ •êþ·¡Àˆ(>ÄÕk(ûÝ ÏS,Gzè·Ïa_Ðvô"°± q8€Dç°/ÝôÒ½Kå¢{]H˜ üS$~OÁºeMkîwƒqìr(«ùBĨï¡Xƒ}Ào“]Ô²û{hÕþA@©zYô IDATrІ&ÓªüÓhbC²úò ¤¦¢™˜´úÆ…Þþ>ð?+ø%¤žM!¬FœEŒý>6Ùeð÷,ºŽR¢êÎÿ ‰óo•1æto;ÑdÛF|S+•¹I8Gtb(I’zÙuÊ ŽúÏÀ¿/c¿†¢‡ä¤Œ·‘þSID[VùæfMÂ[×–ŒLý¿$´ ×Ù3È*ïbòµ'¹¸Üôé3Áù—!Ú,ĵˆ.lGÖíÁ¸+©Œ¥í”Ò½[Ñ8+ \ûÂÛ(ZrŠFì¦8–£Ê•÷Ñl+?ÈÀ“V’ëo€ß$¬ëFÓv“ÐŒ(IÖןE"h³áIlêß"Q¿ZXß5Ê}y¢(­4ºI;5©¨‡Ã}ö\ð×ýlµ)¸î¬ŸFLЃôúJ˳Ÿþ ¥©4s‘¤Þqòg‘¤PŽÝâ /ΈDűáQZál?ÛévÙbÒ£ Ç y“!æc•j·=‡ð=wcÔ{(Ο‰TN4g’ªé ò¾4ë;œyj²–éÜòŠËò©N$^|3õ]â+ ¦|Õ¢ÿ"døÚ@¼!éVl¼û^–{ JÁ]GuÓdkAG±Æ^Qø&á’ï“‘x¿‰úÑ: ÍH§‘º•öŠ™eùC–`uÛ< 7š›Ç c’Ò0ƒ°ïý…ÇÍ W²476¢ÉÖ–0€ÍI0‰S“±f^´npº¿ÚçÂRÊ/·lèùÈ1[q'nÛ^´z=ÀÈÆ&tnHí‹Ä¯fQ¸“î’Œm f`#û2¶mA+å’¥‹h£Î¥9Ç‘WFŽ}VØF8_~)ò2ǦPoD †«žDƒVŠBv °ˆÊ›DõÑK¶[-â8’a:?î|gÄè¤R˰÷ãñŒm]ÌG«ež¢"“Ð3ýˆø²k«1 P\z«´VUÞ@UqãÞ‡ÝØ(Á´dêPšnJkƒßãtþǰjˈé®Ól˜A¾æItœâ‡“YøfM¯¦6èÁŠéîêmV¥òUKr#)·”8†ËÈÖe;‘ß0\\S’éX‰¯” (/ SÚHò»pvb;Œ&¢ƒñÍÀ6 };ræœÄë÷£“â‡V mG:ÁÛ¯ º+N-Ñ^²ÃÈßív)5©+vel[.^$\®kyÌ6&'Oi­RÞ›D[°nG3™rq¦Ä“Îo >sÿòHB9q-å«{°Þ©9¶ßX ªf·ëK>Ié9 ®ZT‹Va“ gRœhÕƒ&èZÀmì’‡LR±AMÅÆ¤Ü€ cô|ÖÙï®Lc•%Š<‡µjgÑH˜¹ãbÕ]2†»Éäï¬c¬âµ²LÏ'©¹ºFç‰CV±—v–ç £æ$ìä:‰biâ #ßkÔ´h!ï_+*§¯{½ÑF|Ȩ¡ýHÞL>‹?Xi¢ÒâipU¯ª×À% Ñæ1idʹ)Á¦ ò›Á6¯ gàÚ¥î¯ÃuŒy\NvQJè(•Ïà3ÐË0'kà 7-/óƒÕwk 7§#®çB-ЂTÀ<÷ë*do:Œ•ãJįD‰æs–WÅ£J˜D²ï¾tgc»k¹¢¸ÃkµmGD÷–pÌZ5 ã ¯g~EÞ ²7Ñd±¹ìæ#£h\Þ¿ùn¤ØŠF º¨MC…a¤›ÞHéÀ£1Ç 6ìi1çré9àÒ¨I0UrMd]Ròj#+‹Ô¥»‘Gå0’2§‚î3DSž©VÀùu¹4‹òfjS¤!®»¬¡Z.+í´ü,REŒ¶^nyêš”ß4¹£Þv’ƒv2 p4+ ȳšÚÕ›Ë –é#»'{Zåâr͈tõÚ))û•‹h5¬Æk³0øû`¥ƒÊ>ò…›ŠÇÃȨׂ Û”pŒê0~œ˜†féçÉfȼt äHZõò¸÷R}W+Ê>ŽtSÃ\¥,u ºqצlcŒ[•VC2¡¼&Ýz}…Ç˃<…c‡QBQ'ÖŠzŸ’<+»IÎìóh0zP ¹¬¢¡Yd\<lj×Qóß®¯òõ]ïÛ¬@÷ãÌkµŸŠ­y—ÄØ¦žâ ÙyìYˆ&Ú”R\¢™it’ô†±}I*]­‚’<ªŒ™(»Òj­q±ç7äÜ·ÚÖm×mJ›=‚Ô<ˆVš™³[¡/ˆA+án=õ¨«ÐEqæ`mÆøó­:µ¿ê8ŒCâr¹±&ÜÓÅ¥%ì_M]|®s\£’<’ó®x;L|n¾éƒ˜4é• ·ÂÎñ*7 ·‘þ\V`uzÓ>û(Ö ÙN8;°6:¡ ‰ÈåHOFŽÕ›²íqÂåαzLqŽ›”cž„h±Ê8¿±›˜•b ²{¸¢ÿž*7æþLoÂZ÷P„ßí„̃j-ì7 ÀD’KA§­þ"lj«h^nW7‘ê¡€V£Ó”&‚K»¡ý1û_‡^òjÔê{N£rÚæÜ»ÓvªØb#Yq[C» >ëêàl[Íb#M€ËHf`—¢%ι6eŸvlŘ3TWW¼Ò¢øº)v‰®ŒÙnÕgd»š“a7ck;,H8¿K/¶ìoÃJD&/a^וè'½»Ì=)û¦¹“¦6 Ö2æ? Ñúr†j]u&- ±”‰«T\‚<÷£RmIcHJ@’a;ÖöQ-IÈ£ qzÐnñ wÕOruMÙÞÐÍH¤4–õFä}G›V¸/~­W²›bÎkT€¨úT-LBFÐP Qœ¯~5¶Ô(6d/R¥¶#o ؼßëa”Ãøñ ÄwpÙArÇߤCÈbeވݻvè!~Ŧ6e³¢Hê ´¸FçOzDß6òK_n¡“JC›=F’&€ýH”âK1Ûš„DHu8¯¶CÄô÷“,Ö‘ßK0Ûó` Z!· 8ý,FÚ9ï ÕeüÅˉ¿æ'É_éȃX›±­Ç(Å]Ä‹ËÑ./½$ǘÖÄã爐¦nZÞÛÿ.ŽîËy®‹Pø¯©U¥¬”VW":Šm]-˜Œ»õX\ÔÀ×â- X#í>_LãJŠ{€bÿøb’™í2Âbä zÁJ1ÎC«Ðé]cZHÏmØ”²¯A¹ÊÌJijšæ#‰ - Ý9çzÊ×ñM÷]ƒÉhBšK¸‹QÉ\Uã Vσa5i$Twò¨1¦nò`è±ôI±äÇŽ|¿1âTdyŸI1Cu#ÛìstÉÁÄÄã0ÙL8éÆîØ]9/L¤ÜRJ«Ô‚T’yÁ~&Þþ14¡›s#z&#÷dá„§£”î]q'ŽÃԯܘG“£ƒx«ù:Â]¯!^$½þž«V<‚µF?ù=NtžŒ2ón%½Ì×M9®3­§ü0¥©,¥x®@’yi˜ïf°Ýß¾àûN¬jâÆì!¾IH¢.[Ÿ¼ãQ„¥‹Õ;Ðú°Ýt*¡×'àl¢]äŸT² ^q5ïÎß½‰\_ÕvN'ÞF1@±´-f»(m¦t#šš½®Œëð#˜Mq<ÀIÂÝk[Ðj’$‚—CÏÆŒ¥‡|+ÖÛ?Œé$æÞ†VÓ›뻯Q[cWÅЧM\O [É,T[!k’{‘ÒKG33Më.Dô_"* ؃VÌJRŠw"æ4«né·¯¡€™<Çp›’æ)jYËhÄvŠÕ™JhÕQLJºéB6ƒ5„Õ¦h¾þ²zxü=n§X x(f;“R5ú%ÑòM/ Ø`vEŽ}AÈUȱ©,f5ÏJuuíÕDR¨q9´¹-óè÷“kpInQûÍêWTÔcaÅÉAIn¢Vä~zœä¤—‡ÐdQ@Ìz1ò,F+\–ø»,8Wé³Ñí? ΟTuo÷" ¥TÓMšØÄDã°ÙGÖ  »F˜˜pÌõx˾G觸ÃpžþNä7ÑÙÏ”üžM~±>ʼÏ@'BW»ì˜AVÇ¡< °ŠÃDÂÏbMxqñQw­‡GYGØÀ7DþÌ97è$V7Aº„p3 /®´L™!Óï¯pëä!S;Ñ µN2èµ }½?Øf*’€’îËi|¦žG‰èAî©EˆQnGzçƒ('ºº%Ÿ©â´â§‘®:ŽøNEk±Ýuó6$ÍCOQyÁÎèµ¹ÒèÂÆ@ÓÃàÄU¾‰|õù ½XåëóáèEâöeh…º­¨"¿ïÊ_]ó–©žE±X<ˆ ÑZý†6cÏÓŠ< ך7þ? ˆ1]ÉåMÒÏ)áºù&Ò®\ë6Š­úo"—Ý$’ïÓ0z~·áÅ|´z?E¾J>•R\“‡{(Î/gÿˆôŠBi´1Ì]ÈPVi«ît_WSéxœpu£8z1§› sYpìIˆ‰œÓ&­$YµxEBzxÐGup îhac]\ícä»…ÕšíŽ*Ë]Õ_C"ø*wç=\ëSm"=©ÈÔ훚±Ý´Ú_Ü7ªÐøæŸA¹im¸ß ®µ]Œš?ÖèŒ0´ Õ¤½l]ý„ó?ÀÇÁß À!r{8èCà|Ì9À¦”þð;ÎoÖaÿ%ð•àÿ{©^åŸÿøZ0îrЋ&¯º/“?¡´ ˜sÀÿ…î£{_þ0øÎ0ú1à«H¢ùºÇçëó•”sœþ'2†î*al#žùk “çêŒ]X†èègƒí¦^]/ŸB/3ȘµÆùý‹Àu>ßA|ÃÐ À;ä_Ñ>F“Êà‡h2ø0Ç~}À£°åjÀü?À·‘‹s'º?_~IGÑî€÷ÉždN!ÍŸ¡I¹ÙÐŽ®Õ¼'®4s =£w± G“!­]³Ki"í3ÎñZ ÛâšW&µ»Å¬Ë9¦¸1îA¢úº½D¸Ìv)´©“±Í/ÇFõ¹ù ¦êÎíÁçœcÏ€éBdzÆÑ³È·ß´£‰~Š |ùä¡ÙK~CñTò+~˜PãQØ8ì*þH%0¹ñ_F«ÏôB'Å~€D×ÐËÿ‚ce®Ý÷W€ïûÜ‚eúo¿sÜ+‘ŠàZ¹/ )a-µ-ƒ] >~]?H•:¼ü2rÇÍþ º§FòùoÀ¿ÅFäý’P¦ûžEA;Ñ„›SÀïbU¥ZÁ¨9SÐõõÔGvcÔÀ>¤níC×GHiA÷e1Riþº¦ÿUåñyLDÖõçá©”N¾/ +üVúp û¾UÌêçºþZ±‘x§IN»½˜pzo3’‘j.Bú¼¸´‰ô¯ îlñSØtZõÝžƒŠûå #ɤԜý<˜ŽÜ“£çç 2=^ ƺ*¸ž›r6šòt÷éG÷cG¯Á#‚¼M5ËŸw#ñ9.iÇ$ùô®i7ÏÛ\¬˜»8åúÈ®ÏWoz‰b=®d·1ÒuE®áí`c)8ÿw i z¬¨~âQ7R¶Ç Ij7 Il*6ߢT“ÏEŒ¥(Žâ ¬Gèùʆe”ÿ’ïFèA$ÌEÒ„)8qñ<£ûð‹dŠ…š¢˜›3EW·6J“OBº³)ÂÑŽl;cÎ÷Íß9g2²Õ<‰$„´|†ƒÈeêkÔq)¸.íELþz/B+P bö9hö¾ åÅo üxh©(#Þº™oƒÁX¢v†«©OpRG«ÚÃ߀‡Ìêö6aÆí@Q6ãî8ɲ´ÎI¬ËrñØ3Hò1ÒÄd?š„6¬;®Å¾h[Ð[˜î~´š­A“À&4!ä‰KO£ýÁ±]†=J8•´@²Gá8Za×aÛDw#¦+Å~Q º‘pQQ×]9 I:íÎw °«ßrçû‰(‰étð\·¤aâ«%7mH¥FVýh¥¡½(@é"ªÓ騣Dô ›%ZñW"ƒ_žsa6 }z©oG†ªehÂÈ›¢jš}D›J¸®?Ó¼˜ãxnÚmRC²*ôTšKoèq4Q=æ|g—;ÐD÷aQöJìz[ðÝ”à»!$*Ç%/í%½GA½1I ÑZ‡†ö øŒº·òk®¾Òû‘õsÁ_㊉sÉýz™:{år㽋˜ý½€Þ'>bÏ Åœ?D80årçLÄŠ¸ÿðt ¼/r¬/vïL@"r4àÅÅà¯ÑDñs¨ºOR;1ƒŸB¶‹¼k¢øšdΟFÁJO£ûpø,ð*²ì?‹îá?Gî:ÐäsGðÿ_¡{Ò‹žã9$e¹bð·QÔcRTbºW]è^™@ƒvì3ø¹b¿[Âõv ëÿ à‘'xx1¿…®ÿB çðH Á½YIW ßö6Ê+ qÉb˜«×_œïÄàO 5àâ Q»œcMÁ2ä’ËW¦¸XfRŸ»rÉã’ª÷d‘qOÖ4iÇZï÷cvßǮܭ„ ŸƒHB0î?÷|÷Q¬_„ ®¯‘Ü!ÉÐPp̓{¹˜øÉ´€ž¹iî¹ IzÛbÆty–!—^SéFËÊßbÑ/G«dµu¦Sh8»=H³ •ŠïŸ#~…šüÒYÛc~7x|˜c¸«d5ð:ðKHR(§8ç«h|ýHziþ7 ²éG«vZå?‹¤ƒÍˆ±Nÿ øšTK9Ï1ô˜ßfô 4qœuöHó>’¾Ì l&õI}©FBŒóBFo×ñzðš4èQE´ j<öAMAz×,$†]üÊå”»*…Þ@þÞh¾ø¬Ñ®½TW£ªÔ2Zë±/b'Zeª5~V›V<ó´RšÏ÷îWxIp ·ê­1>^Š])ÍD0ðê¹éþIçßHùaºn˜íÍèþ 1Î jÚž­F6œkƒñN!}’öh0Æ!1í&$ÒE}èI4ˆfñ'ûìö€q~¿½ KïndžûF]9{C%½dqcHëêû vhAãjXóMAQ7ïÿ%$ÂݘÖÄÑßÙg’ŽZ°Æ¹Al¿·¡ç+h{ ÇØ†¤“&ᙤ*ÃÜ`Óˆ³"]C⠚вÂr=š3#®B"kÞÒ×ÃHx ÛÕ6:£÷!fßäì³'ØÇ¼0‡³>Ù®r'§%È×›¶ýS„­ÅsG–CÆGny³&!×Ùî:$ÉìF®ÈIÁ}2¾w³ª»Å6‘÷¡@8zïÂí®ãh?ñE9'¢f"!é*¯«5N¼+ÑäiYæQ#´Qœê‡~’+¾Ebì½Ès%bbWÌ~kÕîBâÜ"´š=K13η ½À¥¨C¤ G/óD´âœÌqÌW§ÑΡ2 À¼ôî*>=¸Îë±nƒˆùŸw"»…ëF4@´zÐã»2G®w Øÿ4r£ÎEÞ‚Û°|9AS§±¶ŒH"4Öu(aè Í8jÑ‹eºAÒûµÏ¤Øš¿=Ĥxá—a7éé”§‘Ø×–*ú§Ñ㈩“ªì_~Ò Mš.·=h"«$¢ïš` °V7–ÑžÁÙ<ŒÕ¤äžDA,îñÞ ¹+q½ܧÒStóÐcˆÁ7";L\ÿñHÒêB*ÅŠ˜mk­á%äAZNm[£5&žÕ³J'Ï@/ât£¢V߯'Þý–F„›kº˜Cv¹¥ÎgcLKʽ7]w²bòw_€rˆäUa];‰®ÆèÝBrÛ¬•Áý©„A£t’¼ª‘¸Ù ®CÒC?vb‰¢ƒÊkzT=HÌ«F1Źˆù?ÂF•½@>ýpI]„]_SH^ab-Þ "¿%ùÿW¢I/ÏŠ¿48v)R‡)–åXlç&{FÒ>y ©#L'âW°F·Ñâç/}¨xÆuä 8 Ot¿… ‚«H¶â8ìó8šÒÎ÷¶ö]^F«ýTΪ7øœW üM¿Gú„úݶ9rì³4 µ8â .`ãNŸO¡gx6 sÁo;Qa]ÁöÆÕÜMØ~-ãfPp>#>Òï\ð›K'J¿¼bŒEæŸü{dø«‡1çuTlÒTâiC“E zAÆ¿AqÆ^ß~&žÛP5—Z0ã/¢É+Êüõ†aÊcÁßSÎçÎçã„™Ó0²aÃ\§‚c~ìl[:x}hB„Þ1F\nhtŽ Pæ?ÆVA*c-{è´R×â$á"ddúÒý_FÅ4M´Ù(Â- ÿ=è èåú}dq¯¥^z6{“\0Œ ™êŇÃf1vµÆQkìB‹Jfuw©Óùÿ' êìŠü7±w#Õ‡ha) c…ùM»ë< %·¢Ð}XýøQˆ‰9ÿ ´zt¡Uc b˜ÌBUfç:dðz°yº½žG¢ú|jSŠ*¥„-€$’]HÞ…BfßGŒ^)ÚjG÷#Iô5«³àZ©Ë­ÜŽÞEC¿ˆlN“‘¥lŒ$±?i•kG/…±ŒXýI´JNF†º´—ù]”ñ¶›QÖŠ¬é€|·38þǨäóóX}¯þ±æ½ÈMùy¤ó›à¡÷Èά‹Ãßû~å4T»Wü§Ð½xyQ\þ _%žÁ[Ðs0EOMÁÓŸ$¼ ¶cõâÎào6 ¨ÕìˆC[ƒkùs4AttR¡î_ 柂^ðObëÒ÷`k›L)Sí&ŒX8!kÃ2ð ×=ô?ÐK÷+ئ_C"ûj²ã¸Ï¡j²/'üÞŠ&ˆshÒ‰«=Ÿ…?GnÀWƒÏ&¢š0ƒã{þÝoH%¨•/ÞÍäÓÛì$*–›pòJ·¼édÕÕ7UR¯ èF”Ù·šøRPqt?ùÄy3™-@/ï=(™ä5’3þ>B1·R,…]LqÑÇåˆQ¯¦Øû±M”/8ßeÝç•„'·{Ñ=sCV³@+ ƒIDAT/ŠÙï0Êq/ÇS‘:ç±á³ÍŽZ¹úzsþ3ò‹°¯"]øhãÞYäÇ 1ÈÅfÒnMï¾¼xEõmÍØîlg–wBzY¨ñh¥ü!š<6&lwE£ýMð¹I%_¦X¤nERVÒx]‡“MØÒùÿ\@ï R\ǰ]üM_džÞVf\qž Ó†½Íù½°›l,Á8ÏŸE®á¦B5˜¿ÛUu+Zåï!¿(õ1 5p¦õÃØòÎ.ŒËæzÙÌ_®yšìMã?nC–]ÓK~ ¥‹™‰Ôƒ ˆ9—äØçuàw°1qèE+½q7šf•y0O£“çyôÞƒe¢éh²mþoâd íÜfû÷‚¿q w¡pÉ/c'ã*¬%žFA3yñ12]@R@)ÿ}h8„}Ç!qzö…ü ºÉ*ñ܇˜h)ÅÁ1ßDÌõ#ç»)È ßIzl‚[„óé…UÌdþ=$y¼‹ í5©Tü ñUyj “¼cèHäóQŠ“i΢k3I=&† œ²ÛÝÈ.²½ A3Gø™Øær<¥ÀØ$f£L½y5>_©83΂݃^¢Ï"C[4’ñ•ïC éb6G»€¬òièCú!l@ÑyÂ¶Š¯"u"N4ŸŒñ§‘-ã+Áv{(?Gá,aéÏ¥ÃÎÿæ÷CXfóhæØþJâ¡£0¥¶MôŸÃV÷í§|‹¾I@1t +åœ@8“’ özL†™ù¾«&™öUßÄV#î~MV3ˆ·‰œC+Ê·êgW¸Œõ/Ófa—óÿï"‰å1ÂÁEã‚±í Æ:M\‹(ŽÎ¼¹ ÓÄí¯"•òš¬îEïìבJô]Jw³zhæ•? íHÌÿG„ãÉ{°é³q8Ô}ÈËÈǃ¿Qw) Ø®¼ï/mô*ôR—ÒÜa_°Ï2$bŽdi© é›W¡‰ê·HFœŠêçÏG“M 7"cî¥É»V#Cæàÿ«ãyG-FóC"ã dP›PšÞy1Ådx9€DÕ2¿U#ã,Šëè;»ªCÖý$FÜnÑÈ4`dúö]>O~ûk¤Ç›ôØÏ‘·~)bü‰hÿ<ñÇ6dÜûŠzª“yçÆ»»¹ù'ÐsÚ‹ž_šm( F¥0.² }&Á(/ŒÑ9¦.)R®Ý b4+óÏ@¢å¥(8ŠWiÃÄa™ÙüViJ§ÉH3®)S™Å¼´æE}°[k"²œ÷Û¼ƒ¬½Ï‘Üóm1Z¹ã …/¿Š¼ËÑäñ›H¢‰æºÏG¢èE†5Sÿð»Á1¢_7J]¾‘êÖlEá¯?@ÏäbŽJôíR+&c;éL ìF4A;ͬÒ˜Z÷ëuòfdþv´šÄ·D­a*Ð."<ã_@/ðûh%Ú…‚w¾Eùv‰V¶l\ƒ»QîÖwlôZЄ҅­ä“çø¦æ¿YýþUþq'¬$=ÜL²{öC¾üØäÓ˜Òe¶À?¦º†µ+QÀ•Ûдp«µ×˜…À]ÁÏ;¿›,Ñ“hÒ‹$ñ±ahFæoLDŒ`DµT·çZ’柿‚üøqÆ«ôò”"F1RÓ!Oÿ"Çý"Š€t™þRÖc ”dMpíhòX|þ 2$Ö &Ø&n²2uòÀ¹ CõJ{yx„ЉB‹ÝpYÃ4¤ßߊòLÏ‚‡‹‹K ÷ÎFî<×+ЂD{· ÉböÅTçn*W³a¨‡Ç¨@ãÚKrÀ›)Ç,  ¤hk°£gBÎ%܇î8*Å]n³K­ØRäw–yŒ (Ì8js˜Km ¹xxä‚·]:)¿ëÌÅî¿VÄ(Ñeȇïæô"Ÿ¼ÙfÊÇ/µþ@z 7ó8âóÓJƒ· [Á’`ln÷¢yÁ6‘´…‘aÀQ+: åëì¦Dö§°‡«ÈŸ3np Ù®³ˆV½ ȪífͽŒ €¦ÄØ•„ÝûPÝÀ/!¿Á’à»N¤»ßâû“<"H}˜Œâ&z‘þû!ZÙ¿9~ RS~*rcìz'—‰œŽlŸ ®µ-ØÖÔÙ{.8G ’f¶"ƒdÙ%ª=Æ:‘«é4ÒilìpÊÂĬi©ÇƒÄÛôa+í ¡têZ–úëèAÏáNä²{ åMlrhJ^»Er6õ¥ÌÌoV¬óÈŵ«„ý!ß÷d´ °Á!Ъ¼%Œô£b—O’ìgof|€\sûѪ‡ÿB8x¨0¹­â[Qa5‹V6+:‘¤b*»éÄѪÁ&ÃÏð@[™lç$õlGIQ¯ö~—ìJsA~ø¥\\µQ/±¿ eè%œBa£Dº[i*a' Æ?d+Ò}_'œµ6ZVèócCæ¢ØéÁço£¬‘#;î^ésiÃFwND×݇<†áëáÿ¿€Þ³•(ãt*Ö ûC¤æ€-#߆õëBvŸ—©c0OêÅü£Õ7j±=‹tèב®÷UªëO-p‹zDñ‘§à·§ÇþU¶mdâËbäÆüm$,F©ß¦R®Ñ÷Í ûRÕ~„˜ú ”±81z©9÷Æ_ŸvdãÆ ˜ðÞ¤J½û°õâÌɦF½Äþï¡l´hØe³¤V¶¢¥­*ÝÀ_ÆE´sÌ$"nþ–êÍî¿›ò[R™«/R:ãO@aÀŸÂæOtQí¸Û¡g»óÙ-r¹ 1ûÀª%ï?ãö~ž¨k—8÷9TÐ|gî· Ðq3$ÍïÑ8új [kaêœsÙUþ ¿h(´#Ýø%ä+Ç—D'‘x×W…qö–9¾[J8G­²Ž5€ †sÉ/Z×3×£ ŒW_]Èê:ë»7UZL–™›ÄcDSS&ÌýÎ4–ŒV}©®D*S9ø&ºÎ¯.#uR zx=ƒtŸÿ&¾ ¥AÛª¬”ÒÙåb&z†¯3J`Ôc5pâÊG ˆ@·"ÏÅ$› È…ÛʈÔ÷#¿|^\@%Î]ÌE÷ÏdØõaWúÿ†˜¿ E~:ø½«>µ`Ûh™‚÷ˆŸå•xÀÿyd<{Ý­(;®!)²# cuåi¸Y·ŸÀöç+&²ÎTú¶•ÉF;Ü‹[#»•PÜíø\0®5ȵzéÇëÑ‘§­% Ë ·çŠâÕÝ#žù=JE'ªåߊ­rô.ÉÆÅY(\÷WPÑÎ~Šíç‘…ÿà¿çC/’(¦£ªÃçPñÕïä½±Ïü‚©YPÀ·Âòððððððððððððððððððððððððððððððððððððððððððððððƒøÿy‹ö(Æá–IEND®B`‚jigsaw-generator-0.2.7/examples/puzzle-discriminating.yaml000066400000000000000000000030661401032735100240260ustar00rootroot00000000000000# An example proofsort, based on # https://undergroundmathematics.org/quadratics/discriminating format: 1 type: cardsort resource: E1_RT7_3 title: Discriminating note: 'ALWAYS, SOMETIMES or NEVER true: $ax^2+bx+c=0$' # puzzle size rows: 6 columns: 1 # Do we shuffle the order of the cards from the order given when # producing the problem? Say "true" for a proof sorting activity. # It probably does not make sense to say "false" here but still to # produce a solution. shuffleCards: false # Does this puzzle require production of a solution? If so, the cards # must be given in the correct order initially. produceSolution: false # Default text size on cards textSize: 6 # Card title cardTitle: Discriminating cards: - If $a < 0$, then the equation has no real roots. - If $b^2 - 4ac = 0$, then the equation has one repeated real root. - If the equation has no real roots, then the equation $ax^2 + bx - c = 0$ has two distinct real roots. - If $\frac{b^2}{a} < 4c$, then the equation has two distinct real roots. - If $b = 0$, then the equation has one repeated real root. - The equation has three real roots. - If $c = 0$, then the equation has no real roots. - The equation has the same number of real roots as $ax^2 - bx + c = 0$. - If the equation has two distinct real roots, then $ac < \frac{b^2}{4}$. - If $c > 0$, then the equation has two distinct real roots. - The equation has the same number of real roots as the equation $cx^2 + bx + a = 0$. - If the equation has no real roots, then the equation $-ax^2 - bx - c = 0$ has two distinct real roots. jigsaw-generator-0.2.7/examples/puzzle-dominoes.yaml000066400000000000000000000016321401032735100226340ustar00rootroot00000000000000# A trial domino activity format: 1 type: dominoes title: A trial domino puzzle note: This is a silly example of a puzzle # puzzle size rows: 5 columns: 2 # Do we shuffle the order of the pairs from the order given when # producing the problem? shufflePairs: false # Do we randomly flip (swap) individual questions and answers (the # contents of the pairs) on the puzzle? flip: false # Do we have "start" and "finish" cards (loop: false) or do the cards # go in a complete loop (loop: true)? loop: true # Do we number the cards? numberCards: true # Default text size on cards (including sentinel cards, if any) textSize: 5 # Card title cardTitle: My dominoes pairs: - [Q1, A1] - [Q2, A2] - [Q3, A3] - [Q4, A4] - [Q5, A5] - [Q6, A6] - [Q7, A7] - [Q8, A8] - [Q9, A9] - [Q10, A10] - [Q11, A11] - [Q12, A12] - [Q13, A13] - [Q14, A14] - [Q15, A15] - [Q16, A16] jigsaw-generator-0.2.7/examples/puzzle-followme.yaml000066400000000000000000000025041401032735100226420ustar00rootroot00000000000000# A follow-me activity format: 1 type: dominoes title: A follow-me activity # puzzle size rows: 8 columns: 2 # Do we shuffle the order of the pairs from the order given when # producing the problem? shufflePairs: true # Do we randomly flip (swap) individual questions and answers (the # contents of the pairs) on the puzzle? flip: false # Do we have "start" and "finish" cards (loop: false) or do the cards # go in a complete loop (loop: true)? loop: true # Do we number the cards? numberCards: false # Default text size on cards (including sentinel cards, if any) textSize: 4 # Card title cardTitle: Calculation follow-me pairs: - ['Who has $3+4\times5$?', 'I have $23$'] - ['Who has $5+2\times7$?', 'I have $19s$'] - ['Who has $6+3\times8$?', 'I have $30$'] - ['Who has $13-2\times3$?', 'I have $7$'] - ['Who has $15-4\times3$?', 'I have $3$'] - ['Who has $30-2\times6$?', 'I have $18$'] - ['Who has $6\times3-2$?', 'I have $16$'] - ['Who has $5\times4+5$?', 'I have $25$'] - ['Who has $6+4\div2$?', 'I have $8$'] - ['Who has $9+6\div3$?', 'I have $11$'] - ['Who has $15+10\div5$?', 'I have $17$'] - ['Who has $12-8\div4$?', 'I have $10$'] - ['Who has $24-12\div6$?', 'I have $22$'] - ['Who has $18-9\div3$?', 'I have $15$'] - ['Who has $24\div3-2$?', 'I have $6$'] - ['Who has $48\div8-2$?', 'I have $4$'] jigsaw-generator-0.2.7/examples/puzzle-hexagon-example.yaml000066400000000000000000000030601401032735100240760ustar00rootroot00000000000000# A hexagonal jigsaw puzzle, from http://www.mrbartonmaths.com/jigsaw.htm format: 1 type: hexagon title: Powers and roots note: "The `?' means a number for you to fill in" pairs: - ['$10^6\div10^3$', '$1000$'] - ['$10^{23}\div10^{21}$', '$100$'] - ['$9^4\times9^5$', '$9^9$'] - ['$(3^2)^2$', '$81$'] - ['$6\times6^2$', '$216$'] - ['$2^4\div2^6$', '$\dfrac{1}{4}$'] - - '$4^2\times4$' - puzzletext: '?' solutiontext: '$64$' - ['$2^6\times2$', '$128$'] - ['$23.1^0$', '$1$'] - ['$3^3\times3^3$', '$3^6$'] - ['$\sqrt{64}-2^3$', '$0$'] - ['$\dfrac{1}{5^2}\times\dfrac{1}{5}$', '$\dfrac{1}{5^3}$'] - ['$5^2\div5^4$', '$\dfrac{1}{5^2}$'] - ['$3^2\times3^3$', '$3^5$'] - ['$(3^3)^3$', '$3^9$'] - ['$2^3\div\sqrt{16}$', '$2$'] - - '$2^6\div2^4$' - puzzletext: '?' solutiontext: '$4$' - ['$4^4\times4^4$', '$4^8$'] - ['$\sqrt{49}$', '$7$'] - ['$\sqrt{25}\times\sqrt{36}$', '$30$'] - ['$\sqrt{144}\div\sqrt{16}$', '$3$'] - ['$2^3\div2^4$', '$\dfrac{1}{2}$'] - ['$2\times2^2\times2^2$', '$32$'] - ['$10^2\times100$', '$10\,000$'] - ['$3^6\div3^9$', '$\dfrac{1}{3^3}$'] - ['$3^8\div3^5$', '$3^3$'] - ['$5^5\div5\times5^2$', '$5^6$'] - ['$9^9\times9^9$', '$9^{18}$'] - ['$(9^9)^9$', '$9^{81}$'] - ['$(4^4)^4$', '$4^{16}$'] edges: - '$-1$' - '$10$' - '$13^2\div13$' - '$39$' - '$13^3$' - '$108$' - '$\dfrac{1}{2}$' - '$\sqrt{128}$' - '$\sqrt{20}$' - '$2^{\frac{1}{2}}$' - '$\dfrac{3}{2}$' - '$9^{10}$' jigsaw-generator-0.2.7/examples/puzzle-hexagon.yaml000066400000000000000000000013311401032735100224440ustar00rootroot00000000000000# A trial jigsaw puzzle format: 1 type: hexagon title: A trial puzzle note: This is a silly example of a puzzle pairs: - [Q1, A1] - [Q2, A2] - [Q3, A3] - [Q4, A4] - [Q5, A5] - [Q6, A6] - [Q7, A7] - [Q8, A8] - [Q9, A9] - [Q10, A10] - [Q11, A11] - [Q12, A12] - [Q13, A13] - [Q14, A14] - [Q15, A15] - [Q16, A16] - [Q17, A17] - [Q18, A18] - [Q19, A19] - [Q20, A20] - [Q21, A21] - [Q22, A22] - [Q23, A23] - [Q24, A24] - [Q25, A25] - [Q26, A26] - [Q27, A27] - [Q28, A28] - [Q29, A29] - [Q30, A30] edges: - E1 - E2 - E3 - E4 - E5 - E6 - E7 - E8 - E9 - E10 - E11 - E12 jigsaw-generator-0.2.7/examples/puzzle-parquet.yaml000066400000000000000000000007421401032735100225010ustar00rootroot00000000000000# A trial jigsaw puzzle format: 1 type: parquet contributor: Julian title: A trial parquet puzzle note: This is a silly example of a puzzle pairs: - [Q1, A1] - [Q2, A2] - [Q3, A3] - [Q4, A4] - [Q5, A5] - [Q6, A6] - [Q7, A7] - [Q8, A8] - [Q9, A9] - [Q10, A10] - [Q11, A11] - [Q12, A12] - [Q13, A13] - [Q14, A14] - [Q15, A15] edges: - E1 - E2 - E3 - E4 - E5 - E6 - E7 - E8 - E9 - E10 jigsaw-generator-0.2.7/examples/puzzle-proofsorter-quadratic-formula.yaml000066400000000000000000000034231401032735100270210ustar00rootroot00000000000000# A proof sorter activity, based on # https://undergroundmathematics.org/quadratics/proving-quad-formula format: 1 type: cardsort resource: E1_RT5_1 title: $\sqrt{2}$ is irrational note: Sort the cards into order to prove the quadratic formula. # puzzle size rows: 5 columns: 1 # Do we shuffle the order of the cards from the order given when # producing the problem? Say "true" for a proof sorting activity. # It probably does not make sense to say "false" here but still to # produce a solution. shuffleCards: true # Does this puzzle require production of a solution? If so, the cards # must be given in the correct order initially. produceSolution: true # Default text size on cards textSize: 5 # Card title cardTitle: Quadratic formula proof cardTitleSize: 1 cards: - Consider $ax^2 + bx + c = 0$, where $a \neq 0$. - Since $a \neq 0$, we can divide by $a$ to get $$x^2 + \frac{b}{a} x + \frac{c}{a} = 0.$$ - We complete the square. - This shows that the original equation is equivalent to $$\left(x + \frac{b}{2a} \right)^2 - \frac{b^2}{4a^2} + \frac{c}{a} = 0.$$ - Since $x$ appears only once in the equation, we can rearrange this to solve for $x$. - 'Get the squared term on one side of the equation: $$\left(x + \frac{b}{2a} \right)^2 = \frac{b^2}{4a^2} - \frac{c}{a}.$$' - 'We can rewrite the right-hand side by putting it over a common denominator: $$\left(x + \frac{b}{2a} \right)^2 = \frac{b^2 - 4ac}{4a^2}.$$' - We can take the square root of both sides. - Taking account of the possibility of positive and negative square roots, we see $$x + \frac{b}{2a} = \frac{\pm\sqrt{b^2 - 4ac}}{2a}.$$ - Subtracting $\frac{b}{2a}$ from both sides and putting the right-hand side over a common denominator gives $$x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}.$$ jigsaw-generator-0.2.7/examples/puzzle-proofsorter-sqrt2.yaml000066400000000000000000000026711401032735100244600ustar00rootroot00000000000000# A proof sorter activity, based on # https://undergroundmathematics.org/thinking-about-numbers/square-root-of-2-is-irrational format: 1 type: cardsort resource: PI3_RT5_2 title: $\sqrt{2}$ is irrational note: Sort the cards into order to prove that $\sqrt{2}$ is irrational. # puzzle size rows: 6 columns: 1 # Do we shuffle the order of the cards from the order given when # producing the problem? Say "true" for a proof sorting activity. # It probably does not make sense to say "false" here but still to # produce a solution. shuffleCards: true # Does this puzzle require production of a solution? If so, the cards # must be given in the correct order initially. produceSolution: true # Default text size on cards textSize: 6 # Card title cardTitle: $\sqrt{2}$ is irrational cardTitleSize: 2 cards: - Suppose, for a contradiction, that $\sqrt{2}$ is rational. - That is, we can write $\sqrt{2} = \frac{m}{n}$ where $m$ and $n$ are integers and where $n \neq 0$. - Squaring, we have $2 = \frac{m^2}{n^2}$. - Multiply across to get $2n^2 = m^2$. - In the prime factorisations of $m^2$ and $n^2$, $2$ occurs to an even power. - In the prime factorisation of $2n^2$, $2$ occurs to an odd power. - But prime factorisations are unique, so $2$ should appear to the same power in both $2n^2$ and $m^2$. - This is a contradiction, so our original assumption that $\sqrt{2}$ is rational must be wrong. - So $\sqrt{2}$ is irrational. jigsaw-generator-0.2.7/examples/puzzle-smallhexagon-example.yaml000066400000000000000000000007421401032735100251330ustar00rootroot00000000000000format: 1 type: smallhexagon title: An example puzzle note: 'You will have to work out the missing number shown as `?''' pairs: - ['$10^6\div10^3$', '$1000$'] - ['$10^{23}\div10^{21}$', '$100$'] - ['$9^4\times9^5$', '$9^9$'] - - '$(3^2)^2$' - puzzletext: '?' solutiontext: '$81$' - ['$6\times6^2$', '$216$'] - ['$2^4\div2^6$', '$\dfrac{1}{4}$'] edges: - '$-1$' - '$10$' - '$13^2\div13$' - '$39$' - '$13^3$' - '$108$' jigsaw-generator-0.2.7/examples/puzzle-smallhexagon.yaml000066400000000000000000000006421401032735100235010ustar00rootroot00000000000000# A trial jigsaw puzzle format: 1 type: smallhexagon title: A trial puzzle note: This is a silly example of a puzzle pairs: - - text: Q1 size: 3 - text: A1 hidden: true - [Q2, 'A2: ![goosey](goose.png)'] - [Q3, A3] - ['Q4: ![](goose.png)', A4] - [Q5, A5] - - puzzletext: '?' solutiontext: Q6 - A6 edges: - E1 - E2 - E3 - E4 - E5 - E6 jigsaw-generator-0.2.7/examples/puzzle-triangle.yaml000066400000000000000000000010161401032735100226200ustar00rootroot00000000000000# A trial jigsaw puzzle format: 1 type: triangle title: A trial puzzle note: This is a silly example of a puzzle pairs: - [Q1, A1] - [Q2, A2] - [Q3, A3] - [Q4, A4] - [Q5, A5] - [Q6, A6] - [Q7, A7] - [Q8, A8] - [Q9, A9] - [Q10, A10] - [Q11, A11] - [Q12, A12] - [Q13, A13] - [Q14, A14] - [Q15, A15] - [Q16, A16] - [Q17, A17] - [Q18, A18] edges: - E1 - E2 - E3 - E4 - E5 - E6 - E7 - E8 - E9 - E10 - E11 - E12 jigsaw-generator-0.2.7/install-sh000077500000000000000000000354631401032735100170030ustar00rootroot00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2014-09-12.12; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) # $RANDOM is not portable (e.g. dash); use it when possible to # lower collision chance tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 # As "mkdir -p" follows symlinks and we work in /tmp possibly; so # create the $tmpdir first (and fail if unsuccessful) to make sure # that nobody tries to guess the $tmpdir name. if (umask $mkdir_umask && $mkdirprog $mkdir_mode "$tmpdir" && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. test_tmpdir="$tmpdir/a" ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac oIFS=$IFS IFS=/ set -f set fnord $dstdir shift set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: jigsaw-generator-0.2.7/jigsaw-generate.1000066400000000000000000000050131401032735100201210ustar00rootroot00000000000000.\" Hey, EMACS: -*- nroff -*- .\" (C) Copyright 2015 Julian Gilbey .\" For licence conditions, see COPYING .TH JIGSAW-GENERATOR 1 "December 18, 2015" .SH NAME jigsaw-generator \- program to generate jigsaws and card sort activities .SH SYNOPSIS .B jigsaw-generator .RI [ options ] " puzzlefile[.yaml]" .SH DESCRIPTION This manual page briefly documents the .B jigsaw-generator command. .PP .B jigsaw-generator is a program that reads a YAML data file and from it creates a "jigsaw" puzzle or card sorting activity, generally intended for classroom use. For more information, see the documentation in /usr/share/doc/jigsaw. .SH OPTIONS These programs follow the usual GNU command line syntax, with long options starting with two dashes (`-'). .PP A summary of options is included below. .TP .B \-h, \-\-help Show summary of options. .TP .B \-v, \-\-version Show version information. .TP .BI "\-o " OUTPUT ", \-\-output " OUTPUT Use .I OUTPUT as the basename of the output files, rather than puzzlefile. .TP .B \-\-noclean, \-\-no-clean Do not clean the auxiliary files which are created (such as the LaTeX file used to generate the PDF versions of the puzzle). .TP .B \-\-clean Do clean the auxiliary files; this is the default behaviour. .TP .BI "\-\-latex " LATEX The LaTeX variant to run. The default is pdflatex, but this default can be overridden by the template file used. .TP .B \-\-nomakepdf, \-\-no-makepdf Do not make PDF output files. .TP .B \-\-makepdf Make PDF output files; this is the default behaviour. .TP .B \-\-nomakemd, \-\-no-makemd Do not make Markdown output files. .TP .B \-\-makemd Make Markdown output files; this is the default behaviour. .TP .BI "\-\-texfilter " TEXFILTER Run the LaTeX file through .I TEXFILTER before running pdflatex (or whichever LaTeX variant is being used). This filter should accept the original LaTeX file on its standard input and output the filtered file on its standard output. .TP .BI "\-\-mdfilter " MDFILTER Run the Markdown file through .I MDFILTER after producing it. This filter should accept the original Markdown file on its standard input and output the filtered file on its standard output. .SH CONFIGURATION FILES The program reads configuration files and template files when processing the template file. For full information, see the complete documention. .SH SEE ALSO The program is documented fully by the documentation included with the package, typically installed in /usr/share/doc/jigsaw-generator or /usr/local/share/doc/jigsaw-generator. jigsaw-generator-0.2.7/jigsaw-generate.in000077500000000000000000000003721401032735100203750ustar00rootroot00000000000000#! /usr/bin/env python3 # This will be needed to find the template files pkgdatadir = '@pkgdatadir@' pkgversion = '@PACKAGE_VERSION@' import sys sys.path[1:1] = [pkgdatadir] import jigsaw.generate as generate generate.main(pkgdatadir, pkgversion) jigsaw-generator-0.2.7/jigsaw/000077500000000000000000000000001401032735100162505ustar00rootroot00000000000000jigsaw-generator-0.2.7/jigsaw/__init__.py000066400000000000000000000000001401032735100203470ustar00rootroot00000000000000jigsaw-generator-0.2.7/jigsaw/appdirs.py000066400000000000000000000577171401032735100203050ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (c) 2005-2010 ActiveState Software Inc. # Copyright (c) 2013 Eddy PetriÈ™or """Utilities for determining application-specific dirs. See for details and usage. """ # Dev Notes: # - MSDN on where to store app data files: # http://support.microsoft.com/default.aspx?scid=kb;en-us;310294#XSLTH3194121123120121120120 # - Mac OS X: http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileSystem/index.html # - XDG spec for Un*x: https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html __version__ = "1.4.4" __version_info__ = tuple(int(segment) for segment in __version__.split(".")) import sys import os PY3 = sys.version_info[0] == 3 if PY3: unicode = str if sys.platform.startswith('java'): import platform os_name = platform.java_ver()[3][0] if os_name.startswith('Windows'): # "Windows XP", "Windows 7", etc. system = 'win32' elif os_name.startswith('Mac'): # "Mac OS X", etc. system = 'darwin' else: # "Linux", "SunOS", "FreeBSD", etc. # Setting this to "linux2" is not ideal, but only Windows or Mac # are actually checked for and the rest of the module expects # *sys.platform* style strings. system = 'linux2' else: system = sys.platform def user_data_dir(appname=None, appauthor=None, version=None, roaming=False): r"""Return full path to the user-specific data dir for this application. "appname" is the name of application. If None, just the system directory is returned. "appauthor" (only used on Windows) is the name of the appauthor or distributing body for this application. Typically it is the owning company name. This falls back to appname. You may pass False to disable it. "version" is an optional version path element to append to the path. You might want to use this if you want multiple versions of your app to be able to run independently. If used, this would typically be ".". Only applied when appname is present. "roaming" (boolean, default False) can be set True to use the Windows roaming appdata directory. That means that for users on a Windows network setup for roaming profiles, this user data will be sync'd on login. See for a discussion of issues. Typical user data directories are: Mac OS X: ~/Library/Application Support/ Unix: ~/.local/share/ # or in $XDG_DATA_HOME, if defined Win XP (not roaming): C:\Documents and Settings\\Application Data\\ Win XP (roaming): C:\Documents and Settings\\Local Settings\Application Data\\ Win 7 (not roaming): C:\Users\\AppData\Local\\ Win 7 (roaming): C:\Users\\AppData\Roaming\\ For Unix, we follow the XDG spec and support $XDG_DATA_HOME. That means, by default "~/.local/share/". """ if system == "win32": if appauthor is None: appauthor = appname const = "CSIDL_APPDATA" if roaming else "CSIDL_LOCAL_APPDATA" path = os.path.normpath(_get_win_folder(const)) if appname: if appauthor is not False: path = os.path.join(path, appauthor, appname) else: path = os.path.join(path, appname) elif system == 'darwin': path = os.path.expanduser('~/Library/Application Support/') if appname: path = os.path.join(path, appname) else: path = os.getenv('XDG_DATA_HOME', os.path.expanduser("~/.local/share")) if appname: path = os.path.join(path, appname) if appname and version: path = os.path.join(path, version) return path def site_data_dir(appname=None, appauthor=None, version=None, multipath=False): r"""Return full path to the user-shared data dir for this application. "appname" is the name of application. If None, just the system directory is returned. "appauthor" (only used on Windows) is the name of the appauthor or distributing body for this application. Typically it is the owning company name. This falls back to appname. You may pass False to disable it. "version" is an optional version path element to append to the path. You might want to use this if you want multiple versions of your app to be able to run independently. If used, this would typically be ".". Only applied when appname is present. "multipath" is an optional parameter only applicable to *nix which indicates that the entire list of data dirs should be returned. By default, the first item from XDG_DATA_DIRS is returned, or '/usr/local/share/', if XDG_DATA_DIRS is not set Typical site data directories are: Mac OS X: /Library/Application Support/ Unix: /usr/local/share/ or /usr/share/ Win XP: C:\Documents and Settings\All Users\Application Data\\ Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) Win 7: C:\ProgramData\\ # Hidden, but writeable on Win 7. For Unix, this is using the $XDG_DATA_DIRS[0] default. WARNING: Do not use this on Windows. See the Vista-Fail note above for why. """ if system == "win32": if appauthor is None: appauthor = appname path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA")) if appname: if appauthor is not False: path = os.path.join(path, appauthor, appname) else: path = os.path.join(path, appname) elif system == 'darwin': path = os.path.expanduser('/Library/Application Support') if appname: path = os.path.join(path, appname) else: # XDG default for $XDG_DATA_DIRS # only first, if multipath is False path = os.getenv('XDG_DATA_DIRS', os.pathsep.join(['/usr/local/share', '/usr/share'])) pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)] if appname: if version: appname = os.path.join(appname, version) pathlist = [os.sep.join([x, appname]) for x in pathlist] if multipath: path = os.pathsep.join(pathlist) else: path = pathlist[0] return path if appname and version: path = os.path.join(path, version) return path def user_config_dir(appname=None, appauthor=None, version=None, roaming=False): r"""Return full path to the user-specific config dir for this application. "appname" is the name of application. If None, just the system directory is returned. "appauthor" (only used on Windows) is the name of the appauthor or distributing body for this application. Typically it is the owning company name. This falls back to appname. You may pass False to disable it. "version" is an optional version path element to append to the path. You might want to use this if you want multiple versions of your app to be able to run independently. If used, this would typically be ".". Only applied when appname is present. "roaming" (boolean, default False) can be set True to use the Windows roaming appdata directory. That means that for users on a Windows network setup for roaming profiles, this user data will be sync'd on login. See for a discussion of issues. Typical user config directories are: Mac OS X: ~/Library/Preferences/ Unix: ~/.config/ # or in $XDG_CONFIG_HOME, if defined Win *: same as user_data_dir For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME. That means, by default "~/.config/". """ if system == "win32": path = user_data_dir(appname, appauthor, None, roaming) elif system == 'darwin': path = os.path.expanduser('~/Library/Preferences/') if appname: path = os.path.join(path, appname) else: path = os.getenv('XDG_CONFIG_HOME', os.path.expanduser("~/.config")) if appname: path = os.path.join(path, appname) if appname and version: path = os.path.join(path, version) return path def site_config_dir(appname=None, appauthor=None, version=None, multipath=False): r"""Return full path to the user-shared data dir for this application. "appname" is the name of application. If None, just the system directory is returned. "appauthor" (only used on Windows) is the name of the appauthor or distributing body for this application. Typically it is the owning company name. This falls back to appname. You may pass False to disable it. "version" is an optional version path element to append to the path. You might want to use this if you want multiple versions of your app to be able to run independently. If used, this would typically be ".". Only applied when appname is present. "multipath" is an optional parameter only applicable to *nix which indicates that the entire list of config dirs should be returned. By default, the first item from XDG_CONFIG_DIRS is returned, or '/etc/xdg/', if XDG_CONFIG_DIRS is not set Typical site config directories are: Mac OS X: same as site_data_dir Unix: /etc/xdg/ or $XDG_CONFIG_DIRS[i]/ for each value in $XDG_CONFIG_DIRS Win *: same as site_data_dir Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) For Unix, this is using the $XDG_CONFIG_DIRS[0] default, if multipath=False WARNING: Do not use this on Windows. See the Vista-Fail note above for why. """ if system == 'win32': path = site_data_dir(appname, appauthor) if appname and version: path = os.path.join(path, version) elif system == 'darwin': path = os.path.expanduser('/Library/Preferences') if appname: path = os.path.join(path, appname) else: # XDG default for $XDG_CONFIG_DIRS # only first, if multipath is False path = os.getenv('XDG_CONFIG_DIRS', '/etc/xdg') pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)] if appname: if version: appname = os.path.join(appname, version) pathlist = [os.sep.join([x, appname]) for x in pathlist] if multipath: path = os.pathsep.join(pathlist) else: path = pathlist[0] return path def user_cache_dir(appname=None, appauthor=None, version=None, opinion=True): r"""Return full path to the user-specific cache dir for this application. "appname" is the name of application. If None, just the system directory is returned. "appauthor" (only used on Windows) is the name of the appauthor or distributing body for this application. Typically it is the owning company name. This falls back to appname. You may pass False to disable it. "version" is an optional version path element to append to the path. You might want to use this if you want multiple versions of your app to be able to run independently. If used, this would typically be ".". Only applied when appname is present. "opinion" (boolean) can be False to disable the appending of "Cache" to the base app data dir for Windows. See discussion below. Typical user cache directories are: Mac OS X: ~/Library/Caches/ Unix: ~/.cache/ (XDG default) Win XP: C:\Documents and Settings\\Local Settings\Application Data\\\Cache Vista: C:\Users\\AppData\Local\\\Cache On Windows the only suggestion in the MSDN docs is that local settings go in the `CSIDL_LOCAL_APPDATA` directory. This is identical to the non-roaming app data dir (the default returned by `user_data_dir` above). Apps typically put cache data somewhere *under* the given dir here. Some examples: ...\Mozilla\Firefox\Profiles\\Cache ...\Acme\SuperApp\Cache\1.0 OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value. This can be disabled with the `opinion=False` option. """ if system == "win32": if appauthor is None: appauthor = appname path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA")) if appname: if appauthor is not False: path = os.path.join(path, appauthor, appname) else: path = os.path.join(path, appname) if opinion: path = os.path.join(path, "Cache") elif system == 'darwin': path = os.path.expanduser('~/Library/Caches') if appname: path = os.path.join(path, appname) else: path = os.getenv('XDG_CACHE_HOME', os.path.expanduser('~/.cache')) if appname: path = os.path.join(path, appname) if appname and version: path = os.path.join(path, version) return path def user_state_dir(appname=None, appauthor=None, version=None, roaming=False): r"""Return full path to the user-specific state dir for this application. "appname" is the name of application. If None, just the system directory is returned. "appauthor" (only used on Windows) is the name of the appauthor or distributing body for this application. Typically it is the owning company name. This falls back to appname. You may pass False to disable it. "version" is an optional version path element to append to the path. You might want to use this if you want multiple versions of your app to be able to run independently. If used, this would typically be ".". Only applied when appname is present. "roaming" (boolean, default False) can be set True to use the Windows roaming appdata directory. That means that for users on a Windows network setup for roaming profiles, this user data will be sync'd on login. See for a discussion of issues. Typical user state directories are: Mac OS X: same as user_data_dir Unix: ~/.local/state/ # or in $XDG_STATE_HOME, if defined Win *: same as user_data_dir For Unix, we follow this Debian proposal to extend the XDG spec and support $XDG_STATE_HOME. That means, by default "~/.local/state/". """ if system in ["win32", "darwin"]: path = user_data_dir(appname, appauthor, None, roaming) else: path = os.getenv('XDG_STATE_HOME', os.path.expanduser("~/.local/state")) if appname: path = os.path.join(path, appname) if appname and version: path = os.path.join(path, version) return path def user_log_dir(appname=None, appauthor=None, version=None, opinion=True): r"""Return full path to the user-specific log dir for this application. "appname" is the name of application. If None, just the system directory is returned. "appauthor" (only used on Windows) is the name of the appauthor or distributing body for this application. Typically it is the owning company name. This falls back to appname. You may pass False to disable it. "version" is an optional version path element to append to the path. You might want to use this if you want multiple versions of your app to be able to run independently. If used, this would typically be ".". Only applied when appname is present. "opinion" (boolean) can be False to disable the appending of "Logs" to the base app data dir for Windows, and "log" to the base cache dir for Unix. See discussion below. Typical user log directories are: Mac OS X: ~/Library/Logs/ Unix: ~/.cache//log # or under $XDG_CACHE_HOME if defined Win XP: C:\Documents and Settings\\Local Settings\Application Data\\\Logs Vista: C:\Users\\AppData\Local\\\Logs On Windows the only suggestion in the MSDN docs is that local settings go in the `CSIDL_LOCAL_APPDATA` directory. (Note: I'm interested in examples of what some windows apps use for a logs dir.) OPINION: This function appends "Logs" to the `CSIDL_LOCAL_APPDATA` value for Windows and appends "log" to the user cache dir for Unix. This can be disabled with the `opinion=False` option. """ if system == "darwin": path = os.path.join( os.path.expanduser('~/Library/Logs'), appname) elif system == "win32": path = user_data_dir(appname, appauthor, version) version = False if opinion: path = os.path.join(path, "Logs") else: path = user_cache_dir(appname, appauthor, version) version = False if opinion: path = os.path.join(path, "log") if appname and version: path = os.path.join(path, version) return path class AppDirs(object): """Convenience wrapper for getting application dirs.""" def __init__(self, appname=None, appauthor=None, version=None, roaming=False, multipath=False): self.appname = appname self.appauthor = appauthor self.version = version self.roaming = roaming self.multipath = multipath @property def user_data_dir(self): return user_data_dir(self.appname, self.appauthor, version=self.version, roaming=self.roaming) @property def site_data_dir(self): return site_data_dir(self.appname, self.appauthor, version=self.version, multipath=self.multipath) @property def user_config_dir(self): return user_config_dir(self.appname, self.appauthor, version=self.version, roaming=self.roaming) @property def site_config_dir(self): return site_config_dir(self.appname, self.appauthor, version=self.version, multipath=self.multipath) @property def user_cache_dir(self): return user_cache_dir(self.appname, self.appauthor, version=self.version) @property def user_state_dir(self): return user_state_dir(self.appname, self.appauthor, version=self.version) @property def user_log_dir(self): return user_log_dir(self.appname, self.appauthor, version=self.version) #---- internal support stuff def _get_win_folder_from_registry(csidl_name): """This is a fallback technique at best. I'm not sure if using the registry for this guarantees us the correct answer for all CSIDL_* names. """ if PY3: import winreg as _winreg else: import _winreg shell_folder_name = { "CSIDL_APPDATA": "AppData", "CSIDL_COMMON_APPDATA": "Common AppData", "CSIDL_LOCAL_APPDATA": "Local AppData", }[csidl_name] key = _winreg.OpenKey( _winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" ) dir, type = _winreg.QueryValueEx(key, shell_folder_name) return dir def _get_win_folder_with_ctypes(csidl_name): import ctypes csidl_const = { "CSIDL_APPDATA": 26, "CSIDL_COMMON_APPDATA": 35, "CSIDL_LOCAL_APPDATA": 28, }[csidl_name] buf = ctypes.create_unicode_buffer(1024) ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf) # Downgrade to short path name if have highbit chars. See # . has_high_char = False for c in buf: if ord(c) > 255: has_high_char = True break if has_high_char: buf2 = ctypes.create_unicode_buffer(1024) if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024): buf = buf2 return buf.value def _get_win_folder_with_jna(csidl_name): import array from com.sun import jna from com.sun.jna.platform import win32 buf_size = win32.WinDef.MAX_PATH * 2 buf = array.zeros('c', buf_size) shell = win32.Shell32.INSTANCE shell.SHGetFolderPath(None, getattr(win32.ShlObj, csidl_name), None, win32.ShlObj.SHGFP_TYPE_CURRENT, buf) dir = jna.Native.toString(buf.tostring()).rstrip("\0") # Downgrade to short path name if have highbit chars. See # . has_high_char = False for c in dir: if ord(c) > 255: has_high_char = True break if has_high_char: buf = array.zeros('c', buf_size) kernel = win32.Kernel32.INSTANCE if kernel.GetShortPathName(dir, buf, buf_size): dir = jna.Native.toString(buf.tostring()).rstrip("\0") return dir def _get_win_folder_from_environ(csidl_name): env_var_name = { "CSIDL_APPDATA": "APPDATA", "CSIDL_COMMON_APPDATA": "ALLUSERSPROFILE", "CSIDL_LOCAL_APPDATA": "LOCALAPPDATA", }[csidl_name] return os.environ[env_var_name] if system == "win32": try: from ctypes import windll except ImportError: try: import com.sun.jna except ImportError: try: if PY3: import winreg as _winreg else: import _winreg except ImportError: _get_win_folder = _get_win_folder_from_environ else: _get_win_folder = _get_win_folder_from_registry else: _get_win_folder = _get_win_folder_with_jna else: _get_win_folder = _get_win_folder_with_ctypes #---- self test code if __name__ == "__main__": appname = "MyApp" appauthor = "MyCompany" props = ("user_data_dir", "user_config_dir", "user_cache_dir", "user_state_dir", "user_log_dir", "site_data_dir", "site_config_dir") print("-- app dirs %s --" % __version__) print("-- app dirs (with optional 'version')") dirs = AppDirs(appname, appauthor, version="1.0") for prop in props: print("%s: %s" % (prop, getattr(dirs, prop))) print("\n-- app dirs (without optional 'version')") dirs = AppDirs(appname, appauthor) for prop in props: print("%s: %s" % (prop, getattr(dirs, prop))) print("\n-- app dirs (without optional 'appauthor')") dirs = AppDirs(appname) for prop in props: print("%s: %s" % (prop, getattr(dirs, prop))) print("\n-- app dirs (with disabled 'appauthor')") dirs = AppDirs(appname, appauthor=False) for prop in props: print("%s: %s" % (prop, getattr(dirs, prop))) jigsaw-generator-0.2.7/jigsaw/generate.py000077500000000000000000002267041401032735100204320ustar00rootroot00000000000000#! /usr/bin/env python3 """ jigsaw-generate Copyright (C) 2014-2016 Julian Gilbey This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions; see the COPYING file for details. """ import random import sys import os import os.path import shutil import re import argparse import subprocess import configparser from collections import OrderedDict from . import appdirs import yaml from yaml import load, dump try: from yaml import CLoader as Loader, CDumper as Dumper except ImportError: from yaml import Loader, Dumper debug_pdb = 1 debug_getopt = 2 debug = 0 if debug & debug_pdb: import pdb ##################################################################### # Utility functions and global definitions. These might get moved out # to separate modules for clarity at some point in the near future. # LaTeX font sizes sizes = [r'\tiny', r'\scriptsize', r'\footnotesize', r'\small', r'\normalsize', r'\large', r'\Large', r'\LARGE', r'\huge', r'\Huge' ] normalsize = 4 # Is any entry marked as hidden? exists_hidden = False def getopt(layout, data, options, opt, default=None): """Determine the value of opt from various possible sources Check the command-line options first for this option, then the data, then the layout, then the config file; return the first value found, or default if the option is not found anywhere. """ if options and opt in options['options']: if debug & debug_getopt: print('option %s set to "%s" by options' % (opt, options['options'][opt]), file=sys.stderr) return options['options'][opt] if opt in data: if debug & debug_getopt: print('option %s set to "%s" by data' % (opt, data[opt]), file=sys.stderr) return data[opt] if opt in layout: if debug & debug_getopt: print('option %s set to "%s" by layout' % (opt, layout[opt]), file=sys.stderr) return layout[opt] if options and opt in options['config']: if debug & debug_getopt: print('option %s set to "%s" by config' % (opt, options['config'][opt]), file=sys.stderr) if opt in ('clean', 'makepdf', 'makemd'): return options['config'].getboolean(opt) else: return options['config'][opt] if debug & debug_getopt: if default is None: print('option %s set to None by default' % opt, file=sys.stderr) else: print('option %s set to "%s" by default' % (opt, default), file=sys.stderr) return default def dosub(text, subs): """Substitute <: var :> strings in text using the dict subs""" def subtext(matchobj): if matchobj.group(1) in subs: return str(subs[matchobj.group(1)]) else: print('Unrecognised substitution: %s' % matchobj.group(0), file=sys.stderr) return re.sub(r'<:\s*(\S*?)\s*:>', subtext, text) def opentemplate(templatedirs, name): """Searches for and then opens a template file. Search in the directories given in the first argument, which must be an iterable. Typically, this will be the current directory, then the user config directory, then the package data directory. """ for templatedir in templatedirs: try: f = open(os.path.join(templatedir, name)) break except: f = None continue if f: return f else: sys.exit('Could not find template file %s, giving up.' % name) def check_special(c): """Check whether a card or domino is special Special entries currently recognised are: "- newpage: true" this produces a new page in the PDF cards output, but nothing in the table or Markdown outputs "- newlabel: text" "- newlabelsize: num" these will change the default label The function returns either None if the entry is not special, or a dict with entries (t, cont) where t is the type of special entry ('newpage', 'label' or 'labelsize') and cont is the related content. Multiple entries in one card/domino are therefore permitted, but 'text' is not permitted in such a card, and neither is domino data. This function also performs some basic checks to ensure that the card or domino entries are well-formed. """ if isinstance(c, dict): special = False if 'newpage' in c: special = True if c['newpage'] != True: print('Invalid value for newpage, only newpage: true ' 'permitted\nCard/Domino value: %s\nTreating as' 'newpage: true anyway' % c['newpage'], file=sys.stderr) c['newpage'] = True if 'newlabel' in c: special = True if not isinstance(c['newlabel'], str): print('Invalid value for newlabel entry: it must be a string.\n' 'Entry value: %s' % c['newlabel'], file=sys.stderr) del c['newlabel'] if 'newlabelsize' in c: special = True if not isinstance(c['newlabelsize'], int): c['newlabelsize'] = int(c['newlabelsize']) if special: if 'text' in c: print('Cannot have a special entry (newpage, newlabel, ' 'newlabelsize) and text\n' 'on same card! Ignoring special requests.', file=sys.stderr) return None else: return c else: return None def make_entry(entry, defaultsize, style, defaultlabel='', defaultlabelsize=0, blank='(BLANK)', solution=False): """Convert a YAML entry into a LaTeX or Markdown formatted entry Returns the pair (text, label). The text is the content to be used for the LaTeX or Markdown. The label is only of interest for card sorts and similar activities; it is ignored for jigsaws. The YAML entry will either be a simple text entry, or it will be a dictionary with required key "text" and optional entries "size", "hidden" and "label". (The "text" key can optionally be replaced by "puzzletext" and "solutiontext" keys; see below.) If there is a "size" key, this will be added to the defaultsize. If there is a "label" key, this will override the current default label; similarly for the "labelsize" key. An entry can also include keys which are specific for the puzzle and solution: "puzzletext", "puzzlesize": these are the equivalent of the "text" and "size" keys for the puzzle "solutiontext", "solutionsize": these are the equivalent of the "text" and "size" keys for the solution The "puzzletext" and "solutiontext" override the "text" key if present, while the "puzzlesize" and "solutionsize" keys override the "size" key if present. The puzzle* keys are used by default, unless solution=True, in which case the solution* keys are used. This could be used, for example, to have "?" in the puzzle and the correct solution in the solution. If a solutiontext key is present, then "hidden" is regarded as being true, unless hidden: false is explicitly specified. If solution is False (the default, so we're creating the puzzle): - if there is a "puzzletext" parameter, that will be used - if not, then if "hidden" is true, the text will be hidden - else, "text" will be used If solution is True: - if there is a "solutiontext" parameter, that will be used, and the text will be highlighted unless "hidden" is explicitly false - if not, then "text" will be used; if "hidden" is true, the text will be marked The "style" parameter can be: "table": outputs text with no size marker; highlighted hidden text will be prepended with "(*)" "tikz": outputs {regular}{size text} or {hidden}{size text}, where {hidden} highlights the text "md": outputs text for Markdown: highlighted hidden text will be prepended with "(*)"; blank text will be replaced by "(BLANK)" or the setting of the blank parameter, and all entries will be surrounded on either side by a blank space. There is no size marker. """ label = make_entry_label(entry, style, defaultlabel, defaultlabelsize) if isinstance(entry, dict): if 'text' not in entry and ('puzzletext' not in entry or 'solutiontext' not in entry): if 'puzzletext' in entry or 'solutiontext' in entry: print('Cannot have only one of "puzzletext" and "solutiontext"' 'in an entry.\nRelevant entry is:\n', file=sys.stderr) else: print('No "text" field in entry in data file. ' 'Relevant entry is:\n', file=sys.stderr) for f in entry: print(' %s: %s\n' % (f, entry[f]), file=sys.stderr) return (make_entry_util('', '', False, style, blank), label) size = make_entry_size(entry, 'size', defaultsize, None, entry['text'] if 'text' in entry else entry['puzzletext']) # if there is a solutiontext in the entry, this means that we # regard 'hidden' as true, unless it is explicitly set to # false; doing this saves us from having to rewrite the logic # of the next paragraph twice. if 'solutiontext' in entry: if 'hidden' not in entry: entry['hidden'] = True if 'hidden' in entry and entry['hidden']: global exists_hidden exists_hidden = True hide = True else: hide = False if solution: if 'solutiontext' in entry: solnsize = make_entry_size(entry, 'solutionsize', defaultsize, size, entry['solutiontext']) return (make_entry_util(entry['solutiontext'], sizes[solnsize], hide, style, blank), label) else: # We know by now that we have 'text' if we don't have # 'solutiontext' return (make_entry_util(entry['text'], sizes[size], hide, style, blank), label) else: if 'puzzletext' in entry: puzsize = make_entry_size(entry, 'puzzlesize', defaultsize, size, entry['puzzletext']) return (make_entry_util(entry['puzzletext'], sizes[puzsize], False, style, blank), label) elif hide: return (make_entry_util('', '', False, style, blank), '') else: return (make_entry_util(entry['text'], sizes[size], False, style, blank), label) else: # just a plain entry, not a dict return (make_entry_util(entry, sizes[defaultsize], False, style, blank), label) def make_entry_size(entry, sizekey, defaultsize, entrysize, text): """Return size corresponding to sizekey. defaultsize is the global defaultsize for this puzzle. The default if the sizekey is not found in entry or there is a problem with it is entrysize if this is set or defaultsize if not. If there's an error, use text in the error message.""" if sizekey in entry: try: size = defaultsize + int(entry[sizekey]) if size < 0: size = 0 if size >= len(sizes): size = len(sizes) - 1 except: print('Unrecognised size entry for text %s:\n' 'size = %s\n' 'Defaulting to default size\n' % (text, entry[sizekey]), file=sys.stderr) size = entrysize if entrysize != None else defaultsize else: size = entrysize if entrysize != None else defaultsize return size def make_entry_util(text, size, mark_hidden, style, blank): """Create the output once the text, size, hide and style are determined This should be called with mark_hidden being True or False; hidden text should be replaced by '' before this function is called. """ text = text.rstrip() if mark_hidden: if style == 'table': return '(*) %s' % img2tex(text) elif style == 'tikz': return '{hidden}{%s %s}' % (size, img2tex(text)) elif style == 'md': return '(*) %s' % text else: if style == 'table': return img2tex(text) elif style == 'tikz': return '{regular}{%s %s}' % (size, img2tex(text)) elif style == 'md': return '%s' % (text if text else blank) def make_entry_label(entry, style, defaultlabel, defaultlabelsize): if isinstance(entry, dict): if 'label' in entry: labeltext = entry['label'].rstrip() else: labeltext = defaultlabel.rstrip() if 'labelsize' in entry: labelsize = entry['labelsize'] else: labelsize = defaultlabelsize else: labeltext = defaultlabel.rstrip() labelsize = defaultlabelsize if style == 'table': return img2tex(labeltext) elif style == 'tikz': if labeltext: return '%s %s' % (sizes[labelsize], img2tex(labeltext)) else: return '' elif style == 'md': return labeltext img_re = re.compile(r'!\[([^\]]*)\]\(([^\)]*)\)') def img2tex(text): text = str(text) # just in case the text is purely numeric images = img_re.search(text) while images: caption, img = images.groups() if caption: text = img_re.sub(r'\\imagecap{%s}{%s}' % (img, caption), text, count=1) else: text = img_re.sub(r'\\image{%s}' % img, text, count=1) images = img_re.search(text) return text def cardnum(n): """Underline 6 and 9; return everything else as a string""" if n in [6, 9]: return r'\underline{%s}' % n else: return str(n) def make_table(pairs, edges, cards, dsubs, dsubsmd): """Create table substitutions for the pairs and edges""" dsubs['tablepairs'] = '' dsubs['tableedges'] = '' dsubs['tablecards'] = '' dsubsmd['pairs'] = '' dsubsmd['edges'] = '' dsubsmd['cards'] = '' for p in pairs: dsubs['tablepairs'] += ((r'%s&%s\\ \hline' '\n') % (make_entry(p[0], normalsize, 'table', solution=True)[0], make_entry(p[1], normalsize, 'table', solution=True)[0])) row = '|' for entry in p: row += ' ' + make_entry(entry, 0, 'md', solution=True)[0] + ' |' dsubsmd['pairs'] += row + '\n' for e in edges: dsubs['tableedges'] += ((r'\strut %s\\ \hline' '\n') % make_entry(e, normalsize, 'table', solution=True)[0]) dsubsmd['edges'] += ('| ' + make_entry(e, 0, 'md', solution=True)[0] + ' |\n') # The next bit is only used for the PDF version of the table output, # so we don't make too much effort over label handling defaultlabel = dsubs['label'] if 'label' in dsubs else '' for c in cards: s = check_special(c) if s: if 'newlabel' in c: defaultlabel = c['newlabel'] continue cont, label = make_entry(c, normalsize, 'table', defaultlabel, normalsize, solution=True) dsubs['tablecards'] += ((r'%s%s\\ \hline' '\n') % (('[' + label + '] ' if label else ''), cont)) cont, label = make_entry(c, 0, 'md', defaultlabel, solution=True) dsubsmd['cards'] += ('| %s%s |\n' % (('[' + label + '] ' if label else ''), cont)) def make_triangles(data, layout, pairs, edges, dsubs, dsubsmd): """Handle triangular-shaped jigsaw pieces, putting in the Qs and As Read the puzzle layout and the puzzle data, and fill in questions and answers for any triangular-shaped pieces, preparing the output substitution variables in the process. """ puzzle_size = getopt(layout, data, {}, 'puzzleTextSize', 5) solution_size = getopt(layout, data, {}, 'solutionTextSize', 5) numbering_cards = getopt(layout, data, {}, 'numberCards', True) num_triangle_cards = len(layout['triangleSolutionCards']) # We read the solution layout from the YAML file, and place the # data into our lists. We don't format them yet, as the # formatting may be different for the puzzle and solution trianglesolcard = [] for card in layout['triangleSolutionCards']: newcard = [] for entry in card: entrynum = int(entry[1:]) - 1 # -1 to convert to 0-based arrays if entry[0] == 'Q': newcard.append(pairs[entrynum][0]) elif entry[0] == 'A': newcard.append(pairs[entrynum][1]) elif entry[0] == 'E': newcard.append(edges[entrynum]) else: printf('Unrecognised entry in layout file ' '(triangleSolutionCards):\n%s' % card, file=sys.stderr) trianglesolcard.append(newcard) # List: direction of base side trianglesolorient = layout['triangleSolutionOrientation'] # List: direction of base side, direction of card number (from vertical) trianglepuzorient = layout['trianglePuzzleOrientation'] triangleorder = list(range(num_triangle_cards)) random.shuffle(triangleorder) trianglepuzcard = [[]] * num_triangle_cards # We will put solution card i in puzzle position triangleorder[i], # rotated by a random amount for (i, solcard) in enumerate(trianglesolcard): j = triangleorder[i] rot = random.randint(0, 2) # anticlockwise rotation trianglepuzcard[j] = [solcard[(3 - rot) % 3], solcard[(4 - rot) % 3], solcard[(5 - rot) % 3], cardnum(j + 1), trianglepuzorient[j][1]] # Shorthand: puzcard = trianglepuzcard[j] # What angle does the card number go in the solution? # angle of puzzle card + (orientation of sol card - orientation of # puz card) - rotation angle [undoing rotation] angle = (trianglepuzorient[j][1] + (trianglesolorient[i] - trianglepuzorient[j][0]) - 120 * rot) solcard.extend([cardnum(j + 1), (angle + 180) % 360 - 180]) dsubs['trisolcard' + str(i + 1)] = (('{%s}' * 5) % (make_entry(solcard[0], solution_size, 'tikz', solution=True)[0], make_entry(solcard[1], solution_size, 'tikz', solution=True)[0], make_entry(solcard[2], solution_size, 'tikz', solution=True)[0], ('%s %s' % (sizes[max(solution_size-3, 0)], solcard[3])) if numbering_cards else '', solcard[4])) dsubs['tripuzcard' + str(j + 1)] = (('{%s}' * 5) % (make_entry(puzcard[0], puzzle_size, 'tikz')[0], make_entry(puzcard[1], puzzle_size, 'tikz')[0], make_entry(puzcard[2], puzzle_size, 'tikz')[0], ('%s %s' % (sizes[max(puzzle_size-3, 0)], puzcard[3])) if numbering_cards else '', puzcard[4])) # For the Markdown version, we only need to record the puzzle cards at # this point. if 'puzcards3' not in dsubsmd: dsubsmd['puzcards3'] = '' if 'puzcards4' not in dsubsmd: dsubsmd['puzcards4'] = '' for t in trianglepuzcard: row = '|' for entry in t[0:3]: row += ' ' + make_entry(entry, 0, 'md')[0] + ' |' dsubsmd['puzcards3'] += row + '\n' dsubsmd['puzcards4'] += row + '   |\n' # Testing: # for (i, card) in enumerate(trianglesolcard): # print('Sol card %s: (%s, %s, %s), num angle %s' % # (i, card[0], card[1], card[2], card[4])) # # for (i, card) in enumerate(trianglepuzcard): # print('Puz card %s: (%s, %s, %s), num angle %s' % # (i, card[0], card[1], card[2], card[3])) def make_squares(data, layout, pairs, edges, dsubs, dsubsmd): """Handle square-shaped jigsaw pieces, putting in the Qs and As Read the puzzle layout and the puzzle data, and fill in questions and answers for any square-shaped pieces, preparing the output substitution variables in the process. This is very similar to the make_triangles function. """ puzzle_size = getopt(layout, data, {}, 'puzzleTextSize', 5) solution_size = getopt(layout, data, {}, 'solutionTextSize', 5) numbering_cards = getopt(layout, data, {}, 'numberCards', True) num_triangle_cards = len(layout['triangleSolutionCards']) num_square_cards = len(layout['squareSolutionCards']) # We read the solution layout from the YAML file, and place the # data into our lists. We don't format them yet, as the # formatting may be different for the puzzle and solution squaresolcard = [] for card in layout['squareSolutionCards']: newcard = [] for entry in card: entrynum = int(entry[1:]) - 1 # -1 to convert to 0-based arrays if entry[0] == 'Q': newcard.append(pairs[entrynum][0]) elif entry[0] == 'A': newcard.append(pairs[entrynum][1]) elif entry[0] == 'E': newcard.append(edges[entrynum]) else: printf('Unrecognised entry in layout file ' '(squareSolutionCards):\n%s' % card, file=sys.stderr) squaresolcard.append(newcard) # List: direction of base side squaresolorient = layout['squareSolutionOrientation'] # List: direction of base side, direction of card number (from vertical) squarepuzorient = layout['squarePuzzleOrientation'] squareorder = list(range(num_square_cards)) random.shuffle(squareorder) squarepuzcard = [[]] * num_square_cards # We will put solution card i in puzzle position squareorder[i], # rotated by a random amount for (i, solcard) in enumerate(squaresolcard): j = squareorder[i] rot = random.randint(0, 3) # anticlockwise rotation squarepuzcard[j] = [solcard[(4 - rot) % 4], solcard[(5 - rot) % 4], solcard[(6 - rot) % 4], solcard[(7 - rot) % 4], cardnum(j + num_triangle_cards + 1), squarepuzorient[j][1]] # Shorthand: puzcard = squarepuzcard[j] # What angle does the card number go in the solution? # angle of puzzle card + (orientation of sol card - orientation of # puz card) - rotation angle [undoing rotation] angle = (squarepuzorient[j][1] + (squaresolorient[i] - squarepuzorient[j][0]) - 90 * rot) solcard.extend([cardnum(j + num_triangle_cards + 1), (angle + 180) % 360 - 180]) dsubs['sqsolcard' + str(i + 1)] = (('{%s}' * 6) % (make_entry(solcard[0], solution_size, 'tikz', solution=True)[0], make_entry(solcard[1], solution_size, 'tikz', solution=True)[0], make_entry(solcard[2], solution_size, 'tikz', solution=True)[0], make_entry(solcard[3], solution_size, 'tikz', solution=True)[0], ('%s %s' % (sizes[max(solution_size-3, 0)], solcard[4])) if numbering_cards else '', solcard[5])) dsubs['sqpuzcard' + str(j + 1)] = (('{%s}' * 6) % (make_entry(puzcard[0], puzzle_size, 'tikz')[0], make_entry(puzcard[1], puzzle_size, 'tikz')[0], make_entry(puzcard[2], puzzle_size, 'tikz')[0], make_entry(puzcard[3], puzzle_size, 'tikz')[0], ('%s %s' % (sizes[max(puzzle_size-3, 0)], puzcard[4])) if numbering_cards else '', puzcard[5])) # For the Markdown version, we only need to record the puzzle cards at # this point. if 'puzcards4' not in dsubsmd: dsubsmd['puzcards4'] = '' for t in squarepuzcard: row = '|' for entry in t[0:4]: row += ' ' + make_entry(entry, 0, 'md')[0] + ' |' dsubsmd['puzcards4'] += row + '\n' # Testing: # for (i, card) in enumerate(squaresolcard): # print('Sol card %s: (%s, %s, %s, %s), num angle %s' % # (i, card[0], card[1], card[2], card[3], card[5])) # # for (i, card) in enumerate(squarepuzcard): # print('Puz card %s: (%s, %s, %s), num angle %s' % # (i, card[0], card[1], card[2], card[3], card[4])) def make_cardsort_cards(data, layout, options, cards, puztemplate, soltemplate, puztemplatemd, soltemplatemd, dsubs, dsubsmd): """Handle card sorting cards, making the content for puzzle and solution The body content is returned via the dictionaries as dsubs['puzbody'], dsubs['solbody'] and similarly for dsubsmd. Special card content does special things: "- newpage: true" this produces a new page in the PDF cards output, but nothing in the table or Markdown outputs "- newlabel: text" "- newlabelsize: num" these will change the default label """ dosoln = getopt(layout, data, {}, 'produceSolution', True) numbering_cards = getopt(layout, data, {}, 'numberCards', True) size = getopt(layout, data, {}, 'textSize', 5) defaultlabelsize = getopt(layout, data, {}, 'labelSize', max(size - 2,0)) defaultlabel = data['label'] if 'label' in data else '' cardtitle = data['cardTitle'] if 'cardTitle' in data else '' if 'cardTitle' in data: if 'cardTitleSize' in data: titlesize = data['cardTitleSize'] else: titlesize = max(defaultlabelsize - 1, 0) dsubs['cardtitle'] = '%s %s' % (sizes[titlesize], data['cardTitle']) else: dsubs['cardtitle'] = '' dsubsmd['cardtitle'] = data['cardTitle'] if 'cardTitle' in data else '' rows = getopt(layout, data, {}, 'rows') columns = getopt(layout, data, {}, 'columns') cardsep = getopt(layout, data, {}, 'cardsep', '12pt') cardseph = getopt(layout, data, {}, 'cardsepHorizontal') cardsepv = getopt(layout, data, {}, 'cardsepVertical') if cardseph is None: cardseph = cardsep if cardsepv is None: cardsepv = cardsep dsubs['rows'] = rows dsubsmd['rows'] = rows dsubs['columns'] = columns dsubsmd['columns'] = columns dsubs['cardseph'] = cardseph dsubs['cardsepv'] = cardsepv # We do a presift of the cards to identify the real cards as # opposed to the special cards. It would be more efficient to # only read through the cards once, but that would make the code # more complex than needed, and this part of the code is fairly # fast anyway. # When we are done, realcards will contain the indices of all real # cards in the cards list. realcards = [] for (i, c) in enumerate(cards): if check_special(c): continue else: realcards.append(i) num_cards = len(realcards) cardorder = list(range(num_cards)) shufflecards = getopt(layout, data, {}, 'shuffleCards', False) if shufflecards: random.shuffle(cardorder) invcardorder = {j: i for (i, j) in enumerate(cardorder)} puzbody = puztemplate['begin_document'] puzbodymd = puztemplatemd['begin_document'] if dosoln: solbody = soltemplate['begin_document'] solbodymd = soltemplatemd['begin_document'] # We will put solution card i in puzzle position cardorder[i]. i = 0 pagecards = 0 for c in cards: s = check_special(c) if s: if 'newlabel' in c: defaultlabel = c['newlabel'] if 'newlabelsize' in c: defaultlabelsize = c['newlabelsize'] if 'newpage' in c: # this would presumably only occur for non-shuffled cards; # it would make no sense otherwise if shufflecards: print('newpage makes no sense for shuffled cards!' ' Ignoring', file=sys.stderr) else: pagecards = 0 # the next loop through will do the new page stuff continue row = (pagecards % (rows * columns)) // columns + 1 col = pagecards % columns + 1 puzsubs = { 'rownum': row, 'colnum': col } solsubs = { 'rownum': row, 'colnum': col } puzsubsmd = dict(puzsubs) solsubsmd = dict(solsubs) if numbering_cards: puzsubs['cardnum'] = '%s %s' % (sizes[max(size-3, 0)], i + 1) solsubs['cardnum'] = '%s %s' % (sizes[max(size-3, 0)], invcardorder[i] + 1) puzsubsmd['cardnum'] = str(i + 1) solsubsmd['cardnum'] = str(invcardorder[i] + 1) else: puzsubs['cardnum'] = '' solsubs['cardnum'] = '' puzsubsmd['cardnum'] = '' solsubsmd['cardnum'] = '' if pagecards == 0: if i > 0: puzbody += puztemplate['end_page'] puzbody += puztemplate['begin_page'] if dosoln and i % (rows * columns) == 0: if i > 0: solbody += soltemplate['end_page'] solbody += soltemplate['begin_page'] puzsubs['text'], puzsubs['label'] = make_entry( cards[realcards[cardorder[i]]], size, 'tikz', defaultlabel, defaultlabelsize) puzbody += dosub(puztemplate['item'], puzsubs) puzsubsmd['text'], puzsubsmd['label'] = make_entry( cards[realcards[cardorder[i]]], 0, 'md', defaultlabel, blank=' ') puzbodymd += dosub(puztemplatemd['item'], puzsubsmd) if dosoln: solsubs['text'], solsubs['label'] = make_entry( cards[realcards[i]], size, 'tikz', defaultlabel, defaultlabelsize, solution=True) solbody += dosub(soltemplate['item'], solsubs) solsubsmd['text'], solsubsmd['label'] = make_entry( cards[realcards[i]], 0, 'md', defaultlabel, blank=' ', solution=True) solbodymd += dosub(soltemplatemd['item'], solsubsmd) i += 1 pagecards += 1 if pagecards == rows * columns: pagecards = 0 puzbody += puztemplate['end_page'] if dosoln: solbody += soltemplate['end_page'] puzbody += puztemplate['end_document'] puzbodymd += puztemplatemd['end_document'] if dosoln: solbody += soltemplate['end_document'] solbodymd += soltemplatemd['end_document'] dsubs['puzbody'] = puzbody dsubsmd['puzbody'] = puzbodymd if dosoln: dsubs['solbody'] = solbody dsubsmd['solbody'] = solbodymd def make_domino_cards(data, layout, options, pairs, puztemplate, soltemplate, puztemplatemd, soltemplatemd, dsubs, dsubsmd): """Handle domino cards, making the content for puzzle and solution This is very similar to the make_cardsort_cards function. The body content is returned via the dictionaries as dsubs['puzbody'], dsubs['solbody'] and similarly for dsubsmd. """ numbering_cards = getopt(layout, data, {}, 'numberCards', True) size = getopt(layout, data, {}, 'textSize', 5) # We don't use labels for dominoes, but the next two lines do no # harm, and a labelsize is used to calculate the titlesize a few # lines further on defaultlabelsize = getopt(layout, data, {}, 'labelSize', max(size - 2,0)) defaultlabel = data['label'] if 'label' in data else '' cardtitle = data['cardTitle'] if 'cardTitle' in data else '' if 'cardTitle' in data: if 'cardTitleSize' in data: titlesize = data['cardTitleSize'] else: titlesize = max(defaultlabelsize - 1, 0) dsubs['cardtitle'] = '%s %s' % (sizes[titlesize], data['cardTitle']) else: dsubs['cardtitle'] = '' dsubsmd['cardtitle'] = data['cardTitle'] if 'cardTitle' in data else '' rows = getopt(layout, data, {}, 'rows') columns = getopt(layout, data, {}, 'columns') dsubs['rows'] = rows dsubsmd['rows'] = rows dsubs['columns'] = columns dsubsmd['columns'] = columns loop = getopt(layout, data, {}, 'loop', True) start = getopt(layout, data, {}, 'start', 'Start') finish = getopt(layout, data, {}, 'finish', 'Finish') # We temporarily append a terminal pair if we're not looping if not loop: pairs.append([finish, start]) # We do a presift of the domino pairs to identify the real pairs # as opposed to the special ones. It would be more efficient to # only read through the dominoes once, but that would make the code # more complex than needed, and this part of the code is fairly # fast anyway. # At present, there should not be any special domino pairs, but we # leave this code (based on make_cardsort_cards) in case we later # decide to allow this. # When we are done, realpairs will contain the indices of all real # pairs in the pairs list. realpairs = [] for (i, p) in enumerate(pairs): if check_special(p): continue else: realpairs.append(i) num_pairs = len(realpairs) cardorder = list(range(num_pairs)) # In dominoes, we must shuffle the printing order! random.shuffle(cardorder) invcardorder = {j: i for (i, j) in enumerate(cardorder)} # This is how the cards will be laid out (where n=num_pairs-1, # where num_pairs is the number of pairs if loop == True and one # more than this if loop == False (to take account of Start/Finish # pair, where Start=An, Finish=Qn); note that our Q and A counting # starts at 0: # # Solution cards: # solution card 0: An - Q0 # solution card 1: A0 - Q1 # ... # solution card n-1: A(n-2) - Q(n-1) # solution card n: A(n-1) - Qn puzbody = puztemplate['begin_document'] puzbodymd = puztemplatemd['begin_document'] solbody = soltemplate['begin_document'] solbodymd = soltemplatemd['begin_document'] # We will put solution card i in puzzle position cardorder[i]. i = 0 for p in pairs: s = check_special(p) if s: print('Special cards are not accepted for dominoes', file=sys.stderr) continue # the following will never be executed, but it remains in # case we decide to resurrect this behaviour if 'newlabel' in p: defaultlabel = p['newlabel'] if 'newlabelsize' in p: defaultlabelsize = p['newlabelsize'] if 'newpage' in p: # this does not make sense for dominoes print('newpage makes no sense for dominoes! Ignoring.', file=sys.stderr) continue row = (i % (rows * columns)) // columns + 1 col = i % columns + 1 puzsubs = { 'rownum': row, 'colnum': col } solsubs = { 'rownum': row, 'colnum': col } if numbering_cards: puzsubs['cardnum'] = '%s %s' % (sizes[max(size-3, 0)], i + 1) solsubs['cardnum'] = '%s %s' % (sizes[max(size-3, 0)], invcardorder[i] + 1) else: puzsubs['cardnum'] = '' solsubs['cardnum'] = '' puzsubsmd = dict(puzsubs) solsubsmd = dict(solsubs) if i % (rows * columns) == 0: if i > 0: puzbody += puztemplate['end_page'] solbody += soltemplate['end_page'] puzbody += puztemplate['begin_page'] solbody += soltemplate['begin_page'] # on ith solution card, textL = A(l-1), textR = Q(l) puzi = cardorder[i] puzi1 = (cardorder[i] - 1 + num_pairs) % num_pairs soli = i soli1 = (i - 1 + num_pairs) % num_pairs puzsubs['textL'], puzsubs['labelL'] = make_entry( pairs[realpairs[puzi1]][1], size, 'tikz', defaultlabel, defaultlabelsize) puzsubs['textR'], puzsubs['labelR'] = make_entry( pairs[realpairs[puzi]][0], size, 'tikz', defaultlabel, defaultlabelsize) puzbody += dosub(puztemplate['item'], puzsubs) puzsubsmd['textL'], puzsubsmd['labelL'] = make_entry( pairs[realpairs[puzi1]][1], 0, 'md', defaultlabel) puzsubsmd['textR'], puzsubsmd['labelR'] = make_entry( pairs[realpairs[puzi]][0], 0, 'md', defaultlabel) puzbodymd += dosub(puztemplatemd['item'], puzsubsmd) solsubs['textL'], solsubs['labelL'] = make_entry( pairs[realpairs[soli1]][1], size, 'tikz', defaultlabel, defaultlabelsize, solution=True) solsubs['textR'], solsubs['labelR'] = make_entry( pairs[realpairs[soli]][0], size, 'tikz', defaultlabel, defaultlabelsize, solution=True) solbody += dosub(soltemplate['item'], solsubs) solsubsmd['textL'], solsubsmd['labelL'] = make_entry( pairs[realpairs[soli1]][1], 0, 'md', defaultlabel, solution=True) solsubsmd['textR'], solsubsmd['labelR'] = make_entry( pairs[realpairs[soli]][0], 0, 'md', defaultlabel, solution=True) solbodymd += dosub(soltemplatemd['item'], solsubsmd) i += 1 puzbody += puztemplate['end_page'] solbody += soltemplate['end_page'] puzbody += puztemplate['end_document'] puzbodymd += puztemplatemd['end_document'] solbody += soltemplate['end_document'] solbodymd += soltemplatemd['end_document'] dsubs['puzbody'] = puzbody dsubsmd['puzbody'] = puzbodymd dsubs['solbody'] = solbody dsubsmd['solbody'] = solbodymd if not loop: # We remove the temporarily appended terminal pair pairs.pop() rerun_regex = re.compile(r'rerun ', re.I) def runlatex(fn, layout, data, options): """Run LaTeX or a variant on fn""" texfilter = getopt(layout, data, options, 'texfilter') latexprog = getopt(layout, data, options, 'latex', 'pdflatex') filterprog = None error = False if texfilter: for fdir in options['filterdirs']: if os.access(os.path.join(fdir, texfilter), os.X_OK): filterprog = os.path.join(fdir, texfilter) break if not filterprog: print('Warning: Requested LaTeX filter %s not found, skipping' % texfilter, file=sys.stderr) else: os.replace(fn, fn + '.filter') try: output = subprocess.check_output(filterprog, stdin=open(fn + '.filter'), universal_newlines=True) with open(fn, 'w') as filtered: print(output, file=filtered) except subprocess.CalledProcessError as cpe: print('Warning: LaTeX filter failed, return value %s' % cpe.returncode, file=sys.stderr) print('Continuing with LaTeX run on unfiltered file', file=sys.stderr) os.replace(fn + '.filter', fn) error = True for count in range(4): try: output = subprocess.check_output([latexprog, '--interaction=nonstopmode', fn], universal_newlines=True) except subprocess.CalledProcessError as cpe: print('Warning: %s %s failed, return value %s' % (latexprog, fn, cpe.returncode), file=sys.stderr) print('See the %s log file for more details.' % latexprog, file=sys.stderr) error = True break if not rerun_regex.search(output): break doclean = getopt(layout, data, options, 'clean', True) if not error and doclean: basename = os.path.splitext(fn)[0] for junk in ['aux', 'log', 'tex', 'ind', 'idx', 'out', 'tex.filter']: try: os.remove(basename + '.' + junk) except: pass def filtermd(fn, layout, data, options): """Filter Markdown output if required""" mdfilter = getopt(layout, data, options, 'mdfilter') filterprog = None error = False if mdfilter: for fdir in options['filterdirs']: if os.access(os.path.join(fdir, mdfilter), os.X_OK): filterprog = os.path.join(fdir, mdfilter) break if not filterprog: print('Warning: Requested Markdown filter %s not found, skipping' % mdfilter, file=sys.stderr) else: os.replace(fn, fn + '.filter') try: output = subprocess.check_output(filterprog, stdin=open(fn + '.filter'), universal_newlines=True) with open(fn, 'w') as filtered: print(output, file=filtered) except subprocess.CalledProcessError as cpe: print('Warning: Markdown filter failed, return value %s' % cpe.returncode, file=sys.stderr) error = True doclean = getopt(layout, data, options, 'clean', True) if not error and doclean: try: os.remove(fn + '.filter') except: pass ##################################################################### def main(pkgdatadir=None, pkgversion=0.0): """Process the command line and generate the appropriate output files. Command line: jigsaw-generate [options] puzzlefile[.yaml] There are no options at present, but this will change later. We will generate both LaTeX output files and (eventually) a markdown file which can be included where needed. """ if not pkgdatadir: pkgdatadir = appdirs.site_data_dir('jigsaw-generator') userdatadir = appdirs.user_config_dir('jigsaw-generator') templatedirs = ['.', os.path.join(userdatadir, 'templates'), os.path.join(pkgdatadir, 'templates')] filterdirs = ['.', os.path.join(userdatadir, 'filters'), os.path.join(pkgdatadir, 'filters')] # Begin by reading the user config file. If it does not exist, # then copy the default one to the user's config directory. if os.access(os.path.join(userdatadir, 'config.ini'), os.R_OK): config = configparser.ConfigParser() config.read(os.path.join(userdatadir, 'config.ini')) if 'jigsaw-generate' not in config: print('Warning: no "jigsaw-generate" section in config.ini\n' 'Your configuration file will be ignored.', file=sys.stderr) configs = dict() else: configs = config['jigsaw-generate'] else: # Copy the default configuration file os.makedirs(userdatadir, exist_ok=True) shutil.copy(os.path.join(pkgdatadir, 'templates', 'default_config.ini'), os.path.join(userdatadir, 'config.ini')) configs = dict() ### Parse the command line parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter) versioninfo = ''' This is jigsaw-generate, version %s. Copyright (C) 2014-2015 Julian Gilbey This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions; see the COPYING file for details.''' % pkgversion parser.add_argument('-v', '--version', action='version', version=versioninfo) parser.add_argument('puzfile', metavar='puzzlefile[.yaml]', help='yaml file containing puzzle data') parser.add_argument('-o', '--output', help='basename of output files') groupc = parser.add_mutually_exclusive_group() if 'clean' in configs: doclean = configs.getboolean('clean') else: doclean = True groupc.add_argument('--noclean', '--no-clean', help=('do not clean auxiliary files%s' % (' (default)' if not doclean else '')), action='store_true') groupc.add_argument('--clean', help=('clean auxiliary files%s' % (' (default)' if doclean else '')), action='store_true') parser.add_argument('--latex', help=('the LaTeX variant to run (default %s)' % configs['latex'] if 'latex' in configs else 'pdflatex')) groupp = parser.add_mutually_exclusive_group() if 'makepdf' in configs: dopdf = configs.getboolean('makepdf') else: dopdf = True groupp.add_argument('--makepdf', help=('make PDF output via LaTeX%s' % (' (default)' if dopdf else '')), action='store_true') groupp.add_argument('--nomakepdf', '--no-makepdf', help=('do not make PDF output%s' % (' (default)' if not dopdf else '')), action='store_true') groupm = parser.add_mutually_exclusive_group() if 'makemd' in configs: domd = configs.getboolean('makemd') else: domd = True groupm.add_argument('--makemd', help=('make Markdown output%s' % (' (default)' if domd else '')), action='store_true') groupm.add_argument('--nomakemd', '--no-makemd', help=('do not Markdown output%s' % (' (default)' if not domd else '')), action='store_true') if 'texfilter' in configs: conftexfilter = configs['texfilter'] else: conftexfilter = None parser.add_argument('--texfilter', help=('filter to run on LaTeX file%s' % (' (default %s)' % conftexfilter if conftexfilter else ''))) if 'mdfilter' in configs: confmdfilter = configs['mdfilter'] else: confmdfilter = None parser.add_argument('--mdfilter', help=('filter to run on Markdown file%s' % (' (default %s)' % confmdfilter if confmdfilter else ''))) args = parser.parse_args() if args.puzfile[-5:] == '.yaml': puzfile = args.puzfile else: puzfile = args.puzfile + '.yaml' puzbase = puzfile[:-5] # We bundle the command-line args into an options dict options = dict() if args.output: if os.path.dirname(args.output) not in ['', '.']: sys.exit('Cannot currently handle --output not in current ' 'directory;\nplease change directory first') options['output'] = args.output if args.makepdf: options['makepdf'] = True elif args.nomakepdf: options['makepdf'] = False if args.makemd: options['makemd'] = True elif args.nomakemd: options['makemd'] = False if args.latex: options['latex'] = args.latex if args.clean: options['clean'] = True elif args.noclean: options['clean'] = False if args.texfilter != None: options['texfilter'] = args.texfilter if args.mdfilter != None: options['mdfilter'] = args.mdfilter ### Read the puzzle file try: infile = open(puzfile) except: sys.exit('Cannot open %s for reading' % puzfile) try: data = load(infile, Loader=Loader) except yaml.YAMLError as exc: if hasattr(exc, 'problem_mark'): mark = exc.problem_mark sys.exit('Error parsing puzzle data file\n' 'Error position: line %s, column %s' % (mark.line+1, mark.column+1)) # Determine where the templates files live # We use user_config_dir as I think this is configuration data, # not general package data. See the end of the page # https://wiki.debian.org/XDGBaseDirectorySpecification which indicates # that data should not be managed via VCS, whereas config should be; # this alone qualifies templates to be considered config. # However, the package templates are not configurations which should # be modified by the user; they go with the package. Users can modify # templates by providing their own ones, hence site_data_dir is the # appropriate site choice. generate(data, {'puzbase': puzbase, 'templatedirs': templatedirs, 'filterdirs': filterdirs, 'options': options, 'config': configs}) def generate(data, options): """Generate output from data, using options passed to this function. Thus function is presently called from main(), but might well be called from a GUI at some point in the future, which is why it has been separated out. When this function is called, data must contain a recognised jigsaw type, and the options dictionary must contain an entry 'puzbase' with the file basename for this particular puzzle. """ # Open template files and layout file. if 'type' in data: puztype = data['type'] try: layoutf = opentemplate(options['templatedirs'], puztype + '-layout.yaml') except: sys.exit('Unrecognised jigsaw type %s' % data['type']) else: sys.exit('No jigsaw type found in puzzle file') try: layout = load(layoutf, Loader=Loader) except yaml.YAMLError as exc: if hasattr(exc, 'problem_mark'): mark = exc.problem_mark sys.exit('Error parsing puzzle layout file %s.yaml\n' 'Error position: line %s, column %s' % (puztype, mark.line+1, mark.column+1)) category = layout['category'] try: generator = { 'jigsaw': generate_jigsaw, 'cardsort': generate_cardsort, 'dominoes': generate_cardsort }[category] except KeyError: sys.exit('Unrecognised category in %s layout file: %s' % (puztype, category)) generator(data, options, layout) def generate_jigsaw(data, options, layout): """Generate output from data for jigsaw-type puzzles.""" puzbase = options['puzbase'] templatedirs = options['templatedirs'] try: outbase = options['options']['output'] except KeyError: outbase = os.path.basename(puzbase) bodypuzfile = getopt(layout, data, {}, 'puzzleTemplateTeX') makepdf = getopt(layout, data, options, 'makepdf', True) makemd = getopt(layout, data, options, 'makemd', True) if makepdf and bodypuzfile: headerfile = getopt(layout, data, {}, 'puzzleHeaderTeX') if headerfile: bodypuz = opentemplate(templatedirs, bodypuzfile).read() outpuzfile = outbase + '-puzzle.tex' outpuz = open(outpuzfile, 'w') header = opentemplate(templatedirs, headerfile).read() print(header, file=outpuz) puzzletex = True else: print('puzzleTemplateTeX file specified but not puzzleHeaderTeX', file=sys.stderr) puzzletex = False else: puzzletex = False bodysolfile = getopt(layout, data, {}, 'solutionTemplateTeX') if makepdf and bodysolfile: headerfile = getopt(layout, data, {}, 'solutionHeaderTeX') if headerfile: bodysol = opentemplate(templatedirs, bodysolfile).read() outsolfile = outbase + '-solution.tex' outsol = open(outsolfile, 'w') header = opentemplate(templatedirs, headerfile).read() print(header, file=outsol) solutiontex = True else: print('solutionTemplateTeX file specified ' 'but not solutionHeaderTeX', file=sys.stderr) solutiontex = False else: solutiontex = False bodytablefile = getopt(layout, data, {}, 'tableTemplateTeX') if makepdf and bodytablefile: headerfile = getopt(layout, data, {}, 'tableHeaderTeX') if headerfile: bodytable = opentemplate(templatedirs, bodytablefile).read() outtablefile = outbase + '-table.tex' outtable = open(outtablefile, 'w') header = opentemplate(templatedirs, headerfile).read() print(header, file=outtable) tabletex = True else: print('tableTemplateTeX file specified but not tableHeaderTeX', file=sys.stderr) tabletex = False else: tabletex = False bodypuzmdfile = getopt(layout, data, {}, 'puzzleTemplateMarkdown') if makemd and bodypuzmdfile: headerfile = getopt(layout, data, {}, 'puzzleHeaderMarkdown') if headerfile: bodypuzmd = opentemplate(templatedirs, bodypuzmdfile).read() outpuzmdfile = outbase + '-puzzle.md' outpuzmd = open(outpuzmdfile, 'w') header = opentemplate(templatedirs, headerfile).read() print(header, file=outpuzmd) puzzlemd = True else: print('puzzleTemplateMarkdown file specified ' 'but not puzzleHeaderMarkdown', file=sys.stderr) puzzlemd = False else: puzzlemd = False bodysolmdfile = getopt(layout, data, {}, 'solutionTemplateMarkdown') if makemd and bodysolmdfile: headerfile = getopt(layout, data, {}, 'solutionHeaderMarkdown') if headerfile: bodysolmd = opentemplate(templatedirs, bodysolmdfile).read() outsolmdfile = outbase + '-solution.md' outsolmd = open(outsolmdfile, 'w') header = opentemplate(templatedirs, headerfile).read() print(header, file=outsolmd) solutionmd = True else: print('solutionTemplateMarkdown file specified ' 'but not solutionHeaderMarkdown', file=sys.stderr) solutionmd = False else: solutionmd = False # These dicts will contain the substitutions needed for the # template files; the first is for the LaTeX output files, the # second is for the Markdown output files. # The Markdown output files are much simpler, as they are intended # to be embedded in larger documents, for those who cannot access # the PDF files. dsubs = {} dsubsmd = {} if 'title' in data: dsubs['title'] = data['title'] else: dsubs['title'] = '' random.seed(dsubs['title']) # Read the card content # Three types of cards: pairs, edges, cards (which are single cards # for sorting activities, and do not appear in jigsaw types) if 'pairs' in layout: if 'pairs' in data: pairs = data['pairs'] if layout['pairs'] == 0: # which means any number of pairs if len(pairs) == 0: sys.exit('Puzzle type %s needs at least one pair' % layout['typename']) else: if len(pairs) != layout['pairs']: sys.exit('Puzzle type %s needs exactly %s pairs' % (layout['typename'], layout['pairs'])) else: sys.exit('Puzzle type %s requires pairs in data file' % layout['typename']) elif 'pairs' in data: sys.exit('Puzzle type %s does not accept pairs in data file' % layout['typename']) else: pairs = [] # so that later bits of code don't barf if 'edges' in layout: if 'edges' in data: edges = data['edges'] if len(edges) > layout['edges']: print('Warning: more than %s edges given; ' 'extra will be ignored' % layout['edges'], file=sys.stderr) edges = edges[:layout['edges']] elif len(edges) < layout['edges']: print('Warning: fewer than %s edges given; ' 'remainder will be blank' % layout['edges'], file=sys.stderr) edges += [''] * (layout['edges'] - len(edges)) else: edges = [''] * layout['edges'] elif 'edges' in data: sys.exit('Puzzle type %s does not accept edges in data file' % layout['typename']) else: edges = [] # so that later bits of code don't barf if 'cards' in data: sys.exit('Puzzle type %s does not accept cards in data file' % layout['typename']) cards = [] # so later call to make_table doesn't break if getopt(layout, data, {}, 'shufflePairs'): random.shuffle(pairs) if getopt(layout, data, {}, 'shuffleEdges'): random.shuffle(edges) # We preserve the original pairs data for the table; we only flip # the questions and answers (if requested) for the puzzle cards if getopt(layout, data, {}, 'flip'): flippedpairs = [] for p in pairs: if random.choice([True, False]): flippedpairs.append([p[1], p[0]]) else: flippedpairs.append([p[0], p[1]]) else: flippedpairs = pairs # The following calls will add the appropriate substitution # variables to dsubs and dsubsmd global exists_hidden exists_hidden = False if tabletex or solutionmd: make_table(pairs, edges, cards, dsubs, dsubsmd) if 'triangleSolutionCards' in layout: make_triangles(data, layout, flippedpairs, edges, dsubs, dsubsmd) if 'squareSolutionCards' in layout: make_squares(data, layout, flippedpairs, edges, dsubs, dsubsmd) if exists_hidden: hiddennote = getopt(layout, data, {}, 'hiddennote', 'Entries that are hidden in the puzzle are highlighted in yellow.') hiddennotemd = getopt(layout, data, {}, 'hiddennotemd', 'Entries that are hidden in the puzzle are indicated with (*).') hiddennotetable = getopt(layout, data, {}, 'hiddennotetable', hiddennotemd) dsubs['hiddennotesolution'] = hiddennote dsubs['hiddennotetable'] = hiddennotetable dsubsmd['hiddennotemd'] = hiddennotemd else: dsubs['hiddennotesolution'] = '' dsubs['hiddennotetable'] = '' dsubsmd['hiddennotemd'] = '' dsubs['puzzlenote'] = getopt(layout, data, {}, 'note', '') dsubsmd['puzzlenote'] = getopt(layout, data, {}, 'note', '') if tabletex: btext = dosub(bodytable, dsubs) print(btext, file=outtable) outtable.close() runlatex(outtablefile, layout, data, options) if puzzletex: ptext = dosub(bodypuz, dsubs) print(ptext, file=outpuz) outpuz.close() runlatex(outpuzfile, layout, data, options) if solutiontex: stext = dosub(bodysol, dsubs) print(stext, file=outsol) outsol.close() runlatex(outsolfile, layout, data, options) if puzzlemd: ptextmd = dosub(bodypuzmd, dsubsmd) print(ptextmd, file=outpuzmd) outpuzmd.close() filtermd(outpuzmdfile, layout, data, options) if solutionmd: stextmd = dosub(bodysolmd, dsubsmd) print(stextmd, file=outsolmd) outsolmd.close() filtermd(outsolmdfile, layout, data, options) def generate_cardsort(data, options, layout): """Generate cards for a cardsort or domino activity""" puzbase = options['puzbase'] templatedirs = options['templatedirs'] try: outbase = options['options']['output'] except KeyError: outbase = os.path.basename(puzbase) category = layout['category'] if category == 'cardsort': dosoln = getopt(layout, data, {}, 'produceSolution', True) else: dosoln = True bodypuzfile = getopt(layout, data, {}, 'puzzleTemplateTeX') makepdf = getopt(layout, data, options, 'makepdf', True) makemd = getopt(layout, data, options, 'makemd', True) if makepdf and bodypuzfile: headerfile = getopt(layout, data, {}, 'puzzleHeaderTeX') if headerfile: bodypuz = opentemplate(templatedirs, bodypuzfile).read() outpuzfile = outbase + '-puzzle.tex' outpuz = open(outpuzfile, 'w') header = opentemplate(templatedirs, headerfile).read() print(header, file=outpuz) puzzletex = True else: print('puzzleTemplateTeX file specified but not puzzleHeaderTeX', file=sys.stderr) puzzletex = False else: puzzletex = False if dosoln: bodysolfile = getopt(layout, data, {}, 'solutionTemplateTeX') if makepdf and bodysolfile: headerfile = getopt(layout, data, {}, 'solutionHeaderTeX') if headerfile: bodysol = opentemplate(templatedirs, bodysolfile).read() outsolfile = outbase + '-solution.tex' outsol = open(outsolfile, 'w') header = opentemplate(templatedirs, headerfile).read() print(header, file=outsol) solutiontex = True else: print('solutionTemplateTeX file specified ' 'but not solutionHeaderTeX', file=sys.stderr) solutiontex = False else: solutiontex = False else: solutiontex = False bodytablefile = getopt(layout, data, {}, 'tableTemplateTeX') if makepdf and bodytablefile: headerfile = getopt(layout, data, {}, 'tableHeaderTeX') if headerfile: bodytable = opentemplate(templatedirs, bodytablefile).read() outtablefile = outbase + '-table.tex' outtable = open(outtablefile, 'w') header = opentemplate(templatedirs, headerfile).read() print(header, file=outtable) tabletex = True else: print('tableTemplateTeX file specified but not tableHeaderTeX', file=sys.stderr) tabletex = False else: tabletex = False bodypuzmdfile = getopt(layout, data, {}, 'puzzleTemplateMarkdown') if makemd and bodypuzmdfile: headerfile = getopt(layout, data, {}, 'puzzleHeaderMarkdown') if headerfile: bodypuzmd = opentemplate(templatedirs, bodypuzmdfile).read() outpuzmdfile = outbase + '-puzzle.md' outpuzmd = open(outpuzmdfile, 'w') header = opentemplate(templatedirs, headerfile).read() print(header, file=outpuzmd) puzzlemd = True else: print('puzzleTemplateMarkdown file specified ' 'but not puzzleHeaderMarkdown', file=sys.stderr) puzzlemd = False else: puzzlemd = False if dosoln: bodysolmdfile = getopt(layout, data, {}, 'solutionTemplateMarkdown') if makemd and bodysolmdfile: headerfile = getopt(layout, data, {}, 'solutionHeaderMarkdown') if headerfile: bodysolmd = opentemplate(templatedirs, bodysolmdfile).read() outsolmdfile = outbase + '-solution.md' outsolmd = open(outsolmdfile, 'w') header = opentemplate(templatedirs, headerfile).read() print(header, file=outsolmd) solutionmd = True else: print('solutionTemplateMarkdown file specified ' 'but not solutionHeaderMarkdown', file=sys.stderr) solutionmd = False else: solutionmd = False else: solutionmd = False # Templates for card sorts are a little more complex than for # jigsaws, as the TeX version needs explicit blocks for start of # document, start of page, end of page and end of document. The # Markdown version likewise has a template for each item, so that # styling needs - for example, that each card should live inside a #
or element - can be handled. # So the TeX template must have the form: # %%% BEGIN DOCUMENT # ... # %%% BEGIN PAGE # ... # %%% BEGIN ITEM # ... # %%% END PAGE # ... # %%% END DOCUMENT # ... # And the Markdown template has the form: # ### BEGIN DOCUMENT # ... # ### BEGIN ITEM # ... # ### END DOCUMENT # ... # Any content before the initial '%%% BEGIN DOCUMENT' will be # ignored. Also, the '%%%' or '###' must appear at the start of a # line, and anything trailing content following the 'BEGIN # DOCUMENT' etc. will be ignored. # The "item" section for card sorts would normally consist of the # single line something like: # # \card{<: rownum :>}{<: colnum :>}{<: cardnum :>}{<: text :>}{<: label :>} # where the rownum and colnum are clear, the card number will be # from 1 upwards in order in the puzzle, and the content is the # actual text (with size and hidden indicators as with the # jigsaw), and \card is an appropriate TeX command which typesets # the requested card. The Markdown "item" section is likewise # substituted with these variables. # For dominoes, essentially the same is true, except that the # macro has 7 arguments, the last four being textL, textR, labelL, # labelR, being the text for the left and right halves of the # domino and the labels for the same. # The cards will be produced from top (row 1) to bottom (row n) # and in each row from left (column 1) to right (column m). After # the final card on a page, and also after all the cards are used # up, the end page content will be output (but only once if the # final card occurs at the end of a page), and before the first # card of a page, the begin page content will be output. puztemplate = {} puztemplatemd = {} soltemplate = {} soltemplatemd = {} if puzzletex: templatematch = re.search('^%%% BEGIN DOCUMENT.*?^(.*?)' '^%%% BEGIN PAGE.*?^(.*?)' '^%%% BEGIN ITEM.*?^(.*?)' '^%%% END PAGE.*?^(.*?)' '^%%% END DOCUMENT.*?^(.*)', bodypuz, re.M | re.S) if templatematch: puztemplate['begin_document'] = templatematch.group(1) puztemplate['begin_page'] = templatematch.group(2) puztemplate['item'] = templatematch.group(3) puztemplate['end_page'] = templatematch.group(4) puztemplate['end_document'] = templatematch.group(5) else: sys.exit('TeX puzzle template does not have required structure') if dosoln: templatematch = re.search('^%%% BEGIN DOCUMENT.*?^(.*?)' '^%%% BEGIN PAGE.*?^(.*?)' '^%%% BEGIN ITEM.*?^(.*?)' '^%%% END PAGE.*?^(.*?)' '^%%% END DOCUMENT.*?^(.*)', bodysol, re.M | re.S) if templatematch: soltemplate['begin_document'] = templatematch.group(1) soltemplate['begin_page'] = templatematch.group(2) soltemplate['item'] = templatematch.group(3) soltemplate['end_page'] = templatematch.group(4) soltemplate['end_document'] = templatematch.group(5) else: sys.exit('TeX solution template does not have ' 'required structure') if puzzlemd: templatemdmatch = re.search('^### BEGIN DOCUMENT.*?$(.*?)' '^### BEGIN ITEM.*?$(.*?)' '^### END DOCUMENT.*?$(.*)', bodypuzmd, re.M | re.S) if templatemdmatch: puztemplatemd['begin_document'] = templatemdmatch.group(1) puztemplatemd['item'] = templatemdmatch.group(2) puztemplatemd['end_document'] = templatemdmatch.group(3) else: sys.exit('Markdown puzzle template does not have ' 'required structure') if dosoln: templatemdmatch = re.search('^### BEGIN DOCUMENT.*?$(.*?)' '^### BEGIN ITEM.*?$(.*?)' '^### END DOCUMENT.*?$(.*)', bodysolmd, re.M | re.S) if templatemdmatch: soltemplatemd['begin_document'] = templatemdmatch.group(1) soltemplatemd['item'] = templatemdmatch.group(2) soltemplatemd['end_document'] = templatemdmatch.group(3) else: sys.exit('Markdown solution template does not have ' 'required structure') # These dicts will contain the substitutions needed for the # template files; the first is for the LaTeX output files, the # second is for the Markdown output files. These are only used # for the document and page templates; we use separate ones for # each item. # The Markdown output files are much simpler, as they are intended # to be embedded in larger documents, for those who cannot access # the PDF files. dsubs = {} dsubsmd = {} if 'title' in data: dsubs['title'] = data['title'] else: dsubs['title'] = '' random.seed(dsubs['title']) # Read the card content # Two types of cards for cardsort-like puzzles: pairs (for domino # cards) and cards (which are single cards for sorting # activities); edges do not appear in this sort of activity if 'pairs' in layout: if 'pairs' in data: pairs = data['pairs'] if layout['pairs'] == 0: # which means any number of pairs if len(pairs) == 0: sys.exit('Puzzle type %s needs at least one pair' % layout['typename']) else: if len(pairs) != layout['pairs']: sys.exit('Puzzle type %s needs exactly %s pairs' % (layout['typename'], layout['pairs'])) else: sys.exit('Puzzle type %s requires pairs in data file' % layout['typename']) elif 'pairs' in data: sys.exit('Puzzle type %s does not accept pairs in data file' % layout['typename']) else: pairs = [] # so that later bits of code don't barf if 'edges' in data: sys.exit('Puzzle type %s does not accept edges in data file' % layout['typename']) edges = [] # so that later bits of code don't barf if 'cards' in layout: if 'cards' in data: cards = data['cards'] if layout['cards'] == 0: # which means any number of cards if len(cards) == 0: sys.exit('Puzzle type %s needs at least one card' % layout['typename']) else: if len(cards) != layout['cards']: sys.exit('Puzzle type %s needs exactly %s cards' % (layout['typename'], layout['cards'])) else: sys.exit('Puzzle type %s requires cards in data file' % layout['typename']) elif 'cards' in data: sys.exit('Puzzle type %s does not accept cards in data file' % layout['typename']) else: cards = [] # so that later bits of code don't barf # We don't shuffle the cards yet, as we need the original order # for the solution and table. Shuffling pairs is fine, though, as # their original order is immaterial if shufflePairs is requested. if getopt(layout, data, {}, 'shufflePairs'): random.shuffle(pairs) # We preserve the original pairs data for the table; we only flip # the questions and answers (if requested) for the puzzle cards if getopt(layout, data, {}, 'flip'): flippedpairs = [] for p in pairs: if random.choice([True, False]): flippedpairs.append([p[1], p[0]]) else: flippedpairs.append([p[0], p[1]]) else: flippedpairs = pairs # The following calls will add the appropriate substitution # variables to dsubs and dsubsmd global exists_hidden exists_hidden = False if tabletex: make_table(pairs, edges, cards, dsubs, dsubsmd) if layout['category'] == 'cardsort': make_cardsort_cards(data, layout, options, cards, puztemplate, soltemplate, puztemplatemd, soltemplatemd, dsubs, dsubsmd) else: make_domino_cards(data, layout, options, flippedpairs, puztemplate, soltemplate, puztemplatemd, soltemplatemd, dsubs, dsubsmd) if exists_hidden: hiddennote = getopt(layout, data, {}, 'hiddennote', 'Entries that are hidden in the puzzle are highlighted in yellow.') hiddennotemd = getopt(layout, data, {}, 'hiddennotemd', 'Entries that are hidden in the puzzle are indicated with (*).') hiddennotetable = getopt(layout, data, {}, 'hiddennotetable', hiddennotemd) dsubs['hiddennotesolution'] = hiddennote dsubs['hiddennotetable'] = hiddennotetable dsubsmd['hiddennotemd'] = hiddennotemd else: dsubs['hiddennotesolution'] = '' dsubs['hiddennotetable'] = '' dsubsmd['hiddennotemd'] = '' dsubs['puzzlenote'] = getopt(layout, data, {}, 'note', '') dsubsmd['puzzlenote'] = getopt(layout, data, {}, 'note', '') dsubs['puzbody'] = dosub(dsubs['puzbody'], dsubs) dsubsmd['puzbody'] = dosub(dsubsmd['puzbody'], dsubsmd) if dosoln: dsubs['solbody'] = dosub(dsubs['solbody'], dsubs) dsubsmd['solbody'] = dosub(dsubsmd['solbody'], dsubsmd) if tabletex: btext = dosub(bodytable, dsubs) print(btext, file=outtable) outtable.close() runlatex(outtablefile, layout, data, options) if puzzletex: print(dsubs['puzbody'], file=outpuz) outpuz.close() runlatex(outpuzfile, layout, data, options) if solutiontex: print(dsubs['solbody'], file=outsol) outsol.close() runlatex(outsolfile, layout, data, options) if puzzlemd: print(dsubsmd['puzbody'], file=outpuzmd) outpuzmd.close() filtermd(outpuzmdfile, layout, data, options) if solutionmd: print(dsubsmd['solbody'], file=outsolmd) outsolmd.close() filtermd(outsolmdfile, layout, data, options) # This allows this script to be invoked directly and also perhap for # the functions to be called via a GUI if __name__ == '__main__': main() jigsaw-generator-0.2.7/templates/000077500000000000000000000000001401032735100167625ustar00rootroot00000000000000jigsaw-generator-0.2.7/templates/cards-layout.yaml000066400000000000000000000023451401032735100222610ustar00rootroot00000000000000# Template file for generic card sort activity format: 1 category: cardsort type: cards typename: unsorted cards puzzleHeaderTeX: template-cardsort-header.tex puzzleTemplateTeX: template-cardsort-puzzle.tex solutionHeaderTeX: template-cardsort-header.tex solutionTemplateTeX: template-cardsort-solution.tex tableHeaderTeX: template-header.tex tableTemplateTeX: template-cardsort-table.tex puzzleHeaderMarkdown: template-header.md puzzleTemplateMarkdown: template-cardsort-puzzle.md solutionHeaderMarkdown: template-header.md solutionTemplateMarkdown: template-cardsort-solution.md # We accept an arbitrary number of cards cards: 0 # size of puzzle should be specified in the puzzle file - we just give # a fallback here rows: 6 columns: 2 # Do we shuffle the order of the cards from the order given when # producing the problem? Say "true" for a proof sorting activity. # It probably does not make sense to say "false" here but still to # produce a solution. shuffleCards: false # Does this puzzle require production of a solution? If so, the cards # must be given in the correct order initially. produceSolution: false # Do we number the cards? numberCards: true # Default text size on cards textSize: 5 # Default label size on cards labelSize: 3 jigsaw-generator-0.2.7/templates/cardsort-layout.yaml000066400000000000000000000023411401032735100230020ustar00rootroot00000000000000# Template file for generic card sort activity format: 1 category: cardsort type: cardsort typename: card sort puzzleHeaderTeX: template-cardsort-header.tex puzzleTemplateTeX: template-cardsort-puzzle.tex solutionHeaderTeX: template-cardsort-header.tex solutionTemplateTeX: template-cardsort-solution.tex tableHeaderTeX: template-header.tex tableTemplateTeX: template-cardsort-table.tex puzzleHeaderMarkdown: template-header.md puzzleTemplateMarkdown: template-cardsort-puzzle.md solutionHeaderMarkdown: template-header.md solutionTemplateMarkdown: template-cardsort-solution.md # We accept an arbitrary number of cards cards: 0 # size of puzzle should be specified in the puzzle file - we just give # a fallback here rows: 6 columns: 2 # Do we shuffle the order of the cards from the order given when # producing the problem? Say "true" for a proof sorting activity. # It probably does not make sense to say "false" here but still to # produce a solution. shuffleCards: true # Does this puzzle require production of a solution? If so, the cards # must be given in the correct order initially. produceSolution: true # Do we number the cards? numberCards: true # Default text size on cards textSize: 5 # Default label size on cards labelSize: 3 jigsaw-generator-0.2.7/templates/default_config.ini000066400000000000000000000015571401032735100224440ustar00rootroot00000000000000# These are the default settings for jigsaw-generate. [jigsaw-generate] # Should we make a pdf output file? # # makepdf = yes # Should we make a Markdown output file? # # makemd = yes # Which LaTeX engine do we use? # # latex = pdflatex # Should we delete the temporary files after a successful run? # # clean = yes # Should we pass the LaTeX file through any filter prior to # running pdflatex (or other engine) on it? # This program must take the LaTeX file on its standard input # and produce the filtered file on its standard output. # The program must be either in the current directory or in the # jigsaw-generate filters directory (either within the user's config # directory or in the software's filters directory). # # texfilter = # Should we pass the Markdown output through any filter? The same # conditions apply to this as to the texfilter. # # mdfilter = jigsaw-generator-0.2.7/templates/dominoes-layout.yaml000066400000000000000000000023651401032735100230040ustar00rootroot00000000000000# Template file for generic card sort activity format: 1 category: dominoes type: dominoes typename: dominoes puzzleHeaderTeX: template-cardsort-header.tex puzzleTemplateTeX: template-domino-puzzle.tex solutionHeaderTeX: template-cardsort-header.tex solutionTemplateTeX: template-domino-solution.tex tableHeaderTeX: template-header.tex tableTemplateTeX: template-domino-table.tex puzzleHeaderMarkdown: template-header.md puzzleTemplateMarkdown: template-domino-puzzle.md solutionHeaderMarkdown: template-header.md solutionTemplateMarkdown: template-domino-solution.md # We accept an arbitrary number of pairs pairs: 0 # size of puzzle should be specified in the puzzle file - we just give # a fallback here rows: 6 columns: 2 # Do we shuffle the order of the pairs from the order given when # producing the problem? shufflePairs: false # Do we randomly flip (swap) individual questions and answers (the # contents of the pairs) on the puzzle? flip: false # Do we have "start" and "finish" cards (loop: false) or do the cards # go in a complete loop (loop: true)? loop: false # And if we do, how will they be labelled? start: Start finish: Finish # Do we number the cards? numberCards: true # Default text size on cards (including sentinel cards, if any) textSize: 5 jigsaw-generator-0.2.7/templates/hexagon-layout.yaml000066400000000000000000000036571401032735100226250ustar00rootroot00000000000000# Template file for large hexagon jigsaw format: 1 category: jigsaw type: hexagon typename: hexagon puzzleHeaderTeX: template-header.tex puzzleTemplateTeX: template-hexagon-puzzle.tex solutionHeaderTeX: template-header.tex solutionTemplateTeX: template-hexagon-solution.tex tableHeaderTeX: template-header.tex tableTemplateTeX: template-table.tex puzzleHeaderMarkdown: template-header.md puzzleTemplateMarkdown: template-jigsaw-puzzle3.md solutionHeaderMarkdown: template-header.md solutionTemplateMarkdown: template-jigsaw-solution.md pairs: 30 edges: 12 # Do we shuffle the order of the pairs from the order given? shufflePairs: false # Do we randomly flip (swap) individual questions and answers (the # contents of the pairs) on the jigsaw? flip: true # Do we shuffle the order of the edges from the order given? shuffleEdges: false # Default text size on puzzle pieces puzzleTextSize: 5 # Default text size on solution pieces solutionTextSize: 3 # Do we number the pieces? numberCards: true triangleSolutionCards: - [A18, Q1, E1] - [E12, A1, Q2] - [Q19, Q3, A2] - [E11, A3, Q4] - [Q5, E10, A4] - [A16, Q17, E2] - [Q18, A17, Q24] - [A30, Q25, A24] - [A19, A25, Q26] - [Q27, A20, A26] - [A5, Q20, Q6] - [Q7, E9, A6] - [Q16, E3, A15] - [A14, Q23, Q15] - [Q30, A23, A29] - [A22, A28, Q29] - [A27, Q28, A21] - [Q9, A8, Q21] - [A7, Q8, E8] - [Q14, E4, A13] - [E5, A12, Q13] - [Q22, Q12, A11] - [E6, A10, Q11] - [A9, Q10, E7] triangleSolutionOrientation: [0, 180, 0, 180, 0, 0, 180, 0, 180, 0, 180, 0, 180, 0, 180, 0, 180, 0, 180, 180, 0, 180, 0, 180] trianglePuzzleOrientation: - [90, -30] - [270, 30] - [90, -30] - [270, 30] - [270, 30] - [90, -30] - [270, 30] - [90, -30] - [90, -30] - [270, 30] - [90, -30] - [270, 30] - [270, 30] - [90, -30] - [270, 30] - [90, -30] - [90, -30] - [270, 30] - [90, -30] - [270, 30] - [270, 30] - [90, -30] - [270, 30] - [90, -30] jigsaw-generator-0.2.7/templates/parquet-layout.yaml000066400000000000000000000030751401032735100226470ustar00rootroot00000000000000# Template file for parquet jigsaw format: 1 category: jigsaw type: parquet typename: parquet puzzleHeaderTeX: template-header.tex puzzleTemplateTeX: template-parquet-puzzle.tex solutionHeaderTeX: template-header.tex solutionTemplateTeX: template-parquet-solution.tex tableHeaderTeX: template-header.tex tableTemplateTeX: template-table.tex puzzleHeaderMarkdown: template-header.md puzzleTemplateMarkdown: template-jigsaw-puzzle4.md solutionHeaderMarkdown: template-header.md solutionTemplateMarkdown: template-jigsaw-solution.md pairs: 15 edges: 10 # Do we shuffle the order of the pairs from the order given? shufflePairs: false # Do we randomly flip (swap) individual questions and answers (the # contents of the pairs) on the jigsaw? flip: true # Do we shuffle the order of the edges from the order given? shuffleEdges: false # Default text size on puzzle pieces puzzleTextSize: 5 # Default text size on solution pieces solutionTextSize: 4 # Do we number the pieces? numberCards: true triangleSolutionCards: - [A1, Q2, E10] - [E8, A3, Q4] - [Q6, E6, A5] - [A6, Q7, E5] - [E3, A8, Q9] - [Q1, E1, A10] - [Q15, A11, A14] - [A15, A13, A12] triangleSolutionOrientation: [270, 90, 270, 90, 270, 90, 0, 180] squareSolutionCards: - [Q3, E9, A2, Q11] - [Q5, E7, A4, Q12] - [A7, Q13, Q8, E4] - [A9, Q14, Q10, E2] squareSolutionOrientation: [30, -30, 30, -30] trianglePuzzleOrientation: - [90, -30] - [270, 30] - [90, -30] - [270, 30] - [270, 30] - [90 , -30] - [270, 30] - [90, -30] squarePuzzleOrientation: - [0, 0] - [0, 0] - [0, 0] - [0, 0] jigsaw-generator-0.2.7/templates/smallhexagon-layout.yaml000066400000000000000000000024361401032735100236500ustar00rootroot00000000000000# Template file for smallhexagon jigsaw format: 1 category: jigsaw type: smallhexagon typename: small hexagon puzzleHeaderTeX: template-header.tex puzzleTemplateTeX: template-smallhexagon-puzzle.tex solutionHeaderTeX: template-header.tex solutionTemplateTeX: template-smallhexagon-solution.tex tableHeaderTeX: template-header.tex tableTemplateTeX: template-table.tex puzzleHeaderMarkdown: template-header.md puzzleTemplateMarkdown: template-jigsaw-puzzle3.md solutionHeaderMarkdown: template-header.md solutionTemplateMarkdown: template-jigsaw-solution.md pairs: 6 edges: 6 # Do we shuffle the order of the pairs from the order given? shufflePairs: false # Do we randomly flip (swap) individual questions and answers (the # contents of the pairs) on the jigsaw? flip: true # Do we shuffle the order of the edges from the order given? shuffleEdges: false # Default text size on puzzle pieces puzzleTextSize: 7 # Default text size on solution pieces solutionTextSize: 7 # Do we number the pieces? numberCards: true triangleSolutionCards: - [A1, Q2, E6] - [E5, A2, Q3] - [Q4, E4, A3] - [A4, Q5, E3] - [E2, A5, Q6] - [Q1, E1, A6] triangleSolutionOrientation: [270, 90, 270, 90, 270, 90] trianglePuzzleOrientation: - [270, 30] - [90, -30] - [270, 30] - [90, -30] - [270, 30] - [90, -30] jigsaw-generator-0.2.7/templates/template-cardsort-header.tex000066400000000000000000000144321401032735100243700ustar00rootroot00000000000000\documentclass[12pt,a4paper]{article} \usepackage{geometry} \geometry{% a4paper, lmargin=1.7cm, rmargin=1.7cm, tmargin=4cm, bmargin=2cm, footskip=0pt, headheight=2cm} \usepackage{amsmath} \usepackage{amssymb} \let\ge=\geqslant \let\le=\leqslant \usepackage{calc} \usepackage{tikz}[2013/12/13 v3.0.0] \usetikzlibrary{calc} \tikzset{above/.default=6pt} \tikzset{regular/.style={}} \tikzset{hidden/.style={fill=yellow!80!white}} \usepackage{fancyhdr} \pagestyle{fancy} \fancyhead{} \fancyfoot{} \renewcommand{\headrulewidth}{0pt} \renewcommand{\footrulewidth}{0pt} \usepackage{lastpage} \usepackage{ifthen} % The baseline spacing is quite small for larger fonts \makeatletter \renewcommand\large{\@setfontsize\large\@xivpt{20}} \renewcommand\Large{\@setfontsize\Large\@xviipt{24.5}} \renewcommand\LARGE{\@setfontsize\LARGE\@xxpt{28}} \renewcommand\huge{\@setfontsize\huge\@xxvpt{34}} \makeatother \newsavebox\templateimagebox \newdimen\templateimagewd \newif\iftesting % say \testingtrue to have \card use simple % parameters like {Q1} instead of {{regular}{Q1}} \usepackage[export]{adjustbox} \newcommand{\image}[1]{\includegraphics[max height=0.7\cardht, max width=0.7\cardwd]{#1}} % There might be a nicer way to do the following, but I haven't yet % found it. \newcommand{\imagecap}[2]{% \savebox{\templateimagebox}{\includegraphics[max height=0.8\cardht, max width=0.8\cardwd]{#1}}% \setlength{\templateimagewd}{\wd\templateimagebox}% \hbox to \templateimagewd{% \begin{minipage}{\templateimagewd}% \usebox{\templateimagebox}\\ \hbox to \templateimagewd{\hss #2\hss}% \end{minipage}}} \newcommand{\makestyles}[3]{% \iftesting \def#1{regular} \def#2{#3} \else % split #3 into {style}{text} \makestylesa#1#2#3 \fi } \newcommand{\makestylesa}[4]{% \def#1{#3} \def#2{#4} } % How much space should there be around the cards? % The gap between cards is twice this amount % This is zero by default, but can be modified by % users of this header. \newdimen\cardseph \setlength\cardseph{0pt} \newdimen\cardsepv \setlength\cardsepv{0pt} \newdimen\cardwd \newdimen\cardht \newdimen\cardtxtwd \newdimen\offset \setlength{\offset}{6mm} \setlength{\cardwd}{3cm} % defaults so table output works \setlength{\cardht}{2cm} % Card number #3 appears on row #1 column #2 with content #4 and label #5 % If card number is empty, don't draw circle around number % Top left is (0,0) in our drawing \newcommand{\card}[5]{% \coordinate (topl) at ($ (#2*\cardwd-\cardwd+\cardseph, \cardht-#1*\cardht-\cardsepv) $); \coordinate (botr) at ($ (#2*\cardwd-\cardseph, -#1*\cardht+\cardsepv) $); \coordinate (botl) at (topl |- botr); \coordinate (topr) at (topl -| botr); \def\templabel{#3} \ifx\templabel\empty \else \node[circle,draw,thin,inner sep=1pt] at ($ (topl) + (\offset,-\offset) $) {#3}; \fi \def\templabel{#5} \ifx\templabel\empty \else \node at ($ (botl)!0.5!(botr) + (0,\offset) $) {\templabel}; \fi \ifx\cardtitle\empty \else \node at ($ (topl)!0.5!(topr) + (0,-\offset) $) {\cardtitle}; \fi \ifx\cardtitle\empty \ifx\templabel\empty \coordinate (cent) at ($ (topl)!0.5!(botr) $); \else \coordinate (cent) at ($ (topl)!0.5!(botr) + (0,0.5*\offset)$); \fi \else \ifx\templabel\empty \coordinate (cent) at ($ (topl)!0.5!(botr) + (0,-0.5*\offset)$); \else \coordinate (cent) at ($ (topl)!0.5!(botr) $); \fi \fi \makestyles\style\content{#4} \draw (topl) rectangle (botr); \node[text width=\cardtxtwd,align=flush center,\style] at (cent) {\content\par}; } % This is identical to \card, except that it's intended for double-sided % cards, so it doesn't draw a border. \newcommand{\borderlesscard}[5]{% \coordinate (topl) at ($ (#2*\cardwd-\cardwd+\cardseph, \cardht-#1*\cardht-\cardsepv) $); \coordinate (botr) at ($ (#2*\cardwd-\cardseph, -#1*\cardht+\cardsepv) $); \coordinate (botl) at (topl |- botr); \coordinate (topr) at (topl -| botr); \def\templabel{#3} \ifx\templabel\empty \else \node[circle,draw,thin,inner sep=1pt] at ($ (topl) + (\offset,-\offset) $) {#3}; \fi \def\templabel{#5} \ifx\templabel\empty \else \node at ($ (botl)!0.5!(botr) + (0,\offset) $) {\templabel}; \fi \ifx\cardtitle\empty \else \node at ($ (topl)!0.5!(topr) + (0,-\offset) $) {\cardtitle}; \fi \ifx\cardtitle\empty \ifx\templabel\empty \coordinate (cent) at ($ (topl)!0.5!(botr) $); \else \coordinate (cent) at ($ (topl)!0.5!(botr) + (0,0.5*\offset)$); \fi \else \ifx\templabel\empty \coordinate (cent) at ($ (topl)!0.5!(botr) + (0,-0.5*\offset)$); \else \coordinate (cent) at ($ (topl)!0.5!(botr) $); \fi \fi \makestyles\style\content{#4} \node[text width=\cardtxtwd,align=flush center,\style] at (cent) {\content\par}; } % Domino number #3 appears on row #1 column #2 with left content #4, % right content #5 % If card number is empty, don't draw circle around number % Top left is (0,0) in our drawing \newcommand{\domino}[5]{% \coordinate (topl) at ($ (#2*\cardwd-\cardwd+\cardseph, \cardht-#1*\cardht-\cardsepv) $); \coordinate (botr) at ($ (#2*\cardwd-\cardseph, -#1*\cardht+\cardsepv) $); \coordinate (botl) at (topl |- botr); \coordinate (topr) at (topl -| botr); \coordinate (topm) at ($ (topl)!0.5!(topr) $); \coordinate (botm) at ($ (botl)!0.5!(botr) $); \draw (topl) rectangle (botr); \draw [divider] (topm) -- (botm); \ifx\cardtitle\empty \else \node[fill=white] at ($ (topl)!0.5!(topr) + (0,-\offset) $) {\cardtitle}; \fi \def\templabel{#3} \ifx\templabel\empty \else \node[circle,draw,thin,inner sep=1pt,fill=white] at ($ (topl)!0.5!(botr) $) {#3}; \fi \ifx\cardtitle\empty \coordinate (centl) at ($ (topl)!0.5!(botm) $); \coordinate (centr) at ($ (topm)!0.5!(botr) $); \else \coordinate (centl) at ($ (topl)!0.5!(botm) + (0,-0.5*\offset)$); \coordinate (centr) at ($ (topm)!0.5!(botr) + (0,-0.5*\offset)$); \fi \makestyles\stylel\contentl{#4} \makestyles\styler\contentr{#5} \node[text width=\cardtxtwd,align=flush center,\stylel] at (centl) {\contentl\par}; \node[text width=\cardtxtwd,align=flush center,\styler] at (centr) {\contentr\par}; } \setlength{\parindent}{0pt} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: jigsaw-generator-0.2.7/templates/template-cardsort-puzzle-borderless.tex000066400000000000000000000015241401032735100266310ustar00rootroot00000000000000% \input template-cardsort-header % \testingtrue %%% BEGIN DOCUMENT \chead{\begin{minipage}{\textwidth} \centering \textbf{<: title :>}\\[\smallskipamount] \small(Page \thepage\ of \pageref{LastPage})\\[\smallskipamount] \ <: puzzlenote :>\ \end{minipage}} \setlength\cardwd{\textwidth - 6pt} \setlength\cardwd{\cardwd / <: columns :>} \setlength\cardht{\textheight - 6pt} \setlength\cardht{\cardht / <: rows :>} \setlength\cardtxtwd{4\cardwd/5} % text = 80% of card width \tikzset{every picture/.style={line width=3pt}} \def\cardtitle{<: cardtitle :>} \begin{document} %%% BEGIN PAGE \begin{tikzpicture} %%% BEGIN ITEM \card{<: rownum :>}{<: colnum :>}{<: cardnum :>}{<: text :>}{<: label :>} %%% END PAGE \end{tikzpicture} \newpage %%% END DOCUMENT \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: jigsaw-generator-0.2.7/templates/template-cardsort-puzzle.md000066400000000000000000000003551401032735100242700ustar00rootroot00000000000000### BEGIN DOCUMENT <: puzzlenote :> | Row | Column | Card number | Card | Label | |:---:|:------:|:-----------:|:----:|:-----:| ### BEGIN ITEM | <: rownum :> | <: colnum :> | <: cardnum :> | <: text :> | <: label :> | ### END DOCUMENT jigsaw-generator-0.2.7/templates/template-cardsort-puzzle.tex000066400000000000000000000024671401032735100244760ustar00rootroot00000000000000% \input template-cardsort-header % \testingtrue %%% BEGIN DOCUMENT \chead{\begin{minipage}{\textwidth} \centering \textbf{<: title :>}\\[\smallskipamount] \small(Page \thepage\ of \pageref{LastPage})\\[\smallskipamount] \ <: puzzlenote :>\ \end{minipage}} % The card separation is given; we need to halve it to find % the amount of offset of the border on each side. % The 1.5pt (which is half of 3pt) is to take account of the % thickness of the card border. \ifthenelse{\lengthtest{<: cardseph :> > 0pt}} {\setlength\cardseph{<: cardseph :> / 2 + 1.5pt}} {\setlength\cardseph{0pt}} \ifthenelse{\lengthtest{<: cardsepv :> > 0pt}} {\setlength\cardsepv{<: cardsepv :> / 2 + 1.5pt}} {\setlength\cardsepv{0pt}} \setlength\cardwd{\textwidth - 6pt + 2\cardseph} \setlength\cardwd{\cardwd / <: columns :>} \setlength\cardht{\textheight - 6pt + 2\cardsepv} \setlength\cardht{\cardht / <: rows :>} \setlength\cardtxtwd{4\cardwd/5} % text = 80% of card width \tikzset{every picture/.style={line width=3pt}} \def\cardtitle{<: cardtitle :>} \begin{document} %%% BEGIN PAGE \begin{tikzpicture} %%% BEGIN ITEM \card{<: rownum :>}{<: colnum :>}{<: cardnum :>}{<: text :>}{<: label :>} %%% END PAGE \end{tikzpicture} \newpage %%% END DOCUMENT \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: jigsaw-generator-0.2.7/templates/template-cardsort-solution.md000066400000000000000000000004211401032735100246050ustar00rootroot00000000000000### BEGIN DOCUMENT The correct order is as follows. <: hiddennotemd :> | Row | Column | Card number | Card | Label | |:---:|:------:|:-----------:|:----:|:-----:| ### BEGIN ITEM | <: rownum :> | <: colnum :> | <: cardnum :> | <: text :> | <: label :> | ### END DOCUMENT jigsaw-generator-0.2.7/templates/template-cardsort-solution.tex000066400000000000000000000015471401032735100250170ustar00rootroot00000000000000% \input template-cardsort-header % \testingtrue %%% BEGIN DOCUMENT \chead{\begin{minipage}{\textwidth} \centering \textbf{<: title :> (SOLUTION)}\\[\smallskipamount] \ <: hiddennotesolution :>\ \\[\smallskipamount] \small(Page \thepage\ of \pageref{LastPage})\end{minipage}} \setlength\cardwd{\textwidth - 6pt} \setlength\cardwd{\cardwd / <: columns :>} \setlength\cardht{\textheight - 6pt} \setlength\cardht{\cardht / <: rows :>} \setlength\cardtxtwd{4\cardwd/5} % text = 80% of card width \tikzset{every picture/.style={line width=3pt}} \def\cardtitle{<: cardtitle :>} \begin{document} %%% BEGIN PAGE \begin{tikzpicture} %%% BEGIN ITEM \card{<: rownum :>}{<: colnum :>}{<: cardnum :>}{<: text :>}{<: label :>} %%% END PAGE \end{tikzpicture} \newpage %%% END DOCUMENT \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: jigsaw-generator-0.2.7/templates/template-cardsort-table.tex000066400000000000000000000005351401032735100242260ustar00rootroot00000000000000\usepackage{longtable} \begin{document} \begin{center} \textbf{<: title :>} \medskip <: hiddennotetable :> \bigskip \begin{longtable}{|p{0.8\textwidth}|} \hline \textbf{Card}\\\hline\endhead <: tablecards :> \end{longtable} \end{center} \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: jigsaw-generator-0.2.7/templates/template-domino-puzzle.md000066400000000000000000000005261401032735100237340ustar00rootroot00000000000000### BEGIN DOCUMENT The domino puzzle cards have the following entries. ("(BLANK)" indicates than an entry is blank.) <: puzzlenote :> | Left entry | Right entry | Left label | Right label | |:----------:|:-----------:|:----------:|:-----------:| ### BEGIN ITEM | <: textL :> | <: textR :> | <: labelL :> | <: labelR :> | ### END DOCUMENT jigsaw-generator-0.2.7/templates/template-domino-puzzle.tex000066400000000000000000000016061401032735100241340ustar00rootroot00000000000000% \input template-cardsort-header % \testingtrue %%% BEGIN DOCUMENT \chead{\begin{minipage}{\textwidth} \centering \textbf{<: title :>}\\[\smallskipamount] \ <: puzzlenote :>\ \\[\smallskipamount] \small(Page \thepage\ of \pageref{LastPage})\end{minipage}} \setlength\cardwd{\textwidth - 6pt} \setlength\cardwd{\cardwd / <: columns :>} \setlength\cardht{\textheight - 6pt} \setlength\cardht{\cardht / <: rows :>} \setlength\cardtxtwd{2\cardwd/5} % each text = 40% of card width \tikzset{every picture/.style={line width=3pt}} \tikzset{divider/.style={line width=1pt}} \def\cardtitle{<: cardtitle :>} \begin{document} %%% BEGIN PAGE \begin{tikzpicture} %%% BEGIN ITEM \domino{<: rownum :>}{<: colnum :>}{<: cardnum :>}{<: textL :>}{<: textR :>} %%% END PAGE \end{tikzpicture} \newpage %%% END DOCUMENT \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: jigsaw-generator-0.2.7/templates/template-domino-solution.md000066400000000000000000000004431401032735100242550ustar00rootroot00000000000000### BEGIN DOCUMENT The correct pairing is as follows (in order). <: hiddennotemd :> | Right entry | Left entry | Right label | Left label | |:-----------:|:----------:|:-----------:|:----------:| ### BEGIN ITEM | <: textR :> | <: textL :> | <: labelR :> | <: labelL :> | ### END DOCUMENT jigsaw-generator-0.2.7/templates/template-domino-solution.tex000066400000000000000000000016311401032735100244550ustar00rootroot00000000000000% \input template-cardsort-header % \testingtrue %%% BEGIN DOCUMENT \chead{\begin{minipage}{\textwidth} \centering \textbf{<: title :> (SOLUTION)}\\[\smallskipamount] \ <: hiddennotesolution :>\ \\[\smallskipamount] \small(Page \thepage\ of \pageref{LastPage})\end{minipage}} \setlength\cardwd{\textwidth - 6pt} \setlength\cardwd{\cardwd / <: columns :>} \setlength\cardht{\textheight - 6pt} \setlength\cardht{\cardht / <: rows :>} \setlength\cardtxtwd{2\cardwd/5} % each text = 40% of card width \tikzset{every picture/.style={line width=3pt}} \tikzset{divider/.style={line width=1pt}} \def\cardtitle{<: cardtitle :>} \begin{document} %%% BEGIN PAGE \begin{tikzpicture} %%% BEGIN ITEM \domino{<: rownum :>}{<: colnum :>}{<: cardnum :>}{<: textL :>}{<: textR :>} %%% END PAGE \end{tikzpicture} \newpage %%% END DOCUMENT \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: jigsaw-generator-0.2.7/templates/template-domino-table.tex000066400000000000000000000006021401032735100236650ustar00rootroot00000000000000\usepackage{longtable} \begin{document} \begin{center} \textbf{<: title :>} \medskip <: hiddennotetable :> \bigskip \begin{longtable}{|p{0.4\textwidth}|p{0.4\textwidth}|} \hline \textbf{Question}&\textbf{Answer}\\\hline\endhead <: tablepairs :> \end{longtable} \end{center} \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: jigsaw-generator-0.2.7/templates/template-header.md000066400000000000000000000000001401032735100223330ustar00rootroot00000000000000jigsaw-generator-0.2.7/templates/template-header.tex000066400000000000000000000100361401032735100225450ustar00rootroot00000000000000\documentclass[12pt,a4paper]{article} \usepackage{geometry} \geometry{% a4paper, lmargin=1.7cm, rmargin=1.7cm, tmargin=2cm, bmargin=2cm, footskip=0pt, headheight=12pt} \usepackage{amsmath} \usepackage{amssymb} \let\ge=\geqslant \let\le=\leqslant \usepackage{calc} \usepackage{tikz}[2013/12/13 v3.0.0] \usetikzlibrary{calc} \tikzset{above/.default=6pt} \tikzset{regular/.style={sloped, above}} \tikzset{hidden/.style={sloped, above, fill=yellow!80!white}} \newsavebox\templateimagebox \newdimen\templateimagewd \newif\iftesting % say \testingtrue to have \uptriangle etc. use % simple parameters like {Q1} instead of {{regular}{Q1}} \usepackage[export]{adjustbox} \newcommand{\image}[1]{\includegraphics[max height=0.3\trad, max width=0.8\sidelength]{#1}} % There might be a nicer way to do the following, but I haven't yet % found it. \newcommand{\imagecap}[2]{% \savebox{\templateimagebox}{\includegraphics[max height=0.3\trad, max width=0.8\sidelength]{#1}}% \setlength{\templateimagewd}{\wd\templateimagebox}% \hbox to \templateimagewd{% \begin{minipage}{\templateimagewd}% \usebox{\templateimagebox}\\ \hbox to \templateimagewd{\hss #2\hss}% \end{minipage}}} % Usage of these macros: % First do: \setshapesize{size} where size is the side length of % the triangle/square given in cm with no units % Then: % \...triangle{(x0,y0)}{label1}{label2}{label3} % where the first argument is the coordinate of the centre, % and the labels are placed anticlockwise in the following order: % \uptriangle: base, right, left % \downtriangle: base, left, right % \lefttriangle: right, top, bottom % \righttriangle: left, bottom, top \newlength\sidelength % side length \newlength\trad % triangle circumradius \newlength\srad % square circumradius \newcommand{\setshapesize}[1]{% \pgfmathsetlength\sidelength{#1*72.27/2.54} \pgfmathsetlength\trad{(#1*72.27/2.54) / sqrt(3)} \pgfmathsetlength\srad{(#1*72.27/2.54) / sqrt(2)} } \setshapesize{10} % default, so table output works \newcommand{\makestyles}[3]{% \iftesting \def#1{regular} \def#2{#3} \else % split #3 into {style}{text} \makestylesa#1#2#3 \fi } \newcommand{\makestylesa}[4]{% \def#1{#3} \def#2{#4} } \newcommand{\tiltedtriangle}[7]{% \coordinate (a) at ($ #1 +({#2-150}:\trad) $); \coordinate (b) at ($ #1 +({#2-30}:\trad) $); \coordinate (c) at ($ #1 +({#2+90}:\trad) $); \makestyles\stylea\contenta{#3} \makestyles\styleb\contentb{#4} \makestyles\stylec\contentc{#5} \draw[allow upside down] (a) -- node[\stylea] {\contenta} (b) -- node[\styleb] {\contentb} (c) -- node[\stylec] {\contentc} cycle; % If card number is empty, don't draw circle around number \def\templabel{#6} \ifx\templabel\empty \else \node[circle,draw,thin,inner sep=1pt,rotate=#7] at ($ #1 $) {#6}; \fi } \newcommand{\uptriangle}[6]{% \tiltedtriangle{#1}{0}{#2}{#3}{#4}{#5}{#6} } \newcommand{\downtriangle}[6]{% \tiltedtriangle{#1}{180}{#2}{#3}{#4}{#5}{#6} } \newcommand{\lefttriangle}[6]{% \tiltedtriangle{#1}{90}{#2}{#3}{#4}{#5}{#6} } \newcommand{\righttriangle}[6]{% \tiltedtriangle{#1}{270}{#2}{#3}{#4}{#5}{#6} } \newcommand{\tiltedsquare}[8]{% \coordinate (a) at ($ #1 +({#2-135}:\srad) $); \coordinate (b) at ($ #1 +({#2-45}:\srad) $); \coordinate (c) at ($ #1 +({#2+45}:\srad) $); \coordinate (d) at ($ #1 +({#2+135}:\srad) $); \makestyles\stylea\contenta{#3} \makestyles\styleb\contentb{#4} \makestyles\stylec\contentc{#5} \makestyles\styled\contentd{#6} \draw[allow upside down] (a) -- node[\stylea] {\contenta} (b) -- node[\styleb] {\contentb} (c) -- node[\stylec] {\contentc} (d) -- node[\styled] {\contentd} cycle; % If card number is empty, don't draw circle around number \def\templabel{#7} \ifx\templabel\empty \else \node[circle,draw,thin,inner sep=1pt,rotate=#8] at ($ #1 $) {#7}; \fi } \newcommand{\upsquare}[7]{% \tiltedsquare{#1}{0}{#2}{#3}{#4}{#5}{#6}{#7} } \pagestyle{empty} \setlength{\parindent}{0pt} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: jigsaw-generator-0.2.7/templates/template-hexagon-puzzle.tex000066400000000000000000000047011401032735100242770ustar00rootroot00000000000000% \input template-header % \testingtrue \begin{document} \begin{center} \textbf{<: title :>} (Page 1) \medskip <: puzzlenote :> \bigskip \setshapesize{8.5} \begin{tikzpicture}[line width=3pt, rounded corners=1pt] \lefttriangle {(120:\trad)} <: tripuzcard1 :> % {A18}{Q1}{E1}{1}{-30} \righttriangle{(180:\trad)} <: tripuzcard2 :> % {E12}{A1}{Q2}{2}{30} \lefttriangle {(-120:\trad)}<: tripuzcard3 :> % {Q19}{Q3}{A2}{3}{-30} \righttriangle{(0,-\sidelength)+(180:\trad)} <: tripuzcard4 :> % {E11}{A3}{Q4}{4}{30} \righttriangle{(60:\trad)} <: tripuzcard5 :> % {Q5}{E10}{A4}{5}{30} \lefttriangle {(0:\trad)} <: tripuzcard6 :> % {A16}{Q17}{E2}{6}{-30} \righttriangle{(-60:\trad)} <: tripuzcard7 :> % {Q18}{A17}{Q24}{7}{30} \lefttriangle {(0,-\sidelength)+(0:\trad)} <: tripuzcard8 :> % {A30}{Q25}{A24}{8}{-30} \end{tikzpicture} \newpage \textbf{<: title :>} (Page 2) \bigskip \begin{tikzpicture}[line width=3pt, rounded corners=1pt] \lefttriangle {(120:\trad)} <: tripuzcard9 :> % {A19}{A25}{Q26}{9}{-30} \righttriangle{(180:\trad)} <: tripuzcard10 :> % {Q27}{A20}{A26}{10}{30} \lefttriangle {(-120:\trad)}<: tripuzcard11 :> % {A5}{Q20}{Q6}{11}{-30} \righttriangle{(0,-\sidelength)+(180:\trad)} <: tripuzcard12 :> % {Q7}{E9}{A6}{12}{30} \righttriangle{(60:\trad)} <: tripuzcard13 :> % {Q16}{E3}{A15}{13}{30} \lefttriangle {(0:\trad)} <: tripuzcard14 :> % {A14}{Q23}{Q15}{14}{-30} \righttriangle{(-60:\trad)} <: tripuzcard15 :> % {Q30}{A23}{A29}{15}{30} \lefttriangle {(0,-\sidelength)+(0:\trad)} <: tripuzcard16 :> % {A22}{A28}{Q29}{16}{-30} \end{tikzpicture} \newpage \textbf{<: title :>} (Page 3) \bigskip \begin{tikzpicture}[line width=3pt, rounded corners=1pt] \lefttriangle {(120:\trad)} <: tripuzcard17 :> % {A27}{Q28}{A21}{17}{-30} \righttriangle{(180:\trad)} <: tripuzcard18 :> % {Q9}{A8}{Q21}{18}{30} \lefttriangle {(-120:\trad)}<: tripuzcard19 :> % {A7}{Q8}{E8}{19}{-30} \righttriangle{(0,-\sidelength)+(180:\trad)} <: tripuzcard20 :> % {Q14}{E4}{A13}{20}{30} \righttriangle{(60:\trad)} <: tripuzcard21 :> % {E5}{A12}{Q13}{21}{30} \lefttriangle {(0:\trad)} <: tripuzcard22 :> % {Q22}{Q12}{A11}{22}{-30} \righttriangle{(-60:\trad)} <: tripuzcard23 :> %{E6}{A10}{Q11}{23}{30} \lefttriangle {(0,-\sidelength)+(0:\trad)} <: tripuzcard24 :> % {A9}{Q10}{E7}{24}{-30} \end{tikzpicture} \end{center} \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: jigsaw-generator-0.2.7/templates/template-hexagon-solution.tex000066400000000000000000000053771401032735100246340ustar00rootroot00000000000000% \input template-header % \testingtrue \tikzset{above/.default=0pt} \begin{document} \begin{center} \textbf{<: title :>} \medskip \textbf{SOLUTION} \medskip <: hiddennotesolution :> \bigskip \setshapesize{4.5} \begin{tikzpicture}[line width=3pt, rounded corners=1pt] % Row 1 \uptriangle {(120:\sidelength) + (150:\trad)} <: trisolcard1 :> % {A18}{Q1}{E1}{1}{0} \downtriangle {(120:\sidelength) + (90:\trad)} <: trisolcard2 :> % {E12}{A1}{Q2}{2}{180} \uptriangle {(0,2*\trad)} <: trisolcard3 :> % {Q19}{Q3}{A2}{3}{0} \downtriangle {(60:\sidelength) + (90:\trad)} <: trisolcard4 :> % {E11}{A3}{Q4}{4}{180} \uptriangle {(60:\sidelength) + (30:\trad)} <: trisolcard5 :> % {Q5}{E10}{A4}{5}{0} % Row 2 \uptriangle {(-\sidelength,0) + (150:\trad)} <: trisolcard6 :> % {A16}{Q17}{E2}{6}{0} \downtriangle {(-\sidelength,0) + (90:\trad)} <: trisolcard7 :> % {Q18}{A17}{Q24}{7}{180} \uptriangle {(150:\trad)} <: trisolcard8 :> % {A30}{Q25}{A24}{8}{0} \downtriangle {(90:\trad)} <: trisolcard9 :> % {A19}{A25}{Q26}{9}{180} \uptriangle {(30:\trad)} <: trisolcard10 :> % {Q27}{A20}{A26}{10}{0} \downtriangle {(\sidelength,0) + (90:\trad)} <: trisolcard11 :> % {A5}{Q20}{Q6}{11}{180} \uptriangle {(\sidelength,0) + (30:\trad)} <: trisolcard12 :> % {Q7}{E9}{A6}{12}{0} % Row 3 \downtriangle {(-\sidelength,0) + (-150:\trad)} <: trisolcard13 :> % {Q16}{E3}{A15}{13}{180} \uptriangle {(-\sidelength,0) + (-90:\trad)} <: trisolcard14 :> % {A14}{Q23}{Q15}{14}{0} \downtriangle {(-150:\trad)} <: trisolcard15 :> % {Q30}{A23}{A29}{15}{180} \uptriangle {(-90:\trad)} <: trisolcard16 :> % {A22}{A28}{Q29}{16}{0} \downtriangle {(-30:\trad)} <: trisolcard17 :> % {A27}{Q28}{A21}{17}{180} \uptriangle {(\sidelength,0) + (-90:\trad)} <: trisolcard18 :> % {Q9}{A8}{Q21}{18}{0} \downtriangle {(\sidelength,0) + (-30:\trad)} <: trisolcard19 :> % {A7}{Q8}{E8}{19}{180} % Row 4 \downtriangle {(-120:\sidelength) + (-150:\trad)} <: trisolcard20 :> % {Q14}{E4}{A13}{20}{180} \uptriangle {(-120:\sidelength) + (-90:\trad)} <: trisolcard21 :> % {E5}{A12}{Q13}{21}{0} \downtriangle {(0,-2*\trad)} <: trisolcard22 :> % {Q22}{Q12}{A11}{22}{180} \uptriangle {(-60:\sidelength) + (-90:\trad)} <: trisolcard23 :> % {E6}{A10}{Q11}{23}{0} \downtriangle {(-60:\sidelength) + (-30:\trad)} <: trisolcard24 :> % {A9}{Q10}{E7}{24}{180} \end{tikzpicture} \end{center} \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: jigsaw-generator-0.2.7/templates/template-jigsaw-puzzle3.md000066400000000000000000000004171401032735100240150ustar00rootroot00000000000000The puzzle cards have the following edges. ("(BLANK)" indicates than an edge is blank. It is possible that some edges do not match, if they are are the outside of the puzzle.) <: puzzlenote :> | Edge 1 | Edge 2 | Edge 3 | |:------:|:------:|:------:| <: puzcards3 :> jigsaw-generator-0.2.7/templates/template-jigsaw-puzzle4.md000066400000000000000000000005021401032735100240110ustar00rootroot00000000000000The puzzle cards have the following edges. ("(BLANK)" indicates than an edge is blank. Cards which have an empty "Edge 4" are triangular. It is possible that some edges do not match, if they are are the outside of the puzzle.) <: puzzlenote :> | Edge 1 | Edge 2 | Edge 3 | |:------:|:------:|:------:| <: puzcards4 :> jigsaw-generator-0.2.7/templates/template-jigsaw-solution.md000066400000000000000000000003061401032735100242520ustar00rootroot00000000000000The pairs match up as follows: <: hiddennotemd :> | Edge 1 | Edge 2 | |:------:|:------:| <: pairs :> The following border edges did not match any other edges: | Edge 1 | |:------:| <: edges :> jigsaw-generator-0.2.7/templates/template-parquet-puzzle.tex000066400000000000000000000026511401032735100243310ustar00rootroot00000000000000% \input template-header % \testingtrue \begin{document} \begin{center} \textbf{<: title :>} (Page 1) \medskip <: puzzlenote :> \bigskip \setshapesize{8.5} \begin{tikzpicture}[line width=3pt, rounded corners=1pt] \lefttriangle {(120:\trad)} <: tripuzcard1 :> % {A11}{A14}{Q15}{11}{-30} \righttriangle{(180:\trad)} <: tripuzcard2 :> % {Q1}{E10}{A10}{10}{30} \lefttriangle {(-120:\trad)}<: tripuzcard3 :> % {E8}{A8}{Q9}{8}{-30} \righttriangle{(0,-\sidelength)+(180:\trad)} <: tripuzcard4 :> % {A15}{A13}{A12}{12}{30} \righttriangle{(60:\trad)} <: tripuzcard5 :> % {A1}{Q2}{E1}{1}{30} \lefttriangle {(0:\trad)} <: tripuzcard6 :> % {A3}{Q4}{E3}{3}{-30} \righttriangle{(-60:\trad)} <: tripuzcard7 :> % {Q6}{E5}{A5}{5}{30} \lefttriangle {(0,-\sidelength)+(0:\trad)} <: tripuzcard8 :> % {Q7}{E6}{A6}{6}{-30} \end{tikzpicture} \newpage \textbf{<: title :>} (Page 2) \bigskip \begin{tikzpicture}[line width=3pt, rounded corners=1pt] \upsquare{0.5*(-\sidelength,\sidelength)} <: sqpuzcard1 :> % {Q3}{E2}{A2}{Q11}{2}{0} \upsquare{0.5*(\sidelength,\sidelength)} <: sqpuzcard2 :> % {Q5}{E4}{A4}{Q12}{4}{0} \upsquare{0.5*(-\sidelength,-\sidelength)} <: sqpuzcard3 :> % {A7}{Q13}{Q8}{E7}{7}{0} \upsquare{0.5*(\sidelength,-\sidelength)} <: sqpuzcard4 :> % {A9}{Q14}{Q10}{E9}{9}{0} \end{tikzpicture} \end{center} \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: jigsaw-generator-0.2.7/templates/template-parquet-solution.tex000066400000000000000000000031621401032735100246520ustar00rootroot00000000000000% \input template-header % \testingtrue \tikzset{above/.default=0pt} \begin{document} \begin{center} \textbf{<: title :>} \medskip \textbf{SOLUTION} \medskip <: hiddennotesolution :> \bigskip \setshapesize{6} \begin{tikzpicture}[line width=3pt, rounded corners=1pt] % origin is at point of symmetry \righttriangle{1.5*(0,\trad) + (60:\trad)} <: trisolcard1 :> % {A1}{Q2}{E10}{1}{270} \tiltedsquare{(0,0.5*\trad) + 0.5*(30:\trad) + 0.5*(30:\sidelength)}{30} <: sqsolcard1 :> % {Q3}{E9}{A2}{Q11}{2}{30} \lefttriangle{(0.5*\sidelength+\trad,0)} <: trisolcard2 :> % {E8}{A3}{Q4}{3}{90} \tiltedsquare{(0,-0.5*\trad) + 0.5*(-30:\trad) + 0.5*(-30:\sidelength)}{-30} <: sqsolcard2 :> % {Q5}{E7}{A4}{Q12}{4}{-30} \righttriangle{-1.5*(0,\trad) + (-60:\trad)} <: trisolcard3 :> % {Q6}{E6}{A5}{5}{270} \lefttriangle{-1.5*(0,\trad) + (-120:\trad)} <: trisolcard4 :> % {A6}{Q7}{E5}{6}{90} \tiltedsquare{(0,-0.5*\trad) + 0.5*(-150:\trad) + 0.5*(-150:\sidelength)}{30} <: sqsolcard3 :> % {A7}{Q13}{Q8}{E4}{7}{30} \righttriangle{(-0.5*\sidelength-\trad,0)} <: trisolcard5 :> % {E3}{A8}{Q9}{8}{270} \tiltedsquare{(0,0.5*\trad) + 0.5*(150:\trad) + 0.5*(150:\sidelength)}{-30} <: sqsolcard4 :> % {A9}{Q14}{Q10}{E2}{9}{-30} \lefttriangle{1.5*(0,\trad) + (120:\trad)} <: trisolcard6 :> % {Q1}{E1}{A10}{10}{90} \uptriangle{0.5*(0,\trad)} <: trisolcard7 :> % {Q15}{A11}{A14}{11}{0} \downtriangle{-0.5*(0,\trad)} <: trisolcard8 :> % {A15}{A13}{A12}{12}{180} \end{tikzpicture} \end{center} \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: jigsaw-generator-0.2.7/templates/template-smallhexagon-puzzle.tex000066400000000000000000000013671401032735100253350ustar00rootroot00000000000000% \input template-header % \testingtrue \begin{document} \begin{center} \textbf{<: title :>} \medskip <: puzzlenote :> \bigskip \setshapesize{10} \begin{tikzpicture}[line width=3pt, rounded corners=1pt] \righttriangle{(60:\trad)} <: tripuzcard1 :> % {A1}{Q2}{E1}{1}{30} \lefttriangle {(0:\trad)} <: tripuzcard2 :> % {E2}{A2}{Q3}{2}{-30} \righttriangle{(-60:\trad)} <: tripuzcard3 :> % {Q4}{E3}{A3}{3}{30} \lefttriangle {(-120:\trad)}<: tripuzcard4 :> % {A4}{Q5}{E4}{4}{-30} \righttriangle{(180:\trad)} <: tripuzcard5 :> % {E5}{A5}{Q6}{5}{30} \lefttriangle {(120:\trad)} <: tripuzcard6 :> % {Q1}{E6}{A6}{6}{-30} \end{tikzpicture} \end{center} \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: jigsaw-generator-0.2.7/templates/template-smallhexagon-solution.tex000066400000000000000000000014401401032735100256500ustar00rootroot00000000000000% \input template-header % \testingtrue \begin{document} \begin{center} \textbf{<: title :>} \medskip \textbf{SOLUTION} \medskip <: hiddennotesolution :> \bigskip \setshapesize{10} \begin{tikzpicture}[line width=3pt, rounded corners=1pt] \righttriangle{(60:\trad)} <: trisolcard1 :> % {A1}{Q2}{E1}{1}{270} \lefttriangle {(0:\trad)} <: trisolcard2 :> % {E2}{A2}{Q3}{2}{90} \righttriangle{(-60:\trad)} <: trisolcard3 :> % {Q4}{E3}{A3}{3}{270} \lefttriangle {(-120:\trad)}<: trisolcard4 :> % {A4}{Q5}{E4}{4}{90} \righttriangle{(180:\trad)} <: trisolcard5 :> % {E5}{A5}{Q6}{5}{270} \lefttriangle {(120:\trad)} <: trisolcard6 :> % {Q1}{E6}{A6}{6}{90} \end{tikzpicture} \end{center} \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: jigsaw-generator-0.2.7/templates/template-table.tex000066400000000000000000000007371401032735100224130ustar00rootroot00000000000000\usepackage{longtable} \begin{document} \begin{center} \textbf{<: title :>} \medskip <: hiddennotetable :> \bigskip \begin{longtable}{|c|c|} \hline \textbf{Question}&\textbf{Answer}\\\hline\endhead <: tablepairs :> \end{longtable} \bigskip \begin{longtable}{|c|} \hline \textbf{Edges}\\\hline\endhead <: tableedges :> \end{longtable} \end{center} \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: jigsaw-generator-0.2.7/templates/template-triangle-puzzle.tex000066400000000000000000000032701401032735100244530ustar00rootroot00000000000000% \input template-header % \testingtrue \begin{document} \begin{center} \textbf{<: title :>} (Page 1) \medskip <: puzzlenote :> \bigskip \setshapesize{8.5} \begin{tikzpicture}[line width=3pt, rounded corners=1pt] \lefttriangle {(120:\trad)} <: tripuzcard1 :> % {Q1}{E12}{E1}{1}{-30} \righttriangle{(180:\trad)} <: tripuzcard2 :> % {A14}{Q15}{E2}{2}{30} \lefttriangle {(-120:\trad)}<: tripuzcard3 :> % {A1}{A15}{Q2}{3}{-30} \righttriangle{(0,-\sidelength)+(180:\trad)} <: tripuzcard4 :> % {Q3}{E11}{A2}{4}{30} \righttriangle{(60:\trad)} <: tripuzcard5 :> % {A12}{Q13}{E3}{5}{30} \lefttriangle {(0:\trad)} <: tripuzcard6 :> % {Q14}{A13}{Q18}{6}{-30} \righttriangle{(-60:\trad)} <: tripuzcard7 :> % {Q17}{A16}{A18}{7}{30} \lefttriangle {(0,-\sidelength)+(0:\trad)} <: tripuzcard8 :> % {A3}{Q16}{Q4}{8}{-30} \end{tikzpicture} \newpage \textbf{<: title :>} (Page 2) \bigskip \begin{tikzpicture}[line width=3pt, rounded corners=1pt] \lefttriangle {(120:\trad)} <: tripuzcard9 :> % {Q5}{E10}{A4}{9}{-30} \righttriangle{(180:\trad)} <: tripuzcard10 :> % {E5}{A11}{E4}{10}{30} \lefttriangle {(-120:\trad)}<: tripuzcard11 :> % {Q12}{Q11}{A10}{11}{-30} \righttriangle{(0,-\sidelength)+(180:\trad)} <: tripuzcard12 :> % {E6}{A9}{Q10}{12}{30} \righttriangle{(60:\trad)} <: tripuzcard13 :> % {A17}{Q9}{A8}{13}{30} \lefttriangle {(0:\trad)} <: tripuzcard14 :> % {E7}{A7}{Q8}{14}{-30} \righttriangle{(-60:\trad)} <: tripuzcard15 :> % {A5}{Q7}{Q6}{15}{30} \lefttriangle {(0,-\sidelength)+(0:\trad)} <: tripuzcard16 :> % {E8}{E9}{A6}{16}{-30} \end{tikzpicture} \end{center} \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: jigsaw-generator-0.2.7/templates/template-triangle-solution.tex000066400000000000000000000037171401032735100250040ustar00rootroot00000000000000% \input template-header % \testingtrue \tikzset{above/.default=0pt} \begin{document} \begin{center} \textbf{<: title :>} \medskip \textbf{SOLUTION} \medskip <: hiddennotesolution :> \bigskip \setshapesize{4.2} \begin{tikzpicture}[line width=3pt, rounded corners=1pt] % Row 1 \uptriangle {(0,2*\trad)} <: trisolcard1 :> % {Q1}{E12}{E1}{1}{0} % Row 2 \uptriangle {(150:\trad)} <: trisolcard2 :> % {A14}{Q15}{E2}{2}{0} \downtriangle {(90:\trad)} <: trisolcard3 :> % {A1}{A15}{Q2}{3}{180} \uptriangle {(30:\trad)} <: trisolcard4 :> % {Q3}{E11}{A2}{4}{0} % Row 3 \uptriangle {(-\sidelength,0) + (-90:\trad)} <: trisolcard5 :> % {A12}{Q13}{E3}{5}{0} \downtriangle {(-150:\trad)} <: trisolcard6 :> % {Q14}{A13}{Q18}{6}{180} \uptriangle {(-90:\trad)} <: trisolcard7 :> % {Q17}{A16}{A18}{7}{0} \downtriangle {(-30:\trad)} <: trisolcard8 :> % {A3}{Q16}{Q4}{8}{180} \uptriangle {(\sidelength,0) + (-90:\trad)} <: trisolcard9 :> % {Q5}{E10}{A4}{9}{0} % Row 4 \uptriangle {(-120:2\sidelength) + (150:\trad)} <: trisolcard10 :> % {E5}{A11}{E4}{10}{0} \downtriangle {(-120:\sidelength) + (-150:\trad)} <: trisolcard11 :> % {Q12}{Q11}{A10}{11}{180} \uptriangle {(-120:\sidelength) + (-90:\trad)} <: trisolcard12 :> % {E6}{A9}{Q10}{12}{0} \downtriangle {(0,-2*\trad)} <: trisolcard13 :> % {A17}{Q9}{A8}{13}{180} \uptriangle {(-60:\sidelength) + (-90:\trad)} <: trisolcard14 :> % {E7}{A7}{Q8}{14}{0} \downtriangle {(-60:\sidelength) + (-30:\trad)} <: trisolcard15 :> % {A5}{Q7}{Q6}{15}{180} \uptriangle {(-60:2\sidelength) + (30:\trad)} <: trisolcard16 :> % {E8}{E9}{A6}{16}{0} \end{tikzpicture} \end{center} \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: jigsaw-generator-0.2.7/templates/triangle-layout.yaml000066400000000000000000000032001401032735100227610ustar00rootroot00000000000000# Template file for large triangle jigsaw format: 1 category: jigsaw type: triangle typename: triangle puzzleHeaderTeX: template-header.tex puzzleTemplateTeX: template-triangle-puzzle.tex solutionHeaderTeX: template-header.tex solutionTemplateTeX: template-triangle-solution.tex tableHeaderTeX: template-header.tex tableTemplateTeX: template-table.tex puzzleHeaderMarkdown: template-header.md puzzleTemplateMarkdown: template-jigsaw-puzzle3.md solutionHeaderMarkdown: template-header.md solutionTemplateMarkdown: template-jigsaw-solution.md pairs: 18 edges: 12 # Do we shuffle the order of the pairs from the order given? shufflePairs: false # Do we randomly flip (swap) individual questions and answers (the # contents of the pairs) on the jigsaw? flip: true # Do we shuffle the order of the edges from the order given? shuffleEdges: false # Default text size on puzzle pieces puzzleTextSize: 5 # Default text size on solution pieces solutionTextSize: 3 # Do we number the pieces? numberCards: true triangleSolutionCards: - [Q1, E12, E1] - [A14, Q15, E2] - [A1, A15, Q2] - [Q3, E11, A2] - [A12, Q13, E3] - [Q14, A13, Q18] - [Q17, A16, A18] - [A3, Q16, Q4] - [Q5, E10, A4] - [E5, A11, E4] - [Q12, Q11, A10] - [E6, A9, Q10] - [A17, Q9, A8] - [E7, A7, Q8] - [A5, Q7, Q6] - [E8, E9, A6] triangleSolutionOrientation: [0, 0, 180, 0, 0, 180, 0, 180, 0, 0, 180, 0, 180, 0, 180, 0] trianglePuzzleOrientation: - [90, -30] - [270, 30] - [90, -30] - [270, 30] - [270, 30] - [90, -30] - [270, 30] - [90, -30] - [90, -30] - [270, 30] - [90, -30] - [270, 30] - [270, 30] - [90, -30] - [270, 30] - [90, -30]