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";for(var s=0;s";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";for(var r=0;r";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 extends T> visitor) {
+ if ( visitor instanceof cmdVisitor ) return ((cmdVisitor extends T>)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 extends T> visitor) {
+ if ( visitor instanceof cmdVisitor ) return ((cmdVisitor extends T>)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 extends T> visitor) {
+ if ( visitor instanceof cmdVisitor ) return ((cmdVisitor extends T>)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 extends T> visitor) {
+ if ( visitor instanceof cmdVisitor ) return ((cmdVisitor extends T>)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 extends T> visitor) {
+ if ( visitor instanceof cmdVisitor ) return ((cmdVisitor extends T>)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 extends T> visitor) {
+ if ( visitor instanceof cmdVisitor ) return ((cmdVisitor extends T>)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 extends T> visitor) {
+ if ( visitor instanceof cmdVisitor ) return ((cmdVisitor extends T>)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 extends T> visitor) {
+ if ( visitor instanceof cmdVisitor ) return ((cmdVisitor extends T>)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 extends T> visitor) {
+ if ( visitor instanceof cmdVisitor ) return ((cmdVisitor extends T>)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 extends T> visitor) {
+ if ( visitor instanceof calculatorVisitor ) return ((calculatorVisitor extends T>)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 extends T> visitor) {
+ if ( visitor instanceof calculatorVisitor ) return ((calculatorVisitor extends T>)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 extends T> visitor) {
+ if ( visitor instanceof calculatorVisitor ) return ((calculatorVisitor extends T>)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 extends T> visitor) {
+ if ( visitor instanceof calculatorVisitor ) return ((calculatorVisitor extends T>)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 extends T> visitor) {
+ if ( visitor instanceof calculatorVisitor ) return ((calculatorVisitor extends T>)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 extends T> visitor) {
+ if ( visitor instanceof calculatorVisitor ) return ((calculatorVisitor extends T>)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 extends T> visitor) {
+ if ( visitor instanceof calculatorVisitor ) return ((calculatorVisitor extends T>)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 extends T> visitor) {
+ if ( visitor instanceof calculatorVisitor ) return ((calculatorVisitor extends T>)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 extends T> visitor) {
+ if ( visitor instanceof calculatorVisitor ) return ((calculatorVisitor extends T>)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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_simple_help.xml b/app/src/main/res/layout/activity_simple_help.xml
new file mode 100644
index 0000000..d5bf5a3
--- /dev/null
+++ b/app/src/main/res/layout/activity_simple_help.xml
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..a505548
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/btn_close.png b/app/src/main/res/mipmap-xhdpi/btn_close.png
new file mode 100644
index 0000000..d8132d0
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/btn_close.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/btn_close_click.png b/app/src/main/res/mipmap-xhdpi/btn_close_click.png
new file mode 100644
index 0000000..6154f23
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/btn_close_click.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/help_mark.png b/app/src/main/res/mipmap-xhdpi/help_mark.png
new file mode 100644
index 0000000..1d0895a
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/help_mark.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/help_mark_click.png b/app/src/main/res/mipmap-xhdpi/help_mark_click.png
new file mode 100644
index 0000000..7576c98
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/help_mark_click.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/input_ready.png b/app/src/main/res/mipmap-xhdpi/input_ready.png
new file mode 100644
index 0000000..8615859
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/input_ready.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/input_sleep.png b/app/src/main/res/mipmap-xhdpi/input_sleep.png
new file mode 100644
index 0000000..fdb216e
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/input_sleep.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/share_icon.png b/app/src/main/res/mipmap-xhdpi/share_icon.png
new file mode 100644
index 0000000..a60c6da
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/share_icon.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/share_mark.png b/app/src/main/res/mipmap-xhdpi/share_mark.png
new file mode 100644
index 0000000..cdb7a9e
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/share_mark.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/share_mark_click.png b/app/src/main/res/mipmap-xhdpi/share_mark_click.png
new file mode 100644
index 0000000..46273fc
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/share_mark_click.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/start.png b/app/src/main/res/mipmap-xhdpi/start.png
new file mode 100644
index 0000000..91b06b9
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/start.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/stop.png b/app/src/main/res/mipmap-xhdpi/stop.png
new file mode 100644
index 0000000..62839cd
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/stop.png differ
diff --git a/app/src/main/res/mipmap/socialize_qq.png b/app/src/main/res/mipmap/socialize_qq.png
new file mode 100644
index 0000000..486d55c
Binary files /dev/null and b/app/src/main/res/mipmap/socialize_qq.png differ
diff --git a/app/src/main/res/mipmap/socialize_qzone.png b/app/src/main/res/mipmap/socialize_qzone.png
new file mode 100644
index 0000000..754597b
Binary files /dev/null and b/app/src/main/res/mipmap/socialize_qzone.png differ
diff --git a/app/src/main/res/mipmap/socialize_wechat.png b/app/src/main/res/mipmap/socialize_wechat.png
new file mode 100644
index 0000000..927952e
Binary files /dev/null and b/app/src/main/res/mipmap/socialize_wechat.png differ
diff --git a/app/src/main/res/mipmap/socialize_wxcircle.png b/app/src/main/res/mipmap/socialize_wxcircle.png
new file mode 100644
index 0000000..f942544
Binary files /dev/null and b/app/src/main/res/mipmap/socialize_wxcircle.png differ
diff --git a/app/src/main/res/raw/token b/app/src/main/res/raw/token
new file mode 100644
index 0000000..11a4d0b
--- /dev/null
+++ b/app/src/main/res/raw/token
@@ -0,0 +1,401 @@
+A a 阿啊
+AI ai 哎哀埃挨唉癌矮蔼艾爱嫒暧隘碍
+AN an 安氨鞍庵鹌铵俺埯岸按案暗
+ANG ang 肮昂盎
+AO ao 凹遨嗷獒熬翱拗袄坳傲奥澳懊
+BA ba 八扒叭巴芭吧疤捌拔跋把爸罢粑
+BAI bai 掰白百佰伯柏摆败拜
+BAN ban 扳颁班斑般搬板版办半伴扮瓣
+BANG bang 邦帮梆绑榜膀棒谤磅镑
+BAO bao 包苞胞剥煲薄饱宝保堡报抱暴瀑曝爆
+BET bet 杯卑碑背悲北贝备倍焙被辈臂
+BEN ben 奔本苯笨
+BENG beng 崩嘣甭绷泵迸蚌蹦
+BI bi 逼鼻比彼笔鄙币必毕闭敝弊辟壁避碧
+BIAN bian 边编鞭贬扁匾变便遍辩
+BIAO biao 标彪膘表婊裱鳔
+BIE bie 瘪憋鳖别
+BIN bin 宾滨缤彬斌濒殡鬓
+BING bing 冰并兵丙柄炳秉饼屏禀摒病
+BO bo 拨波玻菠剥播伯泊魄驳勃脖博搏薄卜
+BU bu 补捕哺堡不布怖步部埠簿
+CA ca 拆擦嚓
+CAI cai 猜才材财裁采彩睬踩菜蔡
+CAN can 参餐残蚕惭惨灿
+CANG cang 仓苍沧舱藏
+CAO cao 操糙曹嘈草
+CE ce 册厕侧测策
+CEN cen 参
+CENG ceng 噌层曾蹭
+CHA cha 叉杈差插喳茬茶搽查碴察衩岔
+CHAI chai 拆钗差柴豺
+CHAN chan 掺搀婵谗馋潺缠产铲阐忏颤
+CHANG chang 昌猖长场肠尝偿常厂敞畅倡唱
+CHAO chao 抄吵钞超朝嘲潮炒
+CHE che 车尺扯彻掣撤
+CHEN chen 抻琛臣辰晨尘沉陈碜衬称趁
+CHENG cheng 称铛撑成诚城丞呈程承乘惩澄逞秤
+CHI chi 吃痴池驰迟持匙尺齿耻斥赤翅
+CHONG chong 冲充虫重崇宠
+CHOU chou 抽仇筹酬愁丑瞅臭
+CHU chu 出初雏除厨锄处储楚畜触
+CHUAI chuai 揣踹嘬
+CHUAN chuan 川穿传船喘串钏
+CHUANG chuang 创疮窗床闯
+CHUI chui 吹炊垂捶锤槌
+CHUN chun 春纯唇淳鹑醇蠢
+CHUO chuo 戳龊辍绰
+CI ci 刺词祠雌瓷兹慈磁辞此次伺赐
+CONG cong 匆葱苁聪从丛淙
+COU cou 凑
+CU cu 粗猝促醋簇
+CUAN cuan 氽撺蹿攒窜篡
+CUI cui 崔催摧脆萃啐淬粹翠
+CUN cun 村存寸
+CUO cuo 搓蹉撮矬挫措错
+DA da 搭答达打大瘩
+DAI dai 呆待歹逮傣代贷袋殆怠带戴
+DAN dan 丹担单眈耽胆旦但诞淡氮弹蛋
+DANG dang 当裆挡党档荡
+DAO dao 叨刀倒导岛捣祷蹈到盗悼道稻
+DE de 得德地的
+DENG deng 灯登等邓凳澄瞪
+DI di 低堤滴笛敌涤嘀坻抵底地弟递第帝缔
+DIAN dian 掂颠典碘点踮电佃店惦垫奠殿
+DIAO diao 刁叼凋碉雕貂吊钓调掉
+DIE die 爹跌谍喋牒碟蝶叠
+DING ding 丁叮盯钉顶鼎订定锭
+DIU diu 丢
+DONG dong 东冬董懂动冻栋洞
+DOU dou 都兜斗抖蚪陡豆逗痘
+DU du 都嘟督毒独读渎肚堵赌睹杜妒度渡镀
+DUAN duan 端短段缎煅锻断
+DUI dui 堆队对兑碓
+DUN dun 吨敦墩蹲盹囤炖钝顿盾遁
+DUO duo 多哆掇夺朵垛躲驮舵堕惰
+E e 阿讹俄哦娥鹅额恶厄扼饿鄂遏噩
+EN en 恩
+ER er 儿而尔耳饵二贰
+FA fa 发乏伐阀筏罚法
+FAN fan 帆番翻凡矾烦繁反返犯范饭贩泛
+FANG fang 方坊芳防妨房仿访纺放
+FEI fei 飞妃非啡肥匪诽翡肺沸费废痱
+FEN fen 分芬纷氛坟汾焚粉份忿奋愤粪
+FENG feng 丰风疯封峰烽锋蜂逢缝讽凤奉俸
+FO fo 佛
+FOU fou 否
+FU fu 夫肤麸孵敷扶芙拂伏茯袱俘浮符服幅辐福父斧釜抚辅脯府俯腑腐赴付附负妇复腹覆副富赋傅缚咐
+GA ga 旮嘎尬
+GAI gai 该改丐钙盖溉概
+GAN gan 干杆肝矸竿甘泔柑秆赶擀敢感赣
+GANG gang 冈刚岗纲钢肛缸罡港杠
+GAO gao 皋高膏篙羔糕睾搞镐稿告诰锆
+GE ge 戈圪疙咯胳搁哥歌鸽割革蛤阁格隔葛个各
+GEI gei 给
+GEN gen 根跟
+GENG geng 更庚耕羹埂哽梗耿
+GONG gong 工功攻弓躬公供宫恭巩拱共贡
+GOU gou 勾沟钩佝枸篝苟狗构购垢够
+GU gu 估咕沽姑辜孤骨箍古谷股鼓故固顾雇
+GUA gua 瓜呱刮剐寡卦挂褂
+GUAI guai 乖掴拐怪
+GUAN guan 关观官倌棺冠鳏莞馆管贯惯灌罐
+GUANG guang 光咣广犷逛
+GUI gui 归圭闺硅龟规瑰轨诡鬼癸柜刽贵桂跪
+GUN gun 滚磙辊棍
+GUO guo 锅郭蝈聒国帼果裹椁过
+HA ha 哈蛤
+HAI hai 咳还孩骸海亥害
+HAN han 鼾酣憨汗含函涵韩寒罕喊汉旱捍悍焊撼憾翰瀚
+HANG hang 夯行吭杭航巷
+HAO hao 蒿号蚝毫嗥豪壕嚎好郝耗浩皓
+HE he 呵喝禾和合盒何河核阖貉吓贺荷褐赫鹤壑
+HEI hei 黑嘿
+HEN hen 痕很狠恨
+HENG heng 亨哼恒衡横
+HONG hong 轰哄烘弘红虹鸿宏洪
+HOU hou 侯喉猴吼后厚候
+HU hu 乎呼忽糊囫狐弧胡葫湖蝴壶虎唬琥浒互户护沪
+HUA hua 华哗花划骅猾滑化桦画话
+HUAI huai 怀徊淮槐坏
+HUAN huan 欢獾还环寰缓幻换唤涣焕宦浣患
+HUANG huang 荒慌皇凰遑徨惶黄潢恍晃幌谎
+HUI hui 灰诙恢挥晖辉徽回茴悔毁卉汇会荟绘烩讳诲晦贿彗慧秽惠
+HUN hun 昏婚荤浑馄魂混
+HUO huo 豁和活火伙或惑货获祸霍藿
+JI ji 几讥饥机肌击圾芨鸡奇犄畸唧积姬基稽缉跻激及汲级极吉即亟急疾蒺嫉集辑瘠藉籍己纪挤济给脊戟计记纪忌伎技妓系际季悸剂迹既暨继寄祭寂绩稷鲫冀
+JIA jia 加枷嘉夹佳家甲钾贾假价驾架嫁稼
+JIAN jian 戋浅笺溅尖奸歼坚间肩艰监兼菅渐煎缄拣茧柬俭捡检减碱剪简见舰件涧饯贱践建健毽键荐剑鉴箭
+JIANG jiang 江将浆姜僵疆讲奖蒋匠降酱犟
+JIAO jiao 交郊茭姣胶跤浇娇骄教椒焦蕉礁嚼角侥狡饺绞铰矫脚搅缴剿叫轿觉校较酵窖
+JIE jie 节阶皆结秸接揭街劫杰桀拮洁捷睫竭截姐解介芥界戒诫届借
+JIN jin 巾斤今金津筋禁襟仅尽紧谨锦仅进近靳妗劲晋浸
+JING jing 茎经京惊荆睛精旌晶兢井阱颈景儆警劲径痉净静竞竟境镜靖敬
+JIONG jiong 迥窘
+JIU jiu 纠赳究阄揪九久玖灸韭酒旧臼舅咎救就
+JU ju 车拘驹居据锯掬鞠局菊橘矩咀举巨拒炬距句具俱惧剧聚
+JUAN juan 捐涓娟鹃圈卷倦眷绢
+JUE jue 决诀抉角觉绝倔掘厥镢
+JUN jun 军均钧君菌俊峻骏竣郡
+KA ka 咖喀卡咔咯
+KAI kai 开揩凯楷慨忾
+KAN kan 刊看勘堪坎砍侃瞰
+KANG kang 康慷糠扛亢伉抗炕
+KAO kao 考拷烤铐犒靠
+KE ke 坷苛柯科蝌棵稞颗磕瞌壳咳可渴克刻恪客课嗑
+KEI kei 克
+KEN ken 肯啃垦恳
+KENG keng 坑吭铿
+KONG kong 空孔恐控
+KOU kou 抠囗叩扣寇蔻
+KU ku 枯骷哭窟苦库裤酷
+KUA kua 夸垮挎胯跨
+KUAI kuai 会脍块快筷
+KUAN kuan 宽髋款
+KUANG kuang 匡诓哐筐狂诳旷矿况框眶
+KUI kui 亏盔窥奎逵馗魁葵睽傀匮馈溃愧
+KUN kun 坤昆捆困
+KUO kuo 括阔扩廓
+LA la 垃拉啦旯喇辣落腊蜡
+LAI lai 来睐赖癞
+LAN lan 兰拦栏岚婪阑澜蓝褴篮览揽缆懒烂滥
+LANG lang 啷郎廊榔螂狼琅朗浪
+LAO lao 捞劳唠痨牢醪老佬姥络烙落酪涝
+LE le 肋勒乐了
+LEI lei 勒累雷擂垒磊肋泪类嘞
+LENG leng 塄棱冷愣
+LI li 哩丽厘离漓篱梨犁黎蠡礼李里娌理鲤力荔历沥雳厉励立莅粒笠吏利莉痢例唳隶栗蜊璃
+LIA lia 俩
+LIAN lian 连莲涟怜帘联廉镰敛脸练炼恋链
+LIANG liang 良粮凉梁粱量两亮谅晾踉辆靓
+LIAO liao 撩辽疗聊僚獠潦缭燎寥了料撂镣
+LIE lie 咧裂列冽烈趔劣猎
+LIN lin 拎邻林淋琳霖临粼磷鳞麟凛檩吝蔺躏
+LING ling 伶玲铃翎羚零龄灵棂凌陵菱绫岭领另令
+LIU liu 溜熘刘浏留馏瘤流琉柳六遛
+LONG long 龙茏咙珑胧聋笼隆陇拢垄弄
+LOU lou 搂喽楼耧髅篓陋瘘漏露
+LU lu 撸噜卢颅芦庐炉卤虏掳鲁陆录绿禄碌赂鹿辘麓路潞鹭露
+LUU luu 驴吕侣铝旅偻屡缕履律虑滤率绿
+LUAN luan 峦孪挛鸾銮卵乱
+LUUE luue 掠略
+LUN lun 抡仑伦论沦轮
+LUO luo 捋罗逻锣骡螺裸骆络烙落摞漯
+MA ma 妈蚂抹摩吗麻马玛码骂么嘛蟆
+MAI mai 埋买迈麦卖脉
+MAN man 埋蛮蔓馒瞒满曼谩幔漫慢
+MANG mang 芒忙盲氓茫莽
+MAO mao 猫毛髦矛茅锚卯铆耄茂冒帽贸貌
+ME me 么
+MEI mei 没玫枚眉莓梅酶霉媒煤每美镁妹昧寐魅袂媚
+MEN men 闷门焖懑们
+MENG meng 蒙萌盟檬朦瞢猛锰懵孟梦
+MI mi 咪眯弥迷谜醚糜米靡觅泌秘密蜜
+MIAN mian 眠绵棉免勉娩冕缅腼面
+MIAO miao 喵苗描瞄秒渺缈藐妙庙
+MIE mie 咩灭蔑篾
+MIN min 民岷皿闵悯闽抿泯敏
+MING ming 名铭明鸣冥瞑酩命
+MIU miu 谬
+MO mo 末摸谋馍摹模膜麽摩磨蘑魔抹茉沫没殁陌脉莫漠寞墨默
+MOU mou 哞牟眸谋缪某
+MU mu 模母拇姆牡亩木沐目苜牧募墓幕暮慕睦穆
+NA na 拿哪那娜呐纳钠衲捺
+NAI nai 乃奶奈萘耐
+NAN nan 囝囡男南喃楠难腩
+NANG nang 囊囔馕攮
+NAO nao 孬挠铙蛲垴恼脑闹淖
+NE ne 哪讷呢
+NEI nei 哪馁内那
+NEN nen 恁嫩
+NENG neng 能
+NI ni 妮尼呢泥倪霓拟你昵逆匿腻溺
+NIAN nian 拈蔫年粘黏鲶捻辇撵碾廿念
+NIANG niang 娘酿
+NIAO niao 鸟袅嬲尿溺
+NIE nie 捏涅聂嗫镊蹑臬镍孽蘖
+NIN nin 您
+NING ning 宁拧咛狞柠凝泞佞
+NIU niu 妞牛扭忸纽钮拗
+NONG nong 农侬哝浓脓弄
+Nu nu 奴孥驽努弩怒
+NUU nuu 女恧衄
+NUAN nuan 暖
+NUUE nuue 疟虐
+NUO nuo 挪诺喏搦懦糯
+O o 噢哦
+OU ou 讴瓯欧殴鸥呕偶藕沤怄
+PA pa 趴啪葩扒杷爬耙琶帕怕
+PAI pai 拍排徘牌迫哌派湃
+PAN pan 番潘攀胖盘磐蟠判叛畔盼
+PANG pang 乓滂彷庞旁膀磅螃耪胖
+PAO pao 抛泡刨咆狍炮袍跑庖
+PEI pei 呸胚醅陪培赔锫裴沛霈帔佩配
+PEN pen 喷盆
+PENG peng 抨怦砰烹嘭澎朋棚硼鹏彭膨蓬篷捧碰
+PI pi 丕邳坯批纰砒披劈噼霹皮陂疲枇毗蚍琵貔郫埤啤脾匹否痞擗癖屁媲睥辟僻
+PIAN pian 片扁偏篇翩便骈谝骗
+PIAO piao 剽漂缥飘朴嫖瓢殍瞟票嘌骠
+PIE pie 撇瞥
+PIN pin 拚拼姘贫频嫔品骋
+PING ping 乒娉平评坪苹萍凭屏瓶
+PO po 朴陂坡颇泊泼婆鄱叵迫珀粕魄破
+POU pou 剖
+PU pu 仆扑铺噗匍葡莆脯蒲菩璞濮朴埔圃浦普谱蹼堡瀑曝
+QI qi 七柒沏妻凄萋栖戚嘁期欺蹊漆齐脐祁祈芪祗岐歧其萁棋祺旗麒奇崎骑琦耆鳍畦乞岂杞起企启绮稽气汽讫迄弃妻泣亟契砌器憩荠
+QIA qia 掐卡洽恰髌
+QIAN qian 千仟阡扦迁钎签牵铅谦骞黔前虔钱钳掮乾潜浅遣谴欠芡嵌纤茜倩堑慊歉
+QIANG qiang 呛枪戗羌腔锵强墙蔷抢襁炝跄
+QIAO qiao 悄跷雀锹敲橇乔侨荞桥翘谯憔樵瞧巧壳俏峭鞘窍
+QIE qie 切伽茄且窃郄妾怯挈锲惬趄慊
+QIN qin 钦侵亲芹芩琴秦禽擒噙勤寝沁
+QING qing 青圊清蜻轻氢倾卿情晴擎顷请謦庆亲箐磬
+QIONG qiong 穷穹琼
+QIU qiu 丘邱蚯秋囚泅求俅逑球酋糗
+QU qu 区岖驱躯曲蛐诎屈祛蛆趋渠取娶龋去趣觑
+QUAN quan 圈权全痊醛泉拳蜷劝券
+QUE que 鹊炔缺瘸却确雀榷
+QUN qun 裙群
+RAN ran 髯然燃冉染
+RANG rang 嚷穰瓤壤攘让
+RAO rao 饶娆扰绕
+RE re 喏惹热
+REN ren 人壬任仁忍荏稔刃仞纫韧轫认任饪妊葚
+RENG reng 扔仍
+RI ri 日
+RONG rong 戎绒茸荣嵘容蓉溶榕熔融
+ROU rou 柔揉蹂鞣肉
+RU ru 如茹儒濡孺蠕汝乳辱入褥
+RUAN ruan 阮软
+RUI rui 蕊芮锐瑞睿
+RUN run 闰润
+RUO ruo 若偌弱
+SA sa 仨撒洒卅飒萨挲
+SAI sai 腮鳃塞噻赛
+SAN san 三叁伞散馓糁
+SANG sang 丧桑搡嗓
+SAO sao 搔骚缫臊扫嫂埽瘙
+SE se 色涩啬瑟塞
+SEN sen 森
+SENG seng 僧
+SHA sha 杀刹沙莎痧裟鲨纱砂煞啥傻厦霎
+SHAI shai 筛色晒
+SHAN shan 山舢杉衫删姗珊栅跚苫扇煽膻闪陕讪汕疝单骟善缮膳鳝擅嬗赡蟮
+SHANG shang 伤殇商墒上垧晌赏尚绱裳
+SHAO shao 捎梢稍筲艄鞘烧勺芍苕韶少邵劭绍哨
+SHE she 奢赊畲猞舌折佘蛇舍设社射麝涉赦摄慑歙
+SHEI shei 谁
+SHEN shen 申伸呻绅砷身参糁莘娠深什甚神沈审婶肾甚渗蜃慎
+SHENG sheng 升生牲笙甥声绳省圣胜晟盛剩嵊
+SHI shi 尸失师狮诗虱施湿嘘识十什石时识实拾食蚀史驶矢豕使始屎士仕氏舐示世市柿式试拭弑似势事侍峙恃饰视是适室逝誓莳释谥嗜噬螫匙
+SHOU shou 收熟手守首寿受授绶狩售兽瘦
+SHU shu 书戍抒纾舒枢叔菽淑姝殊梳疏蔬输秫孰塾熟赎暑署薯曙黍属蜀鼠数术述戍束树竖腧恕庶墅漱澍
+SHUA shua 刷唰耍
+SHUAI shuai 衰摔甩帅率蟀
+SHUAN shuan 闩拴栓涮
+SHUANG shuang 双霜孀爽
+SHUI shui 谁水说税睡
+SHUN shun 吮顺舜瞬
+SHUO shuo 说妁烁铄朔硕
+SI si 私司丝咝思斯厮撕嘶死巳祀四泗驷寺似姒伺饲嗣俟食肆
+SONG song 忪松凇淞嵩怂耸悚讼颂宋送诵
+SOU sou 搜嗖馊溲飕艘叟嗾擞嗽
+SU su 苏酥俗夙诉肃素嗉速宿缩粟谡塑溯蔌簌
+SUAN suan 狻酸蒜算
+SUI sui 尿虽荽眭绥隋随遂髓岁碎崇隧燧穗
+SUN sun 孙荪狲飧损笋榫
+SUO suo 唆梭羧蓑缩所索唢琐锁嗦
+TA ta 他她它趿塌踏塔獭拓沓榻
+TAI tai 台苔胎抬跆太汰态肽钛泰
+TAN tan 坍贪摊滩瘫坛昙谈痰弹覃谭潭檀忐坦袒毯叹炭碳探
+TANG tang 汤耥趟镗唐塘搪糖堂棠樘膛螳帑倘淌躺傥烫
+TAO tao 叨涛焘绦掏滔韬逃桃陶萄啕淘讨套
+TE te 忒特慝忑
+TENG teng 疼腾誊滕藤
+TI ti 体剔踢梯锑提缇题啼蹄屉剃涕倜惕替嚏
+TIAN tian 天添田佃恬甜填忝舔腆掭
+TIAO tiao 佻挑条苕迢笤调挑窕眺跳粜
+TIE tie 帖贴萜铁
+TING ting 厅汀听烃廷莛庭蜓霆亭停婷挺铤艇
+TONG tong 通仝同茼桐铜佟彤童僮潼瞳筒统捅桶恸痛
+TOU tou 偷头投骰透
+TU tu 凸秃突图荼途涂徒屠土吐兔菟
+TUAN tuan 湍团抟疃
+TUI tui 忒推颓腿退煺褪蜕
+TUN tun 吞屯囤饨豚臀氽褪
+TUO tuo 托拖脱驮佗陀驼鸵妥椭拓唾魄
+WA wa 挖哇洼蛙娲娃瓦佤袜
+WAI wai 歪崴外
+WAN wan 弯湾剜蜿豌丸纨完玩顽烷宛惋婉碗莞脘皖挽晚绾万腕蔓
+WANG wang 亡汪王网罔惘辋魍枉往旺望妄忘
+WEI wei 危委逶巍威偎煨微薇韦违围帏为圩桅唯帷惟维潍伟苇纬玮炜伪尾娓诿萎痿猥卫未味位畏喂胃谓猬渭尉蔚慰魏
+WEN wen 温瘟文纹蚊雯闻刎吻紊稳问
+WENG weng 翁嗡瓮
+WO wo 挝莴涡窝蜗倭喔我沃卧握幄龌斡
+WU wu 乌呜钨圬污巫诬屋恶无芜毋吾唔梧吴蜈五伍午忤妩武鹉侮捂舞兀勿物坞戊务雾误悟晤焐鹜
+XI xi 夕汐矽兮西茜栖牺硒吸希稀昔惜析淅晰蜥息熄螅奚溪悉蟋犀樨锡熙僖嘻嬉熹膝曦醯习席袭媳隰洗铣玺徙屣喜禧戏系细隙
+XIA xia 呷虾瞎匣狎侠峡狭硖遐瑕暇霞辖黠下吓夏厦唬
+XIAN xian 仙籼先纤掀锨鲜闲娴痫贤弦舷咸涎衔嫌冼显险蚬藓苋现县限线宪陷馅羡腺献
+XIANG xiang 乡相厢湘箱香襄镶详祥降翔享响饷想向项巷象像橡
+XIAO xiao 肖削逍消宵硝销霄枭骁萧潇箫嚣淆小晓孝哮笑校效啸
+XIE xie 些楔歇蝎协胁邪挟斜偕谐携鞋写血泄泻卸屑械亵谢榭解邂懈蟹
+XIN xin 心芯辛莘锌新薪忻昕欣歆鑫囟信衅
+XING xing 兴星猩惺腥刑形型行饧陉荥省醒擤杏幸悻性姓
+XIONG xiong 凶匈汹胸兄芎雄熊
+XIU xiu 休咻修羞馐朽宿秀绣锈袖嗅溴
+XU xu 圩吁盱戌须胥虚墟嘘需徐许栩旭序叙恤畜蓄酗绪续絮婿煦蓿
+XUAN xuan 轩宣萱喧暄玄悬旋漩选癣炫眩绚渲楦
+XUE xue 削靴薛穴学雪血谑
+XUN xun 勋熏薰醺旬询恂寻荨巡循训驯讯汛迅徇殉逊浚蕈
+YA ya 丫压呀鸦押鸭垭哑牙伢芽蚜崖涯衙雅轧亚娅讶迓砑
+YAN yan 咽胭烟恹殷焉嫣阉淹腌湮燕延埏蜒筵闫芫严言妍研岩炎沿盐阎颜檐奄掩兖俨衍剡琰魇郾偃眼演鼹厌砚咽唁彦谚艳滟晏宴堰验雁赝焰焱酽
+YANG yang 央泱殃鸯秧鞅扬杨炀疡羊佯徉洋阳仰养氧痒怏样恙烊漾
+YAO yao 幺吆夭妖约要腰邀爻肴尧姚窑谣摇徭遥瑶杳咬舀窈药钥曜耀
+YE ye 耶椰掖噎爷也冶野业叶页曳夜液腋烨谒
+YI yi 一伊咿衣依铱医猗椅漪揖壹噫仪夷荑咦姨胰沂诒饴怡贻迤宜移颐遗疑嶷彝乙已以苡尾矣酏蚁舣倚旖弋亿忆义议艺呓仡屹亦弈奕裔异抑邑悒佚轶役疫毅译驿绎易蜴诣羿翊翌翳翼益嗌溢缢谊逸意薏臆镱癔肄熠殪懿劓
+YIN yin 因茵姻阴音喑殷吟垠银龈淫寅鄞尹引吲蚓饮隐瘾印荫胤窨
+YING ying 应英瑛莺婴撄嘤缨樱鹦罂膺鹰迎茔荧莹萤营蓥滢盈楹蝇嬴瀛颖影映硬
+YO yo 哟
+YONG yong 佣拥痈邕庸雍壅臃永咏泳甬俑勇涌恿蛹踊用
+YOU you 优忧攸悠呦幽尤犹疣鱿由邮油柚铀莜游友有酉莠黝又右佑幼柚釉鼬诱
+YU yu 迂纡淤瘀于盂竽与予妤余馀臾谀萸鱼渔於禺隅喁愚俞逾渝愉瑜榆娱虞舆屿伛宇羽雨禹语玉钰驭芋吁聿峪浴欲裕妪雨郁育昱煜狱域预豫谕喻愈尉蔚熨遇寓御誉毓
+YUAN yuan 鸳冤渊元芫园沅鼋员圆垣爰援媛袁猿辕原塬源缘橼圜远苑怨院垸瑗愿
+YUE yue 曰约乐岳阅悦越跃粤哕月钥
+YUN yun 晕云芸纭耘匀员允陨殒孕运酝郓愠韫蕴韵熨
+ZA za 拶杂砸咋扎匝咂
+ZAI zai 灾甾哉栽仔载宰崽再在
+ZAN zan 簪咱拶昝攒趱暂錾赞瓒
+ZANG zang 赃脏臧驵奘葬藏
+ZAO zao 遭糟凿早枣蚤澡藻皂唣灶造噪燥躁
+ZE ze 则责啧咋择泽仄昃
+ZEI zei 贼
+ZEN zen 怎谮
+ZENG zeng 曾增憎锃缯赠甑
+ZHA zha 扎吒咋查喳渣楂札轧闸炸铡喋眨乍诈痄蚱榨栅
+ZHAI zhai 侧斋摘宅择翟窄债寨
+ZHAN zhan 占沾毡粘詹谵瞻斩崭盏展搌辗战站栈绽湛颤蘸
+ZHANG zhang 张章獐彰漳嫜樟蟑长涨掌丈仗杖帐账胀障嶂幛瘴
+ZHAO zhao 钊招昭着朝爪找沼召诏照兆赵笊棹罩肇
+ZHE zhe 折蜇遮螫哲辄蛰谪辙者锗赭褶这柘浙蔗鹧着
+ZHEI zhei 这
+ZHEN zhen 贞侦帧桢针珍胗真砧蓁榛臻斟甄箴诊畛疹枕缜圳阵鸩振赈震朕镇
+ZHENG zheng 丁正征怔症争挣峥狰睁铮筝蒸拯整证政郑诤
+ZHI zhi 之芝支吱枝肢祗只织栀汁知蜘脂执絷直值埴植殖侄职跖止址芷祉趾枳咫旨指酯纸至郅致窒蛭膣志痣帜帙秩制质炙治栉峙痔陟挚掷智滞置雉稚
+ZHONG zhong 中忠盅钟衷终肿种冢踵仲众重
+ZHOU zhou 舟州洲诌周粥妯轴肘帚纣绉皱咒宙胄昼骤
+ZHU zhu 朱侏诛茱珠株铢蛛诸猪潴术竹竺逐烛舳主拄煮褚属嘱瞩伫苎贮助住注驻柱炷蛀杼祝著翥箸铸筑
+ZHUA zhua 抓爪
+ZHUAI zhuai 拽
+ZHUAN zhuan 专砖颛转传啭赚撰馔篆
+ZHUANG zhuang 妆庄桩装奘壮状僮撞幢戆
+ZHUI zhui 椎锥追坠缀惴缒赘
+ZHUN zhun 肫谆准
+ZHUO zhuo 拙捉桌倬焯涿灼酌茁卓浊镯啄琢著着擢
+ZI zi 孜龇咨姿资兹孳滋淄辎子仔籽姊秭紫訾梓滓自字恣渍
+ZONG zong 枞宗综棕踪鬃总纵粽
+ZOU zou 邹驺诹走奏揍
+ZU zu 租足卒族诅阻组俎祖
+ZUAN zuan 钻缵纂赚攥
+ZUI zui 咀嘴最醉罪
+ZUN zun 尊遵樽撙
+ZUO zuo 作嘬昨笮琢左佐撮怍柞祚坐唑座做
\ No newline at end of file
diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml
new file mode 100644
index 0000000..7abc06d
--- /dev/null
+++ b/app/src/main/res/values-v21/styles.xml
@@ -0,0 +1 @@
+
diff --git a/app/src/main/res/values-w820dp/dimens.xml b/app/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 0000000..63fc816
--- /dev/null
+++ b/app/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..7ce840e
--- /dev/null
+++ b/app/src/main/res/values/attrs.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..9d3bb6e
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,11 @@
+
+
+ #3281c0
+ #3281c0
+ #aaff00
+
+ #ffffff
+ #000000
+ #444444
+ #cccccc
+
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..812cb7b
--- /dev/null
+++ b/app/src/main/res/values/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 16dp
+ 16dp
+ 16dp
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..38e8d76
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,16 @@
+
+ 星星声控计算器
+ 请讲话
+
+ http://xingxing.hongchazn.com/evaluation.php
+ http://xingxing.hongchazn.com/update/update.php
+ http://xingxing.hongchazn.com/help/index.html
+ HelpActivity
+
+
+ 真正的语音输入计算器,彻底解放双手
+ 怎么读就怎么计算,比键盘输入计算器更简单、更快速、更准确、更强大。
+ http://xingxing.hongchazn.com/index.html
+ http://xingxing.hongchazn.com/img/share_icon.png
+
+
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..1135f87
--- /dev/null
+++ b/app/src/main/res/values/styles.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/test/java/org/xing/calc/CalculatorTest.java b/app/src/test/java/org/xing/calc/CalculatorTest.java
new file mode 100644
index 0000000..6786914
--- /dev/null
+++ b/app/src/test/java/org/xing/calc/CalculatorTest.java
@@ -0,0 +1,229 @@
+package org.xing.calc;
+
+import org.junit.Test;
+import org.xing.android.R;
+import org.xing.calc.filter.PinyinExprFilter;
+
+import java.io.FileInputStream;
+import java.util.AbstractMap;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+import static org.xing.calc.Calculator.createDefault;
+
+/**
+ * Created by Administrator on 2017/1/8 0008.
+ */
+public class CalculatorTest{
+
+ @Test
+ public void testEval() throws Exception {
+ HashMap pinyin =
+ PinyinExprFilter.loadTokens(new FileInputStream("D:\\workspaces\\calculator\\app\\src\\main\\res\\raw\\token"));
+ Calculator calc = createDefault(pinyin);
+
+ Map chnMap = new HashMap();
+
+ chnMap.put("sin12", "-0.536573");
+ chnMap.put("10%", "0.1");
+ chnMap.put("2除以2/3", "3");
+ chnMap.put("2除以2/根号3", "1.732050");
+ chnMap.put("2除以根号三分之二", "2.449490");
+
+ chnMap.put("sin12", "-0.536573");
+ chnMap.put("余弦12", "0.843854");
+ chnMap.put("反余弦余弦0.35", "0.35");
+ chnMap.put("反正弦正弦0.35", "0.35");
+ chnMap.put("反正弦0.54", "0.570437");
+
+
+ chnMap.put("1000+两千再加3000=多少", "6000");
+ chnMap.put("一百加1150加1480+两千+3600", "8330");
+
+
+ chnMap.put("对数0.54", "-0.616186");
+ chnMap.put("3对数0.54", "-0.560877");
+ chnMap.put("3根号0.54", "0.814325");
+ chnMap.put("3对数百分之二", "-3.560877");
+ chnMap.put("七的七对数二次方", "2.0");
+
+ chnMap.put("1加上三十五点二", "36.2");
+ chnMap.put("1减10", "-9");
+ chnMap.put("log(3点2加15)^2除2乘以3", "26.282218");
+ chnMap.put("15*3", "45");
+ chnMap.put("(12)", "12");
+ chnMap.put("负12", "-12");
+ chnMap.put("一加三十五", "36");
+ chnMap.put("一减十", "-9");
+ chnMap.put("百分之一", "0.01");
+ chnMap.put("十五除以二", "7.5");
+ chnMap.put("十五乘以三", "45");
+ chnMap.put("15×3", "45");
+ chnMap.put("十五分之三", "0.2");
+ chnMap.put("一点三五加三十五点二零", "36.55");
+ chnMap.put("零点二四减去二点五三", "-2.29");
+ chnMap.put("零点二四乘以二点五三", "0.6072");
+ chnMap.put("零点二四除以二点五三", "0.094861");
+ chnMap.put("零点二四除以五分之三点二", "0.375");
+ chnMap.put("一百零一点三加一万零一百", "10201.3");
+ chnMap.put("一百零一减去一万零一百", "-9999.0");
+ chnMap.put("一百零一乘一万零一百", "1020100.0");
+ chnMap.put("一百零一除以一万零一百点五六", "0.009999");
+ chnMap.put("零点二四减去二点五三的平方", "-6.160899");
+ chnMap.put("零点二四乘以二点五三的开方", "0.381743");
+ chnMap.put("零点二四除以二点五三的五次方", "0.002315");
+ chnMap.put("零点二四除以五的立方", "0.001919");
+ chnMap.put("零点二四加五分之三点二", "0.88");
+ chnMap.put("零点二四减五分之三点二", "-0.4");
+ chnMap.put("零点二四乘五分之三点二", "0.1536");
+ chnMap.put("三千零十五万点二零加上一百五十点三五乘以一百零二", "30165335.9");
+ chnMap.put("三千零十五万点二零减去一百五十点三五除以一百零二", "30149998.725980");
+
+ chnMap.put("一百一加一万零一百", "10210");
+ chnMap.put("一百一加一万一", "11110");
+ chnMap.put("一百零一减去一万零一百", "-9999");
+ chnMap.put("二^2", "4");
+
+ //小数,函数,分数 测试
+ chnMap.put("零点二四加sin五分之三点二", "0.837195");
+ chnMap.put("零点二四减cos五分之三点二", "-0.562096");
+ chnMap.put("零点二四乘tan五分之三点二", "0.178691");
+ chnMap.put("零点二四加lg五分之三点二", "0.0461800");
+ chnMap.put("零点二四减ln五分之三点二", "0.686287");
+ chnMap.put("零点二四乘log五分之三点二", "-0.154525");
+
+ //函数,小数,分数,幂运算 混合测试
+ chnMap.put("零点二四加sin五分之三点二的三点二次方", "0.432120");
+ chnMap.put("零点二四减cos五分之三点二的三点二次方", "-0.253769");
+ chnMap.put("零点二四乘tan五分之三点二的三点二次方", "0.093381");
+
+ chnMap.put("零点二四加lg五分之一百三点二的三点二次方", "2.640244");
+ chnMap.put("零点二四减ln五分之一百三点二的三点二次方", "-34.381491");
+ chnMap.put("零点二四乘log五分之一百三点二的三点二次方", "26.848222");
+
+ chnMap.put("零点二四加lg(五分之一百三点二的三点二次方)", "4.447071");
+ chnMap.put("零点二四减ln(五分之一百三点二的三点二次方)", "-9.447139");
+ chnMap.put("零点二四乘log(五分之一百三点二的三点二次方)", "3.354140");
+
+ //括号测试
+ chnMap.put("括号1+3乘以括号1+2括号括号", "10.0");
+ chnMap.put("|1+3乘以括号1+2|括号", "10.0");
+ chnMap.put("log|1+3乘以括号1+2|括号", "3.321928");
+ chnMap.put("6/3×3派成语括号6+4括号", "188.49555922");
+
+
+ //多重幂运算
+ chnMap.put("根号四的负四分之三次方的二次方", "0.353553");
+ chnMap.put("根号根号八", "1.681792");
+ chnMap.put("三的四次方的负四分之三次方", "0.037037");
+ chnMap.put("零点零零八一的四分之一次方加上四的负四分之三次方的二次方加上根号八的负四分之三次方减去16的负零点75次方", "0.758502");
+ chnMap.put("log根号二十七除以log3加上lg二十五加上lg4加上七的括号log2除以log7括号次方加上负九点八的零次方", "6.5");
+
+ //postFuncname测试
+ chnMap.put("三开方", "1.732051");
+ chnMap.put("三的开方", "1.732051");
+ chnMap.put("三开平方", "1.732051");
+ chnMap.put("三开立方", "1.442250");
+ chnMap.put("三的平方根", "1.732051");
+ chnMap.put("三的立方根", "1.442250");
+ chnMap.put("三平方根", "1.732051");
+ chnMap.put("三乘以三开方", "5.196152");
+
+ //弧度制和π
+ chnMap.put("负三点一五派", "-9.896017");
+ chnMap.put("正弦六十度", "0.866025");
+ chnMap.put("正弦三十度", "0.500000");
+ chnMap.put("1000+两千再加3000=多少", "6000");
+ chnMap.put("派", "3.1415926");
+ chnMap.put("负派", "-3.141593");
+ chnMap.put("根号派", "1.772454");
+
+ int correctNum = 0;
+ int wrongNum = 0;
+ for(String expr : chnMap.keySet()) {
+ double value = Double.parseDouble(chnMap.get(expr));
+
+ double result = Double.NaN;
+ try{
+ result = calc.eval(expr);
+ }catch(Exception ex) {
+ System.err.println(expr);
+ ex.printStackTrace();
+ }
+
+ System.out.printf("%s\n%s\n\t%.6f\n", expr, calc.getReadExpr(), result);
+ if(Double.isNaN(result) || Math.abs(result - value) > 1e-6) {
+ System.out.println("错误:"+expr+", "+value+", 错误结果:"+result+"\n");
+ wrongNum ++;
+ } else {
+ correctNum ++;
+ }
+ }
+
+ //连续运算
+ Vector> contiExpr = new Vector<>();
+
+ contiExpr.add(new AbstractMap.SimpleEntry("6.471928-3.15", "3.321928"));
+ contiExpr.add(new AbstractMap.SimpleEntry("加三点一五", "6.471928"));
+ contiExpr.add(new AbstractMap.SimpleEntry("减三点一五", "3.321928"));
+ contiExpr.add(new AbstractMap.SimpleEntry("乘三点一五", "10.464073"));
+ contiExpr.add(new AbstractMap.SimpleEntry("区三点一五", "3.321928"));
+ contiExpr.add(new AbstractMap.SimpleEntry("根号", "1.822616"));
+ contiExpr.add(new AbstractMap.SimpleEntry("对数", "0.600273"));
+ contiExpr.add(new AbstractMap.SimpleEntry("争先", "0.564868"));
+ contiExpr.add(new AbstractMap.SimpleEntry("反正弦", "0.600273"));
+ contiExpr.add(new AbstractMap.SimpleEntry("开方", "0.774773"));
+ contiExpr.add(new AbstractMap.SimpleEntry("平方根", "0.880212"));
+
+ contiExpr.add(new AbstractMap.SimpleEntry("三又四分之一", "3.25"));
+ contiExpr.add(new AbstractMap.SimpleEntry("三又1/4", "3.25"));
+ contiExpr.add(new AbstractMap.SimpleEntry("负三又四分之一", "-3.25"));
+
+ contiExpr.add(new AbstractMap.SimpleEntry("一千万", "10000000"));
+ contiExpr.add(new AbstractMap.SimpleEntry("十万亿", "10000000000000"));
+ contiExpr.add(new AbstractMap.SimpleEntry("二对数三乘以二队戍午", "3.680169"));
+
+ contiExpr.add(new AbstractMap.SimpleEntry("一百除二等于多少", "50"));
+
+ contiExpr.add(new AbstractMap.SimpleEntry("三点一点零点一加", "3"));
+ contiExpr.add(new AbstractMap.SimpleEntry("三点一点零点一", "3"));
+ contiExpr.add(new AbstractMap.SimpleEntry("26.9点59.9", "-33"));
+ contiExpr.add(new AbstractMap.SimpleEntry("点一八×两点四", "-76.2"));
+ contiExpr.add(new AbstractMap.SimpleEntry("点42", "-118.2"));
+
+ contiExpr.add(new AbstractMap.SimpleEntry("21的三九减四点六", "16.79"));
+ contiExpr.add(new AbstractMap.SimpleEntry("21.39点四点六的差除以七的三", "20.759863"));
+ contiExpr.add(new AbstractMap.SimpleEntry("21.39减四点六的差除以七的三", "20.759863"));
+ contiExpr.add(new AbstractMap.SimpleEntry("五点四乘六得四八成二", "69.984"));
+ contiExpr.add(new AbstractMap.SimpleEntry("正玄三十度", "0.5"));
+ contiExpr.add(new AbstractMap.SimpleEntry("副根号1.96", "-1.4"));
+ contiExpr.add(new AbstractMap.SimpleEntry("三平方", "9"));
+ contiExpr.add(new AbstractMap.SimpleEntry("三平方根", "1.732051"));
+ contiExpr.add(new AbstractMap.SimpleEntry("负二的零次方", "1"));
+
+ for(Map.Entry en : contiExpr) {
+ String expr = en.getKey();
+ double value = Double.parseDouble(en.getValue());
+
+ double result = Double.NaN;
+ try{
+ result = calc.eval(expr);
+ }catch(Exception ex) {
+ System.err.println(expr);
+ ex.printStackTrace();
+ }
+
+ System.out.printf("%s\n%s\n\t%.6f\n", expr, calc.getReadExpr(), result);
+ if(Double.isNaN(result) || Math.abs(result - value) > 1e-6) {
+ System.out.println("错误:"+expr+", "+value+", 错误结果:"+result+"\n");
+ wrongNum ++;
+ } else {
+ correctNum ++;
+ }
+ }
+
+ System.out.println("总计:\n\t正确 "+correctNum+", 错误 "+wrongNum);
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/test/java/org/xing/utils/LoggerTest.java b/app/src/test/java/org/xing/utils/LoggerTest.java
new file mode 100644
index 0000000..b4ebbd5
--- /dev/null
+++ b/app/src/test/java/org/xing/utils/LoggerTest.java
@@ -0,0 +1,24 @@
+package org.xing.utils;
+
+import org.junit.Test;
+import org.xing.logger.impl.EventLogger;
+
+/**
+ * Created by Administrator on 2017/2/21 0021.
+ */
+
+public class LoggerTest {
+ @Test
+ public void testEvent() {
+ EventLogger eventLogger = new EventLogger("1", "1.3.4", "http://xingxing.zysoft.com/evaluation.php");
+
+ eventLogger.onEvent( NumberUtil.format(3.15, 8), "零点一四五", "0.145", 0);
+ eventLogger.onEvent( "start");
+
+ try {
+ Thread.currentThread().sleep(10000);
+ }catch (Exception ex) {
+
+ }
+ }
+}
diff --git a/app/src/test/java/org/xing/utils/NumberUtilTest.java b/app/src/test/java/org/xing/utils/NumberUtilTest.java
new file mode 100644
index 0000000..e26bb02
--- /dev/null
+++ b/app/src/test/java/org/xing/utils/NumberUtilTest.java
@@ -0,0 +1,17 @@
+package org.xing.utils;
+
+import org.junit.Test;
+
+/**
+ * Created by Administrator on 2017/1/9 0009.
+ */
+public class NumberUtilTest {
+ @Test
+ public void getPrintSize() throws Exception {
+ int[] size = new int[] {10100000};
+ for(int i=0;i \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..e7b4def
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+include ':app'