diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea21431 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/app/build +/captures +.externalNativeBuild diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c45207e --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ +GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. [http://fsf.org/] + 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 + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {fullname} + + 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 [http://www.gnu.org/licenses/]. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + ship_gunner Copyright (C) 2018 rocket049 + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +[http://www.gnu.org/licenses/]. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +[http://www.gnu.org/philosophy/why-not-lgpl.html]. \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..60a47af --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,63 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 28 + buildToolsVersion '28.0.2' + defaultConfig { + applicationId "org.xing.android" + minSdkVersion 15 + targetSdkVersion 26 + versionCode 20 + versionName "1.4.2" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + vectorDrawables.useSupportLibrary = true + } + buildTypes { + debug { + manifestPlaceholders = [bd_speech_appid : "9080060", + bd_speech_key : "TgEpVmjjELkIf3FKc1gj2jsj", + bd_speech_secret: "87c4d13cf12a83191e4b4ec23d98530e", + umeng_appkey : "none", + umeng_channel : "none"] + } + release { + minifyEnabled false + manifestPlaceholders = [bd_speech_appid : "9080060", + bd_speech_key : "TgEpVmjjELkIf3FKc1gj2jsj", + bd_speech_secret: "87c4d13cf12a83191e4b4ec23d98530e", + umeng_appkey : "586213d5ae1bf81811000768", + umeng_channel : "xing"] + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + // 自定义输出配置 + applicationVariants.all { variant -> + variant.outputs.all { + outputFileName = rootProject.getName() +"-"+defaultConfig.versionName +"-"+defaultConfig.versionCode +".apk" + } + } + } + } + sourceSets { + main { + jniLibs.srcDirs = ['libs'] + } + } +} + +dependencies { + compile fileTree(include: ['*.jar'], dir: 'libs') + androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { + exclude group: 'com.android.support', module: 'support-annotations' + }) + compile files('libs/antlr-runtime-4.6.jar') + compile files('libs/utdid4all-1.0.4.jar') + compile files('libs/umeng-analytics-v6.0.7.jar') + compile files('libs/Msc.jar') + compile 'com.zhy:okhttputils:2.4.1' + compile 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:1.0.2' + compile 'com.android.support:appcompat-v7:28.+' + compile 'com.android.support:support-v4:28.+' + compile 'com.android.support:support-vector-drawable:28.+' + testCompile 'junit:junit:4.12' + compile files('libs/open_sdk_r5785_lite.jar') + compile files('libs/bdasr_V3_20180320_9066860.jar') +} diff --git a/app/libs/Msc.jar b/app/libs/Msc.jar new file mode 100644 index 0000000..4ac8b2a Binary files /dev/null and b/app/libs/Msc.jar differ diff --git a/app/libs/antlr-runtime-4.6.jar b/app/libs/antlr-runtime-4.6.jar new file mode 100644 index 0000000..3c67046 Binary files /dev/null and b/app/libs/antlr-runtime-4.6.jar differ diff --git a/app/libs/armeabi/libBaiduSpeechSDK.so b/app/libs/armeabi/libBaiduSpeechSDK.so new file mode 100644 index 0000000..9e88a63 Binary files /dev/null and b/app/libs/armeabi/libBaiduSpeechSDK.so differ diff --git a/app/libs/armeabi/libmsc.so b/app/libs/armeabi/libmsc.so new file mode 100644 index 0000000..2ba6eb2 Binary files /dev/null and b/app/libs/armeabi/libmsc.so differ diff --git a/app/libs/armeabi/libvad.dnn.so b/app/libs/armeabi/libvad.dnn.so new file mode 100644 index 0000000..0550061 Binary files /dev/null and b/app/libs/armeabi/libvad.dnn.so differ diff --git a/app/libs/bdasr_V3_20180320_9066860.jar b/app/libs/bdasr_V3_20180320_9066860.jar new file mode 100644 index 0000000..8529288 Binary files /dev/null and b/app/libs/bdasr_V3_20180320_9066860.jar differ diff --git a/app/libs/open_sdk_r5785_lite.jar b/app/libs/open_sdk_r5785_lite.jar new file mode 100644 index 0000000..4683914 Binary files /dev/null and b/app/libs/open_sdk_r5785_lite.jar differ diff --git a/app/libs/umeng-analytics-v6.0.7.jar b/app/libs/umeng-analytics-v6.0.7.jar new file mode 100644 index 0000000..44981f4 Binary files /dev/null and b/app/libs/umeng-analytics-v6.0.7.jar differ diff --git a/app/libs/utdid4all-1.0.4.jar b/app/libs/utdid4all-1.0.4.jar new file mode 100644 index 0000000..34815c3 Binary files /dev/null and b/app/libs/utdid4all-1.0.4.jar differ diff --git a/app/libs/x86/libBaiduSpeechSDK.so b/app/libs/x86/libBaiduSpeechSDK.so new file mode 100644 index 0000000..78ff116 Binary files /dev/null and b/app/libs/x86/libBaiduSpeechSDK.so differ diff --git a/app/libs/x86/libmsc.so b/app/libs/x86/libmsc.so new file mode 100644 index 0000000..da343c7 Binary files /dev/null and b/app/libs/x86/libmsc.so differ diff --git a/app/libs/x86/libvad.dnn.so b/app/libs/x86/libvad.dnn.so new file mode 100644 index 0000000..0550061 Binary files /dev/null and b/app/libs/x86/libvad.dnn.so differ diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..21e2d3c --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in C:\Users\Administrator\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..022f818 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/assets/history.html b/app/src/main/assets/history.html new file mode 100644 index 0000000..db5a398 --- /dev/null +++ b/app/src/main/assets/history.html @@ -0,0 +1,113 @@ + + + + + + + + + + + + + +
+ +
+ + + + + \ No newline at end of file diff --git a/app/src/main/assets/js/KaTeX/fonts/KaTeX_Main-Regular.woff2 b/app/src/main/assets/js/KaTeX/fonts/KaTeX_Main-Regular.woff2 new file mode 100644 index 0000000..4882042 Binary files /dev/null and b/app/src/main/assets/js/KaTeX/fonts/KaTeX_Main-Regular.woff2 differ diff --git a/app/src/main/assets/js/KaTeX/fonts/KaTeX_Math-Italic.woff2 b/app/src/main/assets/js/KaTeX/fonts/KaTeX_Math-Italic.woff2 new file mode 100644 index 0000000..5f8c4bf Binary files /dev/null and b/app/src/main/assets/js/KaTeX/fonts/KaTeX_Math-Italic.woff2 differ diff --git a/app/src/main/assets/js/KaTeX/katex.min.css b/app/src/main/assets/js/KaTeX/katex.min.css new file mode 100644 index 0000000..716f4cf --- /dev/null +++ b/app/src/main/assets/js/KaTeX/katex.min.css @@ -0,0 +1 @@ +@font-face{font-family:KaTeX_AMS;src:url(fonts/KaTeX_AMS-Regular.eot);src:url(fonts/KaTeX_AMS-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_AMS-Regular.woff2) format('woff2'),url(fonts/KaTeX_AMS-Regular.woff) format('woff'),url(fonts/KaTeX_AMS-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Caligraphic;src:url(fonts/KaTeX_Caligraphic-Bold.eot);src:url(fonts/KaTeX_Caligraphic-Bold.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Caligraphic-Bold.woff2) format('woff2'),url(fonts/KaTeX_Caligraphic-Bold.woff) format('woff'),url(fonts/KaTeX_Caligraphic-Bold.ttf) format('truetype');font-weight:700;font-style:normal}@font-face{font-family:KaTeX_Caligraphic;src:url(fonts/KaTeX_Caligraphic-Regular.eot);src:url(fonts/KaTeX_Caligraphic-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Caligraphic-Regular.woff2) format('woff2'),url(fonts/KaTeX_Caligraphic-Regular.woff) format('woff'),url(fonts/KaTeX_Caligraphic-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Fraktur;src:url(fonts/KaTeX_Fraktur-Bold.eot);src:url(fonts/KaTeX_Fraktur-Bold.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Fraktur-Bold.woff2) format('woff2'),url(fonts/KaTeX_Fraktur-Bold.woff) format('woff'),url(fonts/KaTeX_Fraktur-Bold.ttf) format('truetype');font-weight:700;font-style:normal}@font-face{font-family:KaTeX_Fraktur;src:url(fonts/KaTeX_Fraktur-Regular.eot);src:url(fonts/KaTeX_Fraktur-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Fraktur-Regular.woff2) format('woff2'),url(fonts/KaTeX_Fraktur-Regular.woff) format('woff'),url(fonts/KaTeX_Fraktur-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Main;src:url(fonts/KaTeX_Main-Bold.eot);src:url(fonts/KaTeX_Main-Bold.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Main-Bold.woff2) format('woff2'),url(fonts/KaTeX_Main-Bold.woff) format('woff'),url(fonts/KaTeX_Main-Bold.ttf) format('truetype');font-weight:700;font-style:normal}@font-face{font-family:KaTeX_Main;src:url(fonts/KaTeX_Main-Italic.eot);src:url(fonts/KaTeX_Main-Italic.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Main-Italic.woff2) format('woff2'),url(fonts/KaTeX_Main-Italic.woff) format('woff'),url(fonts/KaTeX_Main-Italic.ttf) format('truetype');font-weight:400;font-style:italic}@font-face{font-family:KaTeX_Main;src:url(fonts/KaTeX_Main-Regular.eot);src:url(fonts/KaTeX_Main-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Main-Regular.woff2) format('woff2'),url(fonts/KaTeX_Main-Regular.woff) format('woff'),url(fonts/KaTeX_Main-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Math;src:url(fonts/KaTeX_Math-Italic.eot);src:url(fonts/KaTeX_Math-Italic.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Math-Italic.woff2) format('woff2'),url(fonts/KaTeX_Math-Italic.woff) format('woff'),url(fonts/KaTeX_Math-Italic.ttf) format('truetype');font-weight:400;font-style:italic}@font-face{font-family:KaTeX_SansSerif;src:url(fonts/KaTeX_SansSerif-Regular.eot);src:url(fonts/KaTeX_SansSerif-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_SansSerif-Regular.woff2) format('woff2'),url(fonts/KaTeX_SansSerif-Regular.woff) format('woff'),url(fonts/KaTeX_SansSerif-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Script;src:url(fonts/KaTeX_Script-Regular.eot);src:url(fonts/KaTeX_Script-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Script-Regular.woff2) format('woff2'),url(fonts/KaTeX_Script-Regular.woff) format('woff'),url(fonts/KaTeX_Script-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Size1;src:url(fonts/KaTeX_Size1-Regular.eot);src:url(fonts/KaTeX_Size1-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Size1-Regular.woff2) format('woff2'),url(fonts/KaTeX_Size1-Regular.woff) format('woff'),url(fonts/KaTeX_Size1-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Size2;src:url(fonts/KaTeX_Size2-Regular.eot);src:url(fonts/KaTeX_Size2-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Size2-Regular.woff2) format('woff2'),url(fonts/KaTeX_Size2-Regular.woff) format('woff'),url(fonts/KaTeX_Size2-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Size3;src:url(fonts/KaTeX_Size3-Regular.eot);src:url(fonts/KaTeX_Size3-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Size3-Regular.woff2) format('woff2'),url(fonts/KaTeX_Size3-Regular.woff) format('woff'),url(fonts/KaTeX_Size3-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Size4;src:url(fonts/KaTeX_Size4-Regular.eot);src:url(fonts/KaTeX_Size4-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Size4-Regular.woff2) format('woff2'),url(fonts/KaTeX_Size4-Regular.woff) format('woff'),url(fonts/KaTeX_Size4-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Typewriter;src:url(fonts/KaTeX_Typewriter-Regular.eot);src:url(fonts/KaTeX_Typewriter-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Typewriter-Regular.woff2) format('woff2'),url(fonts/KaTeX_Typewriter-Regular.woff) format('woff'),url(fonts/KaTeX_Typewriter-Regular.ttf) format('truetype');font-weight:400;font-style:normal}.katex-display{display:block;margin:1em 0;text-align:center}.katex-display>.katex{display:inline-block;text-align:initial}.katex{font:400 1.21em KaTeX_Main,Times New Roman,serif;line-height:1.2;white-space:nowrap;text-indent:0}.katex .katex-html{display:inline-block}.katex .katex-mathml{position:absolute;clip:rect(1px,1px,1px,1px);padding:0;border:0;height:1px;width:1px;overflow:hidden}.katex .base,.katex .strut{display:inline-block}.katex .mathrm{font-style:normal}.katex .textit{font-style:italic}.katex .mathit{font-family:KaTeX_Math;font-style:italic}.katex .mathbf{font-family:KaTeX_Main;font-weight:700}.katex .amsrm,.katex .mathbb{font-family:KaTeX_AMS}.katex .mathcal{font-family:KaTeX_Caligraphic}.katex .mathfrak{font-family:KaTeX_Fraktur}.katex .mathtt{font-family:KaTeX_Typewriter}.katex .mathscr{font-family:KaTeX_Script}.katex .mathsf{font-family:KaTeX_SansSerif}.katex .mainit{font-family:KaTeX_Main;font-style:italic}.katex .mord+.mop{margin-left:.16667em}.katex .mord+.mbin{margin-left:.22222em}.katex .mord+.mrel{margin-left:.27778em}.katex .mop+.mop,.katex .mop+.mord,.katex .mord+.minner{margin-left:.16667em}.katex .mop+.mrel{margin-left:.27778em}.katex .mop+.minner{margin-left:.16667em}.katex .mbin+.minner,.katex .mbin+.mop,.katex .mbin+.mopen,.katex .mbin+.mord{margin-left:.22222em}.katex .mrel+.minner,.katex .mrel+.mop,.katex .mrel+.mopen,.katex .mrel+.mord{margin-left:.27778em}.katex .mclose+.mop{margin-left:.16667em}.katex .mclose+.mbin{margin-left:.22222em}.katex .mclose+.mrel{margin-left:.27778em}.katex .mclose+.minner,.katex .minner+.mop,.katex .minner+.mord,.katex .mpunct+.mclose,.katex .mpunct+.minner,.katex .mpunct+.mop,.katex .mpunct+.mopen,.katex .mpunct+.mord,.katex .mpunct+.mpunct,.katex .mpunct+.mrel{margin-left:.16667em}.katex .minner+.mbin{margin-left:.22222em}.katex .minner+.mrel{margin-left:.27778em}.katex .minner+.minner,.katex .minner+.mopen,.katex .minner+.mpunct{margin-left:.16667em}.katex .mbin.mtight,.katex .mclose.mtight,.katex .minner.mtight,.katex .mop.mtight,.katex .mopen.mtight,.katex .mord.mtight,.katex .mpunct.mtight,.katex .mrel.mtight{margin-left:0}.katex .mclose+.mop.mtight,.katex .minner+.mop.mtight,.katex .mop+.mop.mtight,.katex .mop+.mord.mtight,.katex .mord+.mop.mtight{margin-left:.16667em}.katex .reset-textstyle.textstyle{font-size:1em}.katex .reset-textstyle.scriptstyle{font-size:.7em}.katex .reset-textstyle.scriptscriptstyle{font-size:.5em}.katex .reset-scriptstyle.textstyle{font-size:1.42857em}.katex .reset-scriptstyle.scriptstyle{font-size:1em}.katex .reset-scriptstyle.scriptscriptstyle{font-size:.71429em}.katex .reset-scriptscriptstyle.textstyle{font-size:2em}.katex .reset-scriptscriptstyle.scriptstyle{font-size:1.4em}.katex .reset-scriptscriptstyle.scriptscriptstyle{font-size:1em}.katex .style-wrap{position:relative}.katex .vlist{display:inline-block;margin-right: 0.15em;}.katex .vlist>span{display:block;height:0;position:relative}.katex .vlist>span>span{display:inline-block}.katex .vlist .baseline-fix{display:inline-table;table-layout:fixed}.katex .msupsub{text-align:left}.katex .mfrac>span>span{text-align:center}.katex .mfrac .frac-line{width:100%}.katex .mfrac .frac-line:before{border-bottom-style:solid;border-bottom-width:1px;content:"";display:block}.katex .mfrac .frac-line:after{border-bottom-style:solid;border-bottom-width:.04em;content:"";display:block;margin-top:-1px}.katex .mspace{display:inline-block}.katex .mspace.negativethinspace{margin-left:-.16667em}.katex .mspace.thinspace{width:.16667em}.katex .mspace.negativemediumspace{margin-left:-.22222em}.katex .mspace.mediumspace{width:.22222em}.katex .mspace.thickspace{width:.27778em}.katex .mspace.sixmuspace{width:.333333em}.katex .mspace.eightmuspace{width:.444444em}.katex .mspace.enspace{width:.5em}.katex .mspace.twelvemuspace{width:.666667em}.katex .mspace.quad{width:1em}.katex .mspace.qquad{width:2em}.katex .llap,.katex .rlap{width:0;position:relative}.katex .llap>.inner,.katex .rlap>.inner{position:absolute}.katex .llap>.fix,.katex .rlap>.fix{display:inline-block}.katex .llap>.inner{right:0}.katex .rlap>.inner{left:0}.katex .katex-logo .a{font-size:.75em;margin-left:-.32em;position:relative;top:-.2em}.katex .katex-logo .t{margin-left:-.23em}.katex .katex-logo .e{margin-left:-.1667em;position:relative;top:.2155em}.katex .katex-logo .x{margin-left:-.125em}.katex .rule{display:inline-block;border:0 solid;position:relative}.katex .overline .overline-line,.katex .underline .underline-line{width:100%}.katex .overline .overline-line:before,.katex .underline .underline-line:before{border-bottom-style:solid;border-bottom-width:1px;content:"";display:block}.katex .overline .overline-line:after,.katex .underline .underline-line:after{border-bottom-style:solid;border-bottom-width:.04em;content:"";display:block;margin-top:-1px}.katex .sqrt>.sqrt-sign{position:relative}.katex .sqrt .sqrt-line{width:100%}.katex .sqrt .sqrt-line:before{border-bottom-style:solid;border-bottom-width:1px;content:"";display:block}.katex .sqrt .sqrt-line:after{border-bottom-style:solid;border-bottom-width:.04em;content:"";display:block;margin-top:-1px}.katex .sqrt>.root{margin-left:.27777778em;margin-right:-.55555556em}.katex .fontsize-ensurer,.katex .sizing{display:inline-block}.katex .fontsize-ensurer.reset-size1.size1,.katex .sizing.reset-size1.size1{font-size:1em}.katex .fontsize-ensurer.reset-size1.size2,.katex .sizing.reset-size1.size2{font-size:1.4em}.katex .fontsize-ensurer.reset-size1.size3,.katex .sizing.reset-size1.size3{font-size:1.6em}.katex .fontsize-ensurer.reset-size1.size4,.katex .sizing.reset-size1.size4{font-size:1.8em}.katex .fontsize-ensurer.reset-size1.size5,.katex .sizing.reset-size1.size5{font-size:2em}.katex .fontsize-ensurer.reset-size1.size6,.katex .sizing.reset-size1.size6{font-size:2.4em}.katex .fontsize-ensurer.reset-size1.size7,.katex .sizing.reset-size1.size7{font-size:2.88em}.katex .fontsize-ensurer.reset-size1.size8,.katex .sizing.reset-size1.size8{font-size:3.46em}.katex .fontsize-ensurer.reset-size1.size9,.katex .sizing.reset-size1.size9{font-size:4.14em}.katex .fontsize-ensurer.reset-size1.size10,.katex .sizing.reset-size1.size10{font-size:4.98em}.katex .fontsize-ensurer.reset-size2.size1,.katex .sizing.reset-size2.size1{font-size:.71428571em}.katex .fontsize-ensurer.reset-size2.size2,.katex .sizing.reset-size2.size2{font-size:1em}.katex .fontsize-ensurer.reset-size2.size3,.katex .sizing.reset-size2.size3{font-size:1.14285714em}.katex .fontsize-ensurer.reset-size2.size4,.katex .sizing.reset-size2.size4{font-size:1.28571429em}.katex .fontsize-ensurer.reset-size2.size5,.katex .sizing.reset-size2.size5{font-size:1.42857143em}.katex .fontsize-ensurer.reset-size2.size6,.katex .sizing.reset-size2.size6{font-size:1.71428571em}.katex .fontsize-ensurer.reset-size2.size7,.katex .sizing.reset-size2.size7{font-size:2.05714286em}.katex .fontsize-ensurer.reset-size2.size8,.katex .sizing.reset-size2.size8{font-size:2.47142857em}.katex .fontsize-ensurer.reset-size2.size9,.katex .sizing.reset-size2.size9{font-size:2.95714286em}.katex .fontsize-ensurer.reset-size2.size10,.katex .sizing.reset-size2.size10{font-size:3.55714286em}.katex .fontsize-ensurer.reset-size3.size1,.katex .sizing.reset-size3.size1{font-size:.625em}.katex .fontsize-ensurer.reset-size3.size2,.katex .sizing.reset-size3.size2{font-size:.875em}.katex .fontsize-ensurer.reset-size3.size3,.katex .sizing.reset-size3.size3{font-size:1em}.katex .fontsize-ensurer.reset-size3.size4,.katex .sizing.reset-size3.size4{font-size:1.125em}.katex .fontsize-ensurer.reset-size3.size5,.katex .sizing.reset-size3.size5{font-size:1.25em}.katex .fontsize-ensurer.reset-size3.size6,.katex .sizing.reset-size3.size6{font-size:1.5em}.katex .fontsize-ensurer.reset-size3.size7,.katex .sizing.reset-size3.size7{font-size:1.8em}.katex .fontsize-ensurer.reset-size3.size8,.katex .sizing.reset-size3.size8{font-size:2.1625em}.katex .fontsize-ensurer.reset-size3.size9,.katex .sizing.reset-size3.size9{font-size:2.5875em}.katex .fontsize-ensurer.reset-size3.size10,.katex .sizing.reset-size3.size10{font-size:3.1125em}.katex .fontsize-ensurer.reset-size4.size1,.katex .sizing.reset-size4.size1{font-size:.55555556em}.katex .fontsize-ensurer.reset-size4.size2,.katex .sizing.reset-size4.size2{font-size:.77777778em}.katex .fontsize-ensurer.reset-size4.size3,.katex .sizing.reset-size4.size3{font-size:.88888889em}.katex .fontsize-ensurer.reset-size4.size4,.katex .sizing.reset-size4.size4{font-size:1em}.katex .fontsize-ensurer.reset-size4.size5,.katex .sizing.reset-size4.size5{font-size:1.11111111em}.katex .fontsize-ensurer.reset-size4.size6,.katex .sizing.reset-size4.size6{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size4.size7,.katex .sizing.reset-size4.size7{font-size:1.6em}.katex .fontsize-ensurer.reset-size4.size8,.katex .sizing.reset-size4.size8{font-size:1.92222222em}.katex .fontsize-ensurer.reset-size4.size9,.katex .sizing.reset-size4.size9{font-size:2.3em}.katex .fontsize-ensurer.reset-size4.size10,.katex .sizing.reset-size4.size10{font-size:2.76666667em}.katex .fontsize-ensurer.reset-size5.size1,.katex .sizing.reset-size5.size1{font-size:.5em}.katex .fontsize-ensurer.reset-size5.size2,.katex .sizing.reset-size5.size2{font-size:.7em}.katex .fontsize-ensurer.reset-size5.size3,.katex .sizing.reset-size5.size3{font-size:.8em}.katex .fontsize-ensurer.reset-size5.size4,.katex .sizing.reset-size5.size4{font-size:.9em}.katex .fontsize-ensurer.reset-size5.size5,.katex .sizing.reset-size5.size5{font-size:1em}.katex .fontsize-ensurer.reset-size5.size6,.katex .sizing.reset-size5.size6{font-size:1.2em}.katex .fontsize-ensurer.reset-size5.size7,.katex .sizing.reset-size5.size7{font-size:1.44em}.katex .fontsize-ensurer.reset-size5.size8,.katex .sizing.reset-size5.size8{font-size:1.73em}.katex .fontsize-ensurer.reset-size5.size9,.katex .sizing.reset-size5.size9{font-size:2.07em}.katex .fontsize-ensurer.reset-size5.size10,.katex .sizing.reset-size5.size10{font-size:2.49em}.katex .fontsize-ensurer.reset-size6.size1,.katex .sizing.reset-size6.size1{font-size:.41666667em}.katex .fontsize-ensurer.reset-size6.size2,.katex .sizing.reset-size6.size2{font-size:.58333333em}.katex .fontsize-ensurer.reset-size6.size3,.katex .sizing.reset-size6.size3{font-size:.66666667em}.katex .fontsize-ensurer.reset-size6.size4,.katex .sizing.reset-size6.size4{font-size:.75em}.katex .fontsize-ensurer.reset-size6.size5,.katex .sizing.reset-size6.size5{font-size:.83333333em}.katex .fontsize-ensurer.reset-size6.size6,.katex .sizing.reset-size6.size6{font-size:1em}.katex .fontsize-ensurer.reset-size6.size7,.katex .sizing.reset-size6.size7{font-size:1.2em}.katex .fontsize-ensurer.reset-size6.size8,.katex .sizing.reset-size6.size8{font-size:1.44166667em}.katex .fontsize-ensurer.reset-size6.size9,.katex .sizing.reset-size6.size9{font-size:1.725em}.katex .fontsize-ensurer.reset-size6.size10,.katex .sizing.reset-size6.size10{font-size:2.075em}.katex .fontsize-ensurer.reset-size7.size1,.katex .sizing.reset-size7.size1{font-size:.34722222em}.katex .fontsize-ensurer.reset-size7.size2,.katex .sizing.reset-size7.size2{font-size:.48611111em}.katex .fontsize-ensurer.reset-size7.size3,.katex .sizing.reset-size7.size3{font-size:.55555556em}.katex .fontsize-ensurer.reset-size7.size4,.katex .sizing.reset-size7.size4{font-size:.625em}.katex .fontsize-ensurer.reset-size7.size5,.katex .sizing.reset-size7.size5{font-size:.69444444em}.katex .fontsize-ensurer.reset-size7.size6,.katex .sizing.reset-size7.size6{font-size:.83333333em}.katex .fontsize-ensurer.reset-size7.size7,.katex .sizing.reset-size7.size7{font-size:1em}.katex .fontsize-ensurer.reset-size7.size8,.katex .sizing.reset-size7.size8{font-size:1.20138889em}.katex .fontsize-ensurer.reset-size7.size9,.katex .sizing.reset-size7.size9{font-size:1.4375em}.katex .fontsize-ensurer.reset-size7.size10,.katex .sizing.reset-size7.size10{font-size:1.72916667em}.katex .fontsize-ensurer.reset-size8.size1,.katex .sizing.reset-size8.size1{font-size:.28901734em}.katex .fontsize-ensurer.reset-size8.size2,.katex .sizing.reset-size8.size2{font-size:.40462428em}.katex .fontsize-ensurer.reset-size8.size3,.katex .sizing.reset-size8.size3{font-size:.46242775em}.katex .fontsize-ensurer.reset-size8.size4,.katex .sizing.reset-size8.size4{font-size:.52023121em}.katex .fontsize-ensurer.reset-size8.size5,.katex .sizing.reset-size8.size5{font-size:.57803468em}.katex .fontsize-ensurer.reset-size8.size6,.katex .sizing.reset-size8.size6{font-size:.69364162em}.katex .fontsize-ensurer.reset-size8.size7,.katex .sizing.reset-size8.size7{font-size:.83236994em}.katex .fontsize-ensurer.reset-size8.size8,.katex .sizing.reset-size8.size8{font-size:1em}.katex .fontsize-ensurer.reset-size8.size9,.katex .sizing.reset-size8.size9{font-size:1.19653179em}.katex .fontsize-ensurer.reset-size8.size10,.katex .sizing.reset-size8.size10{font-size:1.43930636em}.katex .fontsize-ensurer.reset-size9.size1,.katex .sizing.reset-size9.size1{font-size:.24154589em}.katex .fontsize-ensurer.reset-size9.size2,.katex .sizing.reset-size9.size2{font-size:.33816425em}.katex .fontsize-ensurer.reset-size9.size3,.katex .sizing.reset-size9.size3{font-size:.38647343em}.katex .fontsize-ensurer.reset-size9.size4,.katex .sizing.reset-size9.size4{font-size:.43478261em}.katex .fontsize-ensurer.reset-size9.size5,.katex .sizing.reset-size9.size5{font-size:.48309179em}.katex .fontsize-ensurer.reset-size9.size6,.katex .sizing.reset-size9.size6{font-size:.57971014em}.katex .fontsize-ensurer.reset-size9.size7,.katex .sizing.reset-size9.size7{font-size:.69565217em}.katex .fontsize-ensurer.reset-size9.size8,.katex .sizing.reset-size9.size8{font-size:.83574879em}.katex .fontsize-ensurer.reset-size9.size9,.katex .sizing.reset-size9.size9{font-size:1em}.katex .fontsize-ensurer.reset-size9.size10,.katex .sizing.reset-size9.size10{font-size:1.20289855em}.katex .fontsize-ensurer.reset-size10.size1,.katex .sizing.reset-size10.size1{font-size:.20080321em}.katex .fontsize-ensurer.reset-size10.size2,.katex .sizing.reset-size10.size2{font-size:.2811245em}.katex .fontsize-ensurer.reset-size10.size3,.katex .sizing.reset-size10.size3{font-size:.32128514em}.katex .fontsize-ensurer.reset-size10.size4,.katex .sizing.reset-size10.size4{font-size:.36144578em}.katex .fontsize-ensurer.reset-size10.size5,.katex .sizing.reset-size10.size5{font-size:.40160643em}.katex .fontsize-ensurer.reset-size10.size6,.katex .sizing.reset-size10.size6{font-size:.48192771em}.katex .fontsize-ensurer.reset-size10.size7,.katex .sizing.reset-size10.size7{font-size:.57831325em}.katex .fontsize-ensurer.reset-size10.size8,.katex .sizing.reset-size10.size8{font-size:.69477912em}.katex .fontsize-ensurer.reset-size10.size9,.katex .sizing.reset-size10.size9{font-size:.8313253em}.katex .fontsize-ensurer.reset-size10.size10,.katex .sizing.reset-size10.size10{font-size:1em}.katex .delimsizing.size1{font-family:KaTeX_Size1}.katex .delimsizing.size2{font-family:KaTeX_Size2}.katex .delimsizing.size3{font-family:KaTeX_Size3}.katex .delimsizing.size4{font-family:KaTeX_Size4}.katex .delimsizing.mult .delim-size1>span{font-family:KaTeX_Size1}.katex .delimsizing.mult .delim-size4>span{font-family:KaTeX_Size4}.katex .nulldelimiter{display:inline-block;width:.12em}.katex .op-symbol{position:relative}.katex .op-symbol.small-op{font-family:KaTeX_Size1}.katex .op-symbol.large-op{font-family:KaTeX_Size2}.katex .accent>.vlist>span,.katex .op-limits>.vlist>span{text-align:center}.katex .accent .accent-body>span{width:0}.katex .accent .accent-body.accent-vec>span{position:relative;left:.326em}.katex .mtable .vertical-separator{display:inline-block;margin:0 -.025em;border-right:.05em solid #000}.katex .mtable .arraycolsep{display:inline-block}.katex .mtable .col-align-c>.vlist{text-align:center}.katex .mtable .col-align-l>.vlist{text-align:left}.katex .mtable .col-align-r>.vlist{text-align:right} \ No newline at end of file diff --git a/app/src/main/assets/js/KaTeX/katex.min.js b/app/src/main/assets/js/KaTeX/katex.min.js new file mode 100644 index 0000000..66c0821 --- /dev/null +++ b/app/src/main/assets/js/KaTeX/katex.min.js @@ -0,0 +1,4 @@ +(function(e){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=e()}else if(typeof define==="function"&&define.amd){define([],e)}else{var t;if(typeof window!=="undefined"){t=window}else if(typeof global!=="undefined"){t=global}else if(typeof self!=="undefined"){t=self}else{t=this}t.katex=e()}})(function(){var e,t,r;return function a(e,t,r){function i(s,l){if(!t[s]){if(!e[s]){var o=typeof require=="function"&&require;if(!l&&o)return o(s,!0);if(n)return n(s,!0);var u=new Error("Cannot find module '"+s+"'");throw u.code="MODULE_NOT_FOUND",u}var p=t[s]={exports:{}};e[s][0].call(p.exports,function(t){var r=e[s][1][t];return i(r?r:t)},p,p.exports,a,e,t,r)}return t[s].exports}var n=typeof require=="function"&&require;for(var s=0;s15){o="\u2026"+s.slice(i-15,i)}else{o=s.slice(0,i)}var u;if(n+15v){return this.parseFunction(i)}else{throw new p("Got function '"+i.result+"' with no arguments "+"as "+e,t)}}else{return i.result}};h.prototype.handleUnsupportedCmd=function(){var e=this.nextToken.text;var t=[];for(var r=0;ri){c=this.parseFunction(h)}else{throw new p("Got function '"+h.result+"' as "+"argument to '"+e+"'",o)}}else{c=h.result}s.push(c);n.push(this.pos)}s.push(n);return s};h.prototype.parseGroupOfType=function(e,t){var r=this.mode;if(e==="original"){e=r}if(e==="color"){return this.parseColorGroup(t)}if(e==="size"){return this.parseSizeGroup(t)}this.switchMode(e);if(e==="text"){while(this.nextToken.text===" "){this.consume()}}var a=this.parseGroup(t);this.switchMode(r);return a};h.prototype.parseStringGroup=function(e,t){if(t&&this.nextToken.text!=="["){return null}var r=this.mode;this.mode="text";this.expect(t?"[":"{");var a="";var i=this.nextToken;var n=i;while(this.nextToken.text!==(t?"]":"}")){if(this.nextToken.text==="EOF"){throw new p("Unexpected end of input in "+e,i.range(this.nextToken,a))}n=this.nextToken;a+=n.text;this.consume()}this.mode=r;this.expect(t?"]":"}");return i.range(n,a)};h.prototype.parseRegexGroup=function(e,t){var r=this.mode;this.mode="text";var a=this.nextToken;var i=a;var n="";while(this.nextToken.text!=="EOF"&&e.test(n+this.nextToken.text)){i=this.nextToken;n+=i.text;this.consume()}if(n===""){throw new p("Invalid "+t+": '"+a.text+"'",a)}this.mode=r;return a.range(i,n)};h.prototype.parseColorGroup=function(e){var t=this.parseStringGroup("color",e);if(!t){return null}var r=/^(#[a-z0-9]+|[a-z]+)$/i.exec(t.text);if(!r){throw new p("Invalid color: '"+t.text+"'",t)}return new m(new c("color",r[0],this.mode),false)};h.prototype.parseSizeGroup=function(e){var t;if(!e&&this.nextToken.text!=="{"){t=this.parseRegexGroup(/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2}$/,"size")}else{t=this.parseStringGroup("size",e)}if(!t){return null}var r=/([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(t.text);if(!r){throw new p("Invalid size: '"+t.text+"'",t)}var a={number:+(r[1]+r[2]),unit:r[3]};if(a.unit!=="em"&&a.unit!=="ex"&&a.unit!=="mu"){throw new p("Invalid unit: '"+a.unit+"'",t)}return new m(new c("color",a,this.mode),false)};h.prototype.parseGroup=function(e){var t=this.nextToken;if(this.nextToken.text===(e?"[":"{")){this.consume();var r=this.parseExpression(false,e?"]":null);var a=this.nextToken;this.expect(e?"]":"}");if(this.mode==="text"){this.formLigatures(r)}return new m(new c("ordgroup",r,this.mode,t,a),false)}else{return e?null:this.parseSymbol()}};h.prototype.formLigatures=function(e){var t;var r=e.length-1;for(t=0;t0?t-1:0]}l.prototype.sup=function(){return y[x[this.id]]};l.prototype.sub=function(){return y[b[this.id]]};l.prototype.fracNum=function(){return y[w[this.id]]};l.prototype.fracDen=function(){return y[k[this.id]]};l.prototype.cramp=function(){return y[z[this.id]]};l.prototype.cls=function(){return d[this.size]+(this.cramped?" cramped":" uncramped")};l.prototype.reset=function(){return g[this.size]};l.prototype.isTight=function(){return this.size>=2};var o=0;var u=1;var p=2;var h=3;var c=4;var m=5;var f=6;var v=7;var d=["displaystyle textstyle","textstyle","scriptstyle","scriptscriptstyle"];var g=["reset-textstyle","reset-textstyle","reset-scriptstyle","reset-scriptscriptstyle"];var y=[new l(o,0,1,false),new l(u,0,1,true),new l(p,1,1,false),new l(h,1,1,true),new l(c,2,.7,false),new l(m,2,.7,true),new l(f,3,.5,false),new l(v,3,.5,true)];var x=[c,m,c,m,f,v,f,v];var b=[m,m,m,m,v,v,v,v];var w=[p,h,c,m,f,v,f,v];var k=[h,h,m,m,v,v,v,v];var z=[u,u,h,h,m,m,v,v];t.exports={DISPLAY:y[o],TEXT:y[p],SCRIPT:y[c],SCRIPTSCRIPT:y[f]}},{"./fontMetrics.js":17}],10:[function(e,t,r){var a=e("./domTree");var i=e("./fontMetrics");var n=e("./symbols");var s=e("./utils");var l=["\\Gamma","\\Delta","\\Theta","\\Lambda","\\Xi","\\Pi","\\Sigma","\\Upsilon","\\Phi","\\Psi","\\Omega"];var o=["\u0131","\u0237","\xa3"];var u=function(e,t,r,s,l){if(n[r][e]&&n[r][e].replace){e=n[r][e].replace}var o=i.getCharacterMetrics(e,t);var u;if(o){var p=o.italic;if(r==="text"){p=0}u=new a.symbolNode(e,o.height,o.depth,p,o.skew,l)}else{typeof console!=="undefined"&&console.warn("No character metrics for '"+e+"' in style '"+t+"'");u=new a.symbolNode(e,0,0,0,0,l)}if(s){if(s.style.isTight()){u.classes.push("mtight")}if(s.getColor()){u.style.color=s.getColor()}}return u};var p=function(e,t,r,a){if(e==="\\"||n[t][e].font==="main"){return u(e,"Main-Regular",t,r,a)}else{return u(e,"AMS-Regular",t,r,a.concat(["amsrm"]))}};var h=function(e,t,r,a,i){if(i==="mathord"){return c(e,t,r,a)}else if(i==="textord"){return u(e,"Main-Regular",t,r,a.concat(["mathrm"]))}else{throw new Error("unexpected type: "+i+" in mathDefault")}};var c=function(e,t,r,a){if(/[0-9]/.test(e.charAt(0))||s.contains(o,e)||s.contains(l,e)){return u(e,"Main-Italic",t,r,a.concat(["mainit"]))}else{return u(e,"Math-Italic",t,r,a.concat(["mathit"]))}};var m=function(e,t,r){var a=e.mode;var l=e.value;if(n[a][l]&&n[a][l].replace){l=n[a][l].replace}var p=["mord"];var m=t.font;if(m){if(m==="mathit"||s.contains(o,l)){return c(l,a,t,p)}else{var f=k[m].fontName;if(i.getCharacterMetrics(l,f)){return u(l,f,a,t,p.concat([m]))}else{return h(l,a,t,p,r)}}}else{return h(l,a,t,p,r)}};var f=function(e){var t=0;var r=0;var a=0;if(e.children){for(var i=0;it){t=e.children[i].height}if(e.children[i].depth>r){r=e.children[i].depth}if(e.children[i].maxFontSize>a){a=e.children[i].maxFontSize}}}e.height=t;e.depth=r;e.maxFontSize=a};var v=function(e,t,r){var i=new a.span(e,t,r);f(i);return i};var d=function(e,t){e.children=t.concat(e.children);f(e)};var g=function(e){var t=new a.documentFragment(e);f(t);return t};var y=function(e,t){var r=v([],[new a.symbolNode("\u200b")]);r.style.fontSize=t/e.style.sizeMultiplier+"em";var i=v(["fontsize-ensurer","reset-"+e.size,"size5"],[r]);return i};var x=function(e,t,r,i){var n;var s;var l;if(t==="individualShift"){var o=e;e=[o[0]];n=-o[0].shift-o[0].elem.depth;s=n;for(l=1;l0){f+=T;v-=T}}S=n.makeVList([{type:"elem",elem:s,shift:v},{type:"elem",elem:a,shift:-f}],"individualShift",null,t);if(r instanceof l.symbolNode){S.children[0].style.marginLeft=-r.italic+"em"}S.children[0].style.marginRight=k;S.children[1].style.marginRight=k}var A=d(r)||"mord";return p([A],[r,p(["msupsub"],[S])],t)};w.genfrac=function(e,t){var r=t.style;if(e.value.size==="display"){r=i.DISPLAY}else if(e.value.size==="text"){r=i.TEXT}var a=r.fracNum();var l=r.fracDen();var u;u=t.withStyle(a);var h=z(e.value.numer,u);var c=p([r.reset(),a.cls()],[h],u);u=t.withStyle(l);var m=z(e.value.denom,u);var f=p([r.reset(),l.cls()],[m],u);var v;if(e.value.hasBarLine){v=o.metrics.defaultRuleThickness/t.style.sizeMultiplier}else{v=0}var d;var g;var y;if(r.size===i.DISPLAY.size){d=r.metrics.num1;if(v>0){g=3*v}else{g=7*o.metrics.defaultRuleThickness}y=r.metrics.denom1}else{if(v>0){d=r.metrics.num2;g=v}else{d=r.metrics.num3;g=3*o.metrics.defaultRuleThickness}y=r.metrics.denom2}var x;if(v===0){var w=d-h.depth-(m.height-y);if(w0){N+=x;if(M=l){continue}var I;if(i>0||e.value.hskipBeforeAndAfter){I=u.deflt(O.pregap,f);if(I!==0){C=p(["arraycolsep"],[]);C.style.width=I+"em";E.push(C)}}var L=[];for(r=0;ra.height+a.depth+c){c=(c+d-a.height-a.depth)/2}var g=-(a.height+c+l)+v.height;v.style.top=g+"em";v.height-=g;v.depth+=g;var y;if(a.height===0&&a.depth===0){y=p()}else{y=n.makeVList([{type:"elem",elem:a},{type:"kern",size:c},{type:"elem",elem:u},{type:"kern",size:l}],"firstBaseline",null,t)}if(!e.value.index){return p(["mord","sqrt"],[v,y],t)}else{var x=t.withStyle(i.SCRIPTSCRIPT);var b=z(e.value.index,x);var w=p([r.reset(),i.SCRIPTSCRIPT.cls()],[b],x);var k=Math.max(v.height,y.height);var S=Math.max(v.depth,y.depth);var M=.6*(k-S);var T=n.makeVList([{type:"elem",elem:w}],"shift",-M,t);var A=p(["root"],[T]);return p(["mord","sqrt"],[A,v,y],t)}};w.sizing=function(e,t){var r=v(e.value.value,t.withSize(e.value.size),false);var a=t.style;var i=n.sizingMultiplier[e.value.size];i=i*a.sizeMultiplier;for(var s=0;s","\\langle","\\rangle","/","\\backslash","\\lt","\\gt"];var b=[0,1.2,1.8,2.4,3];var w=function(e,t,r,i,n){if(e==="<"||e==="\\lt"){e="\\langle"}else if(e===">"||e==="\\gt"){e="\\rangle"}if(o.contains(g,e)||o.contains(x,e)){return f(e,t,false,r,i,n)}else if(o.contains(y,e)){return d(e,b[t],false,r,i,n)}else{throw new a("Illegal delimiter: '"+e+"'")}};var k=[{type:"small",style:i.SCRIPTSCRIPT},{type:"small",style:i.SCRIPT},{type:"small",style:i.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4}];var z=[{type:"small",style:i.SCRIPTSCRIPT},{type:"small",style:i.SCRIPT},{type:"small",style:i.TEXT},{type:"stack"}];var S=[{type:"small",style:i.SCRIPTSCRIPT},{type:"small",style:i.SCRIPT},{type:"small",style:i.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4},{type:"stack"}];var M=function(e){if(e.type==="small"){return"Main-Regular"}else if(e.type==="large"){return"Size"+e.size+"-Regular"}else if(e.type==="stack"){return"Size4-Regular"}};var T=function(e,t,r,a){var i=Math.min(2,3-a.style.size);for(var n=i;nt){return r[n]}}return r[r.length-1]};var A=function(e,t,r,a,i,n){if(e==="<"||e==="\\lt"){e="\\langle"}else if(e===">"||e==="\\gt"){e="\\rangle"}var s;if(o.contains(x,e)){s=k}else if(o.contains(g,e)){s=S}else{s=z}var l=T(e,t,s,a);if(l.type==="small"){return m(e,l.style,r,a,i,n)}else if(l.type==="large"){return f(e,l.size,r,a,i,n)}else if(l.type==="stack"){return d(e,t,r,a,i,n)}};var N=function(e,t,r,a,i,n){var l=a.style.metrics.axisHeight*a.style.sizeMultiplier;var o=901;var u=5/s.metrics.ptPerEm;var p=Math.max(t-l,r+l);var h=Math.max(p/500*o,2*p-u);return A(e,h,true,a,i,n)};t.exports={sizedDelim:w,customSizedDelim:A,leftRightDelim:N}},{"./ParseError":6,"./Style":9,"./buildCommon":10,"./fontMetrics":17,"./symbols":23,"./utils":25}],15:[function(e,t,r){var a=e("./unicodeRegexes");var i=e("./utils");var n=function(e){e=e.slice();for(var t=e.length-1;t>=0;t--){if(!e[t]){e.splice(t,1)}}return e.join(" ")};function s(e,t,r){this.classes=e||[];this.children=t||[];this.height=0;this.depth=0;this.maxFontSize=0;this.style={};this.attributes={};if(r){if(r.style.isTight()){this.classes.push("mtight")}if(r.getColor()){this.style.color=r.getColor()}}}s.prototype.setAttribute=function(e,t){this.attributes[e]=t};s.prototype.tryCombine=function(e){return false};s.prototype.toNode=function(){var e=document.createElement("span");e.className=n(this.classes);for(var t in this.style){if(Object.prototype.hasOwnProperty.call(this.style,t)){e.style[t]=this.style[t]}}for(var r in this.attributes){if(Object.prototype.hasOwnProperty.call(this.attributes,r)){e.setAttribute(r,this.attributes[r])}}for(var a=0;a";return e};function l(e){this.children=e||[];this.height=0;this.depth=0;this.maxFontSize=0}l.prototype.toNode=function(){var e=document.createDocumentFragment();for(var t=0;t0||n(this.classes)!==n(e.classes)||this.skew!==e.skew||this.maxFontSize!==e.maxFontSize){return false}for(var t in this.style){if(this.style.hasOwnProperty(t)&&this.style[t]!==e.style[t]){return false}}for(t in e.style){if(e.style.hasOwnProperty(t)&&this.style[t]!==e.style[t]){return false}}this.value+=e.value;this.height=Math.max(this.height,e.height);this.depth=Math.max(this.depth,e.depth);this.italic=e.italic;return true};u.prototype.toNode=function(){var e=document.createTextNode(this.value);var t=null;if(this.italic>0){t=document.createElement("span");t.style.marginRight=this.italic+"em"}if(this.classes.length>0){t=t||document.createElement("span");t.className=n(this.classes)}for(var r in this.style){if(this.style.hasOwnProperty(r)){t=t||document.createElement("span");t.style[r]=this.style[r]}}if(t){t.appendChild(e);return t}else{return e}};u.prototype.toMarkup=function(){var e=false;var t="0){r+="margin-right:"+this.italic+"em;"}for(var a in this.style){if(this.style.hasOwnProperty(a)){r+=i.hyphenate(a)+":"+this.style[a]+";"}}if(r){e=true;t+=' style="'+i.escape(r)+'"'}var s=i.escape(this.value);if(e){t+=">";t+=s;t+="";return t}else{return s}};t.exports={span:s,documentFragment:l,symbolNode:u}},{"./unicodeRegexes":24,"./utils":25}],16:[function(e,t,r){var a=e("./parseData");var i=e("./ParseError");var n=e("./Style");var s=a.ParseNode;function l(e,t){var r=[];var a=[r];var n=[];while(true){var l=e.parseExpression(false,null);r.push(new s("ordgroup",l,e.mode));var o=e.nextToken.text;if(o==="&"){e.consume()}else if(o==="\\end"){break}else if(o==="\\\\"||o==="\\cr"){var u=e.parseFunction();n.push(u.value.size);r=[];a.push(r)}else{throw new i("Expected & or \\\\ or \\end",e.nextToken)}}t.body=a;t.rowGaps=n;return new s(t.type,t,e.mode)}function o(e,r,a){if(typeof e==="string"){e=[e]}if(typeof r==="number"){r={numArgs:r}}var i={numArgs:r.numArgs||0,argTypes:r.argTypes,greediness:1,allowedInText:!!r.allowedInText,numOptionalArgs:r.numOptionalArgs||0,handler:a};for(var n=0;n0){o=2}t.value.cols[i]={type:"align",align:n,pregap:o,postgap:0}}return t})},{"./ParseError":6,"./Style":9,"./parseData":21}],17:[function(e,t,r){var a=e("./Style");var i=e("./unicodeRegexes").cjkRegex;var n={slant:[.25,.25,.25],space:[0,0,0],stretch:[0,0,0],shrink:[0,0,0],xHeight:[.431,.431,.431],quad:[1,1.171,1.472],extraSpace:[0,0,0],num1:[.677,.732,.925],num2:[.394,.384,.387],num3:[.444,.471,.504],denom1:[.686,.752,1.025],denom2:[.345,.344,.532],sup1:[.413,.503,.504],sup2:[.363,.431,.404],sup3:[.289,.286,.294],sub1:[.15,.143,.2],sub2:[.247,.286,.4],supDrop:[.386,.353,.494],subDrop:[.05,.071,.1],delim1:[2.39,1.7,1.98],delim2:[1.01,1.157,1.42],axisHeight:[.25,.25,.25]};var s=0;var l=0;var o=0;var u=0;var p=.431;var h=1;var c=0;var m=.04;var f=.111;var v=.166;var d=.2;var g=.6;var y=.1;var x=10;var b=2/x;var w={defaultRuleThickness:m,bigOpSpacing1:f,bigOpSpacing2:v,bigOpSpacing3:d,bigOpSpacing4:g,bigOpSpacing5:y,ptPerEm:x,doubleRuleSep:b};var k=e("./fontMetricsData");var z={"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xc6":"A","\xc7":"C","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xd0":"D","\xd1":"N","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xdd":"Y","\xde":"o","\xdf":"B","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xe6":"a","\xe7":"c","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xf0":"d","\xf1":"n","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xfd":"y","\xfe":"o","\xff":"y","\u0410":"A","\u0411":"B","\u0412":"B","\u0413":"F","\u0414":"A","\u0415":"E","\u0416":"K","\u0417":"3","\u0418":"N","\u0419":"N","\u041a":"K","\u041b":"N","\u041c":"M","\u041d":"H","\u041e":"O","\u041f":"N","\u0420":"P","\u0421":"C","\u0422":"T","\u0423":"y","\u0424":"O","\u0425":"X","\u0426":"U","\u0427":"h","\u0428":"W","\u0429":"W","\u042a":"B","\u042b":"X","\u042c":"B","\u042d":"3","\u042e":"X","\u042f":"R","\u0430":"a","\u0431":"b","\u0432":"a","\u0433":"r","\u0434":"y","\u0435":"e","\u0436":"m","\u0437":"e","\u0438":"n","\u0439":"n","\u043a":"n","\u043b":"n","\u043c":"m","\u043d":"n","\u043e":"o","\u043f":"n","\u0440":"p","\u0441":"c","\u0442":"o","\u0443":"y","\u0444":"b","\u0445":"x","\u0446":"n","\u0447":"n","\u0448":"w","\u0449":"w","\u044a":"a","\u044b":"m","\u044c":"a","\u044d":"e","\u044e":"m","\u044f":"r"};var S=function(e,t){var r=e.charCodeAt(0);if(e[0]in z){r=z[e[0]].charCodeAt(0)}else if(i.test(e[0])){r="M".charCodeAt(0)}var a=k[t][r];if(a){return{depth:a[0],height:a[1],italic:a[2],skew:a[3],width:a[4]}}};t.exports={metrics:w,sigmas:n,getCharacterMetrics:S}},{"./Style":9,"./fontMetricsData":18,"./unicodeRegexes":24}],18:[function(e,t,r){t.exports={"AMS-Regular":{65:[0,.68889,0,0],66:[0,.68889,0,0],67:[0,.68889,0,0],68:[0,.68889,0,0],69:[0,.68889,0,0],70:[0,.68889,0,0],71:[0,.68889,0,0],72:[0,.68889,0,0],73:[0,.68889,0,0],74:[.16667,.68889,0,0],75:[0,.68889,0,0],76:[0,.68889,0,0],77:[0,.68889,0,0],78:[0,.68889,0,0],79:[.16667,.68889,0,0],80:[0,.68889,0,0],81:[.16667,.68889,0,0],82:[0,.68889,0,0],83:[0,.68889,0,0],84:[0,.68889,0,0],85:[0,.68889,0,0],86:[0,.68889,0,0],87:[0,.68889,0,0],88:[0,.68889,0,0],89:[0,.68889,0,0],90:[0,.68889,0,0],107:[0,.68889,0,0],165:[0,.675,.025,0],174:[.15559,.69224,0,0],240:[0,.68889,0,0],295:[0,.68889,0,0],710:[0,.825,0,0],732:[0,.9,0,0],770:[0,.825,0,0],771:[0,.9,0,0],989:[.08167,.58167,0,0],1008:[0,.43056,.04028,0],8245:[0,.54986,0,0],8463:[0,.68889,0,0],8487:[0,.68889,0,0],8498:[0,.68889,0,0],8502:[0,.68889,0,0],8503:[0,.68889,0,0],8504:[0,.68889,0,0],8513:[0,.68889,0,0],8592:[-.03598,.46402,0,0],8594:[-.03598,.46402,0,0],8602:[-.13313,.36687,0,0],8603:[-.13313,.36687,0,0],8606:[.01354,.52239,0,0],8608:[.01354,.52239,0,0],8610:[.01354,.52239,0,0],8611:[.01354,.52239,0,0],8619:[0,.54986,0,0],8620:[0,.54986,0,0],8621:[-.13313,.37788,0,0],8622:[-.13313,.36687,0,0],8624:[0,.69224,0,0],8625:[0,.69224,0,0],8630:[0,.43056,0,0],8631:[0,.43056,0,0],8634:[.08198,.58198,0,0],8635:[.08198,.58198,0,0],8638:[.19444,.69224,0,0],8639:[.19444,.69224,0,0],8642:[.19444,.69224,0,0],8643:[.19444,.69224,0,0],8644:[.1808,.675,0,0],8646:[.1808,.675,0,0],8647:[.1808,.675,0,0],8648:[.19444,.69224,0,0],8649:[.1808,.675,0,0],8650:[.19444,.69224,0,0],8651:[.01354,.52239,0,0],8652:[.01354,.52239,0,0],8653:[-.13313,.36687,0,0],8654:[-.13313,.36687,0,0],8655:[-.13313,.36687,0,0],8666:[.13667,.63667,0,0],8667:[.13667,.63667,0,0],8669:[-.13313,.37788,0,0],8672:[-.064,.437,0,0],8674:[-.064,.437,0,0],8705:[0,.825,0,0],8708:[0,.68889,0,0],8709:[.08167,.58167,0,0],8717:[0,.43056,0,0],8722:[-.03598,.46402,0,0],8724:[.08198,.69224,0,0],8726:[.08167,.58167,0,0],8733:[0,.69224,0,0],8736:[0,.69224,0,0],8737:[0,.69224,0,0],8738:[.03517,.52239,0,0],8739:[.08167,.58167,0,0],8740:[.25142,.74111,0,0],8741:[.08167,.58167,0,0],8742:[.25142,.74111,0,0],8756:[0,.69224,0,0],8757:[0,.69224,0,0],8764:[-.13313,.36687,0,0],8765:[-.13313,.37788,0,0],8769:[-.13313,.36687,0,0],8770:[-.03625,.46375,0,0],8774:[.30274,.79383,0,0],8776:[-.01688,.48312,0,0],8778:[.08167,.58167,0,0],8782:[.06062,.54986,0,0],8783:[.06062,.54986,0,0],8785:[.08198,.58198,0,0],8786:[.08198,.58198,0,0],8787:[.08198,.58198,0,0],8790:[0,.69224,0,0],8791:[.22958,.72958,0,0],8796:[.08198,.91667,0,0],8806:[.25583,.75583,0,0], +8807:[.25583,.75583,0,0],8808:[.25142,.75726,0,0],8809:[.25142,.75726,0,0],8812:[.25583,.75583,0,0],8814:[.20576,.70576,0,0],8815:[.20576,.70576,0,0],8816:[.30274,.79383,0,0],8817:[.30274,.79383,0,0],8818:[.22958,.72958,0,0],8819:[.22958,.72958,0,0],8822:[.1808,.675,0,0],8823:[.1808,.675,0,0],8828:[.13667,.63667,0,0],8829:[.13667,.63667,0,0],8830:[.22958,.72958,0,0],8831:[.22958,.72958,0,0],8832:[.20576,.70576,0,0],8833:[.20576,.70576,0,0],8840:[.30274,.79383,0,0],8841:[.30274,.79383,0,0],8842:[.13597,.63597,0,0],8843:[.13597,.63597,0,0],8847:[.03517,.54986,0,0],8848:[.03517,.54986,0,0],8858:[.08198,.58198,0,0],8859:[.08198,.58198,0,0],8861:[.08198,.58198,0,0],8862:[0,.675,0,0],8863:[0,.675,0,0],8864:[0,.675,0,0],8865:[0,.675,0,0],8872:[0,.69224,0,0],8873:[0,.69224,0,0],8874:[0,.69224,0,0],8876:[0,.68889,0,0],8877:[0,.68889,0,0],8878:[0,.68889,0,0],8879:[0,.68889,0,0],8882:[.03517,.54986,0,0],8883:[.03517,.54986,0,0],8884:[.13667,.63667,0,0],8885:[.13667,.63667,0,0],8888:[0,.54986,0,0],8890:[.19444,.43056,0,0],8891:[.19444,.69224,0,0],8892:[.19444,.69224,0,0],8901:[0,.54986,0,0],8903:[.08167,.58167,0,0],8905:[.08167,.58167,0,0],8906:[.08167,.58167,0,0],8907:[0,.69224,0,0],8908:[0,.69224,0,0],8909:[-.03598,.46402,0,0],8910:[0,.54986,0,0],8911:[0,.54986,0,0],8912:[.03517,.54986,0,0],8913:[.03517,.54986,0,0],8914:[0,.54986,0,0],8915:[0,.54986,0,0],8916:[0,.69224,0,0],8918:[.0391,.5391,0,0],8919:[.0391,.5391,0,0],8920:[.03517,.54986,0,0],8921:[.03517,.54986,0,0],8922:[.38569,.88569,0,0],8923:[.38569,.88569,0,0],8926:[.13667,.63667,0,0],8927:[.13667,.63667,0,0],8928:[.30274,.79383,0,0],8929:[.30274,.79383,0,0],8934:[.23222,.74111,0,0],8935:[.23222,.74111,0,0],8936:[.23222,.74111,0,0],8937:[.23222,.74111,0,0],8938:[.20576,.70576,0,0],8939:[.20576,.70576,0,0],8940:[.30274,.79383,0,0],8941:[.30274,.79383,0,0],8994:[.19444,.69224,0,0],8995:[.19444,.69224,0,0],9416:[.15559,.69224,0,0],9484:[0,.69224,0,0],9488:[0,.69224,0,0],9492:[0,.37788,0,0],9496:[0,.37788,0,0],9585:[.19444,.68889,0,0],9586:[.19444,.74111,0,0],9632:[0,.675,0,0],9633:[0,.675,0,0],9650:[0,.54986,0,0],9651:[0,.54986,0,0],9654:[.03517,.54986,0,0],9660:[0,.54986,0,0],9661:[0,.54986,0,0],9664:[.03517,.54986,0,0],9674:[.11111,.69224,0,0],9733:[.19444,.69224,0,0],10003:[0,.69224,0,0],10016:[0,.69224,0,0],10731:[.11111,.69224,0,0],10846:[.19444,.75583,0,0],10877:[.13667,.63667,0,0],10878:[.13667,.63667,0,0],10885:[.25583,.75583,0,0],10886:[.25583,.75583,0,0],10887:[.13597,.63597,0,0],10888:[.13597,.63597,0,0],10889:[.26167,.75726,0,0],10890:[.26167,.75726,0,0],10891:[.48256,.98256,0,0],10892:[.48256,.98256,0,0],10901:[.13667,.63667,0,0],10902:[.13667,.63667,0,0],10933:[.25142,.75726,0,0],10934:[.25142,.75726,0,0],10935:[.26167,.75726,0,0],10936:[.26167,.75726,0,0],10937:[.26167,.75726,0,0],10938:[.26167,.75726,0,0],10949:[.25583,.75583,0,0],10950:[.25583,.75583,0,0],10955:[.28481,.79383,0,0],10956:[.28481,.79383,0,0],57350:[.08167,.58167,0,0],57351:[.08167,.58167,0,0],57352:[.08167,.58167,0,0],57353:[0,.43056,.04028,0],57356:[.25142,.75726,0,0],57357:[.25142,.75726,0,0],57358:[.41951,.91951,0,0],57359:[.30274,.79383,0,0],57360:[.30274,.79383,0,0],57361:[.41951,.91951,0,0],57366:[.25142,.75726,0,0],57367:[.25142,.75726,0,0],57368:[.25142,.75726,0,0],57369:[.25142,.75726,0,0],57370:[.13597,.63597,0,0],57371:[.13597,.63597,0,0]},"Caligraphic-Regular":{48:[0,.43056,0,0],49:[0,.43056,0,0],50:[0,.43056,0,0],51:[.19444,.43056,0,0],52:[.19444,.43056,0,0],53:[.19444,.43056,0,0],54:[0,.64444,0,0],55:[.19444,.43056,0,0],56:[0,.64444,0,0],57:[.19444,.43056,0,0],65:[0,.68333,0,.19445],66:[0,.68333,.03041,.13889],67:[0,.68333,.05834,.13889],68:[0,.68333,.02778,.08334],69:[0,.68333,.08944,.11111],70:[0,.68333,.09931,.11111],71:[.09722,.68333,.0593,.11111],72:[0,.68333,.00965,.11111],73:[0,.68333,.07382,0],74:[.09722,.68333,.18472,.16667],75:[0,.68333,.01445,.05556],76:[0,.68333,0,.13889],77:[0,.68333,0,.13889],78:[0,.68333,.14736,.08334],79:[0,.68333,.02778,.11111],80:[0,.68333,.08222,.08334],81:[.09722,.68333,0,.11111],82:[0,.68333,0,.08334],83:[0,.68333,.075,.13889],84:[0,.68333,.25417,0],85:[0,.68333,.09931,.08334],86:[0,.68333,.08222,0],87:[0,.68333,.08222,.08334],88:[0,.68333,.14643,.13889],89:[.09722,.68333,.08222,.08334],90:[0,.68333,.07944,.13889]},"Fraktur-Regular":{33:[0,.69141,0,0],34:[0,.69141,0,0],38:[0,.69141,0,0],39:[0,.69141,0,0],40:[.24982,.74947,0,0],41:[.24982,.74947,0,0],42:[0,.62119,0,0],43:[.08319,.58283,0,0],44:[0,.10803,0,0],45:[.08319,.58283,0,0],46:[0,.10803,0,0],47:[.24982,.74947,0,0],48:[0,.47534,0,0],49:[0,.47534,0,0],50:[0,.47534,0,0],51:[.18906,.47534,0,0],52:[.18906,.47534,0,0],53:[.18906,.47534,0,0],54:[0,.69141,0,0],55:[.18906,.47534,0,0],56:[0,.69141,0,0],57:[.18906,.47534,0,0],58:[0,.47534,0,0],59:[.12604,.47534,0,0],61:[-.13099,.36866,0,0],63:[0,.69141,0,0],65:[0,.69141,0,0],66:[0,.69141,0,0],67:[0,.69141,0,0],68:[0,.69141,0,0],69:[0,.69141,0,0],70:[.12604,.69141,0,0],71:[0,.69141,0,0],72:[.06302,.69141,0,0],73:[0,.69141,0,0],74:[.12604,.69141,0,0],75:[0,.69141,0,0],76:[0,.69141,0,0],77:[0,.69141,0,0],78:[0,.69141,0,0],79:[0,.69141,0,0],80:[.18906,.69141,0,0],81:[.03781,.69141,0,0],82:[0,.69141,0,0],83:[0,.69141,0,0],84:[0,.69141,0,0],85:[0,.69141,0,0],86:[0,.69141,0,0],87:[0,.69141,0,0],88:[0,.69141,0,0],89:[.18906,.69141,0,0],90:[.12604,.69141,0,0],91:[.24982,.74947,0,0],93:[.24982,.74947,0,0],94:[0,.69141,0,0],97:[0,.47534,0,0],98:[0,.69141,0,0],99:[0,.47534,0,0],100:[0,.62119,0,0],101:[0,.47534,0,0],102:[.18906,.69141,0,0],103:[.18906,.47534,0,0],104:[.18906,.69141,0,0],105:[0,.69141,0,0],106:[0,.69141,0,0],107:[0,.69141,0,0],108:[0,.69141,0,0],109:[0,.47534,0,0],110:[0,.47534,0,0],111:[0,.47534,0,0],112:[.18906,.52396,0,0],113:[.18906,.47534,0,0],114:[0,.47534,0,0],115:[0,.47534,0,0],116:[0,.62119,0,0],117:[0,.47534,0,0],118:[0,.52396,0,0],119:[0,.52396,0,0],120:[.18906,.47534,0,0],121:[.18906,.47534,0,0],122:[.18906,.47534,0,0],8216:[0,.69141,0,0],8217:[0,.69141,0,0],58112:[0,.62119,0,0],58113:[0,.62119,0,0],58114:[.18906,.69141,0,0],58115:[.18906,.69141,0,0],58116:[.18906,.47534,0,0],58117:[0,.69141,0,0],58118:[0,.62119,0,0],58119:[0,.47534,0,0]},"Main-Bold":{33:[0,.69444,0,0],34:[0,.69444,0,0],35:[.19444,.69444,0,0],36:[.05556,.75,0,0],37:[.05556,.75,0,0],38:[0,.69444,0,0],39:[0,.69444,0,0],40:[.25,.75,0,0],41:[.25,.75,0,0],42:[0,.75,0,0],43:[.13333,.63333,0,0],44:[.19444,.15556,0,0],45:[0,.44444,0,0],46:[0,.15556,0,0],47:[.25,.75,0,0],48:[0,.64444,0,0],49:[0,.64444,0,0],50:[0,.64444,0,0],51:[0,.64444,0,0],52:[0,.64444,0,0],53:[0,.64444,0,0],54:[0,.64444,0,0],55:[0,.64444,0,0],56:[0,.64444,0,0],57:[0,.64444,0,0],58:[0,.44444,0,0],59:[.19444,.44444,0,0],60:[.08556,.58556,0,0],61:[-.10889,.39111,0,0],62:[.08556,.58556,0,0],63:[0,.69444,0,0],64:[0,.69444,0,0],65:[0,.68611,0,0],66:[0,.68611,0,0],67:[0,.68611,0,0],68:[0,.68611,0,0],69:[0,.68611,0,0],70:[0,.68611,0,0],71:[0,.68611,0,0],72:[0,.68611,0,0],73:[0,.68611,0,0],74:[0,.68611,0,0],75:[0,.68611,0,0],76:[0,.68611,0,0],77:[0,.68611,0,0],78:[0,.68611,0,0],79:[0,.68611,0,0],80:[0,.68611,0,0],81:[.19444,.68611,0,0],82:[0,.68611,0,0],83:[0,.68611,0,0],84:[0,.68611,0,0],85:[0,.68611,0,0],86:[0,.68611,.01597,0],87:[0,.68611,.01597,0],88:[0,.68611,0,0],89:[0,.68611,.02875,0],90:[0,.68611,0,0],91:[.25,.75,0,0],92:[.25,.75,0,0],93:[.25,.75,0,0],94:[0,.69444,0,0],95:[.31,.13444,.03194,0],96:[0,.69444,0,0],97:[0,.44444,0,0],98:[0,.69444,0,0],99:[0,.44444,0,0],100:[0,.69444,0,0],101:[0,.44444,0,0],102:[0,.69444,.10903,0],103:[.19444,.44444,.01597,0],104:[0,.69444,0,0],105:[0,.69444,0,0],106:[.19444,.69444,0,0],107:[0,.69444,0,0],108:[0,.69444,0,0],109:[0,.44444,0,0],110:[0,.44444,0,0],111:[0,.44444,0,0],112:[.19444,.44444,0,0],113:[.19444,.44444,0,0],114:[0,.44444,0,0],115:[0,.44444,0,0],116:[0,.63492,0,0],117:[0,.44444,0,0],118:[0,.44444,.01597,0],119:[0,.44444,.01597,0],120:[0,.44444,0,0],121:[.19444,.44444,.01597,0],122:[0,.44444,0,0],123:[.25,.75,0,0],124:[.25,.75,0,0],125:[.25,.75,0,0],126:[.35,.34444,0,0],168:[0,.69444,0,0],172:[0,.44444,0,0],175:[0,.59611,0,0],176:[0,.69444,0,0],177:[.13333,.63333,0,0],180:[0,.69444,0,0],215:[.13333,.63333,0,0],247:[.13333,.63333,0,0],305:[0,.44444,0,0],567:[.19444,.44444,0,0],710:[0,.69444,0,0],711:[0,.63194,0,0],713:[0,.59611,0,0],714:[0,.69444,0,0],715:[0,.69444,0,0],728:[0,.69444,0,0],729:[0,.69444,0,0],730:[0,.69444,0,0],732:[0,.69444,0,0],768:[0,.69444,0,0],769:[0,.69444,0,0],770:[0,.69444,0,0],771:[0,.69444,0,0],772:[0,.59611,0,0],774:[0,.69444,0,0],775:[0,.69444,0,0],776:[0,.69444,0,0],778:[0,.69444,0,0],779:[0,.69444,0,0],780:[0,.63194,0,0],824:[.19444,.69444,0,0],915:[0,.68611,0,0],916:[0,.68611,0,0],920:[0,.68611,0,0],923:[0,.68611,0,0],926:[0,.68611,0,0],928:[0,.68611,0,0],931:[0,.68611,0,0],933:[0,.68611,0,0],934:[0,.68611,0,0],936:[0,.68611,0,0],937:[0,.68611,0,0],8211:[0,.44444,.03194,0],8212:[0,.44444,.03194,0],8216:[0,.69444,0,0],8217:[0,.69444,0,0],8220:[0,.69444,0,0],8221:[0,.69444,0,0],8224:[.19444,.69444,0,0],8225:[.19444,.69444,0,0],8242:[0,.55556,0,0],8407:[0,.72444,.15486,0],8463:[0,.69444,0,0],8465:[0,.69444,0,0],8467:[0,.69444,0,0],8472:[.19444,.44444,0,0],8476:[0,.69444,0,0],8501:[0,.69444,0,0],8592:[-.10889,.39111,0,0],8593:[.19444,.69444,0,0],8594:[-.10889,.39111,0,0],8595:[.19444,.69444,0,0],8596:[-.10889,.39111,0,0],8597:[.25,.75,0,0],8598:[.19444,.69444,0,0],8599:[.19444,.69444,0,0],8600:[.19444,.69444,0,0],8601:[.19444,.69444,0,0],8636:[-.10889,.39111,0,0],8637:[-.10889,.39111,0,0],8640:[-.10889,.39111,0,0],8641:[-.10889,.39111,0,0],8656:[-.10889,.39111,0,0],8657:[.19444,.69444,0,0],8658:[-.10889,.39111,0,0],8659:[.19444,.69444,0,0],8660:[-.10889,.39111,0,0],8661:[.25,.75,0,0],8704:[0,.69444,0,0],8706:[0,.69444,.06389,0],8707:[0,.69444,0,0],8709:[.05556,.75,0,0],8711:[0,.68611,0,0],8712:[.08556,.58556,0,0],8715:[.08556,.58556,0,0],8722:[.13333,.63333,0,0],8723:[.13333,.63333,0,0],8725:[.25,.75,0,0],8726:[.25,.75,0,0],8727:[-.02778,.47222,0,0],8728:[-.02639,.47361,0,0],8729:[-.02639,.47361,0,0],8730:[.18,.82,0,0],8733:[0,.44444,0,0],8734:[0,.44444,0,0],8736:[0,.69224,0,0],8739:[.25,.75,0,0],8741:[.25,.75,0,0],8743:[0,.55556,0,0],8744:[0,.55556,0,0],8745:[0,.55556,0,0],8746:[0,.55556,0,0],8747:[.19444,.69444,.12778,0],8764:[-.10889,.39111,0,0],8768:[.19444,.69444,0,0],8771:[.00222,.50222,0,0],8776:[.02444,.52444,0,0],8781:[.00222,.50222,0,0],8801:[.00222,.50222,0,0],8804:[.19667,.69667,0,0],8805:[.19667,.69667,0,0],8810:[.08556,.58556,0,0],8811:[.08556,.58556,0,0],8826:[.08556,.58556,0,0],8827:[.08556,.58556,0,0],8834:[.08556,.58556,0,0],8835:[.08556,.58556,0,0],8838:[.19667,.69667,0,0],8839:[.19667,.69667,0,0],8846:[0,.55556,0,0],8849:[.19667,.69667,0,0],8850:[.19667,.69667,0,0],8851:[0,.55556,0,0],8852:[0,.55556,0,0],8853:[.13333,.63333,0,0],8854:[.13333,.63333,0,0],8855:[.13333,.63333,0,0],8856:[.13333,.63333,0,0],8857:[.13333,.63333,0,0],8866:[0,.69444,0,0],8867:[0,.69444,0,0],8868:[0,.69444,0,0],8869:[0,.69444,0,0],8900:[-.02639,.47361,0,0],8901:[-.02639,.47361,0,0],8902:[-.02778,.47222,0,0],8968:[.25,.75,0,0],8969:[.25,.75,0,0],8970:[.25,.75,0,0],8971:[.25,.75,0,0],8994:[-.13889,.36111,0,0],8995:[-.13889,.36111,0,0],9651:[.19444,.69444,0,0],9657:[-.02778,.47222,0,0],9661:[.19444,.69444,0,0],9667:[-.02778,.47222,0,0],9711:[.19444,.69444,0,0],9824:[.12963,.69444,0,0],9825:[.12963,.69444,0,0],9826:[.12963,.69444,0,0],9827:[.12963,.69444,0,0],9837:[0,.75,0,0],9838:[.19444,.69444,0,0],9839:[.19444,.69444,0,0],10216:[.25,.75,0,0],10217:[.25,.75,0,0],10815:[0,.68611,0,0],10927:[.19667,.69667,0,0],10928:[.19667,.69667,0,0]},"Main-Italic":{33:[0,.69444,.12417,0],34:[0,.69444,.06961,0],35:[.19444,.69444,.06616,0],37:[.05556,.75,.13639,0],38:[0,.69444,.09694,0],39:[0,.69444,.12417,0],40:[.25,.75,.16194,0],41:[.25,.75,.03694,0],42:[0,.75,.14917,0],43:[.05667,.56167,.03694,0],44:[.19444,.10556,0,0],45:[0,.43056,.02826,0],46:[0,.10556,0,0],47:[.25,.75,.16194,0],48:[0,.64444,.13556,0],49:[0,.64444,.13556,0],50:[0,.64444,.13556,0],51:[0,.64444,.13556,0],52:[.19444,.64444,.13556,0],53:[0,.64444,.13556,0],54:[0,.64444,.13556,0],55:[.19444,.64444,.13556,0],56:[0,.64444,.13556,0],57:[0,.64444,.13556,0],58:[0,.43056,.0582,0],59:[.19444,.43056,.0582,0],61:[-.13313,.36687,.06616,0],63:[0,.69444,.1225,0],64:[0,.69444,.09597,0],65:[0,.68333,0,0],66:[0,.68333,.10257,0],67:[0,.68333,.14528,0],68:[0,.68333,.09403,0],69:[0,.68333,.12028,0],70:[0,.68333,.13305,0],71:[0,.68333,.08722,0],72:[0,.68333,.16389,0],73:[0,.68333,.15806,0],74:[0,.68333,.14028,0],75:[0,.68333,.14528,0],76:[0,.68333,0,0],77:[0,.68333,.16389,0],78:[0,.68333,.16389,0],79:[0,.68333,.09403,0],80:[0,.68333,.10257,0],81:[.19444,.68333,.09403,0],82:[0,.68333,.03868,0],83:[0,.68333,.11972,0],84:[0,.68333,.13305,0],85:[0,.68333,.16389,0],86:[0,.68333,.18361,0],87:[0,.68333,.18361,0],88:[0,.68333,.15806,0],89:[0,.68333,.19383,0],90:[0,.68333,.14528,0],91:[.25,.75,.1875,0],93:[.25,.75,.10528,0],94:[0,.69444,.06646,0],95:[.31,.12056,.09208,0],97:[0,.43056,.07671,0],98:[0,.69444,.06312,0],99:[0,.43056,.05653,0],100:[0,.69444,.10333,0],101:[0,.43056,.07514,0],102:[.19444,.69444,.21194,0],103:[.19444,.43056,.08847,0],104:[0,.69444,.07671,0],105:[0,.65536,.1019,0],106:[.19444,.65536,.14467,0],107:[0,.69444,.10764,0],108:[0,.69444,.10333,0],109:[0,.43056,.07671,0],110:[0,.43056,.07671,0],111:[0,.43056,.06312,0],112:[.19444,.43056,.06312,0],113:[.19444,.43056,.08847,0],114:[0,.43056,.10764,0],115:[0,.43056,.08208,0],116:[0,.61508,.09486,0],117:[0,.43056,.07671,0],118:[0,.43056,.10764,0],119:[0,.43056,.10764,0],120:[0,.43056,.12042,0],121:[.19444,.43056,.08847,0],122:[0,.43056,.12292,0],126:[.35,.31786,.11585,0],163:[0,.69444,0,0],305:[0,.43056,0,.02778],567:[.19444,.43056,0,.08334],768:[0,.69444,0,0],769:[0,.69444,.09694,0],770:[0,.69444,.06646,0],771:[0,.66786,.11585,0],772:[0,.56167,.10333,0],774:[0,.69444,.10806,0],775:[0,.66786,.11752,0],776:[0,.66786,.10474,0],778:[0,.69444,0,0],779:[0,.69444,.1225,0],780:[0,.62847,.08295,0],915:[0,.68333,.13305,0],916:[0,.68333,0,0],920:[0,.68333,.09403,0],923:[0,.68333,0,0],926:[0,.68333,.15294,0],928:[0,.68333,.16389,0],931:[0,.68333,.12028,0],933:[0,.68333,.11111,0],934:[0,.68333,.05986,0],936:[0,.68333,.11111,0],937:[0,.68333,.10257,0],8211:[0,.43056,.09208,0],8212:[0,.43056,.09208,0],8216:[0,.69444,.12417,0],8217:[0,.69444,.12417,0],8220:[0,.69444,.1685,0],8221:[0,.69444,.06961,0],8463:[0,.68889,0,0]},"Main-Regular":{32:[0,0,0,0],33:[0,.69444,0,0],34:[0,.69444,0,0],35:[.19444,.69444,0,0],36:[.05556,.75,0,0],37:[.05556,.75,0,0],38:[0,.69444,0,0],39:[0,.69444,0,0],40:[.25,.75,0,0],41:[.25,.75,0,0],42:[0,.75,0,0],43:[.08333,.58333,0,0],44:[.19444,.10556,0,0],45:[0,.43056,0,0],46:[0,.10556,0,0],47:[.25,.75,0,0],48:[0,.64444,0,0],49:[0,.64444,0,0],50:[0,.64444,0,0],51:[0,.64444,0,0],52:[0,.64444,0,0],53:[0,.64444,0,0],54:[0,.64444,0,0],55:[0,.64444,0,0],56:[0,.64444,0,0],57:[0,.64444,0,0],58:[0,.43056,0,0],59:[.19444,.43056,0,0],60:[.0391,.5391,0,0],61:[-.13313,.36687,0,0],62:[.0391,.5391,0,0],63:[0,.69444,0,0],64:[0,.69444,0,0],65:[0,.68333,0,0],66:[0,.68333,0,0],67:[0,.68333,0,0],68:[0,.68333,0,0],69:[0,.68333,0,0],70:[0,.68333,0,0],71:[0,.68333,0,0],72:[0,.68333,0,0],73:[0,.68333,0,0],74:[0,.68333,0,0],75:[0,.68333,0,0],76:[0,.68333,0,0],77:[0,.68333,0,0],78:[0,.68333,0,0],79:[0,.68333,0,0],80:[0,.68333,0,0],81:[.19444,.68333,0,0],82:[0,.68333,0,0],83:[0,.68333,0,0],84:[0,.68333,0,0],85:[0,.68333,0,0],86:[0,.68333,.01389,0],87:[0,.68333,.01389,0],88:[0,.68333,0,0],89:[0,.68333,.025,0],90:[0,.68333,0,0],91:[.25,.75,0,0],92:[.25,.75,0,0],93:[.25,.75,0,0],94:[0,.69444,0,0],95:[.31,.12056,.02778,0],96:[0,.69444,0,0],97:[0,.43056,0,0],98:[0,.69444,0,0],99:[0,.43056,0,0],100:[0,.69444,0,0],101:[0,.43056,0,0],102:[0,.69444,.07778,0],103:[.19444,.43056,.01389,0],104:[0,.69444,0,0],105:[0,.66786,0,0],106:[.19444,.66786,0,0],107:[0,.69444,0,0],108:[0,.69444,0,0],109:[0,.43056,0,0],110:[0,.43056,0,0],111:[0,.43056,0,0],112:[.19444,.43056,0,0],113:[.19444,.43056,0,0],114:[0,.43056,0,0],115:[0,.43056,0,0],116:[0,.61508,0,0],117:[0,.43056,0,0],118:[0,.43056,.01389,0],119:[0,.43056,.01389,0],120:[0,.43056,0,0],121:[.19444,.43056,.01389,0],122:[0,.43056,0,0],123:[.25,.75,0,0],124:[.25,.75,0,0],125:[.25,.75,0,0],126:[.35,.31786,0,0],160:[0,0,0,0],168:[0,.66786,0,0],172:[0,.43056,0,0],175:[0,.56778,0,0],176:[0,.69444,0,0],177:[.08333,.58333,0,0],180:[0,.69444,0,0],215:[.08333,.58333,0,0],247:[.08333,.58333,0,0],305:[0,.43056,0,0],567:[.19444,.43056,0,0],710:[0,.69444,0,0],711:[0,.62847,0,0],713:[0,.56778,0,0],714:[0,.69444,0,0],715:[0,.69444,0,0],728:[0,.69444,0,0],729:[0,.66786,0,0],730:[0,.69444,0,0],732:[0,.66786,0,0],768:[0,.69444,0,0],769:[0,.69444,0,0],770:[0,.69444,0,0],771:[0,.66786,0,0],772:[0,.56778,0,0],774:[0,.69444,0,0],775:[0,.66786,0,0],776:[0,.66786,0,0],778:[0,.69444,0,0],779:[0,.69444,0,0],780:[0,.62847,0,0],824:[.19444,.69444,0,0],915:[0,.68333,0,0],916:[0,.68333,0,0],920:[0,.68333,0,0],923:[0,.68333,0,0],926:[0,.68333,0,0],928:[0,.68333,0,0],931:[0,.68333,0,0],933:[0,.68333,0,0],934:[0,.68333,0,0],936:[0,.68333,0,0],937:[0,.68333,0,0],8211:[0,.43056,.02778,0],8212:[0,.43056,.02778,0],8216:[0,.69444,0,0],8217:[0,.69444,0,0],8220:[0,.69444,0,0],8221:[0,.69444,0,0],8224:[.19444,.69444,0,0],8225:[.19444,.69444,0,0],8230:[0,.12,0,0],8242:[0,.55556,0,0],8407:[0,.71444,.15382,0],8463:[0,.68889,0,0],8465:[0,.69444,0,0],8467:[0,.69444,0,.11111],8472:[.19444,.43056,0,.11111],8476:[0,.69444,0,0],8501:[0,.69444,0,0],8592:[-.13313,.36687,0,0],8593:[.19444,.69444,0,0],8594:[-.13313,.36687,0,0],8595:[.19444,.69444,0,0],8596:[-.13313,.36687,0,0],8597:[.25,.75,0,0],8598:[.19444,.69444,0,0],8599:[.19444,.69444,0,0],8600:[.19444,.69444,0,0],8601:[.19444,.69444,0,0],8614:[.011,.511,0,0],8617:[.011,.511,0,0],8618:[.011,.511,0,0],8636:[-.13313,.36687,0,0],8637:[-.13313,.36687,0,0],8640:[-.13313,.36687,0,0],8641:[-.13313,.36687,0,0],8652:[.011,.671,0,0],8656:[-.13313,.36687,0,0],8657:[.19444,.69444,0,0],8658:[-.13313,.36687,0,0],8659:[.19444,.69444,0,0],8660:[-.13313,.36687,0,0],8661:[.25,.75,0,0],8704:[0,.69444,0,0],8706:[0,.69444,.05556,.08334],8707:[0,.69444,0,0],8709:[.05556,.75,0,0],8711:[0,.68333,0,0],8712:[.0391,.5391,0,0],8715:[.0391,.5391,0,0],8722:[.08333,.58333,0,0],8723:[.08333,.58333,0,0],8725:[.25,.75,0,0],8726:[.25,.75,0,0],8727:[-.03472,.46528,0,0],8728:[-.05555,.44445,0,0],8729:[-.05555,.44445,0,0],8730:[.2,.8,0,0],8733:[0,.43056,0,0],8734:[0,.43056,0,0],8736:[0,.69224,0,0],8739:[.25,.75,0,0],8741:[.25,.75,0,0],8743:[0,.55556,0,0],8744:[0,.55556,0,0],8745:[0,.55556,0,0],8746:[0,.55556,0,0],8747:[.19444,.69444,.11111,0],8764:[-.13313,.36687,0,0],8768:[.19444,.69444,0,0],8771:[-.03625,.46375,0,0],8773:[-.022,.589,0,0],8776:[-.01688,.48312,0,0],8781:[-.03625,.46375,0,0],8784:[-.133,.67,0,0],8800:[.215,.716,0,0],8801:[-.03625,.46375,0,0],8804:[.13597,.63597,0,0],8805:[.13597,.63597,0,0],8810:[.0391,.5391,0,0],8811:[.0391,.5391,0,0],8826:[.0391,.5391,0,0],8827:[.0391,.5391,0,0],8834:[.0391,.5391,0,0],8835:[.0391,.5391,0,0],8838:[.13597,.63597,0,0],8839:[.13597,.63597,0,0],8846:[0,.55556,0,0],8849:[.13597,.63597,0,0],8850:[.13597,.63597,0,0],8851:[0,.55556,0,0],8852:[0,.55556,0,0],8853:[.08333,.58333,0,0],8854:[.08333,.58333,0,0],8855:[.08333,.58333,0,0],8856:[.08333,.58333,0,0],8857:[.08333,.58333,0,0],8866:[0,.69444,0,0],8867:[0,.69444,0,0],8868:[0,.69444,0,0],8869:[0,.69444,0,0],8872:[.249,.75,0,0],8900:[-.05555,.44445,0,0],8901:[-.05555,.44445,0,0],8902:[-.03472,.46528,0,0],8904:[.005,.505,0,0],8942:[.03,.9,0,0],8943:[-.19,.31,0,0],8945:[-.1,.82,0,0],8968:[.25,.75,0,0],8969:[.25,.75,0,0],8970:[.25,.75,0,0],8971:[.25,.75,0,0],8994:[-.14236,.35764,0,0],8995:[-.14236,.35764,0,0],9136:[.244,.744,0,0],9137:[.244,.744,0,0],9651:[.19444,.69444,0,0],9657:[-.03472,.46528,0,0],9661:[.19444,.69444,0,0],9667:[-.03472,.46528,0,0],9711:[.19444,.69444,0,0],9824:[.12963,.69444,0,0],9825:[.12963,.69444,0,0],9826:[.12963,.69444,0,0],9827:[.12963,.69444,0,0],9837:[0,.75,0,0],9838:[.19444,.69444,0,0],9839:[.19444,.69444,0,0],10216:[.25,.75,0,0],10217:[.25,.75,0,0],10222:[.244,.744,0,0],10223:[.244,.744,0,0],10229:[.011,.511,0,0],10230:[.011,.511,0,0],10231:[.011,.511,0,0],10232:[.024,.525,0,0],10233:[.024,.525,0,0],10234:[.024,.525,0,0],10236:[.011,.511,0,0],10815:[0,.68333,0,0],10927:[.13597,.63597,0,0],10928:[.13597,.63597,0,0]},"Math-BoldItalic":{47:[.19444,.69444,0,0],65:[0,.68611,0,0],66:[0,.68611,.04835,0],67:[0,.68611,.06979,0],68:[0,.68611,.03194,0],69:[0,.68611,.05451,0],70:[0,.68611,.15972,0],71:[0,.68611,0,0],72:[0,.68611,.08229,0],73:[0,.68611,.07778,0],74:[0,.68611,.10069,0],75:[0,.68611,.06979,0],76:[0,.68611,0,0],77:[0,.68611,.11424,0],78:[0,.68611,.11424,0],79:[0,.68611,.03194,0],80:[0,.68611,.15972,0],81:[.19444,.68611,0,0],82:[0,.68611,.00421,0],83:[0,.68611,.05382,0],84:[0,.68611,.15972,0],85:[0,.68611,.11424,0],86:[0,.68611,.25555,0],87:[0,.68611,.15972,0],88:[0,.68611,.07778,0],89:[0,.68611,.25555,0],90:[0,.68611,.06979,0],97:[0,.44444,0,0],98:[0,.69444,0,0],99:[0,.44444,0,0],100:[0,.69444,0,0],101:[0,.44444,0,0],102:[.19444,.69444,.11042,0],103:[.19444,.44444,.03704,0],104:[0,.69444,0,0],105:[0,.69326,0,0],106:[.19444,.69326,.0622,0],107:[0,.69444,.01852,0],108:[0,.69444,.0088,0],109:[0,.44444,0,0],110:[0,.44444,0,0],111:[0,.44444,0,0],112:[.19444,.44444,0,0],113:[.19444,.44444,.03704,0],114:[0,.44444,.03194,0],115:[0,.44444,0,0],116:[0,.63492,0,0],117:[0,.44444,0,0],118:[0,.44444,.03704,0],119:[0,.44444,.02778,0],120:[0,.44444,0,0],121:[.19444,.44444,.03704,0],122:[0,.44444,.04213,0],915:[0,.68611,.15972,0],916:[0,.68611,0,0],920:[0,.68611,.03194,0],923:[0,.68611,0,0],926:[0,.68611,.07458,0],928:[0,.68611,.08229,0],931:[0,.68611,.05451,0],933:[0,.68611,.15972,0],934:[0,.68611,0,0],936:[0,.68611,.11653,0],937:[0,.68611,.04835,0],945:[0,.44444,0,0],946:[.19444,.69444,.03403,0],947:[.19444,.44444,.06389,0],948:[0,.69444,.03819,0],949:[0,.44444,0,0],950:[.19444,.69444,.06215,0],951:[.19444,.44444,.03704,0],952:[0,.69444,.03194,0],953:[0,.44444,0,0],954:[0,.44444,0,0],955:[0,.69444,0,0],956:[.19444,.44444,0,0],957:[0,.44444,.06898,0],958:[.19444,.69444,.03021,0],959:[0,.44444,0,0],960:[0,.44444,.03704,0],961:[.19444,.44444,0,0],962:[.09722,.44444,.07917,0],963:[0,.44444,.03704,0],964:[0,.44444,.13472,0],965:[0,.44444,.03704,0],966:[.19444,.44444,0,0],967:[.19444,.44444,0,0],968:[.19444,.69444,.03704,0],969:[0,.44444,.03704,0],977:[0,.69444,0,0],981:[.19444,.69444,0,0],982:[0,.44444,.03194,0],1009:[.19444,.44444,0,0],1013:[0,.44444,0,0]},"Math-Italic":{47:[.19444,.69444,0,0],65:[0,.68333,0,.13889],66:[0,.68333,.05017,.08334],67:[0,.68333,.07153,.08334],68:[0,.68333,.02778,.05556],69:[0,.68333,.05764,.08334],70:[0,.68333,.13889,.08334],71:[0,.68333,0,.08334],72:[0,.68333,.08125,.05556],73:[0,.68333,.07847,.11111],74:[0,.68333,.09618,.16667],75:[0,.68333,.07153,.05556],76:[0,.68333,0,.02778],77:[0,.68333,.10903,.08334],78:[0,.68333,.10903,.08334],79:[0,.68333,.02778,.08334],80:[0,.68333,.13889,.08334],81:[.19444,.68333,0,.08334],82:[0,.68333,.00773,.08334],83:[0,.68333,.05764,.08334],84:[0,.68333,.13889,.08334],85:[0,.68333,.10903,.02778],86:[0,.68333,.22222,0],87:[0,.68333,.13889,0],88:[0,.68333,.07847,.08334],89:[0,.68333,.22222,0],90:[0,.68333,.07153,.08334],97:[0,.43056,0,0],98:[0,.69444,0,0],99:[0,.43056,0,.05556],100:[0,.69444,0,.16667],101:[0,.43056,0,.05556],102:[.19444,.69444,.10764,.16667],103:[.19444,.43056,.03588,.02778],104:[0,.69444,0,0],105:[0,.65952,0,0],106:[.19444,.65952,.05724,0],107:[0,.69444,.03148,0],108:[0,.69444,.01968,.08334],109:[0,.43056,0,0],110:[0,.43056,0,0],111:[0,.43056,0,.05556],112:[.19444,.43056,0,.08334],113:[.19444,.43056,.03588,.08334],114:[0,.43056,.02778,.05556],115:[0,.43056,0,.05556],116:[0,.61508,0,.08334],117:[0,.43056,0,.02778],118:[0,.43056,.03588,.02778],119:[0,.43056,.02691,.08334],120:[0,.43056,0,.02778],121:[.19444,.43056,.03588,.05556],122:[0,.43056,.04398,.05556],915:[0,.68333,.13889,.08334],916:[0,.68333,0,.16667],920:[0,.68333,.02778,.08334],923:[0,.68333,0,.16667],926:[0,.68333,.07569,.08334],928:[0,.68333,.08125,.05556],931:[0,.68333,.05764,.08334],933:[0,.68333,.13889,.05556],934:[0,.68333,0,.08334],936:[0,.68333,.11,.05556],937:[0,.68333,.05017,.08334],945:[0,.43056,.0037,.02778],946:[.19444,.69444,.05278,.08334],947:[.19444,.43056,.05556,0],948:[0,.69444,.03785,.05556],949:[0,.43056,0,.08334],950:[.19444,.69444,.07378,.08334],951:[.19444,.43056,.03588,.05556],952:[0,.69444,.02778,.08334],953:[0,.43056,0,.05556],954:[0,.43056,0,0],955:[0,.69444,0,0],956:[.19444,.43056,0,.02778],957:[0,.43056,.06366,.02778],958:[.19444,.69444,.04601,.11111],959:[0,.43056,0,.05556],960:[0,.43056,.03588,0],961:[.19444,.43056,0,.08334],962:[.09722,.43056,.07986,.08334],963:[0,.43056,.03588,0],964:[0,.43056,.1132,.02778],965:[0,.43056,.03588,.02778],966:[.19444,.43056,0,.08334],967:[.19444,.43056,0,.05556],968:[.19444,.69444,.03588,.11111],969:[0,.43056,.03588,0],977:[0,.69444,0,.08334],981:[.19444,.69444,0,.08334],982:[0,.43056,.02778,0],1009:[.19444,.43056,0,.08334],1013:[0,.43056,0,.05556]},"Math-Regular":{65:[0,.68333,0,.13889],66:[0,.68333,.05017,.08334],67:[0,.68333,.07153,.08334],68:[0,.68333,.02778,.05556],69:[0,.68333,.05764,.08334],70:[0,.68333,.13889,.08334],71:[0,.68333,0,.08334],72:[0,.68333,.08125,.05556],73:[0,.68333,.07847,.11111],74:[0,.68333,.09618,.16667],75:[0,.68333,.07153,.05556],76:[0,.68333,0,.02778],77:[0,.68333,.10903,.08334],78:[0,.68333,.10903,.08334],79:[0,.68333,.02778,.08334],80:[0,.68333,.13889,.08334],81:[.19444,.68333,0,.08334],82:[0,.68333,.00773,.08334],83:[0,.68333,.05764,.08334],84:[0,.68333,.13889,.08334],85:[0,.68333,.10903,.02778],86:[0,.68333,.22222,0],87:[0,.68333,.13889,0],88:[0,.68333,.07847,.08334],89:[0,.68333,.22222,0],90:[0,.68333,.07153,.08334],97:[0,.43056,0,0],98:[0,.69444,0,0],99:[0,.43056,0,.05556],100:[0,.69444,0,.16667],101:[0,.43056,0,.05556],102:[.19444,.69444,.10764,.16667],103:[.19444,.43056,.03588,.02778],104:[0,.69444,0,0],105:[0,.65952,0,0],106:[.19444,.65952,.05724,0],107:[0,.69444,.03148,0],108:[0,.69444,.01968,.08334],109:[0,.43056,0,0],110:[0,.43056,0,0],111:[0,.43056,0,.05556],112:[.19444,.43056,0,.08334],113:[.19444,.43056,.03588,.08334],114:[0,.43056,.02778,.05556],115:[0,.43056,0,.05556],116:[0,.61508,0,.08334],117:[0,.43056,0,.02778],118:[0,.43056,.03588,.02778],119:[0,.43056,.02691,.08334],120:[0,.43056,0,.02778],121:[.19444,.43056,.03588,.05556],122:[0,.43056,.04398,.05556],915:[0,.68333,.13889,.08334],916:[0,.68333,0,.16667],920:[0,.68333,.02778,.08334],923:[0,.68333,0,.16667],926:[0,.68333,.07569,.08334],928:[0,.68333,.08125,.05556],931:[0,.68333,.05764,.08334],933:[0,.68333,.13889,.05556],934:[0,.68333,0,.08334],936:[0,.68333,.11,.05556],937:[0,.68333,.05017,.08334],945:[0,.43056,.0037,.02778],946:[.19444,.69444,.05278,.08334],947:[.19444,.43056,.05556,0],948:[0,.69444,.03785,.05556],949:[0,.43056,0,.08334],950:[.19444,.69444,.07378,.08334],951:[.19444,.43056,.03588,.05556],952:[0,.69444,.02778,.08334],953:[0,.43056,0,.05556],954:[0,.43056,0,0],955:[0,.69444,0,0],956:[.19444,.43056,0,.02778],957:[0,.43056,.06366,.02778],958:[.19444,.69444,.04601,.11111],959:[0,.43056,0,.05556],960:[0,.43056,.03588,0],961:[.19444,.43056,0,.08334],962:[.09722,.43056,.07986,.08334],963:[0,.43056,.03588,0],964:[0,.43056,.1132,.02778],965:[0,.43056,.03588,.02778],966:[.19444,.43056,0,.08334],967:[.19444,.43056,0,.05556],968:[.19444,.69444,.03588,.11111],969:[0,.43056,.03588,0],977:[0,.69444,0,.08334],981:[.19444,.69444,0,.08334],982:[0,.43056,.02778,0],1009:[.19444,.43056,0,.08334],1013:[0,.43056,0,.05556]},"SansSerif-Regular":{33:[0,.69444,0,0],34:[0,.69444,0,0],35:[.19444,.69444,0,0],36:[.05556,.75,0,0],37:[.05556,.75,0,0],38:[0,.69444,0,0],39:[0,.69444,0,0],40:[.25,.75,0,0],41:[.25,.75,0,0],42:[0,.75,0,0],43:[.08333,.58333,0,0],44:[.125,.08333,0,0],45:[0,.44444,0,0],46:[0,.08333,0,0],47:[.25,.75,0,0],48:[0,.65556,0,0],49:[0,.65556,0,0],50:[0,.65556,0,0],51:[0,.65556,0,0],52:[0,.65556,0,0],53:[0,.65556,0,0],54:[0,.65556,0,0],55:[0,.65556,0,0],56:[0,.65556,0,0],57:[0,.65556,0,0],58:[0,.44444,0,0],59:[.125,.44444,0,0],61:[-.13,.37,0,0],63:[0,.69444,0,0],64:[0,.69444,0,0],65:[0,.69444,0,0],66:[0,.69444,0,0],67:[0,.69444,0,0],68:[0,.69444,0,0],69:[0,.69444,0,0],70:[0,.69444,0,0],71:[0,.69444,0,0],72:[0,.69444,0,0],73:[0,.69444,0,0],74:[0,.69444,0,0],75:[0,.69444,0,0],76:[0,.69444,0,0],77:[0,.69444,0,0],78:[0,.69444,0,0],79:[0,.69444,0,0],80:[0,.69444,0,0],81:[.125,.69444,0,0],82:[0,.69444,0,0],83:[0,.69444,0,0],84:[0,.69444,0,0],85:[0,.69444,0,0],86:[0,.69444,.01389,0],87:[0,.69444,.01389,0],88:[0,.69444,0,0],89:[0,.69444,.025,0],90:[0,.69444,0,0],91:[.25,.75,0,0],93:[.25,.75,0,0],94:[0,.69444,0,0],95:[.35,.09444,.02778,0],97:[0,.44444,0,0],98:[0,.69444,0,0],99:[0,.44444,0,0],100:[0,.69444,0,0],101:[0,.44444,0,0],102:[0,.69444,.06944,0],103:[.19444,.44444,.01389,0],104:[0,.69444,0,0],105:[0,.67937,0,0],106:[.19444,.67937,0,0],107:[0,.69444,0,0],108:[0,.69444,0,0],109:[0,.44444,0,0],110:[0,.44444,0,0],111:[0,.44444,0,0],112:[.19444,.44444,0,0],113:[.19444,.44444,0,0],114:[0,.44444,.01389,0],115:[0,.44444,0,0],116:[0,.57143,0,0],117:[0,.44444,0,0],118:[0,.44444,.01389,0],119:[0,.44444,.01389,0],120:[0,.44444,0,0],121:[.19444,.44444,.01389,0],122:[0,.44444,0,0],126:[.35,.32659,0,0],305:[0,.44444,0,0],567:[.19444,.44444,0,0],768:[0,.69444,0,0],769:[0,.69444,0,0],770:[0,.69444,0,0],771:[0,.67659,0,0],772:[0,.60889,0,0],774:[0,.69444,0,0],775:[0,.67937,0,0],776:[0,.67937,0,0],778:[0,.69444,0,0],779:[0,.69444,0,0],780:[0,.63194,0,0],915:[0,.69444,0,0],916:[0,.69444,0,0],920:[0,.69444,0,0],923:[0,.69444,0,0],926:[0,.69444,0,0],928:[0,.69444,0,0],931:[0,.69444,0,0],933:[0,.69444,0,0],934:[0,.69444,0,0],936:[0,.69444,0,0],937:[0,.69444,0,0],8211:[0,.44444,.02778,0],8212:[0,.44444,.02778,0],8216:[0,.69444,0,0],8217:[0,.69444,0,0],8220:[0,.69444,0,0],8221:[0,.69444,0,0]},"Script-Regular":{65:[0,.7,.22925,0],66:[0,.7,.04087,0],67:[0,.7,.1689,0],68:[0,.7,.09371,0],69:[0,.7,.18583,0],70:[0,.7,.13634,0],71:[0,.7,.17322,0],72:[0,.7,.29694,0],73:[0,.7,.19189,0],74:[.27778,.7,.19189,0],75:[0,.7,.31259,0],76:[0,.7,.19189,0],77:[0,.7,.15981,0],78:[0,.7,.3525,0],79:[0,.7,.08078,0],80:[0,.7,.08078,0],81:[0,.7,.03305,0],82:[0,.7,.06259,0],83:[0,.7,.19189,0],84:[0,.7,.29087,0],85:[0,.7,.25815,0],86:[0,.7,.27523,0],87:[0,.7,.27523,0],88:[0,.7,.26006,0],89:[0,.7,.2939,0],90:[0,.7,.24037,0]},"Size1-Regular":{40:[.35001,.85,0,0],41:[.35001,.85,0,0],47:[.35001,.85,0,0],91:[.35001,.85,0,0],92:[.35001,.85,0,0],93:[.35001,.85,0,0],123:[.35001,.85,0,0],125:[.35001,.85,0,0],710:[0,.72222,0,0],732:[0,.72222,0,0],770:[0,.72222,0,0],771:[0,.72222,0,0],8214:[-99e-5,.601,0,0],8593:[1e-5,.6,0,0],8595:[1e-5,.6,0,0],8657:[1e-5,.6,0,0],8659:[1e-5,.6,0,0],8719:[.25001,.75,0,0],8720:[.25001,.75,0,0],8721:[.25001,.75,0,0],8730:[.35001,.85,0,0],8739:[-.00599,.606,0,0],8741:[-.00599,.606,0,0],8747:[.30612,.805,.19445,0],8748:[.306,.805,.19445,0],8749:[.306,.805,.19445,0],8750:[.30612,.805,.19445,0],8896:[.25001,.75,0,0],8897:[.25001,.75,0,0],8898:[.25001,.75,0,0],8899:[.25001,.75,0,0],8968:[.35001,.85,0,0],8969:[.35001,.85,0,0],8970:[.35001,.85,0,0],8971:[.35001,.85,0,0],9168:[-99e-5,.601,0,0],10216:[.35001,.85,0,0],10217:[.35001,.85,0,0],10752:[.25001,.75,0,0],10753:[.25001,.75,0,0],10754:[.25001,.75,0,0],10756:[.25001,.75,0,0],10758:[.25001,.75,0,0]},"Size2-Regular":{40:[.65002,1.15,0,0],41:[.65002,1.15,0,0],47:[.65002,1.15,0,0],91:[.65002,1.15,0,0],92:[.65002,1.15,0,0],93:[.65002,1.15,0,0],123:[.65002,1.15,0,0],125:[.65002,1.15,0,0],710:[0,.75,0,0],732:[0,.75,0,0],770:[0,.75,0,0],771:[0,.75,0,0],8719:[.55001,1.05,0,0],8720:[.55001,1.05,0,0],8721:[.55001,1.05,0,0],8730:[.65002,1.15,0,0],8747:[.86225,1.36,.44445,0],8748:[.862,1.36,.44445,0],8749:[.862,1.36,.44445,0],8750:[.86225,1.36,.44445,0],8896:[.55001,1.05,0,0],8897:[.55001,1.05,0,0],8898:[.55001,1.05,0,0],8899:[.55001,1.05,0,0],8968:[.65002,1.15,0,0],8969:[.65002,1.15,0,0],8970:[.65002,1.15,0,0],8971:[.65002,1.15,0,0],10216:[.65002,1.15,0,0],10217:[.65002,1.15,0,0],10752:[.55001,1.05,0,0],10753:[.55001,1.05,0,0],10754:[.55001,1.05,0,0], +10756:[.55001,1.05,0,0],10758:[.55001,1.05,0,0]},"Size3-Regular":{40:[.95003,1.45,0,0],41:[.95003,1.45,0,0],47:[.95003,1.45,0,0],91:[.95003,1.45,0,0],92:[.95003,1.45,0,0],93:[.95003,1.45,0,0],123:[.95003,1.45,0,0],125:[.95003,1.45,0,0],710:[0,.75,0,0],732:[0,.75,0,0],770:[0,.75,0,0],771:[0,.75,0,0],8730:[.95003,1.45,0,0],8968:[.95003,1.45,0,0],8969:[.95003,1.45,0,0],8970:[.95003,1.45,0,0],8971:[.95003,1.45,0,0],10216:[.95003,1.45,0,0],10217:[.95003,1.45,0,0]},"Size4-Regular":{40:[1.25003,1.75,0,0],41:[1.25003,1.75,0,0],47:[1.25003,1.75,0,0],91:[1.25003,1.75,0,0],92:[1.25003,1.75,0,0],93:[1.25003,1.75,0,0],123:[1.25003,1.75,0,0],125:[1.25003,1.75,0,0],710:[0,.825,0,0],732:[0,.825,0,0],770:[0,.825,0,0],771:[0,.825,0,0],8730:[1.25003,1.75,0,0],8968:[1.25003,1.75,0,0],8969:[1.25003,1.75,0,0],8970:[1.25003,1.75,0,0],8971:[1.25003,1.75,0,0],9115:[.64502,1.155,0,0],9116:[1e-5,.6,0,0],9117:[.64502,1.155,0,0],9118:[.64502,1.155,0,0],9119:[1e-5,.6,0,0],9120:[.64502,1.155,0,0],9121:[.64502,1.155,0,0],9122:[-99e-5,.601,0,0],9123:[.64502,1.155,0,0],9124:[.64502,1.155,0,0],9125:[-99e-5,.601,0,0],9126:[.64502,1.155,0,0],9127:[1e-5,.9,0,0],9128:[.65002,1.15,0,0],9129:[.90001,0,0,0],9130:[0,.3,0,0],9131:[1e-5,.9,0,0],9132:[.65002,1.15,0,0],9133:[.90001,0,0,0],9143:[.88502,.915,0,0],10216:[1.25003,1.75,0,0],10217:[1.25003,1.75,0,0],57344:[-.00499,.605,0,0],57345:[-.00499,.605,0,0],57680:[0,.12,0,0],57681:[0,.12,0,0],57682:[0,.12,0,0],57683:[0,.12,0,0]},"Typewriter-Regular":{33:[0,.61111,0,0],34:[0,.61111,0,0],35:[0,.61111,0,0],36:[.08333,.69444,0,0],37:[.08333,.69444,0,0],38:[0,.61111,0,0],39:[0,.61111,0,0],40:[.08333,.69444,0,0],41:[.08333,.69444,0,0],42:[0,.52083,0,0],43:[-.08056,.53055,0,0],44:[.13889,.125,0,0],45:[-.08056,.53055,0,0],46:[0,.125,0,0],47:[.08333,.69444,0,0],48:[0,.61111,0,0],49:[0,.61111,0,0],50:[0,.61111,0,0],51:[0,.61111,0,0],52:[0,.61111,0,0],53:[0,.61111,0,0],54:[0,.61111,0,0],55:[0,.61111,0,0],56:[0,.61111,0,0],57:[0,.61111,0,0],58:[0,.43056,0,0],59:[.13889,.43056,0,0],60:[-.05556,.55556,0,0],61:[-.19549,.41562,0,0],62:[-.05556,.55556,0,0],63:[0,.61111,0,0],64:[0,.61111,0,0],65:[0,.61111,0,0],66:[0,.61111,0,0],67:[0,.61111,0,0],68:[0,.61111,0,0],69:[0,.61111,0,0],70:[0,.61111,0,0],71:[0,.61111,0,0],72:[0,.61111,0,0],73:[0,.61111,0,0],74:[0,.61111,0,0],75:[0,.61111,0,0],76:[0,.61111,0,0],77:[0,.61111,0,0],78:[0,.61111,0,0],79:[0,.61111,0,0],80:[0,.61111,0,0],81:[.13889,.61111,0,0],82:[0,.61111,0,0],83:[0,.61111,0,0],84:[0,.61111,0,0],85:[0,.61111,0,0],86:[0,.61111,0,0],87:[0,.61111,0,0],88:[0,.61111,0,0],89:[0,.61111,0,0],90:[0,.61111,0,0],91:[.08333,.69444,0,0],92:[.08333,.69444,0,0],93:[.08333,.69444,0,0],94:[0,.61111,0,0],95:[.09514,0,0,0],96:[0,.61111,0,0],97:[0,.43056,0,0],98:[0,.61111,0,0],99:[0,.43056,0,0],100:[0,.61111,0,0],101:[0,.43056,0,0],102:[0,.61111,0,0],103:[.22222,.43056,0,0],104:[0,.61111,0,0],105:[0,.61111,0,0],106:[.22222,.61111,0,0],107:[0,.61111,0,0],108:[0,.61111,0,0],109:[0,.43056,0,0],110:[0,.43056,0,0],111:[0,.43056,0,0],112:[.22222,.43056,0,0],113:[.22222,.43056,0,0],114:[0,.43056,0,0],115:[0,.43056,0,0],116:[0,.55358,0,0],117:[0,.43056,0,0],118:[0,.43056,0,0],119:[0,.43056,0,0],120:[0,.43056,0,0],121:[.22222,.43056,0,0],122:[0,.43056,0,0],123:[.08333,.69444,0,0],124:[.08333,.69444,0,0],125:[.08333,.69444,0,0],126:[0,.61111,0,0],127:[0,.61111,0,0],305:[0,.43056,0,0],567:[.22222,.43056,0,0],768:[0,.61111,0,0],769:[0,.61111,0,0],770:[0,.61111,0,0],771:[0,.61111,0,0],772:[0,.56555,0,0],774:[0,.61111,0,0],776:[0,.61111,0,0],778:[0,.61111,0,0],780:[0,.56597,0,0],915:[0,.61111,0,0],916:[0,.61111,0,0],920:[0,.61111,0,0],923:[0,.61111,0,0],926:[0,.61111,0,0],928:[0,.61111,0,0],931:[0,.61111,0,0],933:[0,.61111,0,0],934:[0,.61111,0,0],936:[0,.61111,0,0],937:[0,.61111,0,0],2018:[0,.61111,0,0],2019:[0,.61111,0,0],8242:[0,.61111,0,0]}}},{}],19:[function(e,t,r){var a=e("./utils");var i=e("./ParseError");var n=e("./parseData");var s=n.ParseNode;function l(e,r,a){if(typeof e==="string"){e=[e]}if(typeof r==="number"){r={numArgs:r}}var i={numArgs:r.numArgs,argTypes:r.argTypes,greediness:r.greediness===undefined?1:r.greediness,allowedInText:!!r.allowedInText,numOptionalArgs:r.numOptionalArgs||0,infix:!!r.infix,handler:a};for(var n=0;n","\\langle","\\rangle","\\lt","\\gt","\\lvert","\\rvert","\\lVert","\\rVert","\\lgroup","\\rgroup","\\lmoustache","\\rmoustache","/","\\backslash","|","\\vert","\\|","\\Vert","\\uparrow","\\Uparrow","\\downarrow","\\Downarrow","\\updownarrow","\\Updownarrow","."];var c={"\\Bbb":"\\mathbb","\\bold":"\\mathbf","\\frak":"\\mathfrak"};l(["\\blue","\\orange","\\pink","\\red","\\green","\\gray","\\purple","\\blueA","\\blueB","\\blueC","\\blueD","\\blueE","\\tealA","\\tealB","\\tealC","\\tealD","\\tealE","\\greenA","\\greenB","\\greenC","\\greenD","\\greenE","\\goldA","\\goldB","\\goldC","\\goldD","\\goldE","\\redA","\\redB","\\redC","\\redD","\\redE","\\maroonA","\\maroonB","\\maroonC","\\maroonD","\\maroonE","\\purpleA","\\purpleB","\\purpleC","\\purpleD","\\purpleE","\\mintA","\\mintB","\\mintC","\\grayA","\\grayB","\\grayC","\\grayD","\\grayE","\\grayF","\\grayG","\\grayH","\\grayI","\\kaBlue","\\kaGreen"],{numArgs:1,allowedInText:true,greediness:3},function(e,t){var r=t[0];return{type:"color",color:"katex-"+e.funcName.slice(1),value:o(r)}});l(["\\arcsin","\\arccos","\\arctan","\\arg","\\cos","\\cosh","\\cot","\\coth","\\csc","\\deg","\\dim","\\exp","\\hom","\\ker","\\lg","\\ln","\\log","\\sec","\\sin","\\sinh","\\tan","\\tanh"],{numArgs:0},function(e){return{type:"op",limits:false,symbol:false,body:e.funcName}});l(["\\det","\\gcd","\\inf","\\lim","\\liminf","\\limsup","\\max","\\min","\\Pr","\\sup"],{numArgs:0},function(e){return{type:"op",limits:true,symbol:false,body:e.funcName}});l(["\\int","\\iint","\\iiint","\\oint"],{numArgs:0},function(e){return{type:"op",limits:false,symbol:true,body:e.funcName}});l(["\\coprod","\\bigvee","\\bigwedge","\\biguplus","\\bigcap","\\bigcup","\\intop","\\prod","\\sum","\\bigotimes","\\bigoplus","\\bigodot","\\bigsqcup","\\smallint"],{numArgs:0},function(e){return{type:"op",limits:true,symbol:true,body:e.funcName}});l("\\mathop",{numArgs:1},function(e,t){var r=t[0];return{type:"op",limits:false,symbol:false,value:o(r)}});l(["\\dfrac","\\frac","\\tfrac","\\dbinom","\\binom","\\tbinom","\\\\atopfrac"],{numArgs:2,greediness:2},function(e,t){var r=t[0];var a=t[1];var i;var n=null;var s=null;var l="auto";switch(e.funcName){case"\\dfrac":case"\\frac":case"\\tfrac":i=true;break;case"\\\\atopfrac":i=false;break;case"\\dbinom":case"\\binom":case"\\tbinom":i=false;n="(";s=")";break;default:throw new Error("Unrecognized genfrac command")}switch(e.funcName){case"\\dfrac":case"\\dbinom":l="display";break;case"\\tfrac":case"\\tbinom":l="text";break}return{type:"genfrac",numer:r,denom:a,hasBarLine:i,leftDelim:n,rightDelim:s,size:l}});l(["\\llap","\\rlap"],{numArgs:1,allowedInText:true},function(e,t){var r=t[0];return{type:e.funcName.slice(1),body:r}});var m=function(e,t){if(a.contains(h,e.value)){return e}else{throw new i("Invalid delimiter: '"+e.value+"' after '"+t.funcName+"'",e)}};l(["\\bigl","\\Bigl","\\biggl","\\Biggl","\\bigr","\\Bigr","\\biggr","\\Biggr","\\bigm","\\Bigm","\\biggm","\\Biggm","\\big","\\Big","\\bigg","\\Bigg"],{numArgs:1},function(e,t){var r=m(t[0],e);return{type:"delimsizing",size:p[e.funcName].size,mclass:p[e.funcName].mclass,value:r.value}});l(["\\left","\\right"],{numArgs:1},function(e,t){var r=m(t[0],e);return{type:"leftright",value:r.value}});l("\\middle",{numArgs:1},function(e,t){var r=m(t[0],e);if(!e.parser.leftrightDepth){throw new i("\\middle without preceding \\left",r)}return{type:"middle",value:r.value}});l(["\\tiny","\\scriptsize","\\footnotesize","\\small","\\normalsize","\\large","\\Large","\\LARGE","\\huge","\\Huge"],0,null);l(["\\displaystyle","\\textstyle","\\scriptstyle","\\scriptscriptstyle"],0,null);l(["\\mathrm","\\mathit","\\mathbf","\\mathbb","\\mathcal","\\mathfrak","\\mathscr","\\mathsf","\\mathtt","\\Bbb","\\bold","\\frak"],{numArgs:1,greediness:2},function(e,t){var r=t[0];var a=e.funcName;if(a in c){a=c[a]}return{type:"font",font:a.slice(1),body:r}});l(["\\acute","\\grave","\\ddot","\\tilde","\\bar","\\breve","\\check","\\hat","\\vec","\\dot"],{numArgs:1},function(e,t){var r=t[0];return{type:"accent",accent:e.funcName,base:r}});l(["\\over","\\choose","\\atop"],{numArgs:0,infix:true},function(e){var t;switch(e.funcName){case"\\over":t="\\frac";break;case"\\choose":t="\\binom";break;case"\\atop":t="\\\\atopfrac";break;default:throw new Error("Unrecognized infix genfrac command")}return{type:"infix",replaceWith:t,token:e.token}});l(["\\\\","\\cr"],{numArgs:0,numOptionalArgs:1,argTypes:["size"]},function(e,t){var r=t[0];return{type:"cr",size:r}});l(["\\begin","\\end"],{numArgs:1,argTypes:["text"]},function(e,t){var r=t[0];if(r.type!=="ordgroup"){throw new i("Invalid environment name",r)}var a="";for(var n=0;n";return e};function n(e){this.text=e}n.prototype.toNode=function(){return document.createTextNode(this.text)};n.prototype.toMarkup=function(){return a.escape(this.text)};t.exports={MathNode:i,TextNode:n}},{"./utils":25}],21:[function(e,t,r){function a(e,t,r,a,i){this.type=e;this.value=t;this.mode=r;if(a&&(!i||i.lexer===a.lexer)){this.lexer=a.lexer;this.start=a.start;this.end=(i||a).end}}t.exports={ParseNode:a}},{}],22:[function(e,t,r){var a=e("./Parser");var i=function(e,t){if(!(typeof e==="string"||e instanceof String)){throw new TypeError("KaTeX can only parse string typed expression")}var r=new a(e,t);return r.parse()};t.exports=i},{"./Parser":7}],23:[function(e,t,r){t.exports={math:{},text:{}};function a(e,r,a,i,n){t.exports[e][n]={font:r,group:a,replace:i}}var i="math";var n="text";var s="main";var l="ams";var o="accent";var u="bin";var p="close";var h="inner";var c="mathord";var m="op";var f="open";var v="punct";var d="rel";var g="spacing";var y="textord";a(i,s,d,"\u2261","\\equiv");a(i,s,d,"\u227a","\\prec");a(i,s,d,"\u227b","\\succ");a(i,s,d,"\u223c","\\sim");a(i,s,d,"\u22a5","\\perp");a(i,s,d,"\u2aaf","\\preceq");a(i,s,d,"\u2ab0","\\succeq");a(i,s,d,"\u2243","\\simeq");a(i,s,d,"\u2223","\\mid");a(i,s,d,"\u226a","\\ll");a(i,s,d,"\u226b","\\gg");a(i,s,d,"\u224d","\\asymp");a(i,s,d,"\u2225","\\parallel");a(i,s,d,"\u22c8","\\bowtie");a(i,s,d,"\u2323","\\smile");a(i,s,d,"\u2291","\\sqsubseteq");a(i,s,d,"\u2292","\\sqsupseteq");a(i,s,d,"\u2250","\\doteq");a(i,s,d,"\u2322","\\frown");a(i,s,d,"\u220b","\\ni");a(i,s,d,"\u221d","\\propto");a(i,s,d,"\u22a2","\\vdash");a(i,s,d,"\u22a3","\\dashv");a(i,s,d,"\u220b","\\owns");a(i,s,v,".","\\ldotp");a(i,s,v,"\u22c5","\\cdotp");a(i,s,y,"#","\\#");a(n,s,y,"#","\\#");a(i,s,y,"&","\\&");a(n,s,y,"&","\\&");a(i,s,y,"\u2135","\\aleph");a(i,s,y,"\u2200","\\forall");a(i,s,y,"\u210f","\\hbar");a(i,s,y,"\u2203","\\exists");a(i,s,y,"\u2207","\\nabla");a(i,s,y,"\u266d","\\flat");a(i,s,y,"\u2113","\\ell");a(i,s,y,"\u266e","\\natural");a(i,s,y,"\u2663","\\clubsuit");a(i,s,y,"\u2118","\\wp");a(i,s,y,"\u266f","\\sharp");a(i,s,y,"\u2662","\\diamondsuit");a(i,s,y,"\u211c","\\Re");a(i,s,y,"\u2661","\\heartsuit");a(i,s,y,"\u2111","\\Im");a(i,s,y,"\u2660","\\spadesuit");a(i,s,y,"\u2020","\\dag");a(i,s,y,"\u2021","\\ddag");a(i,s,p,"\u23b1","\\rmoustache");a(i,s,f,"\u23b0","\\lmoustache");a(i,s,p,"\u27ef","\\rgroup");a(i,s,f,"\u27ee","\\lgroup");a(i,s,u,"\u2213","\\mp");a(i,s,u,"\u2296","\\ominus");a(i,s,u,"\u228e","\\uplus");a(i,s,u,"\u2293","\\sqcap");a(i,s,u,"\u2217","\\ast");a(i,s,u,"\u2294","\\sqcup");a(i,s,u,"\u25ef","\\bigcirc");a(i,s,u,"\u2219","\\bullet");a(i,s,u,"\u2021","\\ddagger");a(i,s,u,"\u2240","\\wr");a(i,s,u,"\u2a3f","\\amalg");a(i,s,d,"\u27f5","\\longleftarrow");a(i,s,d,"\u21d0","\\Leftarrow");a(i,s,d,"\u27f8","\\Longleftarrow");a(i,s,d,"\u27f6","\\longrightarrow");a(i,s,d,"\u21d2","\\Rightarrow");a(i,s,d,"\u27f9","\\Longrightarrow");a(i,s,d,"\u2194","\\leftrightarrow");a(i,s,d,"\u27f7","\\longleftrightarrow");a(i,s,d,"\u21d4","\\Leftrightarrow");a(i,s,d,"\u27fa","\\Longleftrightarrow");a(i,s,d,"\u21a6","\\mapsto");a(i,s,d,"\u27fc","\\longmapsto");a(i,s,d,"\u2197","\\nearrow");a(i,s,d,"\u21a9","\\hookleftarrow");a(i,s,d,"\u21aa","\\hookrightarrow");a(i,s,d,"\u2198","\\searrow");a(i,s,d,"\u21bc","\\leftharpoonup");a(i,s,d,"\u21c0","\\rightharpoonup");a(i,s,d,"\u2199","\\swarrow");a(i,s,d,"\u21bd","\\leftharpoondown");a(i,s,d,"\u21c1","\\rightharpoondown");a(i,s,d,"\u2196","\\nwarrow");a(i,s,d,"\u21cc","\\rightleftharpoons");a(i,l,d,"\u226e","\\nless");a(i,l,d,"\ue010","\\nleqslant");a(i,l,d,"\ue011","\\nleqq");a(i,l,d,"\u2a87","\\lneq");a(i,l,d,"\u2268","\\lneqq");a(i,l,d,"\ue00c","\\lvertneqq");a(i,l,d,"\u22e6","\\lnsim");a(i,l,d,"\u2a89","\\lnapprox");a(i,l,d,"\u2280","\\nprec");a(i,l,d,"\u22e0","\\npreceq");a(i,l,d,"\u22e8","\\precnsim");a(i,l,d,"\u2ab9","\\precnapprox");a(i,l,d,"\u2241","\\nsim");a(i,l,d,"\ue006","\\nshortmid");a(i,l,d,"\u2224","\\nmid");a(i,l,d,"\u22ac","\\nvdash");a(i,l,d,"\u22ad","\\nvDash");a(i,l,d,"\u22ea","\\ntriangleleft");a(i,l,d,"\u22ec","\\ntrianglelefteq");a(i,l,d,"\u228a","\\subsetneq");a(i,l,d,"\ue01a","\\varsubsetneq");a(i,l,d,"\u2acb","\\subsetneqq");a(i,l,d,"\ue017","\\varsubsetneqq");a(i,l,d,"\u226f","\\ngtr");a(i,l,d,"\ue00f","\\ngeqslant");a(i,l,d,"\ue00e","\\ngeqq");a(i,l,d,"\u2a88","\\gneq");a(i,l,d,"\u2269","\\gneqq");a(i,l,d,"\ue00d","\\gvertneqq");a(i,l,d,"\u22e7","\\gnsim");a(i,l,d,"\u2a8a","\\gnapprox");a(i,l,d,"\u2281","\\nsucc");a(i,l,d,"\u22e1","\\nsucceq");a(i,l,d,"\u22e9","\\succnsim");a(i,l,d,"\u2aba","\\succnapprox");a(i,l,d,"\u2246","\\ncong");a(i,l,d,"\ue007","\\nshortparallel");a(i,l,d,"\u2226","\\nparallel");a(i,l,d,"\u22af","\\nVDash");a(i,l,d,"\u22eb","\\ntriangleright");a(i,l,d,"\u22ed","\\ntrianglerighteq");a(i,l,d,"\ue018","\\nsupseteqq");a(i,l,d,"\u228b","\\supsetneq");a(i,l,d,"\ue01b","\\varsupsetneq");a(i,l,d,"\u2acc","\\supsetneqq");a(i,l,d,"\ue019","\\varsupsetneqq");a(i,l,d,"\u22ae","\\nVdash");a(i,l,d,"\u2ab5","\\precneqq");a(i,l,d,"\u2ab6","\\succneqq");a(i,l,d,"\ue016","\\nsubseteqq");a(i,l,u,"\u22b4","\\unlhd");a(i,l,u,"\u22b5","\\unrhd");a(i,l,d,"\u219a","\\nleftarrow");a(i,l,d,"\u219b","\\nrightarrow");a(i,l,d,"\u21cd","\\nLeftarrow");a(i,l,d,"\u21cf","\\nRightarrow");a(i,l,d,"\u21ae","\\nleftrightarrow");a(i,l,d,"\u21ce","\\nLeftrightarrow");a(i,l,d,"\u25b3","\\vartriangle");a(i,l,y,"\u210f","\\hslash");a(i,l,y,"\u25bd","\\triangledown");a(i,l,y,"\u25ca","\\lozenge");a(i,l,y,"\u24c8","\\circledS");a(i,l,y,"\xae","\\circledR");a(i,l,y,"\u2221","\\measuredangle");a(i,l,y,"\u2204","\\nexists");a(i,l,y,"\u2127","\\mho");a(i,l,y,"\u2132","\\Finv");a(i,l,y,"\u2141","\\Game");a(i,l,y,"k","\\Bbbk");a(i,l,y,"\u2035","\\backprime");a(i,l,y,"\u25b2","\\blacktriangle");a(i,l,y,"\u25bc","\\blacktriangledown");a(i,l,y,"\u25a0","\\blacksquare");a(i,l,y,"\u29eb","\\blacklozenge");a(i,l,y,"\u2605","\\bigstar");a(i,l,y,"\u2222","\\sphericalangle");a(i,l,y,"\u2201","\\complement");a(i,l,y,"\xf0","\\eth");a(i,l,y,"\u2571","\\diagup");a(i,l,y,"\u2572","\\diagdown");a(i,l,y,"\u25a1","\\square");a(i,l,y,"\u25a1","\\Box");a(i,l,y,"\u25ca","\\Diamond");a(i,l,y,"\xa5","\\yen");a(i,l,y,"\u2713","\\checkmark");a(i,l,y,"\u2136","\\beth");a(i,l,y,"\u2138","\\daleth");a(i,l,y,"\u2137","\\gimel");a(i,l,y,"\u03dd","\\digamma");a(i,l,y,"\u03f0","\\varkappa");a(i,l,f,"\u250c","\\ulcorner");a(i,l,p,"\u2510","\\urcorner");a(i,l,f,"\u2514","\\llcorner");a(i,l,p,"\u2518","\\lrcorner");a(i,l,d,"\u2266","\\leqq");a(i,l,d,"\u2a7d","\\leqslant");a(i,l,d,"\u2a95","\\eqslantless");a(i,l,d,"\u2272","\\lesssim");a(i,l,d,"\u2a85","\\lessapprox");a(i,l,d,"\u224a","\\approxeq");a(i,l,u,"\u22d6","\\lessdot");a(i,l,d,"\u22d8","\\lll");a(i,l,d,"\u2276","\\lessgtr");a(i,l,d,"\u22da","\\lesseqgtr");a(i,l,d,"\u2a8b","\\lesseqqgtr");a(i,l,d,"\u2251","\\doteqdot");a(i,l,d,"\u2253","\\risingdotseq");a(i,l,d,"\u2252","\\fallingdotseq");a(i,l,d,"\u223d","\\backsim");a(i,l,d,"\u22cd","\\backsimeq");a(i,l,d,"\u2ac5","\\subseteqq");a(i,l,d,"\u22d0","\\Subset");a(i,l,d,"\u228f","\\sqsubset");a(i,l,d,"\u227c","\\preccurlyeq");a(i,l,d,"\u22de","\\curlyeqprec");a(i,l,d,"\u227e","\\precsim");a(i,l,d,"\u2ab7","\\precapprox");a(i,l,d,"\u22b2","\\vartriangleleft");a(i,l,d,"\u22b4","\\trianglelefteq");a(i,l,d,"\u22a8","\\vDash");a(i,l,d,"\u22aa","\\Vvdash");a(i,l,d,"\u2323","\\smallsmile");a(i,l,d,"\u2322","\\smallfrown");a(i,l,d,"\u224f","\\bumpeq");a(i,l,d,"\u224e","\\Bumpeq");a(i,l,d,"\u2267","\\geqq");a(i,l,d,"\u2a7e","\\geqslant");a(i,l,d,"\u2a96","\\eqslantgtr");a(i,l,d,"\u2273","\\gtrsim");a(i,l,d,"\u2a86","\\gtrapprox");a(i,l,u,"\u22d7","\\gtrdot");a(i,l,d,"\u22d9","\\ggg");a(i,l,d,"\u2277","\\gtrless");a(i,l,d,"\u22db","\\gtreqless");a(i,l,d,"\u2a8c","\\gtreqqless");a(i,l,d,"\u2256","\\eqcirc");a(i,l,d,"\u2257","\\circeq");a(i,l,d,"\u225c","\\triangleq");a(i,l,d,"\u223c","\\thicksim");a(i,l,d,"\u2248","\\thickapprox");a(i,l,d,"\u2ac6","\\supseteqq");a(i,l,d,"\u22d1","\\Supset");a(i,l,d,"\u2290","\\sqsupset");a(i,l,d,"\u227d","\\succcurlyeq");a(i,l,d,"\u22df","\\curlyeqsucc");a(i,l,d,"\u227f","\\succsim");a(i,l,d,"\u2ab8","\\succapprox");a(i,l,d,"\u22b3","\\vartriangleright");a(i,l,d,"\u22b5","\\trianglerighteq");a(i,l,d,"\u22a9","\\Vdash");a(i,l,d,"\u2223","\\shortmid");a(i,l,d,"\u2225","\\shortparallel");a(i,l,d,"\u226c","\\between");a(i,l,d,"\u22d4","\\pitchfork");a(i,l,d,"\u221d","\\varpropto");a(i,l,d,"\u25c0","\\blacktriangleleft");a(i,l,d,"\u2234","\\therefore");a(i,l,d,"\u220d","\\backepsilon");a(i,l,d,"\u25b6","\\blacktriangleright");a(i,l,d,"\u2235","\\because");a(i,l,d,"\u22d8","\\llless");a(i,l,d,"\u22d9","\\gggtr");a(i,l,u,"\u22b2","\\lhd");a(i,l,u,"\u22b3","\\rhd");a(i,l,d,"\u2242","\\eqsim");a(i,s,d,"\u22c8","\\Join");a(i,l,d,"\u2251","\\Doteq");a(i,l,u,"\u2214","\\dotplus");a(i,l,u,"\u2216","\\smallsetminus");a(i,l,u,"\u22d2","\\Cap");a(i,l,u,"\u22d3","\\Cup");a(i,l,u,"\u2a5e","\\doublebarwedge");a(i,l,u,"\u229f","\\boxminus");a(i,l,u,"\u229e","\\boxplus");a(i,l,u,"\u22c7","\\divideontimes");a(i,l,u,"\u22c9","\\ltimes");a(i,l,u,"\u22ca","\\rtimes");a(i,l,u,"\u22cb","\\leftthreetimes");a(i,l,u,"\u22cc","\\rightthreetimes");a(i,l,u,"\u22cf","\\curlywedge");a(i,l,u,"\u22ce","\\curlyvee");a(i,l,u,"\u229d","\\circleddash");a(i,l,u,"\u229b","\\circledast");a(i,l,u,"\u22c5","\\centerdot");a(i,l,u,"\u22ba","\\intercal");a(i,l,u,"\u22d2","\\doublecap");a(i,l,u,"\u22d3","\\doublecup");a(i,l,u,"\u22a0","\\boxtimes");a(i,l,d,"\u21e2","\\dashrightarrow");a(i,l,d,"\u21e0","\\dashleftarrow");a(i,l,d,"\u21c7","\\leftleftarrows");a(i,l,d,"\u21c6","\\leftrightarrows");a(i,l,d,"\u21da","\\Lleftarrow");a(i,l,d,"\u219e","\\twoheadleftarrow");a(i,l,d,"\u21a2","\\leftarrowtail");a(i,l,d,"\u21ab","\\looparrowleft");a(i,l,d,"\u21cb","\\leftrightharpoons");a(i,l,d,"\u21b6","\\curvearrowleft");a(i,l,d,"\u21ba","\\circlearrowleft");a(i,l,d,"\u21b0","\\Lsh");a(i,l,d,"\u21c8","\\upuparrows");a(i,l,d,"\u21bf","\\upharpoonleft");a(i,l,d,"\u21c3","\\downharpoonleft");a(i,l,d,"\u22b8","\\multimap");a(i,l,d,"\u21ad","\\leftrightsquigarrow");a(i,l,d,"\u21c9","\\rightrightarrows");a(i,l,d,"\u21c4","\\rightleftarrows");a(i,l,d,"\u21a0","\\twoheadrightarrow");a(i,l,d,"\u21a3","\\rightarrowtail");a(i,l,d,"\u21ac","\\looparrowright");a(i,l,d,"\u21b7","\\curvearrowright");a(i,l,d,"\u21bb","\\circlearrowright");a(i,l,d,"\u21b1","\\Rsh");a(i,l,d,"\u21ca","\\downdownarrows");a(i,l,d,"\u21be","\\upharpoonright");a(i,l,d,"\u21c2","\\downharpoonright");a(i,l,d,"\u21dd","\\rightsquigarrow");a(i,l,d,"\u21dd","\\leadsto");a(i,l,d,"\u21db","\\Rrightarrow");a(i,l,d,"\u21be","\\restriction");a(i,s,y,"\u2018","`");a(i,s,y,"$","\\$");a(n,s,y,"$","\\$");a(i,s,y,"%","\\%");a(n,s,y,"%","\\%");a(i,s,y,"_","\\_");a(n,s,y,"_","\\_");a(i,s,y,"\u2220","\\angle");a(i,s,y,"\u221e","\\infty");a(i,s,y,"\u2032","\\prime");a(i,s,y,"\u25b3","\\triangle");a(i,s,y,"\u0393","\\Gamma");a(i,s,y,"\u0394","\\Delta");a(i,s,y,"\u0398","\\Theta");a(i,s,y,"\u039b","\\Lambda");a(i,s,y,"\u039e","\\Xi");a(i,s,y,"\u03a0","\\Pi");a(i,s,y,"\u03a3","\\Sigma");a(i,s,y,"\u03a5","\\Upsilon");a(i,s,y,"\u03a6","\\Phi");a(i,s,y,"\u03a8","\\Psi");a(i,s,y,"\u03a9","\\Omega");a(i,s,y,"\xac","\\neg");a(i,s,y,"\xac","\\lnot");a(i,s,y,"\u22a4","\\top");a(i,s,y,"\u22a5","\\bot");a(i,s,y,"\u2205","\\emptyset");a(i,l,y,"\u2205","\\varnothing");a(i,s,c,"\u03b1","\\alpha");a(i,s,c,"\u03b2","\\beta");a(i,s,c,"\u03b3","\\gamma");a(i,s,c,"\u03b4","\\delta");a(i,s,c,"\u03f5","\\epsilon");a(i,s,c,"\u03b6","\\zeta");a(i,s,c,"\u03b7","\\eta");a(i,s,c,"\u03b8","\\theta");a(i,s,c,"\u03b9","\\iota");a(i,s,c,"\u03ba","\\kappa");a(i,s,c,"\u03bb","\\lambda");a(i,s,c,"\u03bc","\\mu");a(i,s,c,"\u03bd","\\nu");a(i,s,c,"\u03be","\\xi");a(i,s,c,"o","\\omicron");a(i,s,c,"\u03c0","\\pi");a(i,s,c,"\u03c1","\\rho");a(i,s,c,"\u03c3","\\sigma");a(i,s,c,"\u03c4","\\tau");a(i,s,c,"\u03c5","\\upsilon");a(i,s,c,"\u03d5","\\phi");a(i,s,c,"\u03c7","\\chi");a(i,s,c,"\u03c8","\\psi");a(i,s,c,"\u03c9","\\omega");a(i,s,c,"\u03b5","\\varepsilon");a(i,s,c,"\u03d1","\\vartheta");a(i,s,c,"\u03d6","\\varpi");a(i,s,c,"\u03f1","\\varrho");a(i,s,c,"\u03c2","\\varsigma");a(i,s,c,"\u03c6","\\varphi");a(i,s,u,"\u2217","*");a(i,s,u,"+","+");a(i,s,u,"\u2212","-");a(i,s,u,"\u22c5","\\cdot");a(i,s,u,"\u2218","\\circ");a(i,s,u,"\xf7","\\div");a(i,s,u,"\xb1","\\pm");a(i,s,u,"\xd7","\\times");a(i,s,u,"\u2229","\\cap");a(i,s,u,"\u222a","\\cup");a(i,s,u,"\u2216","\\setminus");a(i,s,u,"\u2227","\\land");a(i,s,u,"\u2228","\\lor");a(i,s,u,"\u2227","\\wedge");a(i,s,u,"\u2228","\\vee");a(i,s,y,"\u221a","\\surd");a(i,s,f,"(","(");a(i,s,f,"[","[");a(i,s,f,"\u27e8","\\langle");a(i,s,f,"\u2223","\\lvert");a(i,s,f,"\u2225","\\lVert");a(i,s,p,")",")");a(i,s,p,"]","]");a(i,s,p,"?","?");a(i,s,p,"!","!");a(i,s,p,"\u27e9","\\rangle");a(i,s,p,"\u2223","\\rvert");a(i,s,p,"\u2225","\\rVert");a(i,s,d,"=","=");a(i,s,d,"<","<");a(i,s,d,">",">");a(i,s,d,":",":");a(i,s,d,"\u2248","\\approx");a(i,s,d,"\u2245","\\cong");a(i,s,d,"\u2265","\\ge");a(i,s,d,"\u2265","\\geq");a(i,s,d,"\u2190","\\gets");a(i,s,d,">","\\gt");a(i,s,d,"\u2208","\\in");a(i,s,d,"\u2209","\\notin");a(i,s,d,"\u2282","\\subset");a(i,s,d,"\u2283","\\supset");a(i,s,d,"\u2286","\\subseteq");a(i,s,d,"\u2287","\\supseteq");a(i,l,d,"\u2288","\\nsubseteq");a(i,l,d,"\u2289","\\nsupseteq");a(i,s,d,"\u22a8","\\models");a(i,s,d,"\u2190","\\leftarrow");a(i,s,d,"\u2264","\\le");a(i,s,d,"\u2264","\\leq");a(i,s,d,"<","\\lt");a(i,s,d,"\u2260","\\ne");a(i,s,d,"\u2260","\\neq");a(i,s,d,"\u2192","\\rightarrow");a(i,s,d,"\u2192","\\to");a(i,l,d,"\u2271","\\ngeq");a(i,l,d,"\u2270","\\nleq");a(i,s,g,null,"\\!");a(i,s,g,"\xa0","\\ ");a(i,s,g,"\xa0","~");a(i,s,g,null,"\\,");a(i,s,g,null,"\\:");a(i,s,g,null,"\\;");a(i,s,g,null,"\\enspace");a(i,s,g,null,"\\qquad");a(i,s,g,null,"\\quad");a(i,s,g,"\xa0","\\space");a(i,s,v,",",",");a(i,s,v,";",";");a(i,s,v,":","\\colon");a(i,l,u,"\u22bc","\\barwedge");a(i,l,u,"\u22bb","\\veebar");a(i,s,u,"\u2299","\\odot");a(i,s,u,"\u2295","\\oplus");a(i,s,u,"\u2297","\\otimes");a(i,s,y,"\u2202","\\partial");a(i,s,u,"\u2298","\\oslash");a(i,l,u,"\u229a","\\circledcirc");a(i,l,u,"\u22a1","\\boxdot");a(i,s,u,"\u25b3","\\bigtriangleup");a(i,s,u,"\u25bd","\\bigtriangledown");a(i,s,u,"\u2020","\\dagger");a(i,s,u,"\u22c4","\\diamond");a(i,s,u,"\u22c6","\\star");a(i,s,u,"\u25c3","\\triangleleft");a(i,s,u,"\u25b9","\\triangleright");a(i,s,f,"{","\\{");a(n,s,y,"{","\\{");a(i,s,p,"}","\\}");a(n,s,y,"}","\\}");a(i,s,f,"{","\\lbrace");a(i,s,p,"}","\\rbrace");a(i,s,f,"[","\\lbrack");a(i,s,p,"]","\\rbrack");a(i,s,f,"\u230a","\\lfloor");a(i,s,p,"\u230b","\\rfloor");a(i,s,f,"\u2308","\\lceil");a(i,s,p,"\u2309","\\rceil");a(i,s,y,"\\","\\backslash");a(i,s,y,"\u2223","|");a(i,s,y,"\u2223","\\vert");a(i,s,y,"\u2225","\\|");a(i,s,y,"\u2225","\\Vert");a(i,s,d,"\u2191","\\uparrow");a(i,s,d,"\u21d1","\\Uparrow");a(i,s,d,"\u2193","\\downarrow");a(i,s,d,"\u21d3","\\Downarrow");a(i,s,d,"\u2195","\\updownarrow");a(i,s,d,"\u21d5","\\Updownarrow");a(i,i,m,"\u2210","\\coprod");a(i,i,m,"\u22c1","\\bigvee");a(i,i,m,"\u22c0","\\bigwedge");a(i,i,m,"\u2a04","\\biguplus");a(i,i,m,"\u22c2","\\bigcap");a(i,i,m,"\u22c3","\\bigcup");a(i,i,m,"\u222b","\\int");a(i,i,m,"\u222b","\\intop");a(i,i,m,"\u222c","\\iint");a(i,i,m,"\u222d","\\iiint");a(i,i,m,"\u220f","\\prod");a(i,i,m,"\u2211","\\sum");a(i,i,m,"\u2a02","\\bigotimes");a(i,i,m,"\u2a01","\\bigoplus");a(i,i,m,"\u2a00","\\bigodot");a(i,i,m,"\u222e","\\oint");a(i,i,m,"\u2a06","\\bigsqcup");a(i,i,m,"\u222b","\\smallint");a(n,s,h,"\u2026","\\textellipsis");a(i,s,h,"\u2026","\\mathellipsis");a(n,s,h,"\u2026","\\ldots");a(i,s,h,"\u2026","\\ldots");a(i,s,h,"\u22ef","\\cdots");a(i,s,h,"\u22f1","\\ddots");a(i,s,y,"\u22ee","\\vdots");a(i,s,o,"\xb4","\\acute");a(i,s,o,"`","\\grave");a(i,s,o,"\xa8","\\ddot");a(i,s,o,"~","\\tilde");a(i,s,o,"\xaf","\\bar");a(i,s,o,"\u02d8","\\breve");a(i,s,o,"\u02c7","\\check");a(i,s,o,"^","\\hat");a(i,s,o,"\u20d7","\\vec");a(i,s,o,"\u02d9","\\dot");a(i,s,c,"\u0131","\\imath");a(i,s,c,"\u0237","\\jmath");a(n,s,y,"\u2013","--");a(n,s,y,"\u2014","---");a(n,s,y,"\u2018","`");a(n,s,y,"\u2019","'");a(n,s,y,"\u201c","``");a(n,s,y,"\u201d","''");a(i,s,y,"\xb0","\\degree");a(n,s,y,"\xb0","\\degree");a(i,s,c,"\xa3","\\pounds");a(i,l,y,"\u2720","\\maltese");a(n,l,y,"\u2720","\\maltese");a(n,s,g,"\xa0","\\ ");a(n,s,g,"\xa0"," ");a(n,s,g,"\xa0","~");var x;var b;var w='0123456789/@."';for(x=0;x":">","<":"<",'"':""","'":"'"};var p=/[&><"']/g;function h(e){return u[e]}function c(e){return(""+e).replace(p,h)}var m;if(typeof document!=="undefined"){var f=document.createElement("span");if("textContent"in f){m=function(e,t){e.textContent=t}}else{m=function(e,t){e.innerText=t}}}function v(e){m(e,"")}t.exports={contains:n,deflt:s,escape:c,hyphenate:o,indexOf:i,setTextContent:m,clearNode:v}},{}]},{},[1])(1)}); diff --git a/app/src/main/assets/theme/01.jpg b/app/src/main/assets/theme/01.jpg new file mode 100644 index 0000000..1e14784 Binary files /dev/null and b/app/src/main/assets/theme/01.jpg differ diff --git a/app/src/main/assets/theme/02.jpg b/app/src/main/assets/theme/02.jpg new file mode 100644 index 0000000..233b662 Binary files /dev/null and b/app/src/main/assets/theme/02.jpg differ diff --git a/app/src/main/assets/theme/03.jpg b/app/src/main/assets/theme/03.jpg new file mode 100644 index 0000000..40d67cf Binary files /dev/null and b/app/src/main/assets/theme/03.jpg differ diff --git a/app/src/main/assets/theme/04.jpg b/app/src/main/assets/theme/04.jpg new file mode 100644 index 0000000..f0ccd9c Binary files /dev/null and b/app/src/main/assets/theme/04.jpg differ diff --git a/app/src/main/assets/theme/05.jpg b/app/src/main/assets/theme/05.jpg new file mode 100644 index 0000000..162b8c3 Binary files /dev/null and b/app/src/main/assets/theme/05.jpg differ diff --git a/app/src/main/assets/theme/06.jpg b/app/src/main/assets/theme/06.jpg new file mode 100644 index 0000000..152065a Binary files /dev/null and b/app/src/main/assets/theme/06.jpg differ diff --git a/app/src/main/java/org/xing/android/AppConfig.java b/app/src/main/java/org/xing/android/AppConfig.java new file mode 100644 index 0000000..e686da9 --- /dev/null +++ b/app/src/main/java/org/xing/android/AppConfig.java @@ -0,0 +1,147 @@ +package org.xing.android; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.preference.PreferenceManager; +import android.text.TextUtils; + +/** + * Created by Administrator on 2017/1/9 0009. + */ + +public class AppConfig { + private static String packageName; + private static int versionCode; + private static String versionName; + private static String channel; + + private static String themeId; + + private static String preferedEngine; + private static int shareCount; + + private static boolean isFirstStart; + private static boolean checkUpdate; + private static Context mContext; + private static SharedPreferences prefs; + + public static void loadConfig(Context mContext) { + + isFirstStart = false; + checkUpdate = false; + + mContext = mContext; + packageName = mContext.getApplicationContext().getPackageName(); + prefs = PreferenceManager.getDefaultSharedPreferences(mContext); + + try { + PackageInfo info = mContext.getPackageManager().getPackageInfo(packageName, 0); + versionCode = info.versionCode; + versionName = info.versionName; + + int lastVersionCode = prefs.getInt("versionCode", 0); + if (versionCode > lastVersionCode) { + isFirstStart = true; + prefs.edit().putInt("versionCode", versionCode).commit(); + + //第一次启动,检查版本更新的字段重设 + prefs.edit().putBoolean("checkUpdate", true).commit(); + checkUpdate = true; + } else { + checkUpdate = prefs.getBoolean("checkUpdate", true); + } + + channel = getAppMetaData(mContext, "UMENG_CHANNEL"); + + themeId = prefs.getString("themeId", "0"); + preferedEngine = prefs.getString("preferedEngine", "baidu"); + shareCount = prefs.getInt("shareCount", 0); + + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + } + + public static String getPackageName() { + return packageName; + } + + public static int getVersionCode() { + return versionCode; + } + public static String getVersionName() { + return versionName; + } + public static String getThemeId() { + return themeId; + } + public static void setThemeId(String themeId) { + AppConfig.themeId = themeId; + prefs.edit().putString("themeId", themeId).commit(); + } + public static String getPreferedEngine() { + return preferedEngine; + } + + public static void setPreferedEngine(String preferedEngine) { + AppConfig.preferedEngine = preferedEngine; + prefs.edit().putString("preferedEngine", preferedEngine).commit(); + } + + public static int getShareCount() { + return shareCount; + } + + public static void setShareCount(int shareCount) { + AppConfig.shareCount = shareCount; + prefs.edit().putInt("shareCount", shareCount).commit(); + } + public static void addShareCount() { + AppConfig.shareCount ++; + prefs.edit().putInt("shareCount", shareCount).commit(); + } + + public static boolean getIsFirstStart() { + return isFirstStart; + } + public static void setIsFirstStart(boolean b) { + isFirstStart = b; + } + public static boolean getCheckUpdate() { + return checkUpdate; + } + public static void setCheckUpdate(boolean b) { + checkUpdate = b; + prefs.edit().putBoolean("checkUpdate", b).commit(); + } + + /** + * 获取application中指定的meta-data + * @return 如果没有获取成功(没有对应值,或者异常),则返回值为空 + */ + public static String getAppMetaData(Context ctx, String key) { + if (ctx == null || TextUtils.isEmpty(key)) { + return null; + } + String resultData = null; + try { + PackageManager packageManager = ctx.getPackageManager(); + if (packageManager != null) { + ApplicationInfo applicationInfo = packageManager.getApplicationInfo(ctx.getPackageName(), PackageManager.GET_META_DATA); + if (applicationInfo != null) { + if (applicationInfo.metaData != null) { + resultData = applicationInfo.metaData.getString(key); + } + } + + } + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + + return resultData; + } +} diff --git a/app/src/main/java/org/xing/android/MainActivity.java b/app/src/main/java/org/xing/android/MainActivity.java new file mode 100644 index 0000000..2e4f15f --- /dev/null +++ b/app/src/main/java/org/xing/android/MainActivity.java @@ -0,0 +1,752 @@ +package org.xing.android; + +import android.Manifest; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.res.Configuration; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.Handler; +import android.provider.Settings; +import android.speech.SpeechRecognizer; +import android.support.v7.app.AppCompatActivity; +import android.view.GestureDetector; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.Button; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import com.umeng.analytics.MobclickAgent; + +import org.xing.calc.Calculator; +import org.xing.calc.Tips; +import org.xing.calc.cmd.CmdParser; +import org.xing.calc.filter.ExprFilterChain; +import org.xing.calc.filter.PinyinExprFilter; +import org.xing.engine.BaiduSpeechEngine; +import org.xing.engine.IflySpeechEngine; +import org.xing.engine.SpeechEngine; +import org.xing.engine.SpeechListener; +import org.xing.logger.impl.EventLogger; +import org.xing.share.ShareManager; +import org.xing.theme.Theme; +import org.xing.theme.ThemeChangeListener; +import org.xing.theme.ThemeManager; +import org.xing.update.UpdateManager; +import org.xing.utils.DeviceUtil; +import org.xing.utils.NumberUtil; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +public class MainActivity extends AppCompatActivity implements SpeechListener, ThemeChangeListener { + + private boolean hasAudioError; + private boolean isListening; + private SpeechEngine speechEngine; + + + private Calculator calculator; + + private boolean newFeatureShowed; + private boolean shareTipsShowed; + + public static EventLogger eventLogger; + + private Tips tips; + + private EditText inputText; + private TextView msgText; + private ProgressBar recordDynamic; + private Button stateButton; + private Button startButton; + private WebView historyList; + + /* + 命令 + */ + private Stack historyResult; + private ExprFilterChain cmdFilterChain; + private Map cmdName; + private CmdParser cmdParser; + + /* + 主题 + */ + private Theme currentTheme; + private ThemeManager themeManager; + + /* + 分享 + */ + private LinearLayout shareLayout; + private ShareManager shareManager; + + /* + 空闲状态计数,达到maxNoInputCount暂时停止工作 + */ + private int noInputCount = 0; + private int maxNoInputCount = 5; + + protected void showHelp() { + MobclickAgent.onEvent(this, "help"); + eventLogger.onEvent("help"); + + Intent intent =new Intent(MainActivity.this, SimpleHelpActivity.class); + intent.putExtra("url", getString(R.string.helpUrl)); + startActivity(intent); + } + + /* + 新版本功能提示 + 延迟10s弹出对话框,大致实是在用户说了一句话之后弹出 + */ + protected void showTips(int delaySecond) { + + Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + @Override + public void run() { + //防止当前页面没有显示的时候显示对话框,从而导致程序崩溃 + if(!isListening) return; + + AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); + builder.setTitle("小技巧"); + builder.setMessage(" 说'引擎',切换到讯飞识别引擎,计算速度更快。" + + "立即切换?"); + builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + stopListening(); + Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + @Override + public void run() { + changeSpeechEngine(null); + startListening(true); + } + }, 1000); + } + }); + builder.setNegativeButton("知道", null); + builder.show(); + } + }, delaySecond*1000); + } + + private void initSpeechRecognizer() { + if(speechEngine != null) { + stopListening(); + speechEngine.destroy(); + } + + hasAudioError = false; + isListening = false; + + String preferedEngine = AppConfig.getPreferedEngine(); + eventLogger.onEvent("engine-"+preferedEngine); + + if(preferedEngine.equals("ifly")) { + //速度快,准确性差一点 + speechEngine = new IflySpeechEngine(this); + } else { + //准确性高,速度稍慢 + speechEngine = new BaiduSpeechEngine(this); + } + speechEngine.setSpeechListener(this); + } + + private void changeSpeechEngine(String engine) { + eventLogger.onEvent("changeEngine"); + String preferedEngine = AppConfig.getPreferedEngine(); + if(preferedEngine.equals("ifly") && (engine == null || engine.equals("baidu"))){ + AppConfig.setPreferedEngine("baidu"); + Toast.makeText(this, "切换到百度语音引擎(更准确)\n" + + "说'引擎'或'讯飞'可以切换", Toast.LENGTH_LONG).show(); + initSpeechRecognizer(); + }else if(preferedEngine.equals("baidu") && (engine == null || engine.equals("ifly"))){ + AppConfig.setPreferedEngine("ifly"); + Toast.makeText(this, "切换到科大讯飞引擎(更快速)\n" + + "说'引擎'或'百度'可以切换", Toast.LENGTH_LONG).show(); + initSpeechRecognizer(); + } else { + if(preferedEngine.equals("baidu")) { + Toast.makeText(this, "已经是百度语音引擎,无需重新设置\n" + + "说'引擎'或'讯飞'可以切换", Toast.LENGTH_LONG).show(); + }else { + Toast.makeText(this, "已经是科大讯飞引擎,无需重新设置\n" + + "说'引擎'或'百度'可以切换", Toast.LENGTH_LONG).show(); + } + } + } + + private void initUserView() { + stateButton = (Button) this.findViewById(R.id.stateButton); + stateButton = (Button) this.findViewById(R.id.stateButton); + stateButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + MobclickAgent.onEvent(MainActivity.this, "statusClick"); + eventLogger.onEvent("statusClick"); + Toast toast = Toast.makeText(MainActivity.this, + "图标为绿色可以开始输入\n灰色表示已暂停或者正在识别。", + Toast.LENGTH_SHORT); + toast.setGravity(Gravity.TOP, 0, 0); + toast.show(); + } + }); + startButton = (Button) this.findViewById(R.id.ctrl_start); + startButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + MobclickAgent.onEvent(MainActivity.this, "startClick"); + eventLogger.onEvent("startClick"); + if(isListening) { + stopListening(); + startButton.setBackgroundResource(R.mipmap.start); + msgText.setText("已暂停"); + + if(AppConfig.getIsFirstStart() && (!shareTipsShowed)) { + Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + @Override + public void run() { + Toast.makeText(MainActivity.this, + "小技巧:每一次微信分享或QQ分享都可以减少广告,分享三次即可彻底删除广告。", + Toast.LENGTH_LONG).show(); + } + }, 10 * 1000); + shareTipsShowed = true; + } + } else { + //再次检查录音设备授权,部分用户误操作禁止了录音授权,这行代码可以让用户再次授权 + if(hasAudioError) { + PermissionChecker.requestAudioPermission(MainActivity.this); + } + + startListening(true); + startButton.setBackgroundResource(R.mipmap.stop); + msgText.setText(""); + } + } + }); + + this.findViewById(R.id.help_mark).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showHelp(); + } + }); + + inputText = (EditText) this.findViewById(R.id.input); + inputText.setKeyListener(null); + msgText = (TextView) this.findViewById(R.id.msg); + + recordDynamic = (ProgressBar) this.findViewById(R.id.recordDynamic); + } + + private void initCalculator(HashMap pinyin) { + newFeatureShowed = false; + calculator = Calculator.createDefault(pinyin); + + historyList = (WebView) this.findViewById(R.id.historylist); + historyList.setBackgroundColor(0); + historyList.getSettings().setJavaScriptEnabled(true); + historyList.getSettings().setAppCacheEnabled(true); + historyList.setWebViewClient(new WebViewClient() { + @Override + public void onPageFinished(WebView view, String url) + { + super.onPageFinished(view, url); + + if(currentTheme != null) { + String jsCode = "javascript:setTextColor('" + currentTheme.getStyle("historyColor") + "')"; + historyList.loadUrl(jsCode); + } + } + }); + + //设置单击和双击触发事件 + historyList.setOnTouchListener(new View.OnTouchListener() { + GestureDetector detector = null; + @Override + public boolean onTouch(View v, MotionEvent event) { + if(detector == null) { + detector = new GestureDetector(MainActivity.this, + new GestureDetector.SimpleOnGestureListener() { + @Override + public boolean onDoubleTap(MotionEvent e) { + themeManager.randomTheme(); + return super.onDoubleTap(e); + } + + @Override + public boolean onSingleTapConfirmed(MotionEvent e) { + startListening(true); + startButton.setBackgroundResource(R.mipmap.stop); + msgText.setText(""); + return super.onSingleTapConfirmed(e); + } + } + ); + } + detector.onTouchEvent(event); + + return false; + } + }); + + historyList.loadUrl("javascript:var isFirstStart="+AppConfig.getIsFirstStart()+";"); + historyList.loadUrl("file:///android_asset/history.html"); + + historyResult = new Stack<>(); + } + + private void initCommand(HashMap pinyin) { + cmdName = new HashMap(); + cmdName.put("清屏", 1); + cmdName.put("清空", 1); + cmdName.put("清除", 1); + cmdName.put("全部删除", 1); + + cmdName.put("撤销", 2); + cmdName.put("取消", 2); + cmdName.put("倒退", 2); + cmdName.put("后退", 2); + cmdName.put("删除", 2); + + cmdName.put("帮助", 3); + cmdName.put("示例", 3); + cmdName.put("说明", 3); + + cmdName.put("升级", 4); + cmdName.put("版本", 4); + + cmdName.put("主题", 5); + cmdName.put("背景", 5); + cmdName.put("风格", 5); + + cmdName.put("引擎", 6); + cmdName.put("百度", 6); + cmdName.put("讯飞", 6); + + cmdName.put("退出", 7); + cmdName.put("关闭", 7); + + cmdName.put("暂停", 8); + + StringBuilder allowedChars = new StringBuilder(); + for(String key : cmdName.keySet()) { + allowedChars.append(key); + } + cmdFilterChain = new ExprFilterChain(allowedChars.toString(), pinyin); + cmdParser = new CmdParser(); + } + + private void initTheme() { + themeManager = new ThemeManager(this); + themeManager.addThemeChangeListener(this); + themeManager.applyTheme(AppConfig.getThemeId()); + } + + private void initShare() { + shareTipsShowed = false; + shareManager = new ShareManager(this); + + shareLayout = (LinearLayout) findViewById(R.id.share_board); + this.findViewById(R.id.share_mark).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + shareLayout.setVisibility(View.VISIBLE); + } + }); + this.findViewById(R.id.cancel_btn).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + shareLayout.setVisibility(View.GONE); + } + }); + this.findViewById(R.id.share_weixin).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + shareManager.shareToWeixin(0); + } + }); + this.findViewById(R.id.share_pengyouquan).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + shareManager.shareToWeixin(1); + } + }); + this.findViewById(R.id.share_qq).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + shareManager.shareToQQ(0); + } + }); + this.findViewById(R.id.share_kongjian).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + shareManager.shareToQQ(1); + } + }); + } + + private void initPermission() { + PermissionChecker.requestPermission(this, new String[] { + Manifest.permission.RECORD_AUDIO, + Manifest.permission.ACCESS_NETWORK_STATE, + Manifest.permission.INTERNET, + Manifest.permission.READ_PHONE_STATE + }); + } + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + AppConfig.loadConfig(this); + + String uniqueId = DeviceUtil.getUniqueId(this); + eventLogger = new EventLogger(uniqueId, AppConfig.getVersionName(), + this.getString(R.string.recordUrl)); + + if(AppConfig.getIsFirstStart()) { + eventLogger.onEvent("new-start"); + } else { + eventLogger.onEvent("start"); + } + + tips = Tips.createSimpleTips(); + + //10s后检查更新 + UpdateManager.postUpdate(this, 10); + + MobclickAgent.setScenarioType(this, MobclickAgent.EScenarioType.E_UM_NORMAL); + initPermission(); + initUserView(); + + HashMap pinyin = + PinyinExprFilter.loadTokens(getResources().openRawResource(R.raw.token)); + initCalculator(pinyin); + initCommand(pinyin); + + initTheme(); + initShare(); + initSpeechRecognizer(); + } + + + @Override + public void onResume() { + super.onResume(); + + startListening(true); + startButton.setBackgroundResource(R.mipmap.stop); + msgText.setText(tips.randomGet()); + + MobclickAgent.onResume(this); + } + + @Override + public void onPause() { + super.onPause(); + + stopListening(); + startButton.setBackgroundResource(R.mipmap.start); + + MobclickAgent.onPause(this); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + } + + public synchronized void startListening(boolean resetInputCount) { + if (isListening) return; + + hasAudioError = false; + speechEngine.startListening(); + isListening = true; + lastRmsdB = 0; + if (resetInputCount) { + noInputCount = 0; + } + } + + public void stopListening() { + if(isListening) { + speechEngine.cancel(); + } + listeningStopped(); + } + + public synchronized void listeningStopped() { + isListening = false; + stateButton.setBackgroundResource(R.mipmap.input_sleep); + } + + public void onReadyForSpeech() { + stateButton.setBackgroundResource(R.mipmap.input_ready); + } + + public void onBeginningOfSpeech() { + + } + + private float lastRmsdB=0; + public void onRmsChanged(float rmsdB) { + lastRmsdB = (rmsdB*3+lastRmsdB*7) /10; + recordDynamic.setProgress((int) lastRmsdB); + } + + public void onEndOfSpeech() { + stateButton.setBackgroundResource(R.mipmap.input_sleep); + msgText.setText("正在识别..."); + } + + public void onError(int error) { + listeningStopped(); + + StringBuilder sb = new StringBuilder(); + switch (error) { + case SpeechRecognizer.ERROR_AUDIO: + sb.append("请读出表达式"); + startListening(true); + MobclickAgent.onEvent(this, "noAudio"); + eventLogger.onEvent("noAudio"); + break; + case SpeechRecognizer.ERROR_SPEECH_TIMEOUT: + noInputCount++; + if (noInputCount >= maxNoInputCount) { + sb.append("已暂停"); + startButton.setBackgroundResource(R.mipmap.start); + } else { + startListening(false); + } + break; + case SpeechRecognizer.ERROR_CLIENT: + sb.append("客户端错误"); + startButton.setBackgroundResource(R.mipmap.start); + eventLogger.onEvent("errorClient"); + break; + case SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS: + sb.append("录音设备未授权"); + startButton.setBackgroundResource(R.mipmap.start); + eventLogger.onEvent("errorPermissions"); + hasAudioError = true; + break; + case SpeechRecognizer.ERROR_NETWORK: + sb.append("请检查网络连接"); + MobclickAgent.onEvent(this, "errorNetwork"); + eventLogger.onEvent("errorNetwork"); + startButton.setBackgroundResource(R.mipmap.start); + break; + case SpeechRecognizer.ERROR_NO_MATCH: + sb.append("未识别"); + MobclickAgent.onEvent(this, "failMatch"); + eventLogger.onEvent("failMatch"); + startListening(true); + break; + case SpeechRecognizer.ERROR_RECOGNIZER_BUSY: + sb.append("引擎忙"); + MobclickAgent.onEvent(this, "busy"); + eventLogger.onEvent("busy"); + startButton.setBackgroundResource(R.mipmap.start); + break; + case SpeechRecognizer.ERROR_SERVER: + sb.append("未识别"); + startListening(true); + MobclickAgent.onEvent(this, "failServer"); + eventLogger.onEvent("failServer"); + break; + case SpeechRecognizer.ERROR_NETWORK_TIMEOUT: + sb.append("网络连接连接超时"); + MobclickAgent.onEvent(this, "errorNetworkTimeout"); + eventLogger.onEvent("errorNetworkTimeout"); + startButton.setBackgroundResource(R.mipmap.start); + break; + } + + msgText.setText(sb.toString()); + } + + private String buildExpr(Bundle results) { + ArrayList nbest = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); + StringBuilder expr = new StringBuilder(); + for (String w : nbest) { + expr.append(w); + } + return expr.toString(); + } + + private void showResult(String expr, Double evalResult, String readExpr) { + //界面上显示结果 + if (!Double.isNaN(evalResult)) { + historyResult.push(evalResult); + String text = NumberUtil.format(evalResult, 8); + + String item = readExpr + "=" + text; + + historyList.loadUrl("javascript:addItem('" + item + "')"); + inputText.setText(text); + msgText.setText(""); + } else { + String errMsg = calculator.getErrMsg(); + if(errMsg != null) { + msgText.setText("未识别,'"+errMsg+"'表达错误"); + } else { + msgText.setText("未识别,'"+expr+"'表达错误"); + } + } + } + + public int handleCommand(String expr) { + String cmd = cmdFilterChain.call(expr); + int type = cmdParser.parse(cmd); + if(type > 0) { + this.eventLogger.onEvent("NaN", expr.toString(), "null", type); + switch (type) { + case 1: + historyResult.clear(); + historyList.loadUrl("javascript:clearHistory()"); + calculator.setLastResult(0); + inputText.setText("0"); + break; + case 2: + if(historyResult.size() > 0) { + historyResult.pop(); + historyList.loadUrl("javascript:historyPop()"); + if(historyResult.size() > 0) { + Double lastResult = historyResult.peek(); + calculator.setLastResult(lastResult); + inputText.setText(NumberUtil.format(lastResult, 8)); + } else { + calculator.setLastResult(0); + inputText.setText("0"); + } + } + break; + case 3: + showHelp(); + break; + case 4: + UpdateManager.update(this, true); + break; + case 5: + themeManager.randomTheme(); + break; + case 6: + if(cmd.contains("引擎")) { + changeSpeechEngine(null); + }else if(cmd.contains("百度")){ + changeSpeechEngine("baidu"); + }else { + changeSpeechEngine("ifly"); + } + break; + case 7: + stopListening(); + finish(); + break; + case 8: + stopListening(); + startButton.setBackgroundResource(R.mipmap.start); + msgText.setText("已暂停"); + break; + default: + break; + } + + if(type != 8) { + msgText.setText(""); + } + } + + return type; + } + + public void onResults(String expr) { + int cmdType = handleCommand(expr); + if(expr != null &&expr.length()>0 && + (!expr.equals("。")) && cmdType == 0) { + //结算结果 + String readExpr = null; + Double evalResult = calculator.eval(expr.toString()); + if (evalResult != null && (!evalResult.isNaN())) { + readExpr = calculator.getReadExpr(); + } + + this.eventLogger.onEvent(NumberUtil.format(evalResult, 8), + expr.toString(), readExpr, 0); + + showResult(expr.toString(), evalResult, readExpr); + + if(AppConfig.getIsFirstStart() && (!newFeatureShowed)) { + showTips(10); + newFeatureShowed = true; + } + } + + //不是暂停命令的时候继续开启语音输入 + if(cmdType != 8) { + isListening = false; + startListening(true); + } + } + + public boolean isAlive() { + return !this.isFinishing(); + } + + public void onThemeChange(Theme theme) { + if(theme == null) return; + + eventLogger.onEvent("theme-"+theme.getId()); + try { + currentTheme = theme; + AppConfig.setThemeId(theme.getId()); + + int color; + List backgroundImages = theme.getImagePaths(); + LinearLayout layout = (LinearLayout) this.findViewById(R.id.backgroundLayout); + if(backgroundImages != null && backgroundImages.size() > 0) { + InputStream is = this.getAssets().open(backgroundImages.get(0)); + Drawable background = Drawable.createFromStream(is, "theme"); + layout.setBackgroundDrawable(background); + is.close(); + } else { + layout.setBackgroundDrawable(null); + color = Color.parseColor(theme.getStyle("background")); + layout.setBackgroundColor(color); + } + + String jsCode = "javascript:setTextColor('"+currentTheme.getStyle("historyColor")+"')"; + historyList.loadUrl(jsCode); + + color = Color.parseColor(theme.getStyle("resultColor")); + inputText.setTextColor(color); + color = Color.parseColor(theme.getStyle("msgColor")); + msgText.setTextColor(color); + + }catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/app/src/main/java/org/xing/android/PermissionChecker.java b/app/src/main/java/org/xing/android/PermissionChecker.java new file mode 100644 index 0000000..49d6356 --- /dev/null +++ b/app/src/main/java/org/xing/android/PermissionChecker.java @@ -0,0 +1,83 @@ +package org.xing.android; + +import android.Manifest; +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Build; +import android.os.Handler; +import android.provider.Settings; +import android.support.v4.app.ActivityCompat; +import android.support.v4.content.ContextCompat; +import android.widget.Toast; + +import java.util.Vector; + +/** + * Created by Administrator on 2017/3/18 0018. + */ + +public class PermissionChecker { + public final static int REQUEST_CODE_ALL = 1; + public static void requestPermission(Activity activity, String[] permissions) { + Vector lackedPermissions = new Vector(); + for(String per : permissions) { + if(ContextCompat.checkSelfPermission(activity, per) == PackageManager.PERMISSION_DENIED) { + lackedPermissions.add(per); + } + } + + if(lackedPermissions.size() > 0) { + String[] tempPermissions = new String[lackedPermissions.size()]; + for(int i=0;i'录音'->'星星声控计算器'->'允许'。"); + } + } + + public static void startSetting(final Activity activity, String msg) { + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.setTitle("应用未授权"); + builder.setMessage(msg); + builder.setPositiveButton("打开", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + try { + Intent intent = new Intent(Settings.ACTION_SETTINGS); + activity.startActivity(intent); + }catch (Exception ex) { + Toast.makeText(activity, + "抱歉,无法自动跳转到设置页面,请手动操作。", + Toast.LENGTH_SHORT).show(); + } + } + }); + builder.setNegativeButton("忽略", null); + builder.show(); + } +} diff --git a/app/src/main/java/org/xing/android/SimpleHelpActivity.java b/app/src/main/java/org/xing/android/SimpleHelpActivity.java new file mode 100644 index 0000000..ee9061f --- /dev/null +++ b/app/src/main/java/org/xing/android/SimpleHelpActivity.java @@ -0,0 +1,254 @@ +package org.xing.android; + +import android.content.ActivityNotFoundException; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.net.Uri; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.text.TextUtils; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.WindowManager; +import android.webkit.WebChromeClient; +import android.webkit.WebResourceResponse; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.Button; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; + +import com.umeng.analytics.MobclickAgent; + +import java.io.ByteArrayInputStream; + +public class SimpleHelpActivity extends AppCompatActivity { + private WebView helpWeb; + + private View videoView; + private FrameLayout videoContainerView; + + LinearLayout toolBar; + private ProgressBar progressBar; + private TextView titleText; + private WebChromeClient chromeClient; + + /** + * 设置全屏 + */ + private void setFullScreen() { + // 设置全屏的相关属性,获取当前的屏幕状态,然后设置全屏 + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + // 全屏下的状态码:1098974464 + // 窗口下的状态吗:1098973440 + } + + /** + * 退出全屏 + */ + private void quitFullScreen() { + // 声明当前屏幕状态的参数并获取 + final WindowManager.LayoutParams attrs = getWindow().getAttributes(); + attrs.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN); + getWindow().setAttributes(attrs); + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_simple_help); + + videoView = null; + videoContainerView = (FrameLayout) findViewById(R.id.video); + + toolBar = (LinearLayout) findViewById(R.id.toolBar); + progressBar = (ProgressBar) findViewById(R.id.webProgress); + titleText = (TextView) findViewById(R.id.help_title); + + Button closeButton = (Button) findViewById(R.id.help_close); + closeButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + + helpWeb = (WebView) this.findViewById(R.id.simple_help); + helpWeb.setBackgroundColor(0); + + WebSettings settings = helpWeb.getSettings(); + settings.setJavaScriptEnabled(true); + settings.setJavaScriptCanOpenWindowsAutomatically(true); + settings.setDatabaseEnabled(true); + settings.setAppCacheEnabled(true); + settings.setCacheMode(WebSettings.LOAD_DEFAULT); + settings.setPluginState(WebSettings.PluginState.ON); + settings.setAllowFileAccess(true); + settings.setLoadWithOverviewMode(false); + settings.setDomStorageEnabled(true); + + chromeClient = new WebChromeClient() { + private CustomViewCallback callBack; + + // 播放网络视频时全屏会被调用的方法 + @Override + public void onShowCustomView(View view, CustomViewCallback callback) { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + + toolBar.setVisibility(View.INVISIBLE); + helpWeb.setVisibility(View.INVISIBLE); + + // 如果一个视图已经存在,那么立刻终止并新建一个 + if (videoView != null) { + callback.onCustomViewHidden(); + return; + } + videoContainerView.addView(view); + videoView = view; + callBack = callback; + videoContainerView.setVisibility(View.VISIBLE); + setFullScreen(); + } + + // 视频播放退出全屏会被调用的 + @Override + public void onHideCustomView() { + if (videoView == null)// 不是全屏播放状态 + return; + + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + videoView.setVisibility(View.GONE); + videoContainerView.removeView(videoView); + videoView = null; + videoContainerView.setVisibility(View.GONE); + callBack.onCustomViewHidden(); + + toolBar.setVisibility(View.VISIBLE); + helpWeb.setVisibility(View.VISIBLE); + quitFullScreen(); + } + + @Override + public void onProgressChanged(WebView view, int newProgress) { + if (newProgress == 100) { + progressBar.setVisibility(View.GONE); + } else { + if (View.INVISIBLE == progressBar.getVisibility()) { + progressBar.setVisibility(View.VISIBLE); + titleText.setText("页面加载中..."); + } + progressBar.setProgress(newProgress); + } + super.onProgressChanged(view, newProgress); + } + + }; + helpWeb.setWebChromeClient(chromeClient); + + helpWeb.setWebViewClient(new WebViewClient() { + @Override + public void onPageFinished(WebView view, String url) { + WebView.HitTestResult hitTestResult = view.getHitTestResult(); + if (!TextUtils.isEmpty(url) && hitTestResult == null) { + return; + } + titleText.setText(view.getTitle()); + } + + public boolean shouldOverrideUrlLoading(WebView view, String url) { + view.loadUrl(url); + return true; + } + + @Override + public WebResourceResponse shouldInterceptRequest(WebView view, String url) { + if (url.startsWith("http") || url.startsWith("https") + || url.startsWith("javascript") || url.startsWith("file")) { + return super.shouldInterceptRequest(view, url); + } else { + String tips = "启动外部应用..."; + try { + Intent in = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + startActivity(in); + } catch (ActivityNotFoundException ex) { + tips = "启动外部应用失败,请安装最新版应用。"; + } + + return new WebResourceResponse("text/plain", "utf-8", new ByteArrayInputStream(tips.getBytes())); + } + } + }); + + helpWeb.setOnTouchListener(new View.OnTouchListener() { + private float x1 = 0; + private float x2 = 0; + private float y1 = 0; + private float y2 = 0; + @Override + public boolean onTouch(View v, MotionEvent event) { + + + //继承了Activity的onTouchEvent方法,直接监听点击事件 + if (event.getAction() == MotionEvent.ACTION_DOWN) { + //当手指按下的时候 + x1 = event.getX(); + y1 = event.getY(); + } + if (event.getAction() == MotionEvent.ACTION_UP) { + //当手指离开的时候 + x2 = event.getX(); + y2 = event.getY(); + + if (y1 - y2 > 50) { + toolBar.setVisibility(View.GONE); + } else if (y2 - y1 > 50) { + toolBar.setVisibility(View.VISIBLE); + } + } + return false; + } + }); + + String url = getIntent().getStringExtra("url"); + helpWeb.loadUrl(url); + } + + + @Override + public void onResume() { + super.onResume(); + MobclickAgent.onResume(this); + helpWeb.onResume(); + } + + @Override + public void onPause() { + super.onPause(); + MobclickAgent.onPause(this); + helpWeb.onPause(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && helpWeb.canGoBack()) { + helpWeb.goBack();// 返回前一个页面 + return true; + } + return super.onKeyDown(keyCode, event); + } + + @Override + public void onBackPressed() { + if (videoView == null) { + super.onBackPressed(); + } else { + chromeClient.onHideCustomView(); + } + } +} diff --git a/app/src/main/java/org/xing/calc/Calculator.java b/app/src/main/java/org/xing/calc/Calculator.java new file mode 100644 index 0000000..2c62ad0 --- /dev/null +++ b/app/src/main/java/org/xing/calc/Calculator.java @@ -0,0 +1,282 @@ +package org.xing.calc; + +import org.antlr.v4.runtime.ANTLRErrorListener; +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.Parser; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.Recognizer; +import org.antlr.v4.runtime.atn.ATNConfigSet; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.tree.ParseTree; +import org.xing.calc.filter.CorrectionExprFilter; +import org.xing.calc.filter.ExprFilter; +import org.xing.calc.filter.PinyinExprFilter; +import org.xing.calc.parser.CalculatorEvalVisitor; +import org.xing.calc.parser.CalculatorLatexExprVisitor; +import org.xing.calc.parser.grammer.calculatorLexer; +import org.xing.calc.parser.grammer.calculatorParser; +import org.xing.utils.NumberUtil; + +import java.io.InputStream; +import java.util.BitSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +/** + * @author Administrator + * 计算语音输入的表达式语句的结果 + */ +public class Calculator implements ANTLRErrorListener{ + /** + * 上次计算结果 + */ + private double lastResult; + + /* + * 上次计算的表达式 + */ + private String lastReadExpr; + + /* + 当前输入表达式 + */ + private String orgExpr; + + /* + 解析错误 + */ + private int errPos; + private String errMsg; + private String reason; + + /** + * 表达式过滤器列表,包括纠错、多余字符过滤以及数字转换等 + */ + private List filters; + + /* + * 连续输入表达式的开始字符 + */ + private Set continuousInputTag; + + /* + * 前置函数的连续计算 + */ + private Set continuousFuncTag; + + /* + * 后置函数的连续计算 + */ + private Set continuousPostFuncTag; + + /* + 幂运算命令 + */ + private Set continuousPowTag; + + public Calculator() { + setLastResult(0.0); + + filters = new LinkedList(); + + String inputTags = "加+减-乘*×除/÷"; + continuousInputTag = new HashSet<>(); + for (int i = 0; i < inputTags.length(); i++) { + continuousInputTag.add(inputTags.charAt(i)); + } + + String[] funcTags = new String[]{"cos", "余弦", "sin", + "正弦", "tan", "正切", "acos", "反余弦", "asin", "反正弦", + "atan", "反正切", "ln", "log", "lg", "对数", "根号"}; + continuousFuncTag = new HashSet<>(); + for (int i = 0; i < funcTags.length; i++) { + continuousFuncTag.add(funcTags[i]); + } + + String[] postFuncTags = new String[]{"开方", "开平方", "开立方", "平方根", "立方根"}; + continuousPostFuncTag = new HashSet<>(); + for (int i = 0; i < postFuncTags.length; i++) { + continuousPostFuncTag.add(postFuncTags[i]); + } + + String[] powTags = new String[]{"平方", "立方"}; + continuousPowTag = new HashSet<>(); + for (int i = 0; i < powTags.length; i++) { + continuousPowTag.add(powTags[i]); + } + } + + public void addFilter(ExprFilter filter) { + filters.add(filter); + } + + public String execFilter(String expr) { + if(expr == null) return null; + + for (ExprFilter filter : filters) { + expr = filter.call(expr); + } + return expr; + } + + public double getLastResult() { + return lastResult; + } + + public void setLastResult(double lastResult) { + this.lastResult = lastResult; + } + public String getErrMsg() { + return errMsg; + } + public String getReason() { + return reason; + } + public String getReadExpr() { + return lastReadExpr; + } + + public void setErrorMsg(int pos, String r) { + int offset = 5; + if(errPos != -1) return; + if(orgExpr == null || pos < 0 + || pos >= orgExpr.length()) errMsg = null; + errPos = pos; + reason = r; + int start = pos > offset ? pos-offset:0; + int end = pos + offset < orgExpr.length() ? pos+offset:orgExpr.length(); + errMsg = orgExpr.substring(start, end); + } + + + public Double innerEval(String expr) { + Double result = Double.NaN; + String readExpr = null; + + ANTLRInputStream input = new ANTLRInputStream(expr); + calculatorLexer lexer = new calculatorLexer(input); + CommonTokenStream tokens = new CommonTokenStream(lexer); + calculatorParser parser = new calculatorParser(tokens); + parser.addErrorListener(this); + ParseTree tree = parser.expression(); + + CalculatorEvalVisitor evalVisitor = new CalculatorEvalVisitor(); + result = evalVisitor.visit(tree); + + CalculatorLatexExprVisitor exprVisitor = new CalculatorLatexExprVisitor(); + readExpr = exprVisitor.visit(tree); + + if (result != null && !result.isNaN()) { + lastResult = result; + lastReadExpr = readExpr; + } + + return result != null? result:Double.NaN; + } + + public double eval(String expr) { + errMsg = null; + Double result = Double.NaN; + + if(expr == null || expr.length() == 0) return result; + + expr = expr.replace("再", ""); + expr = expr.replace("等于", ""); + expr = expr.replace("多少", ""); + orgExpr = expr; + + try { + for (ExprFilter filter : filters) { + expr = filter.call(expr); + } + + //过滤的文字太多,视为无效表达式 + if(orgExpr.length() - expr.length() > 4) { + return Double.NaN; + } + + String currentExpr = null; + while(true) { + errPos = -1; + currentExpr = expr; + + if(continuousInputTag.contains(expr.charAt(0))) { + expr = NumberUtil.format(this.lastResult, 8)+expr; + }else if(continuousFuncTag.contains(expr)) { + expr = expr + NumberUtil.format(this.lastResult, 8); + }else if(continuousPostFuncTag.contains(expr)) { + expr = NumberUtil.format(this.lastResult, 8)+ expr; + }else if(continuousPowTag.contains(expr)) { + expr = NumberUtil.format(this.lastResult, 8) + "的" + expr; + } + + result = innerEval(expr); + + if(errPos >= 0 && errPos <= currentExpr.length()) { + if(errPos < currentExpr.length() && currentExpr.charAt(errPos) == '点') { + char[] seq = currentExpr.toCharArray(); + seq[errPos] = '减'; + expr = String.valueOf(seq); + }else if(reason != null && reason.contains("次方")) { + //21的三九减四点六 中间的“的”改为“点” + char[] seq = currentExpr.toCharArray(); + while(errPos >= 0) { + if(errPos < currentExpr.length() && seq[errPos] == '的') { + seq[errPos] = '点'; + expr = String.valueOf(seq); + break; + } + errPos --; + } + if(errPos < 0) break; + } else { + break; + } + } else { + break; + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + + return result; + } + + public static Calculator createDefault(HashMap pinyin) { + String allowedChars = + "0123456789.零一二三四五六七八九点负个十百千万亿+-*/括号加上减去乘以除÷×根号开方的平方次方立方分之" + + "sincostanlglogln反正弦反余弦反正切对数()|^度°派π又"; + + Calculator calc = new Calculator(); + calc.addFilter(new CorrectionExprFilter()); + calc.addFilter(new PinyinExprFilter(allowedChars, pinyin)); + + return calc; + } + + + @Override + public void syntaxError(Recognizer recognizer, Object o, int i, int i1, String s, RecognitionException e) { + setErrorMsg(i1, s); + } + + @Override + public void reportAmbiguity(Parser parser, DFA dfa, int i, int i1, boolean b, BitSet bitSet, ATNConfigSet atnConfigSet) { + setErrorMsg(i1, ""); + } + + @Override + public void reportAttemptingFullContext(Parser parser, DFA dfa, int i, int i1, BitSet bitSet, ATNConfigSet atnConfigSet) { + setErrorMsg(i1, ""); + } + + @Override + public void reportContextSensitivity(Parser parser, DFA dfa, int i, int i1, int i2, ATNConfigSet atnConfigSet) { + setErrorMsg(i1, ""); + } +} diff --git a/app/src/main/java/org/xing/calc/Tips.java b/app/src/main/java/org/xing/calc/Tips.java new file mode 100644 index 0000000..df40218 --- /dev/null +++ b/app/src/main/java/org/xing/calc/Tips.java @@ -0,0 +1,65 @@ +package org.xing.calc; + +import java.util.Random; +import java.util.Vector; + +/** + * Created by Administrator on 2017/2/21 0021. + */ + +public class Tips { + private Random random; + private Vector tipsStr; + + public Tips() { + random = new Random(); + tipsStr = new Vector<>(); + } + + public void add(String tip) { + tipsStr.add(tip); + } + + public String get(int index) { + if(index >= 0 && index < tipsStr.size()) + return tipsStr.get(index); + else + return null; + } + + public String randomGet() { + if(tipsStr.size() > 0) { + return tipsStr.get( + random.nextInt(tipsStr.size()) + ); + } + return null; + } + + public static Tips createSimpleTips() { + Tips tips = new Tips(); + tips.add("试一下:'帮助'"); + tips.add("试一下:'升级'"); + tips.add("试一下:'主题'"); + tips.add("试一下:'三分之一'"); + tips.add("试一下:'加一千'"); + tips.add("试一下:'删除'"); + tips.add("试一下:'对数三'"); + tips.add("试一下:'三对数五'"); + tips.add("试一下:'清空'"); + tips.add("试一下:'二乘括号二加一括号'"); + tips.add("试一下:'正弦零点二'"); + tips.add("试一下:'正弦三分之派'"); + tips.add("试一下:'正弦三十度'"); + tips.add("试一下:'根号五'"); + tips.add("试一下:'三根号五'"); + tips.add("试一下:'三的平方'"); + tips.add("试一下:'三的四次方'"); + tips.add("试一下:'百度'"); + tips.add("试一下:'讯飞'"); + tips.add("试一下:'引擎'"); + tips.add("试一下:'退出'"); + tips.add("提示:分享三次可彻底删除广告"); + return tips; + } +} diff --git a/app/src/main/java/org/xing/calc/cmd/CmdDefaultVisitor.java b/app/src/main/java/org/xing/calc/cmd/CmdDefaultVisitor.java new file mode 100644 index 0000000..a7c1867 --- /dev/null +++ b/app/src/main/java/org/xing/calc/cmd/CmdDefaultVisitor.java @@ -0,0 +1,28 @@ +package org.xing.calc.cmd; + +import org.xing.calc.cmd.grammer.cmdBaseVisitor; +import org.xing.calc.cmd.grammer.cmdParser; + +public class CmdDefaultVisitor extends cmdBaseVisitor{ + @Override public Integer visitCommand(cmdParser.CommandContext ctx) { + if(ctx.qingping() != null) { + return 1; + }else if(ctx.goback() != null) { + return 2; + }else if(ctx.help() != null) { + return 3; + }else if(ctx.update() != null) { + return 4; + }else if(ctx.theme() != null) { + return 5; + }else if(ctx.engine() != null) { + return 6; + }else if(ctx.close() != null) { + return 7; + }else if(ctx.stop() != null) { + return 8; + } + + return 0; + } +} diff --git a/app/src/main/java/org/xing/calc/cmd/CmdParser.java b/app/src/main/java/org/xing/calc/cmd/CmdParser.java new file mode 100644 index 0000000..e9605d7 --- /dev/null +++ b/app/src/main/java/org/xing/calc/cmd/CmdParser.java @@ -0,0 +1,31 @@ +package org.xing.calc.cmd; + +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.ParseTree; +import org.xing.calc.cmd.grammer.cmdLexer; +import org.xing.calc.cmd.grammer.cmdParser; + +public class CmdParser { + public CmdParser() { + + } + + public int parse(String expr) { + try { + ANTLRInputStream input = new ANTLRInputStream(expr); + cmdLexer lexer = new cmdLexer(input); + CommonTokenStream tokens = new CommonTokenStream(lexer); + cmdParser parser = new cmdParser(tokens); + ParseTree tree = parser.command(); + if(tree == null) return 0; + else { + CmdDefaultVisitor visitor = new CmdDefaultVisitor(); + return visitor.visit(tree); + } + }catch (Exception ex) { + ex.printStackTrace(); + } + return 0; + } +} diff --git a/app/src/main/java/org/xing/calc/cmd/grammer/cmdBaseVisitor.java b/app/src/main/java/org/xing/calc/cmd/grammer/cmdBaseVisitor.java new file mode 100644 index 0000000..aefcacc --- /dev/null +++ b/app/src/main/java/org/xing/calc/cmd/grammer/cmdBaseVisitor.java @@ -0,0 +1,77 @@ +// Generated from src/org/xing/calc/cmd/grammer/cmd.g4 by ANTLR 4.6 +package org.xing.calc.cmd.grammer; +import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; + +/** + * This class provides an empty implementation of {@link cmdVisitor}, + * which can be extended to create a visitor which only needs to handle a subset + * of the available methods. + * + * @param The return type of the visit operation. Use {@link Void} for + * operations with no return type. + */ +public class cmdBaseVisitor extends AbstractParseTreeVisitor implements cmdVisitor { + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitCommand(cmdParser.CommandContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitQingping(cmdParser.QingpingContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitGoback(cmdParser.GobackContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitHelp(cmdParser.HelpContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitUpdate(cmdParser.UpdateContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitTheme(cmdParser.ThemeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEngine(cmdParser.EngineContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitClose(cmdParser.CloseContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitStop(cmdParser.StopContext ctx) { return visitChildren(ctx); } +} \ No newline at end of file diff --git a/app/src/main/java/org/xing/calc/cmd/grammer/cmdLexer.java b/app/src/main/java/org/xing/calc/cmd/grammer/cmdLexer.java new file mode 100644 index 0000000..ce1776e --- /dev/null +++ b/app/src/main/java/org/xing/calc/cmd/grammer/cmdLexer.java @@ -0,0 +1,140 @@ +// Generated from src/org/xing/calc/cmd/grammer/cmd.g4 by ANTLR 4.6 +package org.xing.calc.cmd.grammer; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.TokenStream; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.misc.*; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class cmdLexer extends Lexer { + static { RuntimeMetaData.checkVersion("4.6", RuntimeMetaData.VERSION); } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, + T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, + T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, WS=24; + public static String[] modeNames = { + "DEFAULT_MODE" + }; + + public static final String[] ruleNames = { + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", + "T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "T__16", + "T__17", "T__18", "T__19", "T__20", "T__21", "T__22", "WS" + }; + + private static final String[] _LITERAL_NAMES = { + null, "'清屏'", "'清空'", "'清除'", "'全部'", "'撤销'", "'取消'", "'倒退'", "'后退'", + "'删除'", "'帮助'", "'示例'", "'说明'", "'升级'", "'版本'", "'主题'", "'风格'", "'背景'", + "'引擎'", "'百度'", "'讯飞'", "'退出'", "'关闭'", "'暂停'" + }; + private static final String[] _SYMBOLIC_NAMES = { + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + "WS" + }; + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + + public cmdLexer(CharStream input) { + super(input); + _interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); + } + + @Override + public String getGrammarFileName() { return "cmd.g4"; } + + @Override + public String[] getRuleNames() { return ruleNames; } + + @Override + public String getSerializedATN() { return _serializedATN; } + + @Override + public String[] getModeNames() { return modeNames; } + + @Override + public ATN getATN() { return _ATN; } + + public static final String _serializedATN = + "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2\32\177\b\1\4\2\t"+ + "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ + "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ + "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ + "\3\2\3\2\3\2\3\3\3\3\3\3\3\4\3\4\3\4\3\5\3\5\3\5\3\6\3\6\3\6\3\7\3\7\3"+ + "\7\3\b\3\b\3\b\3\t\3\t\3\t\3\n\3\n\3\n\3\13\3\13\3\13\3\f\3\f\3\f\3\r"+ + "\3\r\3\r\3\16\3\16\3\16\3\17\3\17\3\17\3\20\3\20\3\20\3\21\3\21\3\21\3"+ + "\22\3\22\3\22\3\23\3\23\3\23\3\24\3\24\3\24\3\25\3\25\3\25\3\26\3\26\3"+ + "\26\3\27\3\27\3\27\3\30\3\30\3\30\3\31\6\31z\n\31\r\31\16\31{\3\31\3\31"+ + "\2\2\32\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17"+ + "\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\3\2\3\5\2\13\f\17"+ + "\17\"\"\177\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2"+ + "\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27"+ + "\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2"+ + "\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2"+ + "\2/\3\2\2\2\2\61\3\2\2\2\3\63\3\2\2\2\5\66\3\2\2\2\79\3\2\2\2\t<\3\2\2"+ + "\2\13?\3\2\2\2\rB\3\2\2\2\17E\3\2\2\2\21H\3\2\2\2\23K\3\2\2\2\25N\3\2"+ + "\2\2\27Q\3\2\2\2\31T\3\2\2\2\33W\3\2\2\2\35Z\3\2\2\2\37]\3\2\2\2!`\3\2"+ + "\2\2#c\3\2\2\2%f\3\2\2\2\'i\3\2\2\2)l\3\2\2\2+o\3\2\2\2-r\3\2\2\2/u\3"+ + "\2\2\2\61y\3\2\2\2\63\64\7\u6e07\2\2\64\65\7\u5c51\2\2\65\4\3\2\2\2\66"+ + "\67\7\u6e07\2\2\678\7\u7a7c\2\28\6\3\2\2\29:\7\u6e07\2\2:;\7\u9666\2\2"+ + ";\b\3\2\2\2<=\7\u516a\2\2=>\7\u90ea\2\2>\n\3\2\2\2?@\7\u64a6\2\2@A\7\u9502"+ + "\2\2A\f\3\2\2\2BC\7\u53d8\2\2CD\7\u6d8a\2\2D\16\3\2\2\2EF\7\u5014\2\2"+ + "FG\7\u9002\2\2G\20\3\2\2\2HI\7\u5410\2\2IJ\7\u9002\2\2J\22\3\2\2\2KL\7"+ + "\u5222\2\2LM\7\u9666\2\2M\24\3\2\2\2NO\7\u5e30\2\2OP\7\u52ab\2\2P\26\3"+ + "\2\2\2QR\7\u793c\2\2RS\7\u4f8d\2\2S\30\3\2\2\2TU\7\u8bf6\2\2UV\7\u6610"+ + "\2\2V\32\3\2\2\2WX\7\u5349\2\2XY\7\u7ea9\2\2Y\34\3\2\2\2Z[\7\u724a\2\2"+ + "[\\\7\u672e\2\2\\\36\3\2\2\2]^\7\u4e3d\2\2^_\7\u989a\2\2_ \3\2\2\2`a\7"+ + "\u98d0\2\2ab\7\u683e\2\2b\"\3\2\2\2cd\7\u80ce\2\2de\7\u6671\2\2e$\3\2"+ + "\2\2fg\7\u5f17\2\2gh\7\u64d0\2\2h&\3\2\2\2ij\7\u7680\2\2jk\7\u5ea8\2\2"+ + "k(\3\2\2\2lm\7\u8bb1\2\2mn\7\u98e0\2\2n*\3\2\2\2op\7\u9002\2\2pq\7\u51fc"+ + "\2\2q,\3\2\2\2rs\7\u5175\2\2st\7\u95ef\2\2t.\3\2\2\2uv\7\u6684\2\2vw\7"+ + "\u505e\2\2w\60\3\2\2\2xz\t\2\2\2yx\3\2\2\2z{\3\2\2\2{y\3\2\2\2{|\3\2\2"+ + "\2|}\3\2\2\2}~\b\31\2\2~\62\3\2\2\2\4\2{\3\2\3\2"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/xing/calc/cmd/grammer/cmdParser.java b/app/src/main/java/org/xing/calc/cmd/grammer/cmdParser.java new file mode 100644 index 0000000..cd81483 --- /dev/null +++ b/app/src/main/java/org/xing/calc/cmd/grammer/cmdParser.java @@ -0,0 +1,597 @@ +// Generated from src/org/xing/calc/cmd/grammer/cmd.g4 by ANTLR 4.6 +package org.xing.calc.cmd.grammer; +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.misc.*; +import org.antlr.v4.runtime.tree.*; +import java.util.List; +import java.util.Iterator; +import java.util.ArrayList; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class cmdParser extends Parser { + static { RuntimeMetaData.checkVersion("4.6", RuntimeMetaData.VERSION); } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, + T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, + T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, WS=24; + public static final int + RULE_command = 0, RULE_qingping = 1, RULE_goback = 2, RULE_help = 3, RULE_update = 4, + RULE_theme = 5, RULE_engine = 6, RULE_close = 7, RULE_stop = 8; + public static final String[] ruleNames = { + "command", "qingping", "goback", "help", "update", "theme", "engine", + "close", "stop" + }; + + private static final String[] _LITERAL_NAMES = { + null, "'清屏'", "'清空'", "'清除'", "'全部'", "'撤销'", "'取消'", "'倒退'", "'后退'", + "'删除'", "'帮助'", "'示例'", "'说明'", "'升级'", "'版本'", "'主题'", "'风格'", "'背景'", + "'引擎'", "'百度'", "'讯飞'", "'退出'", "'关闭'", "'暂停'" + }; + private static final String[] _SYMBOLIC_NAMES = { + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + "WS" + }; + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + @Override + public String getGrammarFileName() { return "cmd.g4"; } + + @Override + public String[] getRuleNames() { return ruleNames; } + + @Override + public String getSerializedATN() { return _serializedATN; } + + @Override + public ATN getATN() { return _ATN; } + + public cmdParser(TokenStream input) { + super(input); + _interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); + } + public static class CommandContext extends ParserRuleContext { + public QingpingContext qingping() { + return getRuleContext(QingpingContext.class,0); + } + public GobackContext goback() { + return getRuleContext(GobackContext.class,0); + } + public HelpContext help() { + return getRuleContext(HelpContext.class,0); + } + public UpdateContext update() { + return getRuleContext(UpdateContext.class,0); + } + public ThemeContext theme() { + return getRuleContext(ThemeContext.class,0); + } + public EngineContext engine() { + return getRuleContext(EngineContext.class,0); + } + public CloseContext close() { + return getRuleContext(CloseContext.class,0); + } + public StopContext stop() { + return getRuleContext(StopContext.class,0); + } + public CommandContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_command; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof cmdVisitor ) return ((cmdVisitor)visitor).visitCommand(this); + else return visitor.visitChildren(this); + } + } + + public final CommandContext command() throws RecognitionException { + CommandContext _localctx = new CommandContext(_ctx, getState()); + enterRule(_localctx, 0, RULE_command); + try { + setState(26); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__0: + case T__1: + case T__2: + case T__3: + enterOuterAlt(_localctx, 1); + { + setState(18); + qingping(); + } + break; + case T__4: + case T__5: + case T__6: + case T__7: + case T__8: + enterOuterAlt(_localctx, 2); + { + setState(19); + goback(); + } + break; + case T__9: + case T__10: + case T__11: + enterOuterAlt(_localctx, 3); + { + setState(20); + help(); + } + break; + case T__12: + case T__13: + enterOuterAlt(_localctx, 4); + { + setState(21); + update(); + } + break; + case T__14: + case T__15: + case T__16: + enterOuterAlt(_localctx, 5); + { + setState(22); + theme(); + } + break; + case T__17: + case T__18: + case T__19: + enterOuterAlt(_localctx, 6); + { + setState(23); + engine(); + } + break; + case T__20: + case T__21: + enterOuterAlt(_localctx, 7); + { + setState(24); + close(); + } + break; + case T__22: + enterOuterAlt(_localctx, 8); + { + setState(25); + stop(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class QingpingContext extends ParserRuleContext { + public GobackContext goback() { + return getRuleContext(GobackContext.class,0); + } + public QingpingContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_qingping; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof cmdVisitor ) return ((cmdVisitor)visitor).visitQingping(this); + else return visitor.visitChildren(this); + } + } + + public final QingpingContext qingping() throws RecognitionException { + QingpingContext _localctx = new QingpingContext(_ctx, getState()); + enterRule(_localctx, 2, RULE_qingping); + try { + setState(33); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__0: + enterOuterAlt(_localctx, 1); + { + setState(28); + match(T__0); + } + break; + case T__1: + enterOuterAlt(_localctx, 2); + { + setState(29); + match(T__1); + } + break; + case T__2: + enterOuterAlt(_localctx, 3); + { + setState(30); + match(T__2); + } + break; + case T__3: + enterOuterAlt(_localctx, 4); + { + { + setState(31); + match(T__3); + setState(32); + goback(); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class GobackContext extends ParserRuleContext { + public GobackContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_goback; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof cmdVisitor ) return ((cmdVisitor)visitor).visitGoback(this); + else return visitor.visitChildren(this); + } + } + + public final GobackContext goback() throws RecognitionException { + GobackContext _localctx = new GobackContext(_ctx, getState()); + enterRule(_localctx, 4, RULE_goback); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(35); + _la = _input.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__5) | (1L << T__6) | (1L << T__7) | (1L << T__8))) != 0)) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class HelpContext extends ParserRuleContext { + public HelpContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_help; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof cmdVisitor ) return ((cmdVisitor)visitor).visitHelp(this); + else return visitor.visitChildren(this); + } + } + + public final HelpContext help() throws RecognitionException { + HelpContext _localctx = new HelpContext(_ctx, getState()); + enterRule(_localctx, 6, RULE_help); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(37); + _la = _input.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__9) | (1L << T__10) | (1L << T__11))) != 0)) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class UpdateContext extends ParserRuleContext { + public UpdateContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_update; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof cmdVisitor ) return ((cmdVisitor)visitor).visitUpdate(this); + else return visitor.visitChildren(this); + } + } + + public final UpdateContext update() throws RecognitionException { + UpdateContext _localctx = new UpdateContext(_ctx, getState()); + enterRule(_localctx, 8, RULE_update); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(39); + _la = _input.LA(1); + if ( !(_la==T__12 || _la==T__13) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ThemeContext extends ParserRuleContext { + public ThemeContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_theme; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof cmdVisitor ) return ((cmdVisitor)visitor).visitTheme(this); + else return visitor.visitChildren(this); + } + } + + public final ThemeContext theme() throws RecognitionException { + ThemeContext _localctx = new ThemeContext(_ctx, getState()); + enterRule(_localctx, 10, RULE_theme); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(41); + _la = _input.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__14) | (1L << T__15) | (1L << T__16))) != 0)) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EngineContext extends ParserRuleContext { + public EngineContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_engine; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof cmdVisitor ) return ((cmdVisitor)visitor).visitEngine(this); + else return visitor.visitChildren(this); + } + } + + public final EngineContext engine() throws RecognitionException { + EngineContext _localctx = new EngineContext(_ctx, getState()); + enterRule(_localctx, 12, RULE_engine); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(43); + _la = _input.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__17) | (1L << T__18) | (1L << T__19))) != 0)) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class CloseContext extends ParserRuleContext { + public CloseContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_close; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof cmdVisitor ) return ((cmdVisitor)visitor).visitClose(this); + else return visitor.visitChildren(this); + } + } + + public final CloseContext close() throws RecognitionException { + CloseContext _localctx = new CloseContext(_ctx, getState()); + enterRule(_localctx, 14, RULE_close); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(45); + _la = _input.LA(1); + if ( !(_la==T__20 || _la==T__21) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class StopContext extends ParserRuleContext { + public StopContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_stop; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof cmdVisitor ) return ((cmdVisitor)visitor).visitStop(this); + else return visitor.visitChildren(this); + } + } + + public final StopContext stop() throws RecognitionException { + StopContext _localctx = new StopContext(_ctx, getState()); + enterRule(_localctx, 16, RULE_stop); + try { + enterOuterAlt(_localctx, 1); + { + setState(47); + match(T__22); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static final String _serializedATN = + "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3\32\64\4\2\t\2\4\3"+ + "\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\3\2\3\2\3"+ + "\2\3\2\3\2\3\2\3\2\3\2\5\2\35\n\2\3\3\3\3\3\3\3\3\3\3\5\3$\n\3\3\4\3\4"+ + "\3\5\3\5\3\6\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n\3\n\2\2\13\2\4\6\b\n"+ + "\f\16\20\22\2\b\3\2\7\13\3\2\f\16\3\2\17\20\3\2\21\23\3\2\24\26\3\2\27"+ + "\30\64\2\34\3\2\2\2\4#\3\2\2\2\6%\3\2\2\2\b\'\3\2\2\2\n)\3\2\2\2\f+\3"+ + "\2\2\2\16-\3\2\2\2\20/\3\2\2\2\22\61\3\2\2\2\24\35\5\4\3\2\25\35\5\6\4"+ + "\2\26\35\5\b\5\2\27\35\5\n\6\2\30\35\5\f\7\2\31\35\5\16\b\2\32\35\5\20"+ + "\t\2\33\35\5\22\n\2\34\24\3\2\2\2\34\25\3\2\2\2\34\26\3\2\2\2\34\27\3"+ + "\2\2\2\34\30\3\2\2\2\34\31\3\2\2\2\34\32\3\2\2\2\34\33\3\2\2\2\35\3\3"+ + "\2\2\2\36$\7\3\2\2\37$\7\4\2\2 $\7\5\2\2!\"\7\6\2\2\"$\5\6\4\2#\36\3\2"+ + "\2\2#\37\3\2\2\2# \3\2\2\2#!\3\2\2\2$\5\3\2\2\2%&\t\2\2\2&\7\3\2\2\2\'"+ + "(\t\3\2\2(\t\3\2\2\2)*\t\4\2\2*\13\3\2\2\2+,\t\5\2\2,\r\3\2\2\2-.\t\6"+ + "\2\2.\17\3\2\2\2/\60\t\7\2\2\60\21\3\2\2\2\61\62\7\31\2\2\62\23\3\2\2"+ + "\2\4\34#"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/xing/calc/cmd/grammer/cmdVisitor.java b/app/src/main/java/org/xing/calc/cmd/grammer/cmdVisitor.java new file mode 100644 index 0000000..8055bcd --- /dev/null +++ b/app/src/main/java/org/xing/calc/cmd/grammer/cmdVisitor.java @@ -0,0 +1,67 @@ +// Generated from src/org/xing/calc/cmd/grammer/cmd.g4 by ANTLR 4.6 +package org.xing.calc.cmd.grammer; +import org.antlr.v4.runtime.tree.ParseTreeVisitor; + +/** + * This interface defines a complete generic visitor for a parse tree produced + * by {@link cmdParser}. + * + * @param The return type of the visit operation. Use {@link Void} for + * operations with no return type. + */ +public interface cmdVisitor extends ParseTreeVisitor { + /** + * Visit a parse tree produced by {@link cmdParser#command}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitCommand(cmdParser.CommandContext ctx); + /** + * Visit a parse tree produced by {@link cmdParser#qingping}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitQingping(cmdParser.QingpingContext ctx); + /** + * Visit a parse tree produced by {@link cmdParser#goback}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitGoback(cmdParser.GobackContext ctx); + /** + * Visit a parse tree produced by {@link cmdParser#help}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitHelp(cmdParser.HelpContext ctx); + /** + * Visit a parse tree produced by {@link cmdParser#update}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitUpdate(cmdParser.UpdateContext ctx); + /** + * Visit a parse tree produced by {@link cmdParser#theme}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitTheme(cmdParser.ThemeContext ctx); + /** + * Visit a parse tree produced by {@link cmdParser#engine}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEngine(cmdParser.EngineContext ctx); + /** + * Visit a parse tree produced by {@link cmdParser#close}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitClose(cmdParser.CloseContext ctx); + /** + * Visit a parse tree produced by {@link cmdParser#stop}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitStop(cmdParser.StopContext ctx); +} \ No newline at end of file diff --git a/app/src/main/java/org/xing/calc/filter/CorrectionExprFilter.java b/app/src/main/java/org/xing/calc/filter/CorrectionExprFilter.java new file mode 100644 index 0000000..ef41ba2 --- /dev/null +++ b/app/src/main/java/org/xing/calc/filter/CorrectionExprFilter.java @@ -0,0 +1,210 @@ +package org.xing.calc.filter; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class CorrectionExprFilter implements ExprFilter { + private StringBuilder regStr; + private Map correctionStringMap; + + public CorrectionExprFilter() { + regStr = new StringBuilder(); + correctionStringMap = new HashMap<>(); + + addWord("佛", "负"); + addWord("塑", "负"); + + addWord("僵", "加"); + addWord("讲", "加"); + addWord("将", "加"); + addWord("奖", "加"); + + addWord("缉", "减"); + + addWord("倍", "乘"); + addWord("澄", "乘"); + addWord("橙", "乘"); + addWord("盛", "乘"); + addWord("重", "乘"); + addWord("层", "乘"); + addWord("曾", "乘"); + addWord("城里", "乘以"); + addWord("成语", "乘以"); + + addWord("初一", "除以"); + addWord("乘与", "除以"); + addWord("完了", ""); + + addWord("区", "除"); + addWord("褚", "除"); + + addWord("括弧", "括号"); + + //一块二这种金额的表达方式 + addWord("块", "点"); + addWord(":", "点"); + addWord(":", "点"); + + addWord("幺", "一"); + addWord("e", "一"); + addWord("两", "二"); + addWord("俩", "二"); + addWord("山", "3"); + addWord("善", "3"); + addWord("潘", "3"); + addWord("仨", "三"); + addWord("是", "4"); + addWord("事", "4"); + addWord("士", "4"); + addWord("式", "4"); + addWord("氏", "4"); + addWord("市", "4"); + addWord("世", "4"); + addWord("师", "4"); + addWord("我", "5"); + addWord("陆", "6"); + addWord("料", "6"); + addWord("乐", "6"); + addWord("榴", "6"); + addWord("亲", "7"); + addWord("鸡", "7"); + addWord("夕", "7"); + addWord("欹", "7"); + addWord("班", "8"); + addWord("发", "8"); + addWord("近", "9"); + addWord("教", "9"); + + addWord("鱼线", "余弦"); + addWord("预先", "余弦"); + addWord("遇险", "余弦"); + addWord("鱼鲜", "余弦"); + addWord("玉仙", "余弦"); + addWord("欲仙", "余弦"); + addWord("预选", "余弦"); + addWord("雨轩", "余弦"); + addWord("宇轩", "余弦"); + addWord("预选", "余弦"); + addWord("玉轩", "余弦"); + + addWord("范玉献", "反余弦"); + addWord("范瑜轩", "反余弦"); + addWord("赣榆县", "反余弦"); + + addWord("争先", "正弦"); + addWord("正线", "正弦"); + addWord("争鲜", "正弦"); + addWord("正选", "正弦"); + addWord("郑玄", "正弦"); + addWord("郑璇", "正弦"); + + addWord("反正选", "反正弦"); + addWord("反正旋", "反正弦"); + + addWord("正确", "正切"); + addWord("争取", "正切"); + addWord("证券", "正切"); + addWord("挣钱", "正切"); + addWord("正气", "正切"); + addWord("争气", "正切"); + addWord("政权", "正切"); + addWord("征求", "正切"); + + addWord("反正钱", "反正切"); + addWord("反正去", "反正切"); + + addWord("括回", "括号"); + addWord("货号", "括号"); + + addWord("对手", "对数"); + addWord("开封", "开方"); + addWord("次幂", "次方"); + + addWord("等于", ""); + addWord("多少", ""); + addWord("的差", ""); + addWord("的和", ""); + addWord("的积", ""); + addWord("的商", ""); + + addWord("%", "/100"); + addWord("%", "/100"); + addWord("以前", "一千"); + addWord("^2", "的平方"); + addWord("佳茵", "加一"); + addWord("捡漏", "减六"); + addWord("捡了", "减六"); + addWord("图六", "除六"); + addWord("除了", "除六"); + addWord("成龙", "乘六"); + addWord("成了", "乘六"); + addWord("天气", "减七"); + addWord("欹", "七"); + addWord("成绩", "乘七"); + addWord("长期", "乘七"); + addWord("城西", "乘七"); + addWord("晨曦", "乘七"); + addWord("城邦", "乘八"); + addWord("乘邦", "乘八"); + addWord("主角", "除九"); + addWord("图九", "除九"); + + addWord("圆周率", "派"); + addWord("请您", "清零"); + + addWord("清平", "清屏"); + addWord("青平", "清屏"); + addWord("青萍", "清屏"); + addWord("青苹", "清屏"); + addWord("蜻蜓", "清屏"); + addWord("金瓶", "清屏"); + addWord("金平", "清屏"); + addWord("亲萍", "清屏"); + addWord("星空", "清空"); + addWord("净空", "清空"); + + addWord("浙江", "撤销"); + addWord("大腿", "倒退"); + addWord("车享", "倒退"); + + addWord("阴茎", "引擎"); + addWord("隐形", "引擎"); + } + private void addWord(String tar, String with) { + if(regStr.length() > 0) { + regStr.append("|"); + } + regStr.append("("); + String temp = tar; + temp = temp.replace("^", "\\^"); + temp = temp.replace("%", "\\%"); + regStr.append(temp); + regStr.append(")"); + + correctionStringMap.put(tar, with); + } + + @Override + public String call(String expr) { + int start = 0; + StringBuilder str = new StringBuilder(); + + Pattern correctionPattern = Pattern.compile(regStr.toString()); + Matcher mch = correctionPattern.matcher(expr); + while(mch.find()) { + if(mch.start() > start) { + str.append(expr.substring(start, mch.start())); + } + str.append(correctionStringMap.get(mch.group())); + start = mch.end(); + } + if(start < expr.length()) { + str.append(expr.substring(start)); + } + + return str.toString(); + } + +} diff --git a/app/src/main/java/org/xing/calc/filter/ExprFilter.java b/app/src/main/java/org/xing/calc/filter/ExprFilter.java new file mode 100644 index 0000000..d6fe8c5 --- /dev/null +++ b/app/src/main/java/org/xing/calc/filter/ExprFilter.java @@ -0,0 +1,5 @@ +package org.xing.calc.filter; + +public interface ExprFilter { + String call(String expr); +} diff --git a/app/src/main/java/org/xing/calc/filter/ExprFilterChain.java b/app/src/main/java/org/xing/calc/filter/ExprFilterChain.java new file mode 100644 index 0000000..2fe1378 --- /dev/null +++ b/app/src/main/java/org/xing/calc/filter/ExprFilterChain.java @@ -0,0 +1,33 @@ +package org.xing.calc.filter; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +/** + * Created by xing on 2017/5/10. + */ + +public class ExprFilterChain implements ExprFilter { + private LinkedList filters; + public ExprFilterChain() { + filters = new LinkedList<>(); + } + public ExprFilterChain(String allowedChars, HashMap pinyin) { + filters = new LinkedList<>(); + filters.add(new CorrectionExprFilter()); + filters.add(new PinyinExprFilter(allowedChars, pinyin)); + } + + public void addExprFilter(ExprFilter filter) { + filters.add(filter); + } + + public String call(String expr) { + String temp = expr; + for(ExprFilter filter : filters) { + temp = filter.call(temp); + } + return temp; + } +} diff --git a/app/src/main/java/org/xing/calc/filter/PinyinExprFilter.java b/app/src/main/java/org/xing/calc/filter/PinyinExprFilter.java new file mode 100644 index 0000000..0c3c1f0 --- /dev/null +++ b/app/src/main/java/org/xing/calc/filter/PinyinExprFilter.java @@ -0,0 +1,106 @@ +package org.xing.calc.filter; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class PinyinExprFilter implements ExprFilter{ + private Set allowedChars; + private Map allowedCharsPinyin; + + private HashMap pinyin; + + public PinyinExprFilter(String legalChars, HashMap pinyin) { + this.pinyin = (HashMap )pinyin.clone(); + + allowedChars = new HashSet(); + allowedCharsPinyin = new HashMap(); + for(int i=0;i loadTokens(InputStream input) { + HashMap pinyin = new HashMap(); + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(input, "utf-8")); + String line = null; + while((line = reader.readLine()) != null) { + if(line.length() > 0) { + String[] fields = line.split("\\s+"); + String charPinyin = fields[1]; + String chars = fields[2]; + for(int i=0;i { + private NumberParser numParser; + public CalculatorEvalVisitor() { + numParser = new NumberParser(); + } + + @Override + public Double visitExpression(calculatorParser.ExpressionContext ctx) { + Double result = visit(ctx.getChild(0)); + if(ctx.getChildCount() > 2) { + for(int i=1;i 2) { + for(int i=1;i { + protected NumberParser numParser; + + public CalculatorLatexExprVisitor() { + numParser = new NumberParser(); + } + + public enum AtomType{ + None, PosNumber, NegNumber, Sqrt, Frac, Log, Brack, Pow, Mixed + } + + private boolean bracketsLeggal(String expr) { + Stack brackets = new Stack<>(); + for(int i=0;i 0) { + result.append("("+expr+")"); + }else { + result.append(expr); + } + } + } + return result.toString(); + } + + @Override + public String visitMultiplyingExpression( + calculatorParser.MultiplyingExpressionContext ctx) { + StringBuilder result = new StringBuilder(); + for(int i=0;i 0) { + result.append("("+expr+")"); + }else { + result.append(expr); + } + } + } + return result.toString(); + } + + @Override + public String visitPowExpression(calculatorParser.PowExpressionContext ctx) { + int index = 0; + String result = visit(ctx.getChild(index++)); + + while (index < ctx.getChildCount()) { + String[] brackExpr = getBrackExpr(result); + TerminalNode node = (TerminalNode) ctx.getChild(index); + if(node.getSymbol().getType() == calculatorParser.DE) { + if (ctx.getChild(index + 1) instanceof TerminalNode) { + int type = ((TerminalNode) ctx.getChild(index + 1)).getSymbol() + .getType(); + if (type == calculatorParser.PINGFANG) { + result = "{" + brackExpr[0] + "}^2"; + } else if (type == calculatorParser.LIFANG) { + result = "{" + brackExpr[0] + "}^3"; + } else if (type == calculatorParser.KAIFANG) { + result = "\\\\sqrt{" + brackExpr[1] + "}"; + } else { + System.err.println("未处理的终端节点:visitChinaPowExpression"); + } + index += 2; + } else { + String pow = visit(ctx.getChild(index + 1)); + result = "{" + brackExpr[0] + "}^{" + pow + "}"; + index += 3; + } + } else { + String pow = visit(ctx.getChild(index + 1)); + result = "{" + brackExpr[0] + "}^{" + pow + "}"; + index += 2; + } + } + return result; + } + + @Override + public String visitAtom(calculatorParser.AtomContext ctx) { + if(ctx.MINUS() != null) { + return "-" + visit(ctx.getChild(1)); + }else if(ctx.PLUS() != null) { + return visit(ctx.getChild(1)); + }if(ctx.getChildCount() == 3) { + if(ctx.FRAC() != null) { + String expr0 = visit(ctx.getChild(0)); + String expr2 = visit(ctx.getChild(2)); + + //对于负的分数特殊处理 + String negTag = ""; + boolean neg0 = expr0.startsWith("-"); + boolean neg2 = expr2.startsWith("-"); + if(neg0 != neg2) { + if(neg0) { + expr0 = expr0.substring(1); + }else { + expr2 = expr2.substring(1); + } + negTag = "-"; + } + + String[] brackExpr0 = getBrackExpr(expr0); + String[] brackExpr2 = getBrackExpr(expr2); + if(ctx.FRAC().getText().equals("分之")) { + return negTag+"\\\\frac{"+brackExpr2[1]+"}{"+brackExpr0[1]+"}"; + }else { + return negTag+"\\\\frac{"+brackExpr0[1]+"}{"+brackExpr2[1]+"}"; + } + }else { + String[] brackExpr = getBrackExpr(visit(ctx.expression())); + return "("+brackExpr[1]+")"; + } + }else if(ctx.getChildCount() == 5) { + String expr0 = visit(ctx.getChild(0)); + String expr2 = visit(ctx.getChild(2)); + String expr4 = visit(ctx.getChild(4)); + //三又2/3 这种被语音识别引擎处理过的表达方式 + if(ctx.getChild(3).getText().equals("/")) { + expr2 = visit(ctx.getChild(4)); + expr4 = visit(ctx.getChild(2)); + } + return expr0+"\\\\frac{"+expr4+"}{"+expr2+"}"; + }else { + return visit(ctx.getChild(0)); + } + } + + @Override + public String visitFunction(calculatorParser.FunctionContext ctx) { + if(ctx.funcnameEx() != null) { + calculatorParser.FuncnameExContext func = ctx.funcnameEx(); + String firstNum = visit(ctx.getChild(0)); + String secondNum = visit(ctx.getChild(2)); + if(firstNum == null || secondNum == null) return null; + + String[] brackFirstNum = getBrackExpr(firstNum); + String[] brackSecondNum = getBrackExpr(secondNum); + if(func.DUISHU() != null) { + return "log_{"+brackFirstNum[0]+"}"+brackSecondNum[0]; + }else if(func.GENHAO() != null) { + return "\\\\sqrt["+brackFirstNum[0]+"]{"+brackSecondNum[1]+"}"; + } + } else if(ctx.funcname() != null){ + String expr = visit(ctx.getChild(1)); + calculatorParser.FuncnameContext func = ctx.funcname(); + if(expr == null) return null; + + String[] brackExpr = getBrackExpr(expr); + if(func.SIN() != null) { + return "sin("+brackExpr[1]+")"; + }else if(func.COS() != null) { + return "cos("+brackExpr[1]+")"; + }else if(func.TAN() != null) { + return "tan("+brackExpr[1]+")"; + }else if(func.ASIN() != null) { + return "asin("+brackExpr[1]+")"; + }else if(func.ACOS() != null) { + return "acos("+brackExpr[1]+")"; + }else if(func.ATAN() != null) { + return "atan("+brackExpr[1]+")"; + }else if(func.LG() != null) { + return "lg("+brackExpr[1]+")"; + }else if(func.LOG() != null) { + return "log("+brackExpr[1]+")"; + }else if(func.LN() != null) { + return "ln("+brackExpr[1]+")"; + }else if(func.GENHAO() != null) { + return "\\\\sqrt{"+brackExpr[1]+"}"; + }else if(func.DUISHU() != null) { + return "ln("+brackExpr[1]+")"; + }else{ + System.err.println("Not supported function '"+ctx.funcname()+"'"); + } + }else if(ctx.postFuncname() != null) { + calculatorParser.PostFuncnameContext postFuncname = ctx.postFuncname(); + String expr = visit(ctx.getChild(0)); + String[] brackExpr = getBrackExpr(expr); + + if(postFuncname.KAIFANG() != null + || postFuncname.KAIPINGFANG() != null) { + return "\\\\sqrt{"+brackExpr[1]+"}"; + }else if(postFuncname.PINGFANG() != null) { + if(postFuncname.GEN() != null) { + return "\\\\sqrt{"+brackExpr[1]+"}"; + }else { + return expr+"^2"; + } + }else if(postFuncname.KAILIFANG() != null) { + return "\\\\sqrt[3]{"+brackExpr[1]+"}"; + }else if(postFuncname.LIFANG() != null) { + if(postFuncname.GEN() != null) { + return "\\\\sqrt[3]{"+brackExpr[1]+"}"; + }else { + return expr+"^3"; + } + } + } + + return null; + } + + @Override + public String visitNumber(calculatorParser.NumberContext ctx) { + try{ + String expr = ctx.getText(); + StringBuilder result = new StringBuilder(); + if(ctx.PAI() != null || ctx.DU() != null) { + if (ctx.DIGIT().isEmpty()) { + result.append("\\\\pi"); + }else { + numParser.parse(expr.substring(0, expr.length() - 1)); + result.append(numParser.getReadExpr()); + + if (ctx.PAI() != null) { + result.append("\\\\pi"); + } else { + result.append("\\\\degree"); + } + } + } else { + numParser.parse(ctx.getText()); + result.append(numParser.getReadExpr()); + } + return result.toString(); + }catch(Exception ex) { + return null; + } + } +} diff --git a/app/src/main/java/org/xing/calc/parser/NumberParser.java b/app/src/main/java/org/xing/calc/parser/NumberParser.java new file mode 100644 index 0000000..46a7898 --- /dev/null +++ b/app/src/main/java/org/xing/calc/parser/NumberParser.java @@ -0,0 +1,170 @@ +package org.xing.calc.parser; + +import java.util.HashMap; +import java.util.Map; + +public class NumberParser extends Parser { + private Map chineseToMathMap; + private Map numberDigitsMap; + + public NumberParser() { + chineseToMathMap = new HashMap(); + chineseToMathMap.put('零', "0"); + chineseToMathMap.put('一', "1"); + chineseToMathMap.put('二', "2"); + chineseToMathMap.put('三', "3"); + chineseToMathMap.put('四', "4"); + chineseToMathMap.put('五', "5"); + chineseToMathMap.put('六', "6"); + chineseToMathMap.put('七', "7"); + chineseToMathMap.put('八', "8"); + chineseToMathMap.put('九', "9"); + + numberDigitsMap = new HashMap(); + numberDigitsMap.put('个', 0); + numberDigitsMap.put('十', 1); + numberDigitsMap.put('百', 2); + numberDigitsMap.put('千', 3); + numberDigitsMap.put('万', 4); + numberDigitsMap.put('亿', 8); + } + + private boolean isNumber(char c) { + if(c >= '0' && c <= '9') return true; + if(chineseToMathMap.containsKey(c)) return true; + return false; + } + + public void parse(String inputNumber) { + StringBuilder str = new StringBuilder(); + + StringBuilder reversedInputNumber = new StringBuilder(inputNumber).reverse(); + + int numDigits = 0; //整数位的位数 + int maxNumZero = 0; //专门处理类似于三百万这种连续两个单位的数字 + int secondaryMaxNumZero = 0; //二级最大值 + int index = 0; + while(index < reversedInputNumber.length()) { + char c = reversedInputNumber.charAt(index); + if(isNumber(c)) { + if(chineseToMathMap.containsKey(c)) { + str.append(chineseToMathMap.get(c)); + } else { + str.append(c); + } + numDigits ++; + } else if (c == '-' || c == '负'){ + str.append('-'); + } else if(c == '.' || c == '点') { + str.append('.'); + numDigits = 0; + } else if(numberDigitsMap.containsKey(c)){ + int numZero = numberDigitsMap.get(c); + if(numZero <= maxNumZero) { + if(numZero <= secondaryMaxNumZero) { + numZero += secondaryMaxNumZero; + } else { + secondaryMaxNumZero = numZero; + } + numZero += maxNumZero; + } else { + maxNumZero = numZero; + secondaryMaxNumZero = 0; + } + + if(index == 1 + && (!numberDigitsMap.containsKey(reversedInputNumber.charAt(0))) + ) { + //处理‘一万二’、‘三千四’这种简略说法 + int headFilledNumZero = numberDigitsMap.get(c) - numDigits; + for(int i=0;i chnMap = new HashMap(); + chnMap.put("一", "1"); + chnMap.put("一十五", "15"); + chnMap.put("零点三五", "0.35"); + chnMap.put("负十五", "-15"); + chnMap.put("十五", "15"); + chnMap.put("二十", "20"); + chnMap.put("二十三", "23"); + chnMap.put("一百", "100"); + chnMap.put("一百一", "110"); + chnMap.put("一百零一", "101"); + chnMap.put("一百一十", "110"); + chnMap.put("一百一十一", "111"); + chnMap.put("一千", "1000"); + chnMap.put("一千一", "1100"); + chnMap.put("一千零一", "1001"); + chnMap.put("一千零一十", "1010"); + chnMap.put("一千零三十一", "1031"); + chnMap.put("一万零一", "10001"); + chnMap.put("一万一", "11000"); + chnMap.put("一万零一百", "10100"); + chnMap.put("一万零二十一", "10021"); + chnMap.put("一万零三百二十一.三五", "10321.35"); + chnMap.put("一万一千三百二十一", "11321"); + chnMap.put("三千零十五万点二零", "30150000.20"); + chnMap.put("三千零一十五万", "30150000"); + chnMap.put("三千五百六十八万零一百零一", "35680101"); + chnMap.put("五十亿三千零七十五万零六百二十二", "5030750622"); + chnMap.put("十三亿三千零十五万零三百一十二", "1330150312"); + chnMap.put("负三千零七十八亿三千零十五万零三百一十二", "-307830150312"); + chnMap.put("一千二百五十八亿", "125800000000"); + chnMap.put("一千二百五十8万亿零三千三百二十一点124", "1258000000003321.124"); + + int correctNum = 0; + int wrongNum = 0; + NumberParser parser = new NumberParser(); + for(String num : chnMap.keySet()) { + String value = chnMap.get(num); + parser.parse(num); + String result = parser.getEvalExpr(); + if(!result.equals(value)) { + System.err.println("错误:"+num+", "+value+", 错误结果:"+result); + wrongNum ++; + } else { + correctNum ++; + } + } + + System.out.println("总计:\n\t正确 "+correctNum+", 错误 "+wrongNum); + } + + + public static void main(String[] argv) { + testParseNumber(argv); + } +} diff --git a/app/src/main/java/org/xing/calc/parser/Parser.java b/app/src/main/java/org/xing/calc/parser/Parser.java new file mode 100644 index 0000000..b89a0b5 --- /dev/null +++ b/app/src/main/java/org/xing/calc/parser/Parser.java @@ -0,0 +1,41 @@ +package org.xing.calc.parser; + +public abstract class Parser { + + //用于计算的表达式 + protected String evalExpr; + + //易于阅读的表达式 + protected String readExpr; + + //用于语音朗读的表达式 + protected String speechExpr; + + public String getEvalExpr() { + return evalExpr; + } + + public void setEvalExpr(String evalExpr) { + this.evalExpr = evalExpr; + } + + public String getReadExpr() { + return readExpr; + } + + public void setReadExpr(String readExpr) { + this.readExpr = readExpr; + } + + public String getSpeechExpr() { + return speechExpr; + } + + public void setSpeechExpr(String speechExpr) { + this.speechExpr = speechExpr; + } + + public void parse(String expr) { + + } +} diff --git a/app/src/main/java/org/xing/calc/parser/grammer/calculatorBaseVisitor.java b/app/src/main/java/org/xing/calc/parser/grammer/calculatorBaseVisitor.java new file mode 100644 index 0000000..6389914 --- /dev/null +++ b/app/src/main/java/org/xing/calc/parser/grammer/calculatorBaseVisitor.java @@ -0,0 +1,77 @@ +// Generated from src/org/xing/calc/parser/grammer/calculator.g4 by ANTLR 4.6 +package org.xing.calc.parser.grammer; +import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; + +/** + * This class provides an empty implementation of {@link calculatorVisitor}, + * which can be extended to create a visitor which only needs to handle a subset + * of the available methods. + * + * @param The return type of the visit operation. Use {@link Void} for + * operations with no return type. + */ +public class calculatorBaseVisitor extends AbstractParseTreeVisitor implements calculatorVisitor { + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitExpression(calculatorParser.ExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitMultiplyingExpression(calculatorParser.MultiplyingExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitPowExpression(calculatorParser.PowExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitAtom(calculatorParser.AtomContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitFunction(calculatorParser.FunctionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitFuncname(calculatorParser.FuncnameContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitFuncnameEx(calculatorParser.FuncnameExContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitPostFuncname(calculatorParser.PostFuncnameContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitNumber(calculatorParser.NumberContext ctx) { return visitChildren(ctx); } +} \ No newline at end of file diff --git a/app/src/main/java/org/xing/calc/parser/grammer/calculatorLexer.java b/app/src/main/java/org/xing/calc/parser/grammer/calculatorLexer.java new file mode 100644 index 0000000..a73e86a --- /dev/null +++ b/app/src/main/java/org/xing/calc/parser/grammer/calculatorLexer.java @@ -0,0 +1,193 @@ +// Generated from src/org/xing/calc/parser/grammer/calculator.g4 by ANTLR 4.6 +package org.xing.calc.parser.grammer; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.TokenStream; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.misc.*; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class calculatorLexer extends Lexer { + static { RuntimeMetaData.checkVersion("4.6", RuntimeMetaData.VERSION); } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + COS=1, SIN=2, TAN=3, ACOS=4, ASIN=5, ATAN=6, LN=7, LOG=8, LG=9, DUISHU=10, + GENHAO=11, KUOHAO=12, LPAREN=13, RPAREN=14, PLUS=15, MINUS=16, TIMES=17, + DIV=18, FRAC=19, YOU=20, PINGFANG=21, LIFANG=22, CIFANG=23, KAIFANG=24, + KAIPINGFANG=25, KAILIFANG=26, DE=27, GEN=28, DU=29, PAI=30, POINT=31, + E=32, POW=33, LETTER=34, DIGIT=35, WS=36; + public static String[] modeNames = { + "DEFAULT_MODE" + }; + + public static final String[] ruleNames = { + "COS", "SIN", "TAN", "ACOS", "ASIN", "ATAN", "LN", "LOG", "LG", "DUISHU", + "GENHAO", "KUOHAO", "LPAREN", "RPAREN", "PLUS", "MINUS", "TIMES", "DIV", + "FRAC", "YOU", "PINGFANG", "LIFANG", "CIFANG", "KAIFANG", "KAIPINGFANG", + "KAILIFANG", "DE", "GEN", "DU", "PAI", "POINT", "E", "POW", "LETTER", + "DIGIT", "WS" + }; + + private static final String[] _LITERAL_NAMES = { + null, null, null, null, null, null, null, "'ln'", "'log'", "'lg'", "'对数'", + "'根号'", null, "'('", "')'", null, null, null, null, null, "'又'", "'平方'", + "'立方'", "'次方'", "'开方'", "'开平方'", "'开立方'", "'的'", "'根'", null, null, null, + null, "'^'" + }; + private static final String[] _SYMBOLIC_NAMES = { + null, "COS", "SIN", "TAN", "ACOS", "ASIN", "ATAN", "LN", "LOG", "LG", + "DUISHU", "GENHAO", "KUOHAO", "LPAREN", "RPAREN", "PLUS", "MINUS", "TIMES", + "DIV", "FRAC", "YOU", "PINGFANG", "LIFANG", "CIFANG", "KAIFANG", "KAIPINGFANG", + "KAILIFANG", "DE", "GEN", "DU", "PAI", "POINT", "E", "POW", "LETTER", + "DIGIT", "WS" + }; + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + + public calculatorLexer(CharStream input) { + super(input); + _interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); + } + + @Override + public String getGrammarFileName() { return "calculator.g4"; } + + @Override + public String[] getRuleNames() { return ruleNames; } + + @Override + public String getSerializedATN() { return _serializedATN; } + + @Override + public String[] getModeNames() { return modeNames; } + + @Override + public ATN getATN() { return _ATN; } + + public static final String _serializedATN = + "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2&\u00e6\b\1\4\2\t"+ + "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ + "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ + "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ + "\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"+ + "\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\3\2\3\2\3\2\3\2\3\2\5\2Q\n\2\3\3\3\3\3\3"+ + "\3\3\3\3\5\3X\n\3\3\4\3\4\3\4\3\4\3\4\5\4_\n\4\3\5\3\5\3\5\3\5\3\5\3\5"+ + "\3\5\5\5h\n\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\5\6q\n\6\3\7\3\7\3\7\3\7\3\7"+ + "\3\7\3\7\5\7z\n\7\3\b\3\b\3\b\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\13\3\13\3"+ + "\13\3\f\3\f\3\f\3\r\3\r\3\r\5\r\u008f\n\r\3\16\3\16\3\17\3\17\3\20\3\20"+ + "\3\20\5\20\u0098\n\20\5\20\u009a\n\20\3\21\3\21\3\21\5\21\u009f\n\21\5"+ + "\21\u00a1\n\21\3\22\3\22\3\22\5\22\u00a6\n\22\5\22\u00a8\n\22\3\23\3\23"+ + "\3\23\5\23\u00ad\n\23\5\23\u00af\n\23\3\24\3\24\3\24\5\24\u00b4\n\24\3"+ + "\25\3\25\3\26\3\26\3\26\3\27\3\27\3\27\3\30\3\30\3\30\3\31\3\31\3\31\3"+ + "\32\3\32\3\32\3\32\3\33\3\33\3\33\3\33\3\34\3\34\3\35\3\35\3\36\3\36\3"+ + "\37\3\37\3 \3 \3!\3!\3\"\3\"\3#\5#\u00db\n#\3$\5$\u00de\n$\3%\6%\u00e1"+ + "\n%\r%\16%\u00e2\3%\3%\2\2&\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25"+ + "\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32"+ + "\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&\3\2\13\4\2//\u8d21\u8d21\4\2"+ + ",,\u00d9\u00d9\4\2\u00b2\u00b2\u5ea8\u5ea8\4\2\u03c2\u03c2\u6d40\u6d40"+ + "\4\2\60\60\u70bb\u70bb\4\2GGgg\4\2C\\c|\22\2\62;\u4e02\u4e02\u4e05\u4e05"+ + "\u4e09\u4e09\u4e0b\u4e0b\u4e5f\u4e5f\u4e8e\u4e8e\u4e96\u4e96\u4ec1\u4ec1"+ + "\u516d\u516d\u516f\u516f\u5343\u5343\u5345\u5345\u56dd\u56dd\u7680\u7680"+ + "\u96f8\u96f8\5\2\13\f\17\17\"\"\u00f6\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2"+ + "\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2"+ + "\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3"+ + "\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3"+ + "\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65"+ + "\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3"+ + "\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\3P\3\2\2\2\5W\3\2\2"+ + "\2\7^\3\2\2\2\tg\3\2\2\2\13p\3\2\2\2\ry\3\2\2\2\17{\3\2\2\2\21~\3\2\2"+ + "\2\23\u0082\3\2\2\2\25\u0085\3\2\2\2\27\u0088\3\2\2\2\31\u008e\3\2\2\2"+ + "\33\u0090\3\2\2\2\35\u0092\3\2\2\2\37\u0099\3\2\2\2!\u00a0\3\2\2\2#\u00a7"+ + "\3\2\2\2%\u00ae\3\2\2\2\'\u00b3\3\2\2\2)\u00b5\3\2\2\2+\u00b7\3\2\2\2"+ + "-\u00ba\3\2\2\2/\u00bd\3\2\2\2\61\u00c0\3\2\2\2\63\u00c3\3\2\2\2\65\u00c7"+ + "\3\2\2\2\67\u00cb\3\2\2\29\u00cd\3\2\2\2;\u00cf\3\2\2\2=\u00d1\3\2\2\2"+ + "?\u00d3\3\2\2\2A\u00d5\3\2\2\2C\u00d7\3\2\2\2E\u00da\3\2\2\2G\u00dd\3"+ + "\2\2\2I\u00e0\3\2\2\2KL\7e\2\2LM\7q\2\2MQ\7u\2\2NO\7\u4f5b\2\2OQ\7\u5f28"+ + "\2\2PK\3\2\2\2PN\3\2\2\2Q\4\3\2\2\2RS\7u\2\2ST\7k\2\2TX\7p\2\2UV\7\u6b65"+ + "\2\2VX\7\u5f28\2\2WR\3\2\2\2WU\3\2\2\2X\6\3\2\2\2YZ\7v\2\2Z[\7c\2\2[_"+ + "\7p\2\2\\]\7\u6b65\2\2]_\7\u5209\2\2^Y\3\2\2\2^\\\3\2\2\2_\b\3\2\2\2`"+ + "a\7c\2\2ab\7e\2\2bc\7q\2\2ch\7u\2\2de\7\u53cf\2\2ef\7\u4f5b\2\2fh\7\u5f28"+ + "\2\2g`\3\2\2\2gd\3\2\2\2h\n\3\2\2\2ij\7c\2\2jk\7u\2\2kl\7k\2\2lq\7p\2"+ + "\2mn\7\u53cf\2\2no\7\u6b65\2\2oq\7\u5f28\2\2pi\3\2\2\2pm\3\2\2\2q\f\3"+ + "\2\2\2rs\7c\2\2st\7v\2\2tu\7c\2\2uz\7p\2\2vw\7\u53cf\2\2wx\7\u6b65\2\2"+ + "xz\7\u5209\2\2yr\3\2\2\2yv\3\2\2\2z\16\3\2\2\2{|\7n\2\2|}\7p\2\2}\20\3"+ + "\2\2\2~\177\7n\2\2\177\u0080\7q\2\2\u0080\u0081\7i\2\2\u0081\22\3\2\2"+ + "\2\u0082\u0083\7n\2\2\u0083\u0084\7i\2\2\u0084\24\3\2\2\2\u0085\u0086"+ + "\7\u5bfb\2\2\u0086\u0087\7\u6572\2\2\u0087\26\3\2\2\2\u0088\u0089\7\u683b"+ + "\2\2\u0089\u008a\7\u53f9\2\2\u008a\30\3\2\2\2\u008b\u008f\7~\2\2\u008c"+ + "\u008d\7\u62ee\2\2\u008d\u008f\7\u53f9\2\2\u008e\u008b\3\2\2\2\u008e\u008c"+ + "\3\2\2\2\u008f\32\3\2\2\2\u0090\u0091\7*\2\2\u0091\34\3\2\2\2\u0092\u0093"+ + "\7+\2\2\u0093\36\3\2\2\2\u0094\u009a\7-\2\2\u0095\u0097\7\u52a2\2\2\u0096"+ + "\u0098\7\u4e0c\2\2\u0097\u0096\3\2\2\2\u0097\u0098\3\2\2\2\u0098\u009a"+ + "\3\2\2\2\u0099\u0094\3\2\2\2\u0099\u0095\3\2\2\2\u009a \3\2\2\2\u009b"+ + "\u00a1\t\2\2\2\u009c\u009e\7\u51d1\2\2\u009d\u009f\7\u53bd\2\2\u009e\u009d"+ + "\3\2\2\2\u009e\u009f\3\2\2\2\u009f\u00a1\3\2\2\2\u00a0\u009b\3\2\2\2\u00a0"+ + "\u009c\3\2\2\2\u00a1\"\3\2\2\2\u00a2\u00a8\t\3\2\2\u00a3\u00a5\7\u4e5a"+ + "\2\2\u00a4\u00a6\7\u4ee7\2\2\u00a5\u00a4\3\2\2\2\u00a5\u00a6\3\2\2\2\u00a6"+ + "\u00a8\3\2\2\2\u00a7\u00a2\3\2\2\2\u00a7\u00a3\3\2\2\2\u00a8$\3\2\2\2"+ + "\u00a9\u00af\7\u00f9\2\2\u00aa\u00ac\7\u9666\2\2\u00ab\u00ad\7\u4ee7\2"+ + "\2\u00ac\u00ab\3\2\2\2\u00ac\u00ad\3\2\2\2\u00ad\u00af\3\2\2\2\u00ae\u00a9"+ + "\3\2\2\2\u00ae\u00aa\3\2\2\2\u00af&\3\2\2\2\u00b0\u00b4\7\61\2\2\u00b1"+ + "\u00b2\7\u5208\2\2\u00b2\u00b4\7\u4e4d\2\2\u00b3\u00b0\3\2\2\2\u00b3\u00b1"+ + "\3\2\2\2\u00b4(\3\2\2\2\u00b5\u00b6\7\u53ca\2\2\u00b6*\3\2\2\2\u00b7\u00b8"+ + "\7\u5e75\2\2\u00b8\u00b9\7\u65bb\2\2\u00b9,\3\2\2\2\u00ba\u00bb\7\u7acd"+ + "\2\2\u00bb\u00bc\7\u65bb\2\2\u00bc.\3\2\2\2\u00bd\u00be\7\u6b23\2\2\u00be"+ + "\u00bf\7\u65bb\2\2\u00bf\60\3\2\2\2\u00c0\u00c1\7\u5f02\2\2\u00c1\u00c2"+ + "\7\u65bb\2\2\u00c2\62\3\2\2\2\u00c3\u00c4\7\u5f02\2\2\u00c4\u00c5\7\u5e75"+ + "\2\2\u00c5\u00c6\7\u65bb\2\2\u00c6\64\3\2\2\2\u00c7\u00c8\7\u5f02\2\2"+ + "\u00c8\u00c9\7\u7acd\2\2\u00c9\u00ca\7\u65bb\2\2\u00ca\66\3\2\2\2\u00cb"+ + "\u00cc\7\u7686\2\2\u00cc8\3\2\2\2\u00cd\u00ce\7\u683b\2\2\u00ce:\3\2\2"+ + "\2\u00cf\u00d0\t\4\2\2\u00d0<\3\2\2\2\u00d1\u00d2\t\5\2\2\u00d2>\3\2\2"+ + "\2\u00d3\u00d4\t\6\2\2\u00d4@\3\2\2\2\u00d5\u00d6\t\7\2\2\u00d6B\3\2\2"+ + "\2\u00d7\u00d8\7`\2\2\u00d8D\3\2\2\2\u00d9\u00db\t\b\2\2\u00da\u00d9\3"+ + "\2\2\2\u00dbF\3\2\2\2\u00dc\u00de\t\t\2\2\u00dd\u00dc\3\2\2\2\u00deH\3"+ + "\2\2\2\u00df\u00e1\t\n\2\2\u00e0\u00df\3\2\2\2\u00e1\u00e2\3\2\2\2\u00e2"+ + "\u00e0\3\2\2\2\u00e2\u00e3\3\2\2\2\u00e3\u00e4\3\2\2\2\u00e4\u00e5\b%"+ + "\2\2\u00e5J\3\2\2\2\26\2PW^gpy\u008e\u0097\u0099\u009e\u00a0\u00a5\u00a7"+ + "\u00ac\u00ae\u00b3\u00da\u00dd\u00e2\3\2\3\2"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/xing/calc/parser/grammer/calculatorParser.java b/app/src/main/java/org/xing/calc/parser/grammer/calculatorParser.java new file mode 100644 index 0000000..ce9a27b --- /dev/null +++ b/app/src/main/java/org/xing/calc/parser/grammer/calculatorParser.java @@ -0,0 +1,1014 @@ +// Generated from src/org/xing/calc/parser/grammer/calculator.g4 by ANTLR 4.6 +package org.xing.calc.parser.grammer; +import org.antlr.v4.runtime.FailedPredicateException; +import org.antlr.v4.runtime.NoViableAltException; +import org.antlr.v4.runtime.Parser; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.RuleContext; +import org.antlr.v4.runtime.RuntimeMetaData; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.TokenStream; +import org.antlr.v4.runtime.Vocabulary; +import org.antlr.v4.runtime.VocabularyImpl; +import org.antlr.v4.runtime.atn.ATN; +import org.antlr.v4.runtime.atn.ATNDeserializer; +import org.antlr.v4.runtime.atn.ParserATNSimulator; +import org.antlr.v4.runtime.atn.PredictionContextCache; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.tree.ParseTreeVisitor; +import org.antlr.v4.runtime.tree.TerminalNode; + +import java.util.List; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class calculatorParser extends Parser { + static { RuntimeMetaData.checkVersion("4.6", RuntimeMetaData.VERSION); } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + COS=1, SIN=2, TAN=3, ACOS=4, ASIN=5, ATAN=6, LN=7, LOG=8, LG=9, DUISHU=10, + GENHAO=11, KUOHAO=12, LPAREN=13, RPAREN=14, PLUS=15, MINUS=16, TIMES=17, + DIV=18, FRAC=19, YOU=20, PINGFANG=21, LIFANG=22, CIFANG=23, KAIFANG=24, + KAIPINGFANG=25, KAILIFANG=26, DE=27, GEN=28, DU=29, PAI=30, POINT=31, + E=32, POW=33, LETTER=34, DIGIT=35, WS=36; + public static final int + RULE_expression = 0, RULE_multiplyingExpression = 1, RULE_powExpression = 2, + RULE_atom = 3, RULE_function = 4, RULE_funcname = 5, RULE_funcnameEx = 6, + RULE_postFuncname = 7, RULE_number = 8; + public static final String[] ruleNames = { + "expression", "multiplyingExpression", "powExpression", "atom", "function", + "funcname", "funcnameEx", "postFuncname", "number" + }; + + private static final String[] _LITERAL_NAMES = { + null, null, null, null, null, null, null, "'ln'", "'log'", "'lg'", "'对数'", + "'根号'", null, "'('", "')'", null, null, null, null, null, "'又'", "'平方'", + "'立方'", "'次方'", "'开方'", "'开平方'", "'开立方'", "'的'", "'根'", null, null, null, + null, "'^'" + }; + private static final String[] _SYMBOLIC_NAMES = { + null, "COS", "SIN", "TAN", "ACOS", "ASIN", "ATAN", "LN", "LOG", "LG", + "DUISHU", "GENHAO", "KUOHAO", "LPAREN", "RPAREN", "PLUS", "MINUS", "TIMES", + "DIV", "FRAC", "YOU", "PINGFANG", "LIFANG", "CIFANG", "KAIFANG", "KAIPINGFANG", + "KAILIFANG", "DE", "GEN", "DU", "PAI", "POINT", "E", "POW", "LETTER", + "DIGIT", "WS" + }; + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + @Override + public String getGrammarFileName() { return "calculator.g4"; } + + @Override + public String[] getRuleNames() { return ruleNames; } + + @Override + public String getSerializedATN() { return _serializedATN; } + + @Override + public ATN getATN() { return _ATN; } + + public calculatorParser(TokenStream input) { + super(input); + _interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); + } + public static class ExpressionContext extends ParserRuleContext { + public List multiplyingExpression() { + return getRuleContexts(MultiplyingExpressionContext.class); + } + public MultiplyingExpressionContext multiplyingExpression(int i) { + return getRuleContext(MultiplyingExpressionContext.class,i); + } + public List PLUS() { return getTokens(calculatorParser.PLUS); } + public TerminalNode PLUS(int i) { + return getToken(calculatorParser.PLUS, i); + } + public List MINUS() { return getTokens(calculatorParser.MINUS); } + public TerminalNode MINUS(int i) { + return getToken(calculatorParser.MINUS, i); + } + public ExpressionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_expression; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof calculatorVisitor ) return ((calculatorVisitor)visitor).visitExpression(this); + else return visitor.visitChildren(this); + } + } + + public final ExpressionContext expression() throws RecognitionException { + ExpressionContext _localctx = new ExpressionContext(_ctx, getState()); + enterRule(_localctx, 0, RULE_expression); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(18); + multiplyingExpression(); + setState(23); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==PLUS || _la==MINUS) { + { + { + setState(19); + _la = _input.LA(1); + if ( !(_la==PLUS || _la==MINUS) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(20); + multiplyingExpression(); + } + } + setState(25); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class MultiplyingExpressionContext extends ParserRuleContext { + public List powExpression() { + return getRuleContexts(PowExpressionContext.class); + } + public PowExpressionContext powExpression(int i) { + return getRuleContext(PowExpressionContext.class,i); + } + public List TIMES() { return getTokens(calculatorParser.TIMES); } + public TerminalNode TIMES(int i) { + return getToken(calculatorParser.TIMES, i); + } + public List DIV() { return getTokens(calculatorParser.DIV); } + public TerminalNode DIV(int i) { + return getToken(calculatorParser.DIV, i); + } + public MultiplyingExpressionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_multiplyingExpression; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof calculatorVisitor ) return ((calculatorVisitor)visitor).visitMultiplyingExpression(this); + else return visitor.visitChildren(this); + } + } + + public final MultiplyingExpressionContext multiplyingExpression() throws RecognitionException { + MultiplyingExpressionContext _localctx = new MultiplyingExpressionContext(_ctx, getState()); + enterRule(_localctx, 2, RULE_multiplyingExpression); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(26); + powExpression(); + setState(31); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==TIMES || _la==DIV) { + { + { + setState(27); + _la = _input.LA(1); + if ( !(_la==TIMES || _la==DIV) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(28); + powExpression(); + } + } + setState(33); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class PowExpressionContext extends ParserRuleContext { + public List atom() { + return getRuleContexts(AtomContext.class); + } + public AtomContext atom(int i) { + return getRuleContext(AtomContext.class,i); + } + public List POW() { return getTokens(calculatorParser.POW); } + public TerminalNode POW(int i) { + return getToken(calculatorParser.POW, i); + } + public List DE() { return getTokens(calculatorParser.DE); } + public TerminalNode DE(int i) { + return getToken(calculatorParser.DE, i); + } + public List PINGFANG() { return getTokens(calculatorParser.PINGFANG); } + public TerminalNode PINGFANG(int i) { + return getToken(calculatorParser.PINGFANG, i); + } + public List LIFANG() { return getTokens(calculatorParser.LIFANG); } + public TerminalNode LIFANG(int i) { + return getToken(calculatorParser.LIFANG, i); + } + public List CIFANG() { return getTokens(calculatorParser.CIFANG); } + public TerminalNode CIFANG(int i) { + return getToken(calculatorParser.CIFANG, i); + } + public PowExpressionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_powExpression; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof calculatorVisitor ) return ((calculatorVisitor)visitor).visitPowExpression(this); + else return visitor.visitChildren(this); + } + } + + public final PowExpressionContext powExpression() throws RecognitionException { + PowExpressionContext _localctx = new PowExpressionContext(_ctx, getState()); + enterRule(_localctx, 4, RULE_powExpression); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(34); + atom(0); + setState(47); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==DE || _la==POW) { + { + setState(45); + _errHandler.sync(this); + switch (_input.LA(1)) { + case POW: + { + { + setState(35); + match(POW); + setState(36); + atom(0); + } + } + break; + case DE: + { + { + setState(37); + match(DE); + setState(43); + _errHandler.sync(this); + switch (_input.LA(1)) { + case COS: + case SIN: + case TAN: + case ACOS: + case ASIN: + case ATAN: + case LN: + case LOG: + case LG: + case DUISHU: + case GENHAO: + case KUOHAO: + case LPAREN: + case PLUS: + case MINUS: + case PAI: + case DIGIT: + { + { + setState(38); + atom(0); + setState(39); + match(CIFANG); + } + } + break; + case PINGFANG: + { + setState(41); + match(PINGFANG); + } + break; + case LIFANG: + { + setState(42); + match(LIFANG); + } + break; + default: + throw new NoViableAltException(this); + } + } + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(49); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class AtomContext extends ParserRuleContext { + public List number() { + return getRuleContexts(NumberContext.class); + } + public NumberContext number(int i) { + return getRuleContext(NumberContext.class,i); + } + public TerminalNode YOU() { return getToken(calculatorParser.YOU, 0); } + public TerminalNode FRAC() { return getToken(calculatorParser.FRAC, 0); } + public TerminalNode LPAREN() { return getToken(calculatorParser.LPAREN, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public TerminalNode RPAREN() { return getToken(calculatorParser.RPAREN, 0); } + public List KUOHAO() { return getTokens(calculatorParser.KUOHAO); } + public TerminalNode KUOHAO(int i) { + return getToken(calculatorParser.KUOHAO, i); + } + public FunctionContext function() { + return getRuleContext(FunctionContext.class,0); + } + public List atom() { + return getRuleContexts(AtomContext.class); + } + public AtomContext atom(int i) { + return getRuleContext(AtomContext.class,i); + } + public TerminalNode MINUS() { return getToken(calculatorParser.MINUS, 0); } + public TerminalNode PLUS() { return getToken(calculatorParser.PLUS, 0); } + public AtomContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_atom; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof calculatorVisitor ) return ((calculatorVisitor)visitor).visitAtom(this); + else return visitor.visitChildren(this); + } + } + + public final AtomContext atom() throws RecognitionException { + return atom(0); + } + + private AtomContext atom(int _p) throws RecognitionException { + ParserRuleContext _parentctx = _ctx; + int _parentState = getState(); + AtomContext _localctx = new AtomContext(_ctx, _parentState); + AtomContext _prevctx = _localctx; + int _startState = 6; + enterRecursionRule(_localctx, 6, RULE_atom, _p); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(69); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,5,_ctx) ) { + case 1: + { + setState(51); + number(); + } + break; + case 2: + { + setState(52); + number(); + setState(53); + match(YOU); + setState(54); + number(); + setState(55); + match(FRAC); + setState(56); + number(); + } + break; + case 3: + { + setState(58); + match(LPAREN); + setState(59); + expression(); + setState(60); + match(RPAREN); + } + break; + case 4: + { + setState(62); + match(KUOHAO); + setState(63); + expression(); + setState(64); + match(KUOHAO); + } + break; + case 5: + { + setState(66); + function(); + } + break; + case 6: + { + setState(67); + _la = _input.LA(1); + if ( !(_la==PLUS || _la==MINUS) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(68); + atom(1); + } + break; + } + _ctx.stop = _input.LT(-1); + setState(76); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,6,_ctx); + while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + if ( _parseListeners!=null ) triggerExitRuleEvent(); + _prevctx = _localctx; + { + { + _localctx = new AtomContext(_parentctx, _parentState); + pushNewRecursionContext(_localctx, _startState, RULE_atom); + setState(71); + if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)"); + setState(72); + match(FRAC); + setState(73); + atom(7); + } + } + } + setState(78); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,6,_ctx); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + unrollRecursionContexts(_parentctx); + } + return _localctx; + } + + public static class FunctionContext extends ParserRuleContext { + public FuncnameContext funcname() { + return getRuleContext(FuncnameContext.class,0); + } + public AtomContext atom() { + return getRuleContext(AtomContext.class,0); + } + public NumberContext number() { + return getRuleContext(NumberContext.class,0); + } + public PostFuncnameContext postFuncname() { + return getRuleContext(PostFuncnameContext.class,0); + } + public TerminalNode DE() { return getToken(calculatorParser.DE, 0); } + public FuncnameExContext funcnameEx() { + return getRuleContext(FuncnameExContext.class,0); + } + public FunctionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_function; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof calculatorVisitor ) return ((calculatorVisitor)visitor).visitFunction(this); + else return visitor.visitChildren(this); + } + } + + public final FunctionContext function() throws RecognitionException { + FunctionContext _localctx = new FunctionContext(_ctx, getState()); + enterRule(_localctx, 8, RULE_function); + int _la; + try { + setState(92); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,8,_ctx) ) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(79); + funcname(); + setState(80); + atom(0); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(82); + number(); + setState(84); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==DE) { + { + setState(83); + match(DE); + } + } + + setState(86); + postFuncname(); + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(88); + number(); + setState(89); + funcnameEx(); + setState(90); + atom(0); + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class FuncnameContext extends ParserRuleContext { + public TerminalNode COS() { return getToken(calculatorParser.COS, 0); } + public TerminalNode TAN() { return getToken(calculatorParser.TAN, 0); } + public TerminalNode SIN() { return getToken(calculatorParser.SIN, 0); } + public TerminalNode ACOS() { return getToken(calculatorParser.ACOS, 0); } + public TerminalNode ATAN() { return getToken(calculatorParser.ATAN, 0); } + public TerminalNode ASIN() { return getToken(calculatorParser.ASIN, 0); } + public TerminalNode LOG() { return getToken(calculatorParser.LOG, 0); } + public TerminalNode LN() { return getToken(calculatorParser.LN, 0); } + public TerminalNode LG() { return getToken(calculatorParser.LG, 0); } + public TerminalNode GENHAO() { return getToken(calculatorParser.GENHAO, 0); } + public TerminalNode DUISHU() { return getToken(calculatorParser.DUISHU, 0); } + public FuncnameContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_funcname; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof calculatorVisitor ) return ((calculatorVisitor)visitor).visitFuncname(this); + else return visitor.visitChildren(this); + } + } + + public final FuncnameContext funcname() throws RecognitionException { + FuncnameContext _localctx = new FuncnameContext(_ctx, getState()); + enterRule(_localctx, 10, RULE_funcname); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(94); + _la = _input.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << COS) | (1L << SIN) | (1L << TAN) | (1L << ACOS) | (1L << ASIN) | (1L << ATAN) | (1L << LN) | (1L << LOG) | (1L << LG) | (1L << DUISHU) | (1L << GENHAO))) != 0)) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class FuncnameExContext extends ParserRuleContext { + public TerminalNode DUISHU() { return getToken(calculatorParser.DUISHU, 0); } + public TerminalNode GENHAO() { return getToken(calculatorParser.GENHAO, 0); } + public FuncnameExContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_funcnameEx; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof calculatorVisitor ) return ((calculatorVisitor)visitor).visitFuncnameEx(this); + else return visitor.visitChildren(this); + } + } + + public final FuncnameExContext funcnameEx() throws RecognitionException { + FuncnameExContext _localctx = new FuncnameExContext(_ctx, getState()); + enterRule(_localctx, 12, RULE_funcnameEx); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(96); + _la = _input.LA(1); + if ( !(_la==DUISHU || _la==GENHAO) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class PostFuncnameContext extends ParserRuleContext { + public TerminalNode KAIFANG() { return getToken(calculatorParser.KAIFANG, 0); } + public TerminalNode KAIPINGFANG() { return getToken(calculatorParser.KAIPINGFANG, 0); } + public TerminalNode KAILIFANG() { return getToken(calculatorParser.KAILIFANG, 0); } + public TerminalNode PINGFANG() { return getToken(calculatorParser.PINGFANG, 0); } + public TerminalNode GEN() { return getToken(calculatorParser.GEN, 0); } + public TerminalNode LIFANG() { return getToken(calculatorParser.LIFANG, 0); } + public PostFuncnameContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_postFuncname; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof calculatorVisitor ) return ((calculatorVisitor)visitor).visitPostFuncname(this); + else return visitor.visitChildren(this); + } + } + + public final PostFuncnameContext postFuncname() throws RecognitionException { + PostFuncnameContext _localctx = new PostFuncnameContext(_ctx, getState()); + enterRule(_localctx, 14, RULE_postFuncname); + try { + setState(109); + _errHandler.sync(this); + switch (_input.LA(1)) { + case KAIFANG: + enterOuterAlt(_localctx, 1); + { + setState(98); + match(KAIFANG); + } + break; + case KAIPINGFANG: + enterOuterAlt(_localctx, 2); + { + setState(99); + match(KAIPINGFANG); + } + break; + case KAILIFANG: + enterOuterAlt(_localctx, 3); + { + setState(100); + match(KAILIFANG); + } + break; + case PINGFANG: + enterOuterAlt(_localctx, 4); + { + setState(101); + match(PINGFANG); + setState(103); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,9,_ctx) ) { + case 1: + { + setState(102); + match(GEN); + } + break; + } + } + break; + case LIFANG: + enterOuterAlt(_localctx, 5); + { + setState(105); + match(LIFANG); + setState(107); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,10,_ctx) ) { + case 1: + { + setState(106); + match(GEN); + } + break; + } + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class NumberContext extends ParserRuleContext { + public List DIGIT() { return getTokens(calculatorParser.DIGIT); } + public TerminalNode DIGIT(int i) { + return getToken(calculatorParser.DIGIT, i); + } + public TerminalNode POINT() { return getToken(calculatorParser.POINT, 0); } + public TerminalNode DU() { return getToken(calculatorParser.DU, 0); } + public TerminalNode PAI() { return getToken(calculatorParser.PAI, 0); } + public NumberContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_number; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof calculatorVisitor ) return ((calculatorVisitor)visitor).visitNumber(this); + else return visitor.visitChildren(this); + } + } + + public final NumberContext number() throws RecognitionException { + NumberContext _localctx = new NumberContext(_ctx, getState()); + enterRule(_localctx, 16, RULE_number); + int _la; + try { + int _alt; + setState(128); + _errHandler.sync(this); + switch (_input.LA(1)) { + case DIGIT: + enterOuterAlt(_localctx, 1); + { + { + setState(112); + _errHandler.sync(this); + _alt = 1; + do { + switch (_alt) { + case 1: + { + { + setState(111); + match(DIGIT); + } + } + break; + default: + throw new NoViableAltException(this); + } + setState(114); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,12,_ctx); + } while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ); + setState(122); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,14,_ctx) ) { + case 1: + { + setState(116); + match(POINT); + setState(118); + _errHandler.sync(this); + _alt = 1; + do { + switch (_alt) { + case 1: + { + { + setState(117); + match(DIGIT); + } + } + break; + default: + throw new NoViableAltException(this); + } + setState(120); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,13,_ctx); + } while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER ); + } + break; + } + setState(125); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,15,_ctx) ) { + case 1: + { + setState(124); + _la = _input.LA(1); + if ( !(_la==DU || _la==PAI) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + break; + } + } + } + break; + case PAI: + enterOuterAlt(_localctx, 2); + { + setState(127); + match(PAI); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) { + switch (ruleIndex) { + case 3: + return atom_sempred((AtomContext)_localctx, predIndex); + } + return true; + } + private boolean atom_sempred(AtomContext _localctx, int predIndex) { + switch (predIndex) { + case 0: + return precpred(_ctx, 6); + } + return true; + } + + public static final String _serializedATN = + "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3&\u0085\4\2\t\2\4"+ + "\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\3\2\3\2"+ + "\3\2\7\2\30\n\2\f\2\16\2\33\13\2\3\3\3\3\3\3\7\3 \n\3\f\3\16\3#\13\3\3"+ + "\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\5\4.\n\4\7\4\60\n\4\f\4\16\4\63\13"+ + "\4\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5"+ + "\3\5\3\5\5\5H\n\5\3\5\3\5\3\5\7\5M\n\5\f\5\16\5P\13\5\3\6\3\6\3\6\3\6"+ + "\3\6\5\6W\n\6\3\6\3\6\3\6\3\6\3\6\3\6\5\6_\n\6\3\7\3\7\3\b\3\b\3\t\3\t"+ + "\3\t\3\t\3\t\5\tj\n\t\3\t\3\t\5\tn\n\t\5\tp\n\t\3\n\6\ns\n\n\r\n\16\n"+ + "t\3\n\3\n\6\ny\n\n\r\n\16\nz\5\n}\n\n\3\n\5\n\u0080\n\n\3\n\5\n\u0083"+ + "\n\n\3\n\2\3\b\13\2\4\6\b\n\f\16\20\22\2\7\3\2\21\22\3\2\23\24\3\2\3\r"+ + "\3\2\f\r\3\2\37 \u0095\2\24\3\2\2\2\4\34\3\2\2\2\6$\3\2\2\2\bG\3\2\2\2"+ + "\n^\3\2\2\2\f`\3\2\2\2\16b\3\2\2\2\20o\3\2\2\2\22\u0082\3\2\2\2\24\31"+ + "\5\4\3\2\25\26\t\2\2\2\26\30\5\4\3\2\27\25\3\2\2\2\30\33\3\2\2\2\31\27"+ + "\3\2\2\2\31\32\3\2\2\2\32\3\3\2\2\2\33\31\3\2\2\2\34!\5\6\4\2\35\36\t"+ + "\3\2\2\36 \5\6\4\2\37\35\3\2\2\2 #\3\2\2\2!\37\3\2\2\2!\"\3\2\2\2\"\5"+ + "\3\2\2\2#!\3\2\2\2$\61\5\b\5\2%&\7#\2\2&\60\5\b\5\2\'-\7\35\2\2()\5\b"+ + "\5\2)*\7\31\2\2*.\3\2\2\2+.\7\27\2\2,.\7\30\2\2-(\3\2\2\2-+\3\2\2\2-,"+ + "\3\2\2\2.\60\3\2\2\2/%\3\2\2\2/\'\3\2\2\2\60\63\3\2\2\2\61/\3\2\2\2\61"+ + "\62\3\2\2\2\62\7\3\2\2\2\63\61\3\2\2\2\64\65\b\5\1\2\65H\5\22\n\2\66\67"+ + "\5\22\n\2\678\7\26\2\289\5\22\n\29:\7\25\2\2:;\5\22\n\2;H\3\2\2\2<=\7"+ + "\17\2\2=>\5\2\2\2>?\7\20\2\2?H\3\2\2\2@A\7\16\2\2AB\5\2\2\2BC\7\16\2\2"+ + "CH\3\2\2\2DH\5\n\6\2EF\t\2\2\2FH\5\b\5\3G\64\3\2\2\2G\66\3\2\2\2G<\3\2"+ + "\2\2G@\3\2\2\2GD\3\2\2\2GE\3\2\2\2HN\3\2\2\2IJ\f\b\2\2JK\7\25\2\2KM\5"+ + "\b\5\tLI\3\2\2\2MP\3\2\2\2NL\3\2\2\2NO\3\2\2\2O\t\3\2\2\2PN\3\2\2\2QR"+ + "\5\f\7\2RS\5\b\5\2S_\3\2\2\2TV\5\22\n\2UW\7\35\2\2VU\3\2\2\2VW\3\2\2\2"+ + "WX\3\2\2\2XY\5\20\t\2Y_\3\2\2\2Z[\5\22\n\2[\\\5\16\b\2\\]\5\b\5\2]_\3"+ + "\2\2\2^Q\3\2\2\2^T\3\2\2\2^Z\3\2\2\2_\13\3\2\2\2`a\t\4\2\2a\r\3\2\2\2"+ + "bc\t\5\2\2c\17\3\2\2\2dp\7\32\2\2ep\7\33\2\2fp\7\34\2\2gi\7\27\2\2hj\7"+ + "\36\2\2ih\3\2\2\2ij\3\2\2\2jp\3\2\2\2km\7\30\2\2ln\7\36\2\2ml\3\2\2\2"+ + "mn\3\2\2\2np\3\2\2\2od\3\2\2\2oe\3\2\2\2of\3\2\2\2og\3\2\2\2ok\3\2\2\2"+ + "p\21\3\2\2\2qs\7%\2\2rq\3\2\2\2st\3\2\2\2tr\3\2\2\2tu\3\2\2\2u|\3\2\2"+ + "\2vx\7!\2\2wy\7%\2\2xw\3\2\2\2yz\3\2\2\2zx\3\2\2\2z{\3\2\2\2{}\3\2\2\2"+ + "|v\3\2\2\2|}\3\2\2\2}\177\3\2\2\2~\u0080\t\6\2\2\177~\3\2\2\2\177\u0080"+ + "\3\2\2\2\u0080\u0083\3\2\2\2\u0081\u0083\7 \2\2\u0082r\3\2\2\2\u0082\u0081"+ + "\3\2\2\2\u0083\23\3\2\2\2\23\31!-/\61GNV^imotz|\177\u0082"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/xing/calc/parser/grammer/calculatorVisitor.java b/app/src/main/java/org/xing/calc/parser/grammer/calculatorVisitor.java new file mode 100644 index 0000000..263b9f1 --- /dev/null +++ b/app/src/main/java/org/xing/calc/parser/grammer/calculatorVisitor.java @@ -0,0 +1,67 @@ +// Generated from src/org/xing/calc/parser/grammer/calculator.g4 by ANTLR 4.6 +package org.xing.calc.parser.grammer; +import org.antlr.v4.runtime.tree.ParseTreeVisitor; + +/** + * This interface defines a complete generic visitor for a parse tree produced + * by {@link calculatorParser}. + * + * @param The return type of the visit operation. Use {@link Void} for + * operations with no return type. + */ +public interface calculatorVisitor extends ParseTreeVisitor { + /** + * Visit a parse tree produced by {@link calculatorParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitExpression(calculatorParser.ExpressionContext ctx); + /** + * Visit a parse tree produced by {@link calculatorParser#multiplyingExpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitMultiplyingExpression(calculatorParser.MultiplyingExpressionContext ctx); + /** + * Visit a parse tree produced by {@link calculatorParser#powExpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitPowExpression(calculatorParser.PowExpressionContext ctx); + /** + * Visit a parse tree produced by {@link calculatorParser#atom}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitAtom(calculatorParser.AtomContext ctx); + /** + * Visit a parse tree produced by {@link calculatorParser#function}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitFunction(calculatorParser.FunctionContext ctx); + /** + * Visit a parse tree produced by {@link calculatorParser#funcname}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitFuncname(calculatorParser.FuncnameContext ctx); + /** + * Visit a parse tree produced by {@link calculatorParser#funcnameEx}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitFuncnameEx(calculatorParser.FuncnameExContext ctx); + /** + * Visit a parse tree produced by {@link calculatorParser#postFuncname}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitPostFuncname(calculatorParser.PostFuncnameContext ctx); + /** + * Visit a parse tree produced by {@link calculatorParser#number}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitNumber(calculatorParser.NumberContext ctx); +} \ No newline at end of file diff --git a/app/src/main/java/org/xing/engine/BaiduSpeechEngine.java b/app/src/main/java/org/xing/engine/BaiduSpeechEngine.java new file mode 100644 index 0000000..8218737 --- /dev/null +++ b/app/src/main/java/org/xing/engine/BaiduSpeechEngine.java @@ -0,0 +1,105 @@ +package org.xing.engine; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.speech.RecognitionListener; +import android.speech.SpeechRecognizer; + +import com.baidu.speech.VoiceRecognitionService; + +import org.xing.utils.Logger; + +import java.util.ArrayList; + +/** + * Created by Administrator on 2017/3/8 0008. + */ + +public class BaiduSpeechEngine implements SpeechEngine{ + private Context ctx; + private SpeechListener listener; + private SpeechRecognizer speechRecognizer; + private InternalRecognitionListener _listener; + + public BaiduSpeechEngine(Context ctx) { + this.ctx = ctx; + speechRecognizer = SpeechRecognizer.createSpeechRecognizer( + ctx, new ComponentName(ctx, VoiceRecognitionService.class)); + } + + public void setSpeechListener(SpeechListener listener){ + this.listener = listener; + this._listener = new InternalRecognitionListener(listener); + speechRecognizer.setRecognitionListener(_listener); + } + + public void startListening() { + speechRecognizer.startListening(new Intent()); + } + + public void stopListening() { + speechRecognizer.stopListening(); + } + public void cancel() { + speechRecognizer.cancel(); + } + public void destroy() { + speechRecognizer.destroy(); + } + + private static class InternalRecognitionListener implements RecognitionListener { + private SpeechListener listener; + public InternalRecognitionListener(SpeechListener listener) { + this.listener = listener; + } + + public void onResults(Bundle results) { + ArrayList nbest = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); + StringBuilder expr = new StringBuilder(); + for (String w : nbest) { + expr.append(w); + } + + listener.onResults(expr.toString()); + } + + public void onReadyForSpeech(Bundle bundle) { + listener.onReadyForSpeech(); + } + + //会话发生错误回调接口 + public void onError(int error) { + listener.onError(error); + } + + //开始录音 + public void onBeginningOfSpeech() { + listener.onBeginningOfSpeech(); + } + + //音量值 + public void onRmsChanged(float rms){ + listener.onRmsChanged(rms/20); + } + + //结束录音 + public void onEndOfSpeech() { + listener.onEndOfSpeech(); + } + + + public void onPartialResults(Bundle partialResults) { + + } + + public void onEvent(int eventType, Bundle params) { + Logger.info("xing", String.valueOf(eventType)+": "+params.toString()); + } + + public void onBufferReceived(byte[] buffer) { + + } + }; +} diff --git a/app/src/main/java/org/xing/engine/IflySpeechEngine.java b/app/src/main/java/org/xing/engine/IflySpeechEngine.java new file mode 100644 index 0000000..592062d --- /dev/null +++ b/app/src/main/java/org/xing/engine/IflySpeechEngine.java @@ -0,0 +1,132 @@ +package org.xing.engine; + +import android.content.Context; +import android.os.Bundle; + +import com.iflytek.cloud.RecognizerListener; +import com.iflytek.cloud.RecognizerResult; +import com.iflytek.cloud.SpeechConstant; +import com.iflytek.cloud.SpeechError; +import com.iflytek.cloud.SpeechRecognizer; +import com.iflytek.cloud.SpeechUtility; + +import org.xing.android.MainActivity; +import org.xing.logger.impl.EventLogger; +import org.xing.utils.JsonParser; + +import static com.iflytek.cloud.ErrorCode.ERROR_AUDIO_RECORD; +import static com.iflytek.cloud.ErrorCode.ERROR_ENGINE_BUSY; +import static com.iflytek.cloud.ErrorCode.ERROR_NETWORK_TIMEOUT; +import static com.iflytek.cloud.ErrorCode.ERROR_NO_MATCH; +import static com.iflytek.cloud.ErrorCode.ERROR_NO_NETWORK; +import static com.iflytek.cloud.ErrorCode.ERROR_PERMISSION_DENIED; +import static com.iflytek.cloud.ErrorCode.MSP_ERROR_NO_DATA; + +/** + * Created by Administrator on 2017/3/8 0008. + */ + +public class IflySpeechEngine implements SpeechEngine{ + private Context ctx; + private SpeechListener listener; + private SpeechRecognizer speechRecognizer; + private InternalRecognizerListener _listener; + + private static EventLogger eventLogger; + + public IflySpeechEngine(Context ctx) { + this.ctx = ctx; + SpeechUtility.createUtility(ctx, SpeechConstant.APPID +"=585290e7"); + + speechRecognizer= SpeechRecognizer.createRecognizer(ctx, null); + speechRecognizer.setParameter(SpeechConstant.DOMAIN, "iat"); //{短信和日常用语:iat (默认) 视频:video 地图:poi 音乐:music + speechRecognizer.setParameter(SpeechConstant.LANGUAGE, "zh_cn"); + speechRecognizer.setParameter(SpeechConstant.ACCENT, "mandarin"); + speechRecognizer.setParameter(SpeechConstant.VAD_BOS, "10000"); //十秒超时 + speechRecognizer.setParameter(SpeechConstant.ASR_PTT, "0"); //不带标点 + + eventLogger = MainActivity.eventLogger; + } + + public void setSpeechListener(SpeechListener listener){ + this.listener = listener; + _listener = new InternalRecognizerListener(listener); + } + + public void startListening() { + speechRecognizer.startListening(_listener); + listener.onReadyForSpeech(); + } + + public void stopListening() { + speechRecognizer.stopListening(); + } + public void cancel() { + speechRecognizer.cancel(); + } + public void destroy() { + speechRecognizer.destroy(); + } + + private static class InternalRecognizerListener implements RecognizerListener{ + private SpeechListener listener; + public InternalRecognizerListener(SpeechListener listener) { + this.listener = listener; + } + public void onResult(RecognizerResult results, boolean isLast) { + String expr = JsonParser.parseIatResult(results.getResultString()); + listener.onResults(expr); + } + + //会话发生错误回调接口 + public void onError(SpeechError error) { + switch (error.getErrorCode()) { + case ERROR_AUDIO_RECORD: + listener.onError(android.speech.SpeechRecognizer.ERROR_AUDIO); + break; + case ERROR_ENGINE_BUSY: + listener.onError(android.speech.SpeechRecognizer.ERROR_RECOGNIZER_BUSY); + break; + case ERROR_PERMISSION_DENIED: + listener.onError(android.speech.SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS); + break; + case ERROR_NO_NETWORK: + listener.onError(android.speech.SpeechRecognizer.ERROR_NETWORK); + break; + case ERROR_NETWORK_TIMEOUT: + listener.onError(android.speech.SpeechRecognizer.ERROR_NETWORK_TIMEOUT); + break; + case ERROR_NO_MATCH: + listener.onError(android.speech.SpeechRecognizer.ERROR_NO_MATCH); + break; + case MSP_ERROR_NO_DATA: + listener.onError(android.speech.SpeechRecognizer.ERROR_SPEECH_TIMEOUT); + break; + default: + eventLogger.onEvent("ifly-error-"+error.getErrorCode()+": "+error.getErrorDescription()); + listener.onError(android.speech.SpeechRecognizer.ERROR_CLIENT); + break; + } + } + + //开始录音 + public void onBeginOfSpeech() { + listener.onBeginningOfSpeech(); + } + + //音量值0~30 + public void onVolumeChanged(int volume, byte[] data){ + listener.onRmsChanged((float)volume * 10); + } + + //结束录音 + public void onEndOfSpeech() { + listener.onEndOfSpeech(); + } + + //扩展用接口 + public void onEvent(int eventType, int arg1, int arg2, Bundle obj) { + + } + }; +} diff --git a/app/src/main/java/org/xing/engine/SpeechEngine.java b/app/src/main/java/org/xing/engine/SpeechEngine.java new file mode 100644 index 0000000..9d4c7b5 --- /dev/null +++ b/app/src/main/java/org/xing/engine/SpeechEngine.java @@ -0,0 +1,13 @@ +package org.xing.engine; + +/** + * Created by Administrator on 2017/3/8 0008. + */ + +public interface SpeechEngine { + void setSpeechListener(SpeechListener listener); + void startListening(); + void stopListening(); + void cancel(); + void destroy(); +} diff --git a/app/src/main/java/org/xing/engine/SpeechListener.java b/app/src/main/java/org/xing/engine/SpeechListener.java new file mode 100644 index 0000000..8254956 --- /dev/null +++ b/app/src/main/java/org/xing/engine/SpeechListener.java @@ -0,0 +1,20 @@ +package org.xing.engine; + +/** + * Created by Administrator on 2017/3/8 0008. + */ + +public interface SpeechListener{ + + void onReadyForSpeech(); + + void onBeginningOfSpeech(); + + void onRmsChanged(float rmsdB); + + void onEndOfSpeech(); + + void onError(int error); + + void onResults(String expr); +} diff --git a/app/src/main/java/org/xing/logger/AsyncLog.java b/app/src/main/java/org/xing/logger/AsyncLog.java new file mode 100644 index 0000000..6ca298f --- /dev/null +++ b/app/src/main/java/org/xing/logger/AsyncLog.java @@ -0,0 +1,35 @@ +package org.xing.logger; + +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * Created by Administrator on 2016/12/29 0029. + */ + +public class AsyncLog implements Log { + + private Log syncLog; + private ExecutorService executorService; + + public AsyncLog(Log log) { + this.syncLog = log; + executorService = Executors.newSingleThreadExecutor(); + } + + @Override + public boolean log(final Map params) { + executorService.submit(new Runnable() { + @Override + public void run() { + syncLog.log(params); + } + }); + return true; + } + + public static AsyncLog createAsyncHttpLog(String url) { + return new AsyncLog(new HttpLog(url)); + } +} diff --git a/app/src/main/java/org/xing/logger/HttpLog.java b/app/src/main/java/org/xing/logger/HttpLog.java new file mode 100644 index 0000000..432cc6e --- /dev/null +++ b/app/src/main/java/org/xing/logger/HttpLog.java @@ -0,0 +1,24 @@ +package org.xing.logger; + +import org.xing.utils.HttpUtil; + +import java.util.Map; + +/** + * Created by Administrator on 2016/12/29 0029. + */ + +public class HttpLog implements Log { + private String url; + public HttpLog(String url) { + this.url = url; + } + + + @Override + public boolean log(Map params) { + HttpUtil.doPost(this.url, params, "utf-8"); + + return true; + } +} diff --git a/app/src/main/java/org/xing/logger/Log.java b/app/src/main/java/org/xing/logger/Log.java new file mode 100644 index 0000000..0a10cee --- /dev/null +++ b/app/src/main/java/org/xing/logger/Log.java @@ -0,0 +1,11 @@ +package org.xing.logger; + +import java.util.Map; + +/** + * Created by Administrator on 2016/12/29 0029. + */ + +public interface Log { + boolean log(Map params); +} diff --git a/app/src/main/java/org/xing/logger/impl/EventLogger.java b/app/src/main/java/org/xing/logger/impl/EventLogger.java new file mode 100644 index 0000000..3f31d3b --- /dev/null +++ b/app/src/main/java/org/xing/logger/impl/EventLogger.java @@ -0,0 +1,53 @@ +package org.xing.logger.impl; + +import android.os.Build; + +import org.xing.logger.AsyncLog; +import org.xing.logger.Log; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by Administrator on 2017/2/21 0021. + */ + +public class EventLogger { + private String userId; + private String version; + private Log eventLogger; + + public EventLogger(String userId, String version, String url) { + this.userId = userId; + this.version = version; + eventLogger = AsyncLog.createAsyncHttpLog(url); + } + + /* + 常规计数事件 + */ + public void onEvent(String event) { + Map params = new HashMap<>(); + params.put("_eventType", 1); + params.put("version", version); + params.put("userId", userId); + params.put("model", Build.VERSION.SDK_INT + " " + Build.BRAND + " " + Build.MODEL); + params.put("event", event); + eventLogger.log(params); + } + + /* + 计算事件 + */ + public void onEvent(String result, String inputExpr, String readExpr, int type) { + Map params = new HashMap<>(); + params.put("_eventType", 2); + params.put("userId", userId); + params.put("version", version); + params.put("result", result); + params.put("inputExpr", inputExpr); + params.put("readExpr", readExpr == null ? "null" : readExpr); + params.put("type", type); + eventLogger.log(params); + } +} diff --git a/app/src/main/java/org/xing/share/ShareManager.java b/app/src/main/java/org/xing/share/ShareManager.java new file mode 100644 index 0000000..c5cbe5e --- /dev/null +++ b/app/src/main/java/org/xing/share/ShareManager.java @@ -0,0 +1,114 @@ +package org.xing.share; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Bundle; + +import com.tencent.connect.share.QQShare; +import com.tencent.connect.share.QzoneShare; +import com.tencent.mm.opensdk.modelmsg.SendMessageToWX; +import com.tencent.mm.opensdk.modelmsg.WXMediaMessage; +import com.tencent.mm.opensdk.modelmsg.WXWebpageObject; +import com.tencent.mm.opensdk.openapi.IWXAPI; +import com.tencent.mm.opensdk.openapi.WXAPIFactory; +import com.tencent.tauth.IUiListener; +import com.tencent.tauth.Tencent; +import com.tencent.tauth.UiError; + +import org.xing.android.MainActivity; +import org.xing.android.R; +import org.xing.logger.impl.EventLogger; + +import java.util.ArrayList; + +/** + * Created by Administrator on 2017/3/19 0019. + */ + +public class ShareManager { + private Activity activity; + + /* + 微信相关配置 + */ + private String weixinAppid; + private IWXAPI iwxapi; + + /* + QQ配置 + */ + private String qqAppid; + private Tencent mTencent; + + private EventLogger eventLogger; + + public ShareManager(Activity activity) { + eventLogger = MainActivity.eventLogger; + + this.activity = activity; + + weixinAppid = "wxf3bb46c3047a46dd"; + iwxapi = WXAPIFactory.createWXAPI(activity, weixinAppid, true); + iwxapi.registerApp(weixinAppid); + + qqAppid = "1105840771"; + mTencent = Tencent.createInstance(qqAppid, activity.getApplicationContext()); + } + + public void shareToWeixin(int flag) { + WXWebpageObject webpage = new WXWebpageObject(); + webpage.webpageUrl = activity.getString(R.string.shareUrl); + + WXMediaMessage msg = new WXMediaMessage(webpage); + msg.title = activity.getString(R.string.shareTitle); + msg.description = activity.getString(R.string.shareDesc); + + //这里替换一张自己工程里的图片资源 + Bitmap thumb = BitmapFactory.decodeResource(activity.getResources(), R.mipmap.share_icon); + msg.setThumbImage(thumb); + + SendMessageToWX.Req req = new SendMessageToWX.Req(); + req.transaction = String.valueOf(System.currentTimeMillis()); + req.message = msg; + req.scene = flag == 0? SendMessageToWX.Req.WXSceneSession:SendMessageToWX.Req.WXSceneTimeline; + eventLogger.onEvent(flag == 0? "weixinShare":"pengyouquanShare"); + iwxapi.sendReq(req); + } + + public void shareToQQ(int flag) { + final Bundle params = new Bundle(); + if(flag == 0) { + params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_DEFAULT); + params.putString(QQShare.SHARE_TO_QQ_TITLE, activity.getString(R.string.shareTitle)); + params.putString(QQShare.SHARE_TO_QQ_SUMMARY, activity.getString(R.string.shareDesc)); + params.putString(QQShare.SHARE_TO_QQ_TARGET_URL, activity.getString(R.string.shareUrl)); + params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, activity.getString(R.string.shareImage)); + params.putString(QQShare.SHARE_TO_QQ_APP_NAME, activity.getString(R.string.app_name)); + } else { + params.putInt(QzoneShare.SHARE_TO_QZONE_KEY_TYPE, QzoneShare.SHARE_TO_QZONE_TYPE_IMAGE_TEXT ); + params.putString(QzoneShare.SHARE_TO_QQ_TITLE, activity.getString(R.string.shareTitle)); + params.putString(QzoneShare.SHARE_TO_QQ_SUMMARY, activity.getString(R.string.shareDesc)); + params.putString(QzoneShare.SHARE_TO_QQ_TARGET_URL, activity.getString(R.string.shareUrl)); + ArrayList imageList = new ArrayList<>(); + imageList.add(activity.getString(R.string.shareImage)); + params.putStringArrayList(QzoneShare.SHARE_TO_QQ_IMAGE_URL, imageList); + } + + IUiListener defaultUiListener = new IUiListener() { + public void onComplete(Object var1){} + public void onError(UiError var1){} + public void onCancel() {} + }; + + if(flag == 0) { + eventLogger.onEvent("qqShare"); + mTencent.shareToQQ(activity, params, defaultUiListener); + } else { + eventLogger.onEvent("qzoneShare"); + mTencent.shareToQzone(activity, params, defaultUiListener); + } + } + +} diff --git a/app/src/main/java/org/xing/theme/Theme.java b/app/src/main/java/org/xing/theme/Theme.java new file mode 100644 index 0000000..36c0aff --- /dev/null +++ b/app/src/main/java/org/xing/theme/Theme.java @@ -0,0 +1,104 @@ +package org.xing.theme; + +import org.json.JSONObject; + +import java.util.LinkedList; +import java.util.List; + +/** + * Created by Administrator on 2017/3/1 0001. + */ + +public class Theme { + private String id; + private String name; + private JSONObject style; + private List imagePaths; + + public Theme () { + //默认全白色背景,黑色字体 + id = "0"; + name = "默认主题"; + style = null; + imagePaths = new LinkedList<>(); + } + + public Theme (String id, String name, String style, String imagePathStr) { + this.id = id; + this.name = name; + try { + this.style = new JSONObject(style); + }catch (Exception e) { } + imagePaths = new LinkedList<>(); + + if(imagePathStr != null) { + String[] fields = imagePathStr.split(";"); + for(String path : fields) { + if(path.length() > 0) { + imagePaths.add(path); + } + } + } + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + public String getStyle() { + return style.toString(); + } + public String getStyle(String name) { + try { + return style.getString(name); + }catch (Exception e) { } + return null; + } + + public void setStyle(String style) { + try { + this.style = new JSONObject(style); + }catch (Exception e) { } + imagePaths = new LinkedList<>(); + } + + public List getImagePaths() { + return imagePaths; + } + + public String getImagePathsStr() { + StringBuilder str= new StringBuilder(); + for(String path : imagePaths) { + if(str.length() > 0) { + str.append(";"); + } + str.append(path); + } + return str.toString(); + } + + public void setBackgroundImage(String imagePathStr) { + imagePaths.clear(); + + if(imagePathStr != null) { + String[] fields = imagePathStr.split(";"); + for(String path : fields) { + if(path.length() > 0) { + imagePaths.add(path); + } + } + } + } + +} diff --git a/app/src/main/java/org/xing/theme/ThemeChangeListener.java b/app/src/main/java/org/xing/theme/ThemeChangeListener.java new file mode 100644 index 0000000..29f4d52 --- /dev/null +++ b/app/src/main/java/org/xing/theme/ThemeChangeListener.java @@ -0,0 +1,10 @@ +package org.xing.theme; + +/** + * Created by Administrator on 2017/3/1 0001. + */ + +public interface ThemeChangeListener { + boolean isAlive(); + void onThemeChange(Theme theme); +} diff --git a/app/src/main/java/org/xing/theme/ThemeManager.java b/app/src/main/java/org/xing/theme/ThemeManager.java new file mode 100644 index 0000000..a7dc6c5 --- /dev/null +++ b/app/src/main/java/org/xing/theme/ThemeManager.java @@ -0,0 +1,173 @@ +package org.xing.theme; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; + +import org.xing.android.AppConfig; +import org.xing.android.MainActivity; +import org.xing.logger.impl.EventLogger; + +import java.util.LinkedList; +import java.util.List; + +/** + * Created by Administrator on 2017/3/1 0001. + */ + +public class ThemeManager { + private int nextTheme; + private SQLiteDatabase database; + private LinkedList listeners; + private EventLogger eventLogger; + + public ThemeManager(Context ctx) { + nextTheme = 0; + listeners = new LinkedList<>(); + eventLogger = MainActivity.eventLogger; + + try { + String databasePath = ctx.getFilesDir().getAbsolutePath() + "/theme.db"; + database = SQLiteDatabase.openOrCreateDatabase(databasePath, null); + + if(AppConfig.getIsFirstStart()) { + database.execSQL("drop table if exists themes"); + String createTableSql = "create table if not exists themes (" + + "id CHAR(32) PRIMARY KEY, " + + "name CHAR(32), " + + "style VARCHAR, " + + "img_paths VARCHAR" + + ")"; + database.execSQL(createTableSql); + }else { + database.delete("themes", null, null); + } + + addTheme(new Theme("0", "白色", "{'resultColor':'#000000', 'historyColor':'#444444', 'msgColor':'#555555', 'background':'#ffffff'}", null)); + addTheme(new Theme("1", "大鱼", "{'resultColor':'#FF3300', 'historyColor':'#ee3300', 'msgColor':'#aa3300'}", "theme/01.jpg")); + addTheme(new Theme("2", "银河", "{'resultColor':'#ffffff', 'historyColor':'#f0f0f0', 'msgColor':'#aaaaaa'}", "theme/02.jpg")); + addTheme(new Theme("3", "萌宠", "{'resultColor':'#ffa000', 'historyColor':'#ee9000', 'msgColor':'#cc7000'}", "theme/03.jpg")); + addTheme(new Theme("4", "雪景", "{'resultColor':'#3eb3ed', 'historyColor':'#2ea3dd', 'msgColor':'#ffa066'}", "theme/04.jpg")); + addTheme(new Theme("5", "银色", "{'resultColor':'#333333', 'historyColor':'#444444', 'msgColor':'#555555'}", "theme/05.jpg")); + }catch (Exception e) { + e.printStackTrace(); + database = null; + } + } + + public boolean addTheme(Theme theme) { + if(database == null) return false; + + ContentValues values = new ContentValues(); + values.put("id", theme.getId()); + values.put("name", theme.getName()); + values.put("style", theme.getStyle()); + values.put("img_paths", theme.getImagePathsStr()); + + try { + long result = database.insert("themes", null, values); + if (result > 0) return true; + }catch (Exception e) { + e.printStackTrace(); + } + + return false; + } + + public boolean deleteTheme(String id) { + if(database == null || id == null) return false; + + String whereClause = "id=?"; + String[] whereArgs = {id}; + try { + long result = database.delete("themes", whereClause, whereArgs); + if (result > 0) return true; + }catch (Exception e) { + e.printStackTrace(); + } + + return false; + } + + public boolean deleteTheme(Theme theme) { + return deleteTheme(theme.getId()); + } + + public Theme getTheme(String id) { + try { + Cursor cursor = database.rawQuery("select id, name, style, img_paths from themes where id='"+id+"'", null); + if(cursor.moveToFirst()) { + Theme theme = new Theme(cursor.getString(0), cursor.getString(1), + cursor.getString(2), cursor.getString(3)); + return theme; + } + }catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + public List getAllTheme() { + List themes = new LinkedList<>(); + try { + Cursor cursor = database.rawQuery("select id, name, style, img_paths from themes", null); + if(cursor.moveToFirst()) { + do { + Theme theme = new Theme(cursor.getString(0), cursor.getString(1), + cursor.getString(2), cursor.getString(3)); + themes.add(theme); + }while(cursor.moveToNext()); + } + }catch (Exception e) { + e.printStackTrace(); + } + + return themes; + } + + public void addThemeChangeListener(ThemeChangeListener listener) { + listeners.add(listener); + } + + public void applyTheme(String id) { + if(id == null) return; + + List themes = getAllTheme(); + nextTheme = 0; + for(Theme theme : themes) { + nextTheme ++; + if(theme.getId().equals(id)) { + break; + } + } + + applyTheme(getTheme(id)); + } + + public void applyTheme(Theme theme) { + if(theme == null) return; + for(ThemeChangeListener listener : listeners) { + if(listener.isAlive()) { + listener.onThemeChange(theme); + } + } + } + + public void randomTheme() { + eventLogger.onEvent("changeTheme"); + + List themes = getAllTheme(); + + if(themes.size() > 0) { + if(nextTheme >= themes.size()) { + nextTheme %= themes.size(); + } + + applyTheme( + themes.get(nextTheme++) + ); + } + } +} diff --git a/app/src/main/java/org/xing/update/UpdateEntity.java b/app/src/main/java/org/xing/update/UpdateEntity.java new file mode 100644 index 0000000..90a72cb --- /dev/null +++ b/app/src/main/java/org/xing/update/UpdateEntity.java @@ -0,0 +1,38 @@ +package org.xing.update; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.math.BigInteger; + +/** + * Created by sangbo on 16-5-19. + */ +public class UpdateEntity { + + public int versionCode = 0; + public int isForceUpdate = 0; + public int preBaselineCode = 0; + public String versionName = ""; + public String downUrl = ""; + public String updateLog = ""; + public BigInteger md5 = null; + public int fileSize = 0; + + + public UpdateEntity(String json) throws JSONException { + + JSONObject jsonObject = new JSONObject(json); + this.versionCode = jsonObject.getInt("versionCode"); + this.versionName = jsonObject.getString("versionName"); + this.isForceUpdate = jsonObject.getInt("isForceUpdate"); + this.downUrl = jsonObject.getString("downUrl"); + this.preBaselineCode = jsonObject.getInt("preBaselineCode"); + this.updateLog = jsonObject.getString("updateLog"); + String md5String = jsonObject.getString("md5"); + if(md5String != null) { + this.md5 = new BigInteger(md5String, 16); + } + this.fileSize = jsonObject.getInt("fileSize"); + } +} \ No newline at end of file diff --git a/app/src/main/java/org/xing/update/UpdateManager.java b/app/src/main/java/org/xing/update/UpdateManager.java new file mode 100644 index 0000000..720c80e --- /dev/null +++ b/app/src/main/java/org/xing/update/UpdateManager.java @@ -0,0 +1,295 @@ +package org.xing.update; + +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.net.Uri; +import android.os.Environment; +import android.os.Handler; +import android.text.TextUtils; +import android.util.Log; +import android.widget.Toast; + +import com.umeng.analytics.MobclickAgent; +import com.zhy.http.okhttp.OkHttpUtils; +import com.zhy.http.okhttp.callback.FileCallBack; +import com.zhy.http.okhttp.callback.StringCallback; + +import org.json.JSONException; +import org.xing.android.AppConfig; +import org.xing.android.MainActivity; +import org.xing.android.R; +import org.xing.logger.impl.EventLogger; +import org.xing.utils.NumberUtil; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.math.BigInteger; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.security.MessageDigest; + +import okhttp3.Call; + +/** + * app更新 + * Created by sangbo on 16-5-19. + */ +public class UpdateManager { + private static int mAppVersionCode = 0; + private static Context mContext; + private static ProgressDialog mAlertDialog; + private static boolean mIsEnforceCheck = false; + private static EventLogger eventLogger = null; + + public static String checkUrl = ""; + public static UpdateEntity mUpdateEntity; + + + public static void postUpdate(final Context context, int delaySecond) { + Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + @Override + public void run() { + if(AppConfig.getCheckUpdate()) { + mIsEnforceCheck = false; + update(context); + } + } + }, delaySecond*1000); + } + + public static void update(Context context){ + update(context,mIsEnforceCheck); + } + + public static void update(Context context, final boolean isEnforceCheck){ + mContext = context; + mIsEnforceCheck = isEnforceCheck; + mAppVersionCode = AppConfig.getVersionCode(); + + if(eventLogger == null) { + eventLogger = MainActivity.eventLogger; + } + + checkUrl = mContext.getString(R.string.updateCheckUrl); + if(TextUtils.isEmpty(checkUrl)){ + Toast.makeText(mContext, "url不能为空,请设置url", Toast.LENGTH_SHORT).show(); + return; + } + + OkHttpUtils.get().url(checkUrl).build().execute(new StringCallback() { + @Override + public void onError(Call call, Exception e) { + if(mIsEnforceCheck) + Toast.makeText(mContext, "更新失败,请检查网络", Toast.LENGTH_SHORT).show(); + } + + @Override + public void onResponse(String response) { + + loadOnlineData(response); + + } + }); + } + + private static void loadOnlineData(String json) { + try { + UpdateEntity updateEntity = new UpdateEntity(json); + if(updateEntity == null){ + if(mIsEnforceCheck) + Toast.makeText(mContext, "网络信息获取失败,请重试", Toast.LENGTH_SHORT).show(); + return; + } + mUpdateEntity = updateEntity; + + if(mAppVersionCode < mUpdateEntity.versionCode){ + //启动更新 + AlertUpdate(); + } else if(mIsEnforceCheck){ + AlertDialog.Builder builder = new AlertDialog.Builder(mContext); + builder.setTitle("更新"); + builder.setMessage("已是最新版本:"+AppConfig.getVersionName()); + builder.setPositiveButton("确定", null); + builder.show(); + } + } catch (JSONException e) { + MobclickAgent.reportError(mContext, e); + } + + } + + + private static void AlertUpdate(){ + + AlertDialog.Builder builder = new AlertDialog.Builder(mContext); + builder.setTitle("发现新版本"); + builder.setMessage("当前版本:" + AppConfig.getVersionName() + "\n" + + "新版本:" + mUpdateEntity.versionName + "\n" + + "大小:" + NumberUtil.getPrintSize(mUpdateEntity.fileSize) + "\n" + + mUpdateEntity.updateLog + "\n"); + builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + eventLogger.onEvent("updateConfirm"); + updateApp(); + } + }); + builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + eventLogger.onEvent("updateCancel"); + //选择取消之后,不再检查更新 + AppConfig.setCheckUpdate(false); + } + }); + builder.show(); + } + + private static void updateApp() { + updateApp(false); + } + + private static void updateApp(boolean isEnforceDown) { + String filePath = Environment.getExternalStorageDirectory().getAbsolutePath(); + String fileName = AppConfig.getPackageName() + mUpdateEntity.versionName +".apk"; + + if(!isEnforceDown){ + File file = new File(filePath+"/"+fileName); + if(file.exists()){ + install(file); + return; + } + } + + mAlertDialog = new ProgressDialog(mContext); + mAlertDialog.setTitle("更新("+mUpdateEntity.versionName+")"); + mAlertDialog.setMessage("正在下载最新版本..."); + mAlertDialog.setCancelable(false); + mAlertDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); + mAlertDialog.setProgress(0); + mAlertDialog.setMax(100); + mAlertDialog.setIndeterminate(false); + mAlertDialog.setProgressNumberFormat(""); + mAlertDialog.show(); + + OkHttpUtils.get().url(mUpdateEntity.downUrl).build().execute( + new FileCallBack( + filePath, + fileName) { + @Override + public void inProgress(float progress, long total) { + int downloadSize = (int)(progress * total); + if(downloadSize > mAlertDialog.getProgress() + 100 * 1024) { + mAlertDialog.setProgress((int)(100*progress)); + mAlertDialog.setProgressNumberFormat( + String.format("%s/%s", + NumberUtil.getPrintSize(downloadSize), + NumberUtil.getPrintSize(total)) + ); + } + } + + @Override + public void onError(Call call, Exception e) { + //下载失败,是否重试 + resterAlert(); + eventLogger.onEvent("updateError-"+e.getMessage()); + } + + @Override + public void onResponse(File file) { + //下载成功,开始安装 + install(file); + } + + @Override + public void onAfter() { + mAlertDialog.dismiss(); + } + }); + } + + + public static void install(File file) { + + if(!checkMD5(file)){ + md5Alert(); + return; + } + + eventLogger.onEvent("install"); + + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); + } + + private static void md5Alert() { + + AlertDialog.Builder builder = new AlertDialog.Builder(mContext); + builder.setTitle("提示"); + builder.setMessage("\n安装文件不完整,是否重新下载\n"); + builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + updateApp(true); + } + }); + builder.setNegativeButton("取消", null); + builder.show(); + } + + private static void resterAlert() { + AlertDialog.Builder builder = new AlertDialog.Builder(mContext); + builder.setTitle("提示"); + builder.setMessage("\n文件下载失败,是否重试?\n"); + builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + updateApp(); + } + }); + builder.setNegativeButton("取消", null); + builder.show(); + } + + private static boolean checkMD5(File file) { + BigInteger md5Value = null; + try { + md5Value = getMd5ByFile(file); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + Log.d("md5:",md5Value.toString(16)); + return md5Value != null && mUpdateEntity.md5 != null && md5Value.equals(mUpdateEntity.md5); + } + + public static BigInteger getMd5ByFile(File file) throws FileNotFoundException { + BigInteger value = null; + FileInputStream in = new FileInputStream(file); + try { + MappedByteBuffer byteBuffer = in.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length()); + MessageDigest md5 = MessageDigest.getInstance("MD5"); + md5.update(byteBuffer); + value = new BigInteger(1, md5.digest()); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if(null != in) { + try { + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return value; + } +} diff --git a/app/src/main/java/org/xing/utils/DeviceUtil.java b/app/src/main/java/org/xing/utils/DeviceUtil.java new file mode 100644 index 0000000..b325f31 --- /dev/null +++ b/app/src/main/java/org/xing/utils/DeviceUtil.java @@ -0,0 +1,39 @@ +package org.xing.utils; + +import android.app.Activity; +import android.content.Context; +import android.os.Build; +import android.telephony.TelephonyManager; + +import java.util.UUID; + +/** + * Created by Administrator on 2016/12/29 0029. + */ + +public class DeviceUtil { + public static String getUniqueId(Activity act) { + TelephonyManager tm = (TelephonyManager) act.getBaseContext().getSystemService(Context.TELEPHONY_SERVICE); + + String tmDevice, tmSerial, tmPhone, androidId; + + tmDevice = Build.BRAND; + tmSerial = Build.SERIAL; + androidId = Build.MODEL; + + try { + //部分机型这里会抛出异常 + tmDevice += tm.getDeviceId(); + tmSerial += tm.getSimSerialNumber(); + androidId += android.provider.Settings.Secure.getString( + act.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID); + }catch (Exception ex) { + ex.printStackTrace(); + } + + UUID deviceUuid = new UUID(androidId.hashCode(), ((long)tmDevice.hashCode() << 32) | tmSerial.hashCode()); + String uniqueId = deviceUuid.toString(); + + return uniqueId; + } +} diff --git a/app/src/main/java/org/xing/utils/HttpUtil.java b/app/src/main/java/org/xing/utils/HttpUtil.java new file mode 100644 index 0000000..96e5f44 --- /dev/null +++ b/app/src/main/java/org/xing/utils/HttpUtil.java @@ -0,0 +1,104 @@ +package org.xing.utils; + +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Collections; +import java.util.Map; +import java.util.Vector; + +/** + * Created by Administrator on 2016/12/29 0029. + */ + +public class HttpUtil { + public static String bytes2HexString(byte[] b) { + String ret = ""; + for (int i = 0; i < b.length; i++) { + String hex = Integer.toHexString(b[i] & 0xFF); + if (hex.length() == 1) { + hex = '0' + hex; + } + ret += hex.toUpperCase(); + } + return ret; + } + + public static String md5Encode(String str) + throws NoSuchAlgorithmException, UnsupportedEncodingException{ + MessageDigest md5=MessageDigest.getInstance("MD5"); + String newstr=bytes2HexString(md5.digest(str.getBytes("utf-8"))); + return newstr; + } + + public static String formPostParams(Map params, String charset, String secret) + throws UnsupportedEncodingException { + StringBuilder str = new StringBuilder(); + + Vector fields = new Vector<>(); + for(Map.Entry en : params.entrySet()) { + fields.add(URLEncoder.encode(en.getKey(), charset)+ + "="+URLEncoder.encode(en.getValue().toString(), charset)); + } + + Collections.sort(fields); + for(String field : fields) { + if(str.length() > 0) { + str.append("&"); + } + str.append(field); + } + + try { + String sign = md5Encode(str.toString()+secret); + str.append("&sign="+sign); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + + //System.out.println(str.toString()); + + return str.toString(); + } + + public static String doPost(String urlString, Map params, String charset) { + StringBuilder result = new StringBuilder(); + String secret = "862369397363725329"; + try{ + String bodyData = formPostParams(params, charset, secret); + + URL url = new URL(urlString); + HttpURLConnection urlConn=(HttpURLConnection)url.openConnection(); + urlConn.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); + urlConn.setDoOutput(true); + urlConn.setDoInput(true); + urlConn.setRequestMethod("POST"); + urlConn.setUseCaches(false); + urlConn.connect(); + + DataOutputStream out = new DataOutputStream(urlConn.getOutputStream()); + out.writeBytes(bodyData); + + String line = null; + BufferedReader reader = new BufferedReader( + new InputStreamReader(urlConn.getInputStream(), "utf-8")); + while((line = reader.readLine()) != null) { + result.append(line); + } + //System.out.println(result.toString()); + + out.flush(); + out.close(); + }catch(Exception e){ + e.printStackTrace(); + } + + return result.toString(); + } +} diff --git a/app/src/main/java/org/xing/utils/JsonParser.java b/app/src/main/java/org/xing/utils/JsonParser.java new file mode 100644 index 0000000..f01908e --- /dev/null +++ b/app/src/main/java/org/xing/utils/JsonParser.java @@ -0,0 +1,95 @@ +package org.xing.utils; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.json.JSONTokener; + +/** + * Json结果解析类 + */ +public class JsonParser { + + public static String parseIatResult(String json) { + StringBuffer ret = new StringBuffer(); + try { + JSONTokener tokener = new JSONTokener(json); + JSONObject joResult = new JSONObject(tokener); + + JSONArray words = joResult.getJSONArray("ws"); + for (int i = 0; i < words.length(); i++) { + // 转写结果词,默认使用第一个结果 + JSONArray items = words.getJSONObject(i).getJSONArray("cw"); + JSONObject obj = items.getJSONObject(0); + ret.append(obj.getString("w")); +// 如果需要多候选结果,解析数组其他字段 +// for(int j = 0; j < items.length(); j++) +// { +// JSONObject obj = items.getJSONObject(j); +// ret.append(obj.getString("w")); +// } + } + } catch (Exception e) { + e.printStackTrace(); + } + return ret.toString(); + } + + public static String parseGrammarResult(String json) { + StringBuffer ret = new StringBuffer(); + try { + JSONTokener tokener = new JSONTokener(json); + JSONObject joResult = new JSONObject(tokener); + + JSONArray words = joResult.getJSONArray("ws"); + for (int i = 0; i < words.length(); i++) { + JSONArray items = words.getJSONObject(i).getJSONArray("cw"); + for(int j = 0; j < items.length(); j++) + { + JSONObject obj = items.getJSONObject(j); + if(obj.getString("w").contains("nomatch")) + { + ret.append("没有匹配结果."); + return ret.toString(); + } + ret.append("【结果】" + obj.getString("w")); + ret.append("【置信度】" + obj.getInt("sc")); + ret.append("\n"); + } + } + } catch (Exception e) { + e.printStackTrace(); + ret.append("没有匹配结果."); + } + return ret.toString(); + } + + public static String parseLocalGrammarResult(String json) { + StringBuffer ret = new StringBuffer(); + try { + JSONTokener tokener = new JSONTokener(json); + JSONObject joResult = new JSONObject(tokener); + + JSONArray words = joResult.getJSONArray("ws"); + for (int i = 0; i < words.length(); i++) { + JSONArray items = words.getJSONObject(i).getJSONArray("cw"); + for(int j = 0; j < items.length(); j++) + { + JSONObject obj = items.getJSONObject(j); + if(obj.getString("w").contains("nomatch")) + { + ret.append("没有匹配结果."); + return ret.toString(); + } + ret.append("【结果】" + obj.getString("w")); + ret.append("\n"); + } + } + ret.append("【置信度】" + joResult.optInt("sc")); + + } catch (Exception e) { + e.printStackTrace(); + ret.append("没有匹配结果."); + } + return ret.toString(); + } +} diff --git a/app/src/main/java/org/xing/utils/Logger.java b/app/src/main/java/org/xing/utils/Logger.java new file mode 100644 index 0000000..c2e6ecd --- /dev/null +++ b/app/src/main/java/org/xing/utils/Logger.java @@ -0,0 +1,63 @@ +package org.xing.utils; + +import android.os.Handler; +import android.os.Message; +import android.util.Log; + + +/** + * Created by fujiayi on 2017/5/17. + */ + +public class Logger { + private static final String TAG = "Logger"; + + private static final String INFO = "INFO"; + + private static final String ERROR = "ERROR"; + + private static boolean ENABLE = true; + + private static Handler handler; + + public static void info(String message) { + info(TAG, message); + } + + public static void info(String tag, String message) { + log(INFO, tag, message); + } + + public static void error(String message) { + error(TAG, message); + } + + public static void error(String tag, String message) { + log(ERROR, tag, message); + } + + public static void setHandler(Handler handler) { + Logger.handler = handler; + } + + private static void log(String level, String tag, String message) { + if (!ENABLE) { + return; + } + if (level.equals(INFO)) { + Log.i(tag, message); + + } else if (level.equals(ERROR)) { + Log.e(tag, message); + } + if (handler != null) { + Message msg = Message.obtain(); + msg.obj = "[" + level + "]" + message + "\n"; + handler.sendMessage(msg); + } + } + + public static void setEnable(boolean isEnable) { + ENABLE = isEnable; + } +} diff --git a/app/src/main/java/org/xing/utils/NumberUtil.java b/app/src/main/java/org/xing/utils/NumberUtil.java new file mode 100644 index 0000000..39b046a --- /dev/null +++ b/app/src/main/java/org/xing/utils/NumberUtil.java @@ -0,0 +1,27 @@ +package org.xing.utils; + +/** + * Created by Administrator on 2016/12/30 0030. + */ + +public class NumberUtil { + public static String format(double num, int maxFloat) { + String text = String.format("%."+maxFloat+"f", num); + text = text.replaceAll("(\\.)?0*$", ""); + return text; + } + + public static String getPrintSize(long size) { + float printSize = (float)size / 1024/ 1024; + return String.format("%.1fMB", printSize); + } + + public static String toFraction(Double number) { + if(number == null || number.isNaN() || number.isInfinite()) { + return null; + } + StringBuilder frac = new StringBuilder(); + + return frac.toString(); + } +} diff --git a/app/src/main/res/drawable/backgroud.xml b/app/src/main/res/drawable/backgroud.xml new file mode 100644 index 0000000..0315c5e --- /dev/null +++ b/app/src/main/res/drawable/backgroud.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/boder.xml b/app/src/main/res/drawable/boder.xml new file mode 100644 index 0000000..41ef444 --- /dev/null +++ b/app/src/main/res/drawable/boder.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/btn_close_selector.xml b/app/src/main/res/drawable/btn_close_selector.xml new file mode 100644 index 0000000..2227656 --- /dev/null +++ b/app/src/main/res/drawable/btn_close_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/button.xml b/app/src/main/res/drawable/button.xml new file mode 100644 index 0000000..ac683fd --- /dev/null +++ b/app/src/main/res/drawable/button.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/image_selector.xml b/app/src/main/res/drawable/image_selector.xml new file mode 100644 index 0000000..085d5b5 --- /dev/null +++ b/app/src/main/res/drawable/image_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/record_progress.xml b/app/src/main/res/drawable/record_progress.xml new file mode 100644 index 0000000..8651eb2 --- /dev/null +++ b/app/src/main/res/drawable/record_progress.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/share_boder.xml b/app/src/main/res/drawable/share_boder.xml new file mode 100644 index 0000000..496c76f --- /dev/null +++ b/app/src/main/res/drawable/share_boder.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_help_selector.xml b/app/src/main/res/drawable/textview_help_selector.xml new file mode 100644 index 0000000..e102911 --- /dev/null +++ b/app/src/main/res/drawable/textview_help_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_share_selector.xml b/app/src/main/res/drawable/textview_share_selector.xml new file mode 100644 index 0000000..2e93313 --- /dev/null +++ b/app/src/main/res/drawable/textview_share_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..2466d37 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,247 @@ + + + + + + + + + + + + +