diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f0344f5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.deploy*/ +node_modules/ +public/ +services/*/site/ +db.json +.DS_Store +Thumbs.db +_multiconfig.yml +*.log \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..66539cf --- /dev/null +++ b/LICENSE @@ -0,0 +1,437 @@ +Attribution-NonCommercial-ShareAlike 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International +Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-NonCommercial-ShareAlike 4.0 International Public License +("Public License"). To the extent this Public License may be +interpreted as a contract, You are granted the Licensed Rights in +consideration of Your acceptance of these terms and conditions, and the +Licensor grants You such rights in consideration of benefits the +Licensor receives from making the Licensed Material available under +these terms and conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. BY-NC-SA Compatible License means a license listed at + creativecommons.org/compatiblelicenses, approved by Creative + Commons as essentially the equivalent of this Public License. + + d. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + e. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + f. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + g. License Elements means the license attributes listed in the name + of a Creative Commons Public License. The License Elements of this + Public License are Attribution, NonCommercial, and ShareAlike. + + h. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + i. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + j. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + k. NonCommercial means not primarily intended for or directed towards + commercial advantage or monetary compensation. For purposes of + this Public License, the exchange of the Licensed Material for + other material subject to Copyright and Similar Rights by digital + file-sharing or similar means is NonCommercial provided there is + no payment of monetary compensation in connection with the + exchange. + + l. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + m. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + n. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part, for NonCommercial purposes only; and + + b. produce, reproduce, and Share Adapted Material for + NonCommercial purposes only. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties, including when + the Licensed Material is used other than for NonCommercial + purposes. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + b. ShareAlike. + + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-NC-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database for NonCommercial purposes + only; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material, + including for purposes of Section 3(b); and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/README.md b/README.md new file mode 100644 index 0000000..1a5f4c6 --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# My-Blog + +这是 [leverimmy](https://github.com/leverimmy) 的个人博客。 + +## 内容 + +- 笔记 +- 课程报告 +- 讲义 +- 随笔 +- 游记 + +## 主题 + +使用的是 [NexT](https://github.com/next-theme/hexo-theme-next) 主题。 + +## LICENSE + +除非另有说明,本仓库的内容采用 [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) 许可协议。在遵守许可协议的前提下,您可以自由地分享、修改本文档的内容,但不得用于商业目的。 + +如果您认为文档的部分内容侵犯了您的合法权益,请联系项目维护者,我们会尽快删除相关内容。 diff --git a/_config.yml b/_config.yml new file mode 100644 index 0000000..ff92e28 --- /dev/null +++ b/_config.yml @@ -0,0 +1,88 @@ +title: "Clever_Jimmy's Blog" +subtitle: '' +description: '' +keywords: null +author: Clever_Jimmy +language: zh-CN +timezone: '' +url: https://leverimmy.top/ +permalink: ':year/:month/:day/:id/' +permalink_defaults: null +pretty_urls: + trailing_index: true + trailing_html: true +source_dir: source +public_dir: public +tag_dir: tags +archive_dir: archives +category_dir: categories +code_dir: downloads/code +i18n_dir: ':lang' +skip_render: README.md +new_post_name: ':title.md' +default_layout: post +titlecase: false +external_link: + enable: true + field: site + exclude: '' +filename_case: 0 +render_drafts: false +post_asset_folder: false +relative_link: false +future: true +highlight: + enable: true + line_number: true + auto_detect: false + tab_replace: '' + wrap: true + hljs: false + exclude_languages: + - mermaid +prismjs: + enable: false + preprocess: true + line_number: true + tab_replace: '' +index_generator: + path: '' + per_page: 10 + order_by: '-date' +default_category: uncategorized +category_map: null +tag_map: null +meta_generator: true +date_format: YYYY-MM-DD +time_format: HH:mm:ss +updated_option: mtime +per_page: 10 +pagination_dir: page +include: null +exclude: null +ignore: null +theme: next +deploy: + type: git + repo: git@47.120.48.46:/home/git/hexo.git + branch: main + extend_dirs: + - services/homework-ans/site +# Extensions +plugins: + hexo-generator-feed +#Feed Atom +feed: + type: atom + path: atom.xml + limit: 20 + hub: + content: + content_limit: 140 + content_limit_delim: ' ' + order_by: -date +rss: /atom.xml +# lazyload: +# enable: true +# onlypost: true +# loadingImg: # eg. ./images/loading.png \ No newline at end of file diff --git a/drafts/hello-world.md b/drafts/hello-world.md new file mode 100644 index 0000000..ae8d154 --- /dev/null +++ b/drafts/hello-world.md @@ -0,0 +1,38 @@ +--- +title: Hello World +--- +Welcome to [Hexo](https://hexo.io/)! This is your very first post. Check [documentation](https://hexo.io/docs/) for more info. If you get any problems when using Hexo, you can find the answer in [troubleshooting](https://hexo.io/docs/troubleshooting.html) or you can ask me on [GitHub](https://github.com/hexojs/hexo/issues). + +## Quick Start + +### Create a new post + +``` bash +$ hexo new "My New Post" +``` + +More info: [Writing](https://hexo.io/docs/writing.html) + +### Run server + +``` bash +$ hexo server +``` + +More info: [Server](https://hexo.io/docs/server.html) + +### Generate static files + +``` bash +$ hexo generate +``` + +More info: [Generating](https://hexo.io/docs/generating.html) + +### Deploy to remote sites + +``` bash +$ hexo deploy +``` + +More info: [Deployment](https://hexo.io/docs/one-command-deployment.html) diff --git "a/drafts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221Introduction-to-Theoretical-Computer-Science.md" "b/drafts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221Introduction-to-Theoretical-Computer-Science.md" new file mode 100644 index 0000000..bbd7098 --- /dev/null +++ "b/drafts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221Introduction-to-Theoretical-Computer-Science.md" @@ -0,0 +1,19 @@ +--- +title: 【学习笔记】Introduction to Theoretical Computer Science +tags: + - 理论计算机科学 +categories: + - 笔记 +mathjax: true +toc: true +date: 2024-03-01 20:14:22 +password: +id: ITCS +--- + +这是 *[Introduction to Theoretical Computer Science](https://introtcs.org/)* 的学习笔记。 + + + +## + diff --git "a/drafts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221Karatsuba-\344\271\230\346\263\225\345\255\246\344\271\240\347\254\224\350\256\260.md" "b/drafts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221Karatsuba-\344\271\230\346\263\225\345\255\246\344\271\240\347\254\224\350\256\260.md" new file mode 100644 index 0000000..d18fe8e --- /dev/null +++ "b/drafts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221Karatsuba-\344\271\230\346\263\225\345\255\246\344\271\240\347\254\224\350\256\260.md" @@ -0,0 +1,157 @@ +--- +title: 【学习笔记】Karatsuba 乘法学习笔记 +tags: + - 高精度 + - 分治 + - 技巧 +categories: + - 学习笔记 +mathjax: true +toc: true +date: 2020-05-04 15:40:30 +password: +--- + +上个学期在联赛前听 EternalAlexander 提到了一下这个玄学的算法,现在就学习一下吧。 + + + +### **简介** + +「Karatsuba 乘法」是 1960 年由 Anatolii Alexeevitch Karatsuba 提出的可用于大整数乘法的算法。 + +### **理论推导** + +不妨设我们要相乘的两个数字分别为 $a$ 和 $b$,其乘积,也就是我们要求的数,为 $c$。 + +设 $a = x_1\cdot10^m + x_0, b = y_1\cdot10^m + y_0$,其中 $0 < x_1, x_0, y_1, y_0 < 10^m$,则 + +$\begin{aligned}c = ab & = (x_1\cdot10^m + x_0) \cdot (y_1\cdot10^m + y_0) \\\\ & = (x_1\cdot y_1)10^{2m} + (x_1\cdot y_0 + x_0\cdot y_1)10^m + x_0\cdot y_0\end{aligned}$ + +记 $z_2 = x_1\cdot y_1, z_1 = x_1\cdot y_0 + x_0\cdot y_1, z_0 = x_0\cdot y_0$。 + +**注意到**,$z_1 = (x_1 + x_0)(y_1 + y_0) - z_2 - z_0$。 + +于是我们可以分步计算 $(x_1 + x_0)(y_1 + y_0), z_2, z_0$ 即可。 + +### **时间复杂度** + +我们实质上是把一个 $n \times n$ 的乘法化简为了三个长度更小的乘法。 + +当 $m = \left\lfloor\dfrac{n}{2}\right\rfloor$ 时,有递推式 $T(n) = 3T(\left\lfloor\dfrac{n}{2}\right\rfloor) + O(n)$。 + +不难由主定理得知 $T(n) = \Theta(n^{\log_{2}3}) \approx \Theta(n^{1.585})$ + +### **代码实现** + +这个是 [MUL - Fast Multiplication](http://www.spoj.com/problems/MUL/en/) 的代码。 + +```cpp +#include +#define LL long long +#define LOCAL + +namespace io { + template inline void read(T & _x) { + int f = 0, ch; _x = 0; + while(!isdigit(ch = getchar())) f |= ch == '-'; + while(isdigit(ch)) _x = _x * 10 + ch - '0', ch = getchar(); + if(f) _x = -_x; + } + template inline void read(T &_f, Args& ... args) { + read(_f), read(args ...); + } + inline void _deal(char ch) { putchar(ch); } + template inline void _deal(T _x) { + if (_x < 0) putchar('-'), _x = -_x; + if (_x > 9) _deal(_x / 10); + putchar(_x % 10 + '0'); + } + inline void write() {} + template inline void write(T _f, Args ... args) { + _deal(_f), write(args...); + } +} + +const int N = 1e4 + 5; + +int t, n, m; +int a[N], b[N], c[N << 1]; +char A[N], B[N]; + +int *Kmul(int len, int ra[], int rb[]) { + if(len <= 32) { + int *r = new int[len * 2 + 1](); + for(int i = 0; i <= len; ++i) + for(int j = 0; j <= len; ++j) + r[i + j] += ra[i] * rb[j]; + return r; + } + int hf = len / 2 + 1; + int *r = new int[hf * 4 + 1](); + int *z0, *z1, *z2; + + z0 = Kmul(hf - 1, ra, rb); + z2 = Kmul(len - hf, ra + hf, rb + hf); + + for(int i = 0; i + hf <= len; ++i) ra[i] += ra[i + hf]; + for(int i = 0; i + hf <= len; ++i) rb[i] += rb[i + hf]; + z1 = Kmul(hf - 1, ra, rb); + for(int i = 0; i + hf <= len; ++i) ra[i] -= ra[i + hf]; + for(int i = 0; i + hf <= len; ++i) rb[i] -= rb[i + hf]; + + for(int i = 0; i <= (hf - 1) * 2; ++i) z1[i] -= z0[i]; + for(int i = 0; i <= (len - hf) * 2; ++i) z1[i] -= z2[i]; + + for(int i = 0; i <= (hf - 1) * 2; ++i) r[i] += z0[i]; + for(int i = 0; i <= (hf - 1) * 2; ++i) r[i + hf] += z1[i]; + for(int i = 0; i <= (len - hf) * 2; ++i) r[i + hf * 2] += z2[i]; + + delete[] z0; + delete[] z1; + delete[] z2; + return r; +} + +void Karatsuba(int ra[], int rb[], int rc[]) { + int *r = Kmul(n - 1, ra, rb); + memcpy(rc, r, sizeof(int) * m); + for(int i = 0; i < m - 1; ++i) { + if(rc[i] >= 10) { + rc[i + 1] += rc[i] / 10; + rc[i] %= 10; + } + } + delete[] r; +} + +int main() { +#ifdef LOCAL + freopen("mul.in", "r", stdin); + freopen("mul.out", "w", stdout); +#endif + io::read(t); + while(t--) { + int len1, len2; + scanf("%s %s", A + 1, B + 1); + len1 = strlen(A + 1), len2 = strlen(B + 1); + n = std::max(len1, len2); + for(int i = len1, j = len2, k = 0; k < n; --i, --j, ++k) { + if(i >= 1) a[k] = A[i] - '0'; + else a[k] = 0; + if(j >= 1) b[k] = B[j] - '0'; + else b[k] = 0; + } + /*for(int i = 1; i <= n; ++i) printf("%d", a[i]); + putchar('\n'); + for(int i = 1; i <= n; ++i) printf("%d", b[i]); + putchar('\n');*/ + m = len1 + len2 - 1; + Karatsuba(a, b, c); + while(!c[m - 1] && m > 1) --m; + for(int i = m - 1; i >= 0; --i) io::write(c[i]); + io::write('\n'); + } + return 0; +} +``` diff --git "a/drafts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221Quantum-Computation-and-Quantum-Information.md" "b/drafts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221Quantum-Computation-and-Quantum-Information.md" new file mode 100644 index 0000000..cd99fa9 --- /dev/null +++ "b/drafts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221Quantum-Computation-and-Quantum-Information.md" @@ -0,0 +1,56 @@ +--- +title: 【学习笔记】Quantum Computation and Quantum Information +tags: + - 理论计算机科学 + - 量子计算 +categories: + - 笔记 +mathjax: true +toc: true +date: 2024-05-12 20:14:22 +password: +id: QCQI +--- + +这是 *Quantum Computation and Quantum Information* 的学习笔记。 + + + +## Nomenclature and notation + +### Linear Algebra and quantum mechanics + +#### Positive, positive definite, and support + +An operator $A$ is *positive* if $\braket{\psi |A| \psi} \ge 0$ holds for all $\ket{\psi}$. + +An operator $A$ is *positive definite* if $\braket{\psi |A| \psi} > 0$ holds for all $\ket{\psi}$. + +The *support* of an operator is defined to be the vector space orthogonal to its kernel. + +#### The Letter H + +$H$ is for *Hadamard Gate*, which has the matrix representation +$$ +H = \frac{1}{\sqrt{2}}\begin{bmatrix}1 & 1 \\ 1 & -1\end{bmatrix}. +$$ +Or, it could be the *Hamiltonian* for a quantum system. + +### Information theory and probability + +#### Relative Entropy + +The *relative entropy* of a positive operator $A$ **relative to ** another positive operator B is defined as +$$ +S(A \parallel B) = \text{tr}(A \log A) - \text{tr}(B \log B). +$$ +Note that the order of the operators matters. $A$ and $B$ need to be positive because of the $\log$ function. + +### Frequently used quantum gates and circuit symbols + +TBA + +## Fundamental concepts + +### Introduction and overview + diff --git "a/drafts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\347\273\217\345\205\270\345\212\250\346\200\201\350\247\204\345\210\222\346\250\241\345\236\213\345\255\246\344\271\240\347\254\224\350\256\260.md" "b/drafts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\347\273\217\345\205\270\345\212\250\346\200\201\350\247\204\345\210\222\346\250\241\345\236\213\345\255\246\344\271\240\347\254\224\350\256\260.md" new file mode 100644 index 0000000..456c60d --- /dev/null +++ "b/drafts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\347\273\217\345\205\270\345\212\250\346\200\201\350\247\204\345\210\222\346\250\241\345\236\213\345\255\246\344\271\240\347\254\224\350\256\260.md" @@ -0,0 +1,258 @@ +--- +title: 【学习笔记】经典动态规划模型学习笔记 +tags: + - 动态规划 +categories: + - 学习笔记 +mathjax: true +toc: true +date: 2020-04-27 11:35:44 +password: +--- + +~~「用集合的角度来理解dp。」~~ $\gets$ 这个东西好像不是很好用。 + +大概这篇博文就只能熟悉一下各大dp模型吧? + + + +## 区间dp + +### **概述** + +区间dp是dp的一种,一般处理在一个序列上的关于区间的一些问题。 + +因为 $[l, r]$ 这个区间,可以用很多个 $[l, k] \bigcap (k, r]$ **重复地** 覆盖, + +也就是通过枚举断点 $k$,来实现区间 $[l, r] \gets [l, k] + (k, r]$ 信息的转移。 + +即 $f(l, r) = \operatorname{op}\\{f(l, k) + f(k + 1, r)\\} \quad k \in [l, r)$。 + +需要注意的是 $k$ 的范围也不一定是 $[l, r)$,也有许多题是 $k \in (l, r)$ 的, + +这个时候我们就需要处理出 $len = 2$ 的,然后 `for` 循环从 $len = 3$ 开始。 + +### **例题** + +1. [「NOI1995」石子合并](https://www.luogu.com.cn/problem/P1880) + + > **拆环成链**,令 $a[n + 1\ldots 2n] \gets a[1 \ldots n]$,这样就把一个环形的问题转化到了序列上。 + + 设 $f(l, r)$ 表示第 $l$ 堆石子一直合并到第 $r$ 堆石子,能获得的最大值; + + 设 $g(l, r)$ 表示第 $l$ 堆石子一直合并到第 $r$ 堆石子,能获得的最小值。 + + 因为 $[l, r]$ 可以被分成 $[l, k]$ 和 $(k, r]$,所以我们可以这么转移: + + $$ + \begin{aligned} + f(l, r) & = \max\\{sum_r - sum_{l - 1} + f(l, k) + f(k + 1, r)\\} \quad k \in [l, r) \\\\ + g(l, r) & = \max\\{sum_r - sum_{l - 1} + g(l, k) + g(k + 1, r)\\} \quad k \in [l, r) + \end{aligned} + $$ + +2. [「一本通 5.1 例 3」凸多边形的划分](https://loj.ac/problem/10149) + + > 我们将这个凸多边形的每个顶点顺时针排成一行,环上的顶点其实和序列没有区别。 + + 设 $f(l, r)$ 表示第 $l$ 个顶点到第 $r$ 个顶点所组成的凸多边形划分后,能得到的最小值。 + + 因为 $S(l, r)$ 可以被分成 $(l, k)$ 和 $(k, r)$,再加上 $a_l, a_r, a_k$ 的贡献,所以我们可以这么转移: + + $$ + f(l, r) = \min\\{f(l, k) + f(k, r) + a_l\cdot a_k\cdot a_r\\} \quad k \in (l, r) + $$ + +3. [「NOIP2007」矩阵取数游戏](https://www.luogu.com.cn/problem/P1005) + + > 注意到每一行的贡献其实是互不干扰的,所以我们分别对每一行进行 dp。 + + 设 $f(l, r)$ 表示这一行取了 $m - (r - l + 1)$ 步后,还剩 $[l, r]$ 能得到的最大值。 + + 因为 $S(l, r)$ 可以是 $S(l - 1, r) - a_{l - 1}$ 得来的,也可以是 $S(l, r + 1) - a_{r + 1}$ 得来的,所以我们可以这么转移: + + $$ + f(l, r) = \max + \begin{cases} + f(l - 1, r) + a_{l - 1} \cdot 2^{m - (r - l + 1)} \\\\ + f(l, r + 1) + a_{r + 1} \cdot 2^{m - (r - l + 1)} + \end{cases} + $$ + +4. [「CF Edu #83」E. Array Shrinking](https://codeforces.ml/contest/1312/problem/E) + + > 这题比较综合,要先用区间dp预处理,然后再线性递推。 + + 设 $f(l, r)$ 表示 $[l, r]$ 能缩合得到的数字(如果无法缩合,则 $f(l, r) = 0$) + + 设 $g(i)$ 表示 $[1, i]$ 可以被分成的段数的最小值。 + + 如果 $[l, r]$ 能从 $[l, k]$ 和 $(k, r]$ 组成,那么 $f(l, k)$ 是应该等于 $f(k + 1, r)$ 的,这样才能「缩合」。所以这么转移 $f$: + + $$ + f(l, r) = \max\\{f(l, k) + 1\\} \quad (k \in [l, r) \bigwedge f(l, k) = f(k + 1, r) > 0) + $$ + + 因为 $[1, i]$ 能被分成 $[1, j]$ 和 $(j, i]$ 两段,我们只用考虑 $(j, i]$ 能否缩合得到。所以我们可以这么转移: + + $$ + g(i) = \min\\{g(j) + 1\\} \quad (j \in [1, i) \bigwedge f(j + 1, i) \neq 0) + $$ + +## 树型dp + +### **概述** + +树型dp是dp的一种,一般处理子树中最优解的一些问题。当然,也有「换根dp」之类的处理 **整棵树** 上最优解的一些问题。 + +### **例题** + +1. [「一本通 5.2 例 4」战略游戏](https://loj.ac/problem/10156) + + > 树型dp入门题。 + + 设 $f(u, 0)$ 表示 $u$ 上不放士兵,使得所有以 $u$ 为根的子树中的 **边** 被「瞭望」到,所需放置的士兵最少个数。 + + 设 $f(u, 1)$ 表示 $u$ 上放士兵,使得所有以 $u$ 为根的子树中的 **边** 被「瞭望」到,所需放置的士兵最少个数。 + + 若 $u$ 上不放置士兵,那么所有的 $v \in \text{son}(u)$ 上都得放士兵,才能使所有的边 $(u, v) \quad (v \in \text{son}(u))$ 被瞭望到; + + 若 $u$ 上放置了士兵,那么所有的 $v \in \text{son}(u)$ 上需不需要放置士兵是随意的。所以我们可以这么转移: + + $$ + \begin{aligned} + f(u, 0) & = \sum_{v \in \text{son}(u)} f(v, 1) \\\\ + f(u, 1) & = \sum_{v \in \text{son}(u)} \min f(v, 0), f(v, 1) + \end{aligned} + $$ + +2. [「一本通 5.2 练习 2」旅游规划](https://loj.ac/problem/10159) + + > 一个比较基础的换根dp。 + + 首先我们钦定一个根,对这棵有根树进行dfs;再换根,算出换根后的贡献。 + + 设 $f(u, 0)$ 表示以 $u$ 为根的子树中,最远的点的距离。 + + 设 $f(u, 1)$ 表示以 $u$ 为根的子树中,次远的点的距离。 + + 设 $g(u)$ 表示以 $u$ 为根的子树中,最远的点是在 **哪一个孩子的子树中**。 + + 设 $h(u)$ 表示不经过 $u$ 的子树,最远的点的距离。 + + 不难发现,原来的无根树的直径,为 $\max\\{f(i, 0), \max\\{f(i, 1), h(i)\\}\\}$,即 + + 从自己的某个孩子的子树中有一条路径一直延伸到另一个孩子,或者是这棵树的「另一半部分」。 + + 最后我们输出的,就是所有 $f(i, 0), \max\\{f(i, 1), h(i)\\}$ 等于直径长度的 $i$。 + + 在第一次dfs中,我们是 **从孩子往双亲** 转移的,方程是显然的: + + $$ + \begin{aligned} + f(u, 0) & = \max_{v \in \text{son}(u)}\\{f(v, 0) + 1\\} \\\\ + f(u, 1) & = \text{second}\max_{v \in \text{son}(u)}\\{f(v, 0) + 1\\} + \end{aligned} + $$ + + 转移时顺便更新 $g$ 即可。接下来我们要重点考虑的是 **第二次dfs** 会带来什么样的影响,也就是应该如何计算 $h$ 值。 + + 第二次dfs是自顶向下的,也就是 **从双亲往孩子** 转移的。 + + 从 $u$ 不经过子树的最长距离,肯定是 $u$ 的父亲 $x$ 能走一条特别远的路径出来。 + + 那么这条路径有两种可能:要么是 $x$ 往 $x$ 的孩子(但不是 $u$)的方向走,要么是 $x$ 往 $x$ 的父亲 $y$ 的方向走。 + + 如果 $u$ 是 $g$ 中记录的最大孩子,那么第一种可能,就只能走次大孩子,即 $f(x, 1)$;第二种可能就是 $h(x)$; + + 如果 $u$ 不是 $g$ 中记录的最大孩子,那么第一种可能,就能走最大孩子,即 $f(x, 0)$;第二种可能还是 $h(x)$; + + 那么我们可以推导出转移方程: + + $$ + h(v) = \begin{cases}\max\\{h(u), f(u, 1)\\} & v = g(u), u = \text{father}(v) \\\\ \max\\{h(u), f(u, 0)\\} & v \neq g(u), u = \text{father}(v)\end{cases} + $$ + +## 状压dp + +### **概述** + +假设有一行格子,要你黑白染色,你会怎么考虑表示这一行的状态呢? + +假设 $1$ 表示黑色,$0$ 表示白色,那这一行是不是就等价于一个二进制数呢? + +状压dp 就是通过用二进制数来表示状态的一种dp类型。 + +通常除了二进制,还有三进制(不能使用位运算,但是能暴力拆位)。 + +### **例题** + +1. [「SCOI2005」互不侵犯](https://www.luogu.com.cn/problem/P1896) + + > 状压dp 入门题。 + + 我们可以用一个 $n$ 位二进制数 $st$ 来表示这一行的状态,第 $i$ 位为 $1$ 表示这个格子上有王,为 $0$ 则表示这个格子是空的。 + + 显然如果一个状态 $st$ 是合法的,当且仅当 $st\&(st/2) = 0 \bigwedge st\&(st\cdot2) = 0$。 + + 然后还要枚举上一行的状态,判断上一行的状态会不会和这一行的状态冲突。 + + 状态转移方程便是: + + $$ + f(i, st, cnt) = \sum_{pr}f(i - 1, pr, cnt - \operatorname{popcount}(st)) + $$ + + 其中 $st, pr$ 均为合法状态,且 $st$ 与 $pr$ 不冲突,后文同。 + + $\operatorname{popcount}(x)$ 表示 $x$ 的二进制表示中 $1$ 的个数。 + + 答案即为 $\sum_{st}f(n, st, k)$。 + +2. [「一本通 5.4 练习 1」涂抹果酱](https://loj.ac/problem/10172) + + > 稍微有点复杂的三进制状态压缩。 + + 首先,一个状态是否是合法的,我们可以暴力求出这个状态的三进制表示。 + + 然后逐个判断相邻的两个位是否不同即可。 + + 其次,相邻两行的状态是否不会冲突,我们可以暴力同时取出这两个状态在三进制表示下的每一位,逐个比较是否相同即可。 + + 然后是转移,因为已经固定了第 $k$ 行,我们可以看做是把这个棋盘分割成了 **互不干扰** 的 $[1, k)$ 和 $(k, n]$ 两部分。 + + 分别求出来方案数然后 **相乘** 即可得到最终答案。 + + 剩下的部分与 [「SCOI2005」互不侵犯](https://www.luogu.com.cn/problem/P1896) 类似,就不再赘述。 + + 状态转移方程如下: + + $$ + f(i, st) = \sum_{pr}f(i - 1, pr) + $$ + + 答案即为 + + $$ + ans_{k}\cdot ans_{n - k + 1} = \left(\sum_{st}f(k, st)\right)\cdot\left(\sum_{st}f(n - k + 1, st)\right) + $$ + +3. [「APIO2007」动物园](https://www.luogu.com.cn/problem/P3622) + + > 比较有技巧性的一道状压dp题。 + + 我们可以发现,一个人只能看见长度为 $5$ 的「窗口」,所以我们可以利用这一点来进行状态压缩。我们把一个人能看到的动物压缩成一个二进制数,第 $i$ 位为 $1$ 表示能看见 $i$ 这个动物,否则就看不见这个动物。 + + 首先我们预处理出 $g(i, st)$,表示从第 $i$ 个动物开始,往后的 $5$ 个动物被移走,即移走状态为 $st$ 时的满意人数。 + + 其次我们设 $f(i, st)$ 表示 $[1, i]$,往后的 $5$ 个动物被移走,即移走状态为 $st$ 时的最大满意人数。 + + 可以推出状态转移方程: + + $$ + f(i, st) = \max\\{f(i - 1, st \cdot 2), f(i - 1, st \cdot 2 + 1) + g(i, st)\\} + $$ + + 我们从第 $1$ 个开始枚举,然后要满足第 $n + 1$ 个的状态和第 $1$ 个状态相同即可。 + +## 数位dp diff --git "a/drafts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\351\205\215\345\257\271\345\240\206\345\255\246\344\271\240\347\254\224\350\256\260.md" "b/drafts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\351\205\215\345\257\271\345\240\206\345\255\246\344\271\240\347\254\224\350\256\260.md" new file mode 100644 index 0000000..4915e26 --- /dev/null +++ "b/drafts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\351\205\215\345\257\271\345\240\206\345\255\246\344\271\240\347\254\224\350\256\260.md" @@ -0,0 +1,99 @@ +--- +title: 【学习笔记】配对堆学习笔记 +tags: + - 配对堆 + - 可并堆 +categories: + - 数据结构 +mathjax: true +toc: true +date: 2020-03-16 11:51:46 +password: +id: pairing-heap +--- + +配对堆是一种 **被猜想** 能均摊 $O(\log n)$ 删除,其余 **所有** 操作(包括但不限于 $\text{top}, \text{make-heap}, \text{decrease-key}, \text{meld}$ 等)均摊 $O(1)$ 的数据结构。 + +[pdf 论文](https://www.cs.cmu.edu/afs/cs.cmu.edu/user/sleator/www/papers/pairing-heaps.pdf) + + + +Warning: 这真的是一篇 **学习笔记**,只尝试着解释论文中一些(也许)不那么显而易见的内容,并不给出配对堆的完整实现。 + +1. 随意排列子结点链表最坏可使 $\text{delete min}$ 操作达到 $O(\sqrt{n})$。 + + 证明如下: + + 定义一棵 $n$ 个点的树中有 $d$ 个孩子的结点 $u$ 的势能 $\Phi(u) = 1 - \min\\{d, \lfloor\sqrt{n}\rfloor\\}$。 + + **我们将 $\text{delete min}$ 操作拆成 $\text{delete}$ 和 $\text{pair}$ 两个操作。** + + 那么将根节点 $root$ 移去时,根节点的势能原来是 $\Phi(root) = 1 - \lfloor\sqrt{n}\rfloor$,现在变成了 $0$,则最多会导致 $\sqrt{n}$ 的势能 **增加**。 + + 剩下的每个子结点的势能我们这么计算: + + 如果有已经达到 $\sqrt{n}$ 个子结点的某个点 $u \in son(root)$,则 $\Phi(u) = 1 - d$。根节点的移除会使 $\Phi(u)' = 1 - (d - 1) = 2 - d$,即 $\Phi(u)' = \Phi(u) + 1$。 + + 不难看出最多只会有 $\sqrt{n}$ 个这样的点,因此这样也最多会导致 $\sqrt{n}$ 的势能 **增加**。 + + 综上所述,$\text{delete}$ 操作最多会引起 $2\sqrt{n}$ 的势能 **增加**。 + + 不妨设移除根后有 $k$ 个儿子,则我们会用 $\lfloor\dfrac{k}{2}\rfloor + 1$ 次 $\text{link}$ 操作。 + + 注意到 $\text{link}$ 两个已经有 $\sqrt{n}$ 个儿子的结点 **并不会引起** 势能的变化,而最多会有 $\sqrt{n}$ 个这样的结点。 + + 所以 $\text{pair}$ 操作会导致 $\lfloor\dfrac{k}{2}\rfloor - \sqrt{n}$ 的势能 **减少**。 + + 那么 $\text{delete min}$ 操作的均摊复杂度是 $(\lfloor\dfrac{k}{2}\rfloor + 1) + 2\sqrt{n} - (\lfloor\dfrac{k}{2}\rfloor - \sqrt{n}) = O(\sqrt{n})$ 的。 + +2. 除 $\text{find min}$ 和 $\text{make heap}$ 操作均摊 $O(1)$ 外,其余操作的时间复杂度是均摊 $O(\log n)$ 的。 + + 证明如下: + + 设 $s(u)$ 表示 $u$ 所在子树的大小,定义一个结点 $u$ 的势能 $\Phi(u) = \sum_{v \in \text{subtree of } u}\log_2s(v)$。 + + *现在我们用 $\log$ 来简写 $\log_2$。* + + $\text{insert}, \text{meld}, \text{decrease key}$ 的时间复杂度比较好分析。 + + 当我们在 $\text{link}(u, v)$ 时,$\Phi(u)$ 和 $\Phi(v)$ 将会变化,不妨设 $v \to u$ + + 那么 $\Phi(v)$ 最多会有 $\log n$ 的势能 **增加**,$\Phi(u)$ 最多会有 $1$ 的势能增加。 + + 显然这三个操作的时间复杂度是均摊 $O(\log n)$ 的。 + + 下面我们来重点分析 $\text{delete min}$ 操作。 + + ![1.png](https://i.loli.net/2020/03/11/jbvr8atpmdXAqo2.png) + + + + 我们来看这么一个图,即 $\text{link}(x, y)$ 后的变化。 + + 我们先分析第一轮 $\text{pairing}$ 的时间复杂度。 + + 注:$x, y \in \mathbb{R_+}, x + y \le 1$ 时 $\log x + \log y$ 的最大值为 $-1$(初中内容)。 + + $\begin{aligned}\Delta\Phi = \Phi_1 - \Phi_2 & = rank(x) + rank(y) - rank(x') - rank(y') \\\\ & = \log (s(a) + s(b) + s(c) + 2) + \log(s(b) + s(c) + 1) - \log(s(a) + s(b) + 1) - \log(s(b) + s(c) + 1) \\\\ & = \log(s(a) + s(b) + 1) - \log(s(b) + s(c) + 1)\end{aligned}$ + + $\begin{aligned}\therefore & \log(s(a) + s(b) + 1) + \log(s(c)) - 2\log(s(a) + s(b) + s(c) + 2) \\\\ & = \log\dfrac{s(a) + s(b) + 1}{s(a) + s(b) + s(c) + 2} + \log\dfrac{s(c)}{s(a) + s(b) + s(c) + 2} \\\\ & \le -2 \end{aligned}$(这里用了刚才的 *注*) + + 又 $\log s(c) \le \log(s(b) + s(c) + 1)$ + + $\therefore \log(s(a) + s(b) + 1) - \log(s(b) + s(c) + 1) \le 2\log(s(a) + s(b) + s(c) + 2) - 2\log s(c) - 2$ + + $\because s(x) = s(a) + s(b) + s(c) + 2$ + + $\Delta\Phi \le 2\log s(x) - 2\log s(c) - 2$ + + $\therefore$ $2\log s(x) - 2\log s(c) - 2$ 是 $\text{link}$ 能达到的势能 **增加** 最大值。 + + 当且仅当 $c = \varnothing$ 时取得最大值。 + + 则总势能变化量 + + $\begin{aligned}\Sigma\Phi & = \sum\limits_{i - 1}^{k - 1}(2 \log s(x_{2i - 1}) - 2 \log s(x_{2i}) - 2) + 2 \log s(x_{2k - 1}) \\\\ & = \sum\limits_{i - 1}^{k - 1}(2 \log s(x_{2i - 1}) - 2 \log s(x_{2i})) + 2 \log s(x_{2k - 1}) - 2(k - 1) \\\\ & \le \sum\limits_{i = 1}^{k - 1}(2 \log s(x_{2i - 1}) - 2 \log s(x_{2i + 1})) + 2 \log s(x_{2k - 1}) - 2(k - 1) \\\\ & = 2 \log s(x_1) - 2(k - 1) \\\\ & = 2 \log n - 2(k - 1)\end{aligned}$ + + 而旧根的删除会使总势能 **减少** $\Phi(root) = \log n$,而最后只会有新根的势能会 **增加** $\Phi' = \log(n - 1)$。 + + 综上所述,$\text{delete min}$ 的时间复杂度为均摊 $O(\log n)$。 diff --git "a/drafts/\343\200\220\351\230\205\350\257\273\347\254\224\350\256\260\343\200\221\343\200\212C-\347\250\213\345\272\217\350\256\276\350\256\241\346\225\231\347\250\213\343\200\213\347\254\2548\347\253\240-\346\214\207\351\222\210.md" "b/drafts/\343\200\220\351\230\205\350\257\273\347\254\224\350\256\260\343\200\221\343\200\212C-\347\250\213\345\272\217\350\256\276\350\256\241\346\225\231\347\250\213\343\200\213\347\254\2548\347\253\240-\346\214\207\351\222\210.md" new file mode 100644 index 0000000..e4b6ad2 --- /dev/null +++ "b/drafts/\343\200\220\351\230\205\350\257\273\347\254\224\350\256\260\343\200\221\343\200\212C-\347\250\213\345\272\217\350\256\276\350\256\241\346\225\231\347\250\213\343\200\213\347\254\2548\347\253\240-\346\214\207\351\222\210.md" @@ -0,0 +1,218 @@ +--- +title: 【阅读笔记】《C++程序设计教程》第8章-指针 +tags: + - C++程序设计 + - 指针 +categories: + - 阅读笔记 +mathjax: true +toc: true +date: 2023-01-09 15:46:15 +password: +--- + +阅读《C++程序设计教程》(钱能 主编)摘抄/整理的笔记。 + + + +## 命令行参数 + +### 命令行参数的概念 + +main 函数是由操作系统调用的函数,在调用程序的过程中,可能需要传递参数,这就衍生出了“命令行参数”的概念。 + +```shell +copy filea fileb +type C:autoexec.bat +``` + +`copy` 命令需要两个参数,`type` 命令只需要一个参数。操作系统将命令行参数以字符串的形式传递给 main 函数。 + +```cpp +void main (int argc, char* argv[]) { // 等价于 char** argv + // ... +} +``` + +`argc` 是参数个数,`argv` 是参数数组。 + +`argv` 是一个字符指针数组,它把命令行参数以字符串常量的形式读入。 + +```shell +prog.exe C:\file1.img D:\abc\file2.img +``` + +其中 + +| | | 栈 | +| ---- | ------- | :----------------- | +| | - | ... | +| | env | | +| | argv[0] | **"prog.exe"** | +| main | argv[1] | "C:\file1.img" | +| | argv[2] | "D:\abc\file2.img" | +| | argv[3] | **NULL** | +| | argc | 3 | +| | - | 返回地址 | + +需要注意 `argv[0]` 和 `argv[argc]` 的值。 + +### 命令行参数的使用形式 + +有四种声明 main 函数的方法: + +```cpp +void main() +``` +```cpp +void main(int argc) +``` +```cpp +void main(int argc, char* argv[]) +``` +```cpp +void main(int argc, char* argv[], char* env[]) +``` + +`env[]` 是环境变量。 + +如果单个命令行参数中带有空格,为了不被识别成两个命令行参数,则需要用双引号括起来。例如 + +```shell +prog.exe how are you "How are you" +``` + +上述命令有五个命令行参数。 + +### main 函数的返回 + +在函数里直接 `exit(val);` 来 **结束程序**(而不是返回到 main 函数),返回 `val` 给操作系统。使用 `exit()` 时,可以不论 main 函数的返回类型。 + +## 函数指针 + +由于函数的代码存放在内存中的代码区,也有地址,因此可以设计指针指向它们。通过函数指针,我们可以调用相应的函数。 + +### 定义函数指针 + +```cpp +int (*func)(char a, char b); +``` + +`int` 为函数的范围类型,`*func` 表示定义的是一个指针。这个函数指针可以指向所有参数为两个字符的函数。 + +注意这与返回值为指针的函数的定义有所不同: + +```cpp +int* func (char a, char b); +``` + +上面这行代码定义的是一个 **返回值为整形指针的函数**。这个差异是因为 `()` 的优先级大于 `*`。 + +### 函数指针的赋值与调用 + +```cpp +int fn1(char x, char y); +int* fn2(char x, char y); +int fn3(int a); + +int (*fp1)(char a, char b); +int (*fp2)(int s); + +fp1 = fn1; // 正确。 +fp1 = fn2; // 错误。函数的类型与函数指针的类型不同。 +fp2 = fn3; // 正确。 +fp2 = fp1; // 错误。函数指针类型不同。 +fp2 = fn3(5); // 错误。fn3(5) 是函数的调用,实际上是一个整型! +``` + +只有 **相同返回类型、相同参数种类及对应顺序** 的函数可以被赋值给函数指针。也只有这样的函数指针可以互相赋值。 + +函数名加上括号就成了函数的调用,所以上面的例子中的 `fn3(5)` 是一个整型数,而非一个函数。 + +尽管函数指针与其他数据类型的指针都是地址,但在类型上有很大的区别。**两类指针之间不允许互相赋值,甚至显式转换也不行。**因为函数指针指向的是代码区,其他数据类型的指针指向的是数据区、栈区和堆区。 + +可以用 `typedef` 来简化函数指针的定义: + +```cpp +typedef int(*FUNC)(int a, int b); // 声明 FUNC 是一个函数指针类型 +FUNC funp; // funp 是一个返回整型,具有两个整型参数的函数指针 +``` + +`FUNC` 不是一个函数指针变量,它是一种指针 **类型**。`funp` 是一个函数指针变量。 + +### 函数指针用作函数参数 + +看一个例子: + +```cpp +#include +#include +using namespace std; + +// double(*func)(double), 不需要给形参 +double sigma(double(*func)(double), double dl, double du) { + double dt = 0.0; + for (double d = dl; d < du; d += 0.1) + dt += func(d); + return dt; +} + +void main() { + double dsum; + dsum = sigma(sin, 0.1, 1.0); + cout << "the sum of sin from 0.1 to 1.0 is " << dsum << endl; + dsum = sigma(cos, 0.5, 3.0); + cout << "the sum of cos from 0.5 to 3.0 is " << dsum << endl; +} +``` + +上述例子中,函数 `sigma()` 的第一个参数是一个函数指针,它指向返回 double 类型的具有一个 double 类型参数的函数。`sin()` 和 `cos()` 都是这样的函数,因此可以调用。 + +### 由函数指针构成的指针数组 + +看一个例子: + +```cpp +#include +using namespace std; + +typedef void (*MenuFun)(); +void f1() { cout << "good" << endl; } +void f2() { cout << "better" << endl; } +void f3() { cout << "best" << endl; } + +MenuFun fun[] = { f1, f2, f3 }; + +void main() { + int choice = -1; + cin >> choice; + switch (choice) { + case 1: fun[0](); break; + case 2: fun[1](); break; + case 3: fun[2](); break; + case 0: return; + default: cout <<"Entered wrong key." << endl; + } +} +``` + +`fun[]` 就是一个由函数指针组成的数组。 + +### 函数的返回类型可以是函数指针 + +例如: + +```cpp +typedef int (*SIG)(); // 声明了一个返回整型的无参数的函数的函数指针 +typedef void (*SIGARG)(); // 声明了一个无返回的无参数的函数的函数指针 +SIG signal(int, SIGARG)(); // 声明了一个返回 SIG 类型的有两个参数的函数指针 +``` + +## 小结 + +指针是C++的一大特色,通过合理地运用指针,可以直接对内存进行操作。指针功能最强,但又最危险。我认为,学习了指针相关知识之后,让我对“内存”等概念有了更深刻的了解。一个变量、一个函数都可以对应内存中的一个地址。 + +指针数组不等于二维数组。不严谨地来解释,二维数组是定长的,指针数组中的每个元素可以是“不定长的”,因为它们指向的内存空间可以是不连续的。 + +函数指针加上指针数组,可以使我们方便地调用一系列函数。 + diff --git "a/drafts/\343\200\220\351\232\217\347\254\224\343\200\2212024\345\271\264\351\232\217\347\254\224.md" "b/drafts/\343\200\220\351\232\217\347\254\224\343\200\2212024\345\271\264\351\232\217\347\254\224.md" new file mode 100644 index 0000000..74ffd95 --- /dev/null +++ "b/drafts/\343\200\220\351\232\217\347\254\224\343\200\2212024\345\271\264\351\232\217\347\254\224.md" @@ -0,0 +1,37 @@ +--- +title: 【随笔】2024 年随笔 +tags: + - 生活 +categories: + - 随笔 +mathjax: true +toc: true +date: 2024-04-20 23:06:40 +password: +id: 2024Journal +--- + +都是些碎碎念而已。 + + + +## 2024-04-20 + +今天复习了一早上 [TCS](http://itcs.finite-dimensional.space/) 和一下午的[软工](https://leverimmy.top/2024/04/20/SE/),为了两门期中考试,绞尽脑汁往脑子里塞进更多的内容。脑子在不停地转呀转呀转,一直在尝试理解讲义上的内容;但效率有多高却又是另一回事了。“Oracle”“relativization”“NP-hard”;“user story”“sprint”“issue board”. 这些名词在我脑子里围着圈圈跳着舞,也不知道它们为什么如此开心。 + +瘫在北馆的椅子上,看着 TCS 讲义上的各种构造和证明,我感受到了时间的流逝:人真的会一天一天地老去。曾经的我还自诩聪明,从 Clever_Jimmy 这个我常用的昵称中就可看出(虽然这是我小学时一个培优班英语老师取的);但现在随便一个证明理解起来都觉得费劲。突然有种感觉,好像自己的最聪明的几年被荒废了。但我有时还是很不甘心:虽然理论计算机科学是属于“聪明人”的领域,但我等凡人想窥见一隅总还是可以的吧? + +再谈到自己最近的状态。每天浑浑噩噩,我有种找不着北的感觉。毽球队训练我也没参加了,软工的代码任务我也开始变得拖沓了,甚至有些课的作业都是赶 DDL 完成的。好消息是,我有三门前八周的课程结课了,后八周能轻松很多;况且有一个五一假期,希望我能重拾自己节奏吧。 + +还有未来发展。我已经大二下了,似乎对我的未来开始有了一种初步的、模糊的感觉。在我的梦想中,我想做理论方面的研究,例如算法复杂性理论;但现实是残酷的,我本身资质就很平庸,做理论很难不延毕。同时,做理论似乎未来的出路只能是在高校找教职。另一方面,我希望能做人机交互相关研究,这样能够进入与产业融合,拥有一定的应用前景。除此之外,我还想过本科毕业就业,因为我很喜欢写代码,即使我有代码洁癖,也有一点点完美主义,但在闲暇时光我也一直希望为开源社区做贡献;可是,相较于我认识的一些学长,我认为我没有能力和资格去当一个不平庸的开发者。 + +我仍然无所适从。我到底想要过一个怎样的人生?保研还是工作?读博还是读硕?这些选择会对我的人生造成多大的影响呢?不知道,感觉我的人生仍不是定数。 + +随手写下两句, + +> The skies are dark and the world collides, +> +> Yet, there's nowhere for me to hide. + +## 2024-04-21 + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..4de252d --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4342 @@ +{ + "name": "hexo-site", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "hexo-site", + "version": "0.0.0", + "dependencies": { + "bulma-stylus": "^0.8.0", + "hexo": "^6.2.0", + "hexo-component-inferno": "^1.2.0", + "hexo-deployer-git": "^3.0.0", + "hexo-generator-archive": "^1.0.0", + "hexo-generator-category": "^1.0.0", + "hexo-generator-feed": "^3.0.0", + "hexo-generator-index": "^2.0.0", + "hexo-generator-searchdb": "^1.4.1", + "hexo-generator-tag": "^1.0.0", + "hexo-lazyload-image": "^1.0.13", + "hexo-pagination": "^2.0.0", + "hexo-renderer-ejs": "^2.0.0", + "hexo-renderer-inferno": "^0.1.3", + "hexo-renderer-pandoc": "^0.4.0", + "hexo-renderer-stylus": "^2.1.0", + "hexo-server": "^3.0.0", + "hexo-theme-landscape": "^0.0.3", + "inferno": "^7.3.3", + "inferno-create-element": "^7.3.3", + "semver": "^7.3.7" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dependencies": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.23.2", + "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.23.2.tgz", + "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.2", + "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.23.2.tgz", + "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.2", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dependencies": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.15", + "resolved": "https://registry.npmmirror.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.15", + "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmmirror.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz", + "integrity": "sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmmirror.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.4.3", + "resolved": "https://registry.npmmirror.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.3.tgz", + "integrity": "sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmmirror.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmmirror.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.23.0", + "resolved": "https://registry.npmmirror.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "dependencies": { + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.0", + "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.22.20", + "resolved": "https://registry.npmmirror.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.22.20", + "resolved": "https://registry.npmmirror.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.22.15", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.22.20", + "resolved": "https://registry.npmmirror.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "dependencies": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.2", + "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.23.2.tgz", + "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmmirror.com/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.22.15", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz", + "integrity": "sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.22.15", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz", + "integrity": "sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmmirror.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz", + "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz", + "integrity": "sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz", + "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.23.2", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.2.tgz", + "integrity": "sha512-BBYVGxbDVHfoeXbOwcagAkOQAm9NxoTdMGfTqghu1GrvadSaw6iW3Je6IcL5PNOw8VwjxqBECXy50/iCQSY/lQ==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz", + "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz", + "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.23.0", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.0.tgz", + "integrity": "sha512-cOsrbmIOXmf+5YbL99/S49Y3j46k/T16b9ml8bm9lP6N9US5iQ2yBK7gpui1pg0V/WMcXdkfKbTb7HXq9u+v4g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz", + "integrity": "sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.22.11", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.11.tgz", + "integrity": "sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.11", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.22.15", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz", + "integrity": "sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", + "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.23.0", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.0.tgz", + "integrity": "sha512-vaMdgNXFkYrB+8lbgniSYWHsgqK5gjaMNcc84bMIOMRLH0L9AqYq3hwMdvnyqj1OPqea8UtjPEuS/DCenah1wg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz", + "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz", + "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.22.11", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.11.tgz", + "integrity": "sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz", + "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.22.11", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.11.tgz", + "integrity": "sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.22.15", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz", + "integrity": "sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz", + "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.22.11", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.11.tgz", + "integrity": "sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz", + "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.22.11", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.11.tgz", + "integrity": "sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz", + "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.23.0", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.0.tgz", + "integrity": "sha512-xWT5gefv2HGSm4QHtgc1sYPbseOyf+FFDo2JbpE25GWl5BqTGO9IMwTYJRoIdjsF85GE+VegHxSCUt5EvoYTAw==", + "dependencies": { + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.23.0", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz", + "integrity": "sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==", + "dependencies": { + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.23.0", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.0.tgz", + "integrity": "sha512-qBej6ctXZD2f+DhlOC9yO47yEYgUh5CZNz/aBoH4j/3NOlRfJXJbY7xDQCqQVf9KbrqGzIWER1f23doHGrIHFg==", + "dependencies": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz", + "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==", + "dependencies": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz", + "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.22.11", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.11.tgz", + "integrity": "sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.22.11", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.11.tgz", + "integrity": "sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.22.15", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.15.tgz", + "integrity": "sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q==", + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz", + "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.22.11", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.11.tgz", + "integrity": "sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.23.0", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.0.tgz", + "integrity": "sha512-sBBGXbLJjxTzLBF5rFWaikMnOGOk/BmK6vVByIdEggZ7Vn6CvWXZyRkkLFK6WE0IF8jSliyOkUN6SScFgzCM0g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.22.15", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz", + "integrity": "sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz", + "integrity": "sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.22.11", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.11.tgz", + "integrity": "sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.11", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz", + "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.22.10", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz", + "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz", + "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz", + "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz", + "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz", + "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz", + "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz", + "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.22.10", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz", + "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz", + "integrity": "sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz", + "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz", + "integrity": "sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.23.2", + "resolved": "https://registry.npmmirror.com/@babel/preset-env/-/preset-env-7.23.2.tgz", + "integrity": "sha512-BW3gsuDD+rvHL2VO2SjAUNTBe5YrjsTiDyqamPDWY723na3/yPQ65X5oQkFVJZ0o50/2d+svm1rkPoJeR1KxVQ==", + "dependencies": { + "@babel/compat-data": "^7.23.2", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.15", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.15", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.22.5", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.22.5", + "@babel/plugin-transform-async-generator-functions": "^7.23.2", + "@babel/plugin-transform-async-to-generator": "^7.22.5", + "@babel/plugin-transform-block-scoped-functions": "^7.22.5", + "@babel/plugin-transform-block-scoping": "^7.23.0", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-class-static-block": "^7.22.11", + "@babel/plugin-transform-classes": "^7.22.15", + "@babel/plugin-transform-computed-properties": "^7.22.5", + "@babel/plugin-transform-destructuring": "^7.23.0", + "@babel/plugin-transform-dotall-regex": "^7.22.5", + "@babel/plugin-transform-duplicate-keys": "^7.22.5", + "@babel/plugin-transform-dynamic-import": "^7.22.11", + "@babel/plugin-transform-exponentiation-operator": "^7.22.5", + "@babel/plugin-transform-export-namespace-from": "^7.22.11", + "@babel/plugin-transform-for-of": "^7.22.15", + "@babel/plugin-transform-function-name": "^7.22.5", + "@babel/plugin-transform-json-strings": "^7.22.11", + "@babel/plugin-transform-literals": "^7.22.5", + "@babel/plugin-transform-logical-assignment-operators": "^7.22.11", + "@babel/plugin-transform-member-expression-literals": "^7.22.5", + "@babel/plugin-transform-modules-amd": "^7.23.0", + "@babel/plugin-transform-modules-commonjs": "^7.23.0", + "@babel/plugin-transform-modules-systemjs": "^7.23.0", + "@babel/plugin-transform-modules-umd": "^7.22.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.22.5", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", + "@babel/plugin-transform-numeric-separator": "^7.22.11", + "@babel/plugin-transform-object-rest-spread": "^7.22.15", + "@babel/plugin-transform-object-super": "^7.22.5", + "@babel/plugin-transform-optional-catch-binding": "^7.22.11", + "@babel/plugin-transform-optional-chaining": "^7.23.0", + "@babel/plugin-transform-parameters": "^7.22.15", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.11", + "@babel/plugin-transform-property-literals": "^7.22.5", + "@babel/plugin-transform-regenerator": "^7.22.10", + "@babel/plugin-transform-reserved-words": "^7.22.5", + "@babel/plugin-transform-shorthand-properties": "^7.22.5", + "@babel/plugin-transform-spread": "^7.22.5", + "@babel/plugin-transform-sticky-regex": "^7.22.5", + "@babel/plugin-transform-template-literals": "^7.22.5", + "@babel/plugin-transform-typeof-symbol": "^7.22.5", + "@babel/plugin-transform-unicode-escapes": "^7.22.10", + "@babel/plugin-transform-unicode-property-regex": "^7.22.5", + "@babel/plugin-transform-unicode-regex": "^7.22.5", + "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "@babel/types": "^7.23.0", + "babel-plugin-polyfill-corejs2": "^0.4.6", + "babel-plugin-polyfill-corejs3": "^0.8.5", + "babel-plugin-polyfill-regenerator": "^0.5.3", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmmirror.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/register": { + "version": "7.22.15", + "resolved": "https://registry.npmmirror.com/@babel/register/-/register-7.22.15.tgz", + "integrity": "sha512-V3Q3EqoQdn65RCgTLwauZaTfd1ShhwPmbBv+1dkZV/HpCGMKVyn6oFcRlI7RaKqiDQjX2Qd3AuoEguBgdjIKlg==", + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.5", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmmirror.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + }, + "node_modules/@babel/runtime": { + "version": "7.23.2", + "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.23.2.tgz", + "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.2", + "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/a-sync-waterfall": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==" + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmmirror.com/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/archy/-/archy-1.0.0.tgz", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmmirror.com/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/babel-plugin-inferno": { + "version": "6.7.0", + "resolved": "https://registry.npmmirror.com/babel-plugin-inferno/-/babel-plugin-inferno-6.7.0.tgz", + "integrity": "sha512-CLDNIoctex09NRbPP3GOq+B18Tj0luQOOevTAQzKWkwa45SqeoeFCY1XBq7p2TXrmifUAXbuCRrFKmA05codAA==", + "dependencies": { + "@babel/plugin-syntax-jsx": "^7", + "@babel/types": "^7" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.6", + "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.6.tgz", + "integrity": "sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q==", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.4.3", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.8.6", + "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.6.tgz", + "integrity": "sha512-leDIc4l4tUgU7str5BWLS2h8q2N4Nf6lGZP6UrNDxdtfF2g69eJ5L0H7S8A5Ln/arfFAfHor5InAdZuIOwZdgQ==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.3", + "core-js-compat": "^3.33.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.5.3", + "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.3.tgz", + "integrity": "sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.3" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmmirror.com/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.22.1", + "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "dependencies": { + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/bulma-stylus": { + "version": "0.8.0", + "resolved": "https://registry.npmmirror.com/bulma-stylus/-/bulma-stylus-0.8.0.tgz", + "integrity": "sha512-9Q9BMPeHFyJ5EWh/tJPCcLDYEovKzUBOyMHsKEIyxSYEKG8wqt9RVuTumaJ2AfDjyHC9OifWKOfJSweKYD5IMQ==" + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001557", + "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001557.tgz", + "integrity": "sha512-91oR7hLNUP3gG6MLU+n96em322a8Xzes8wWdBKhLgUoiJsAF5irZnxSUCbc+qUZXNnPCfUwLOi9ZCZpkvjQajw==" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmmirror.com/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" + }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmmirror.com/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmmirror.com/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmmirror.com/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/core-js-compat": { + "version": "3.33.1", + "resolved": "https://registry.npmmirror.com/core-js-compat/-/core-js-compat-3.33.1.tgz", + "integrity": "sha512-6pYKNOgD/j/bkC5xS5IIg6bncid3rfrI42oBH1SQJbsmYPKF7rhzcFzYCcxYMmNQQ0rCEB8WqpW7QHndOggaeQ==", + "dependencies": { + "browserslist": "^4.22.1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/css/-/css-3.0.0.tgz", + "integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==", + "dependencies": { + "inherits": "^2.0.4", + "source-map": "^0.6.1", + "source-map-resolve": "^0.6.0" + } + }, + "node_modules/cuid": { + "version": "2.1.8", + "resolved": "https://registry.npmmirror.com/cuid/-/cuid-2.1.8.tgz", + "integrity": "sha512-xiEMER6E7TlTPnDxrM4eRiC6TRgjNX9xzEZ5U/Se2YJKr7Mq4pJn/2XEHjl3STcSh96GmkHPcBXLES8M29wyyg==", + "deprecated": "Cuid and other k-sortable and non-cryptographic ids (Ulid, ObjectId, KSUID, all UUIDs) are all insecure. Use @paralleldrive/cuid2 instead." + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmmirror.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "engines": { + "node": ">=8" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmmirror.com/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/ejs": { + "version": "3.1.9", + "resolved": "https://registry.npmmirror.com/ejs/-/ejs-3.1.9.tgz", + "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.569", + "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.569.tgz", + "integrity": "sha512-LsrJjZ0IbVy12ApW3gpYpcmHS3iRxH4bkKOW98y1/D+3cvDUWGcbzbsFinfUS8knpcZk/PG/2p/RnkMCYN7PVg==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "engines": { + "node": ">=0.12" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmmirror.com/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-equals": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/fast-equals/-/fast-equals-3.0.3.tgz", + "integrity": "sha512-NCe8qxnZFARSHGztGMZOO/PC1qa5MIFB5Hp66WdzbCRAz8U8US3bx1UTgLS49efBQPcUtO9gf5oVEY8o7y/7Kg==" + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmmirror.com/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmmirror.com/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hexo": { + "version": "6.3.0", + "resolved": "https://registry.npmmirror.com/hexo/-/hexo-6.3.0.tgz", + "integrity": "sha512-4Jq+rWd8sYvR1YdIQyndN/9WboQ/Mqm6eax8CjrjO+ePFm2oMVafSOx9WEyJ42wcLOHjfyMfnlQhnUuNmJIpPg==", + "dependencies": { + "abbrev": "^1.1.1", + "archy": "^1.0.0", + "bluebird": "^3.7.2", + "hexo-cli": "^4.3.0", + "hexo-front-matter": "^3.0.0", + "hexo-fs": "^3.1.0", + "hexo-i18n": "^1.0.0", + "hexo-log": "^3.2.0", + "hexo-util": "^2.7.0", + "js-yaml": "^4.1.0", + "js-yaml-js-types": "^1.0.0", + "micromatch": "^4.0.4", + "moize": "^6.1.0", + "moment": "^2.29.1", + "moment-timezone": "^0.5.34", + "nunjucks": "^3.2.3", + "picocolors": "^1.0.0", + "pretty-hrtime": "^1.0.3", + "resolve": "^1.22.0", + "strip-ansi": "^6.0.0", + "text-table": "^0.2.0", + "tildify": "^2.0.0", + "titlecase": "^1.1.3", + "warehouse": "^4.0.2" + }, + "bin": { + "hexo": "bin/hexo" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/hexo-cli": { + "version": "4.3.1", + "resolved": "https://registry.npmmirror.com/hexo-cli/-/hexo-cli-4.3.1.tgz", + "integrity": "sha512-nYe7yJhXT7MwlDEpIAjneMfz0wnWTdIhRv+cVW2OPTw8JtG2X+8Y/sYhPDvQz/ZqjFRZ4qgiKFXN5orFJ/u1vg==", + "dependencies": { + "abbrev": "^2.0.0", + "bluebird": "^3.7.2", + "command-exists": "^1.2.9", + "hexo-fs": "^4.1.1", + "hexo-log": "^4.0.1", + "hexo-util": "^2.5.0", + "minimist": "^1.2.5", + "picocolors": "^1.0.0", + "resolve": "^1.20.0", + "tildify": "^2.0.0" + }, + "bin": { + "hexo": "bin/hexo" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/hexo-cli/node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/hexo-cli/node_modules/hexo-fs": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/hexo-fs/-/hexo-fs-4.1.1.tgz", + "integrity": "sha512-aDysNTyv8ElcerbFVbPLRXnYt+QDY6gAOZZ5DLbCxudY0Ywppqd+uZ03gZ2BDypIBvmNB27WYWYz76M+Yv/YXw==", + "dependencies": { + "bluebird": "^3.7.2", + "chokidar": "^3.5.3", + "graceful-fs": "^4.2.10", + "hexo-util": "^2.7.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/hexo-cli/node_modules/hexo-log": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/hexo-log/-/hexo-log-4.1.0.tgz", + "integrity": "sha512-i2Sgxk8Cgx5viSjq5qW5N/rBFfwoCKQcH8qnnW1fawCapcdEAhIsq+Y3vbrs9bssyDlyU6Vqm4oQmosREaNI7Q==", + "dependencies": { + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/hexo-component-inferno": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/hexo-component-inferno/-/hexo-component-inferno-1.2.0.tgz", + "integrity": "sha512-UGrkw14QwnlOsMkLbdD6fA+ZJWYRwUaWojwN7f2wKP/wNZMCYWDDjiB02rqZXeOwOEXm4HNQmVboS/oQUEzYTw==", + "dependencies": { + "ajv": "^8.8.2", + "hexo": "^6.0.0", + "hexo-pagination": "^2.0.0", + "hexo-util": "^2.2.0", + "inferno": "^7.3.3", + "inferno-create-element": "^7.3.3", + "js-yaml": "^4.1.0", + "moment": "^2.24.0", + "semver": "^7.1.1" + }, + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/hexo-deployer-git": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/hexo-deployer-git/-/hexo-deployer-git-3.0.0.tgz", + "integrity": "sha512-U2Xewjab+rvUDNTcuYYnOxitkDXL3f5VMUH32jKDHs3OC4YFVGRoEaTTDVHskqr3KRi78Wohjc6BSRHOoG3oxA==", + "dependencies": { + "bluebird": "^3.5.0", + "chalk": "^4.0.0", + "hexo-fs": "^3.0.1", + "hexo-util": "^2.1.0", + "moment": "^2.18.0", + "nunjucks": "^3.2.1" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/hexo-front-matter": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/hexo-front-matter/-/hexo-front-matter-3.0.0.tgz", + "integrity": "sha512-hSQTPUmB/BCe1BFYmXRkPyLk8rqbBqHCQq+rjwwOJuEfOADrFaVK2VPZb90tJzPyXE1xSxpgCxE/AZq0CyTVwg==", + "dependencies": { + "js-yaml": "^4.1.0" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/hexo-fs": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/hexo-fs/-/hexo-fs-3.1.0.tgz", + "integrity": "sha512-SfoDH7zlU9Iop+bAfEONXezbNIkpVX1QqjNCBYpapilZR+xVOCfTEdlNixanrKBbLGPb2fXqrdDBFgrKuiVGQQ==", + "dependencies": { + "bluebird": "^3.5.1", + "chokidar": "^3.0.0", + "graceful-fs": "^4.1.11", + "hexo-util": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/hexo-generator-archive": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/hexo-generator-archive/-/hexo-generator-archive-1.0.0.tgz", + "integrity": "sha512-24TeanDGpMBUIq37DHpSESQbeN6ssZ06edsGSI76tN4Yit50TgsgzP5g5DSu0yJk0jUtHJntysWE8NYAlFXibA==", + "dependencies": { + "hexo-pagination": "1.0.0" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/hexo-generator-archive/node_modules/hexo-pagination": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/hexo-pagination/-/hexo-pagination-1.0.0.tgz", + "integrity": "sha512-miEVFgxchPr2qNWxw0JWpJ9R/Yaf7HjHBZVjvCCcqfbsLyYtCvIfJDxcEwz1sDOC/fLzYPqNnhUI73uNxBHRSA==", + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/hexo-generator-category": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/hexo-generator-category/-/hexo-generator-category-1.0.0.tgz", + "integrity": "sha512-kmtwT1SHYL2ismbGnYQXNtqLFSeTdtHNbJIqno3LKROpCK8ybST5QVXF1bZI9LkFcXV/H8ilt8gfg4/dNNcQQQ==", + "dependencies": { + "hexo-pagination": "1.0.0" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/hexo-generator-category/node_modules/hexo-pagination": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/hexo-pagination/-/hexo-pagination-1.0.0.tgz", + "integrity": "sha512-miEVFgxchPr2qNWxw0JWpJ9R/Yaf7HjHBZVjvCCcqfbsLyYtCvIfJDxcEwz1sDOC/fLzYPqNnhUI73uNxBHRSA==", + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/hexo-generator-feed": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/hexo-generator-feed/-/hexo-generator-feed-3.0.0.tgz", + "integrity": "sha512-Jo35VSRSNeMitS2JmjCq3OHAXXYU4+JIODujHtubdG/NRj2++b3Tgyz9pwTmROx6Yxr2php/hC8og5AGZHh8UQ==", + "dependencies": { + "hexo-util": "^2.1.0", + "nunjucks": "^3.0.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/hexo-generator-index": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/hexo-generator-index/-/hexo-generator-index-2.0.0.tgz", + "integrity": "sha512-q/29Vj9BZs0dwBcF+s9IT8ymS4aYZsDwBEYDnh96C8tsX+KPY5v6TzCdttz58BchifaJpP/l9mi6u9rZuYqA0g==", + "dependencies": { + "hexo-pagination": "1.0.0", + "timsort": "^0.3.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/hexo-generator-index/node_modules/hexo-pagination": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/hexo-pagination/-/hexo-pagination-1.0.0.tgz", + "integrity": "sha512-miEVFgxchPr2qNWxw0JWpJ9R/Yaf7HjHBZVjvCCcqfbsLyYtCvIfJDxcEwz1sDOC/fLzYPqNnhUI73uNxBHRSA==", + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/hexo-generator-searchdb": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/hexo-generator-searchdb/-/hexo-generator-searchdb-1.4.1.tgz", + "integrity": "sha512-7m8IBpZbI6iKb2jRYxs4pghD6Ln8ylQSRGl6MIC4G9wws21vYSXSD8rvC3MoCO+pWBHs6E/mTA/rjG+p2AZfVg==", + "dependencies": { + "nunjucks": "^3.2.2" + } + }, + "node_modules/hexo-generator-tag": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/hexo-generator-tag/-/hexo-generator-tag-1.0.0.tgz", + "integrity": "sha512-JDoB2T1EncRlyGSjuAhkGxRfKkN8tq0i8tFlk9I4q2L6iYxPaUnFenhji0oxufTADC16/IchuPjmMk//dt8Msg==", + "dependencies": { + "hexo-pagination": "1.0.0" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/hexo-generator-tag/node_modules/hexo-pagination": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/hexo-pagination/-/hexo-pagination-1.0.0.tgz", + "integrity": "sha512-miEVFgxchPr2qNWxw0JWpJ9R/Yaf7HjHBZVjvCCcqfbsLyYtCvIfJDxcEwz1sDOC/fLzYPqNnhUI73uNxBHRSA==", + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/hexo-i18n": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/hexo-i18n/-/hexo-i18n-1.0.0.tgz", + "integrity": "sha512-yw90JHr7ybUHN/QOkpHmlWJj1luVk5/v8CUU5NRA0n4TFp6av8NT7ujZ10GDawgnQEdMHnN5PUfAbNIVGR6axg==", + "dependencies": { + "sprintf-js": "^1.0.3" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/hexo-lazyload-image": { + "version": "1.0.13", + "resolved": "https://registry.npmmirror.com/hexo-lazyload-image/-/hexo-lazyload-image-1.0.13.tgz", + "integrity": "sha512-6Xz+V3Rwr3zuUTo4rGnVYa2QBBOAmdjYWeVxZql1TD2CteD8gh2L7EP9d7QsFfwtMDK3BTGY2FETCdtwZx8cRw==", + "dependencies": { + "uglify-js": "^3.0.27" + } + }, + "node_modules/hexo-log": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/hexo-log/-/hexo-log-3.2.0.tgz", + "integrity": "sha512-fk7jOW3hvKiAv4Q/d8UxaQlARwcv+5KjGcnxexUrqBqyWbMCLmw7jhMHTSRLNNQpaoTlF5ff+kQkPi4yhp9iag==", + "dependencies": { + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/hexo-pagination": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/hexo-pagination/-/hexo-pagination-2.0.0.tgz", + "integrity": "sha512-ZZQli5UwFWTW6bJNF4zwp2PCeGsipgoPxadud8+cPPxvygTP5GjTS5eVWcUTcfEaCluP+O1maxZCCWmYQoJkiQ==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/hexo-renderer-ejs": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/hexo-renderer-ejs/-/hexo-renderer-ejs-2.0.0.tgz", + "integrity": "sha512-qCjE1IdwgDgv65qyb0KMVCwCdSVAkH0vwAe9XihjvaKWkmb9dtt8DgErOdqCXn0HReSyWiEVP2BrLRj3gyHwOQ==", + "dependencies": { + "ejs": "^3.1.6" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/hexo-renderer-inferno": { + "version": "0.1.3", + "resolved": "https://registry.npmmirror.com/hexo-renderer-inferno/-/hexo-renderer-inferno-0.1.3.tgz", + "integrity": "sha512-crtisttRWnpNKmhscYPTDGOIT7txTQPre9QU4+WkIHKKO7RCjjIT+Qt62GzX5mb0px/BLd2P4gZ5TItNY6ig1g==", + "dependencies": { + "@babel/core": "^7.7.7", + "@babel/preset-env": "^7.7.7", + "@babel/register": "^7.7.7", + "babel-plugin-inferno": "^6.1.0", + "inferno": "^7.3.3", + "inferno-create-element": "^7.3.3", + "inferno-server": "^7.3.3" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/hexo-renderer-pandoc": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/hexo-renderer-pandoc/-/hexo-renderer-pandoc-0.4.0.tgz", + "integrity": "sha512-e913A2EZbhwbIfg+QvYUalEPHtK5qs9Rqj3ZrsQ3cYTbbiETMWhUQ7bzSlgUeh639eL0UDuBmv2vrEqj5RBchg==" + }, + "node_modules/hexo-renderer-stylus": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/hexo-renderer-stylus/-/hexo-renderer-stylus-2.1.0.tgz", + "integrity": "sha512-Nef4YCr7JX8jaRaByhzXMSsWnDed+RgJj6aU/ARnYu3Bn5xz/qRz52VJG7KqD0Xuysxa9TIBdVUgNzBrSFn3DQ==", + "dependencies": { + "nib": "^1.2.0", + "stylus": "^0.57.0" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/hexo-server": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/hexo-server/-/hexo-server-3.0.0.tgz", + "integrity": "sha512-u4s0ty9Aew6jV+a9oMrXBwhrRpUQ0U8PWM/88a5aHgDru58VY81mVrxOFxs788NAsWQ8OvsJtF5m7mnXoRnSIA==", + "dependencies": { + "bluebird": "^3.5.5", + "compression": "^1.7.4", + "connect": "^3.7.0", + "mime": "^3.0.0", + "morgan": "^1.9.1", + "open": "^8.0.9", + "picocolors": "^1.0.0", + "serve-static": "^1.14.1" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/hexo-theme-landscape": { + "version": "0.0.3", + "resolved": "https://registry.npmmirror.com/hexo-theme-landscape/-/hexo-theme-landscape-0.0.3.tgz", + "integrity": "sha512-b0Di+TUVs4ESrNX4ULEh9uQmADpO6kr10rIJ2OGZM8suNQNFKdxn+vJUjnLfKkCPJAfVmS7/S83KCNYe4tpoNw==" + }, + "node_modules/hexo-util": { + "version": "2.7.0", + "resolved": "https://registry.npmmirror.com/hexo-util/-/hexo-util-2.7.0.tgz", + "integrity": "sha512-hQM3h34nhDg0bSe/Tg1lnpODvNkz7h2u0+lZGzlKL0Oufp+5KCAEUX9wal7/xC7ax3/cwEn8IuoU75kNpZLpJQ==", + "dependencies": { + "bluebird": "^3.5.2", + "camel-case": "^4.0.0", + "cross-spawn": "^7.0.0", + "deepmerge": "^4.2.2", + "highlight.js": "^11.0.1", + "htmlparser2": "^7.0.0", + "prismjs": "^1.17.1", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/highlight.js": { + "version": "11.9.0", + "resolved": "https://registry.npmmirror.com/highlight.js/-/highlight.js-11.9.0.tgz", + "integrity": "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/htmlparser2": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-7.2.0.tgz", + "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.2", + "domutils": "^2.8.0", + "entities": "^3.0.1" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/inferno": { + "version": "7.4.11", + "resolved": "https://registry.npmmirror.com/inferno/-/inferno-7.4.11.tgz", + "integrity": "sha512-N+cs33ESWI8fdToCd98yMRYl7jkLnCkJskxov3FKKlaKOvk3PRlAttbhmUaYdWXlRvt2WeXi+J4MbzNj3V6G0w==", + "hasInstallScript": true, + "dependencies": { + "inferno-shared": "7.4.11", + "inferno-vnode-flags": "7.4.11", + "opencollective-postinstall": "^2.0.3" + } + }, + "node_modules/inferno-create-element": { + "version": "7.4.11", + "resolved": "https://registry.npmmirror.com/inferno-create-element/-/inferno-create-element-7.4.11.tgz", + "integrity": "sha512-kE6XIx2hPAd5qpDli2iGjNXgubvuyxdLvoiW71WnSzIIxA+Uxa/s8lY8m03VyHHVypFV3n329ZY5dFvKc7UQMg==", + "dependencies": { + "inferno": "7.4.11" + } + }, + "node_modules/inferno-server": { + "version": "7.4.11", + "resolved": "https://registry.npmmirror.com/inferno-server/-/inferno-server-7.4.11.tgz", + "integrity": "sha512-SUnkCqZNWOIrjRVoVk/E1/70O1f1ImkCX9H2gDPbS0uc3GDxuzIeCgn0rpcc0XV9KzZJ2LTGxuBtEoQQOjUn2Q==", + "dependencies": { + "inferno": "7.4.11" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/inferno-shared": { + "version": "7.4.11", + "resolved": "https://registry.npmmirror.com/inferno-shared/-/inferno-shared-7.4.11.tgz", + "integrity": "sha512-pN725bDSTxkQmRS3e/3H02/xAqgHl+xgddCMjPm8M0etRdRcVCisi3NGPhzSbDDmiftrxhY31exs7+dwsngcDA==" + }, + "node_modules/inferno-vnode-flags": { + "version": "7.4.11", + "resolved": "https://registry.npmmirror.com/inferno-vnode-flags/-/inferno-vnode-flags-7.4.11.tgz", + "integrity": "sha512-L7lslEQCq3IfwgT/b9zhuMf8fv6KXCNXXHZevk/WYxnqJsOWGDcKpJn0zkzXfvmj0otbB149iLUQVBq3oe2sfA==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jake": { + "version": "10.8.7", + "resolved": "https://registry.npmmirror.com/jake/-/jake-10.8.7.tgz", + "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/js-yaml-js-types": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/js-yaml-js-types/-/js-yaml-js-types-1.0.1.tgz", + "integrity": "sha512-5tpfyORs8OQ43alNERbWfYRCtWgykvzYgY46fUhrQi2+kS7N0NuuFYLZ/IrfmVm5muLTndeMublgraXiFRjEPw==", + "dependencies": { + "esprima": "^4.0.1" + }, + "peerDependencies": { + "js-yaml": "4.x" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmmirror.com/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/micro-memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/micro-memoize/-/micro-memoize-4.1.2.tgz", + "integrity": "sha512-+HzcV2H+rbSJzApgkj0NdTakkC+bnyeiUxgT6/m7mjcz1CmM22KYFKp+EVj1sWe4UYcnriJr5uqHQD/gMHLD+g==" + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "node_modules/moize": { + "version": "6.1.6", + "resolved": "https://registry.npmmirror.com/moize/-/moize-6.1.6.tgz", + "integrity": "sha512-vSKdIUO61iCmTqhdoIDrqyrtp87nWZUmBPniNjO0fX49wEYmyDO4lvlnFXiGcaH1JLE/s/9HbiK4LSHsbiUY6Q==", + "dependencies": { + "fast-equals": "^3.0.1", + "micro-memoize": "^4.1.2" + } + }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmmirror.com/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.43", + "resolved": "https://registry.npmmirror.com/moment-timezone/-/moment-timezone-0.5.43.tgz", + "integrity": "sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, + "node_modules/morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmmirror.com/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nib": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/nib/-/nib-1.2.0.tgz", + "integrity": "sha512-7HgrnMl/3yOmWykueO8/D0q+0iWwe7Z+CK2Eaq/xQV8w1hK80WN1oReRQkfkrztbAAnp/nTHkUSl5EcVkor6JQ==", + "engines": { + "node": "*" + }, + "peerDependencies": { + "stylus": "*" + } + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nunjucks": { + "version": "3.2.4", + "resolved": "https://registry.npmmirror.com/nunjucks/-/nunjucks-3.2.4.tgz", + "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", + "dependencies": { + "a-sync-waterfall": "^1.0.0", + "asap": "^2.0.3", + "commander": "^5.1.0" + }, + "bin": { + "nunjucks-precompile": "bin/precompile" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "chokidar": "^3.3.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmmirror.com/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "bin": { + "opencollective-postinstall": "index.js" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmmirror.com/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/prismjs": { + "version": "1.29.0", + "resolved": "https://registry.npmmirror.com/prismjs/-/prismjs-1.29.0.tgz", + "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmmirror.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmmirror.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmmirror.com/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmmirror.com/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + } + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmmirror.com/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/send/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmmirror.com/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.6.0", + "resolved": "https://registry.npmmirror.com/source-map-resolve/-/source-map-resolve-0.6.0.tgz", + "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stylus": { + "version": "0.57.0", + "resolved": "https://registry.npmmirror.com/stylus/-/stylus-0.57.0.tgz", + "integrity": "sha512-yOI6G8WYfr0q8v8rRvE91wbxFU+rJPo760Va4MF6K0I6BZjO4r+xSynkvyPBP9tV1CIEUeRsiidjIs2rzb1CnQ==", + "dependencies": { + "css": "^3.0.0", + "debug": "^4.3.2", + "glob": "^7.1.6", + "safer-buffer": "^2.1.2", + "sax": "~1.2.4", + "source-map": "^0.7.3" + }, + "bin": { + "stylus": "bin/stylus" + }, + "engines": { + "node": "*" + } + }, + "node_modules/stylus/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/tildify": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/tildify/-/tildify-2.0.0.tgz", + "integrity": "sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmmirror.com/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==" + }, + "node_modules/titlecase": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/titlecase/-/titlecase-1.1.3.tgz", + "integrity": "sha512-pQX4oiemzjBEELPqgK4WE+q0yhAqjp/yzusGtlSJsOuiDys0RQxggepYmo0BuegIDppYS3b3cpdegRwkpyN3hw==", + "bin": { + "to-title-case": "bin.js" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmmirror.com/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/warehouse": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/warehouse/-/warehouse-4.0.2.tgz", + "integrity": "sha512-GixS7SolBGu81rnxYM6bScxdElLM97Jx/kr0a6B6PGBWFqvHeuWFj7QbgEX1YWZSxiJt/aR6dBVQKC/PvvihdQ==", + "dependencies": { + "bluebird": "^3.2.2", + "cuid": "^2.1.4", + "graceful-fs": "^4.1.3", + "hexo-log": "^3.0.0", + "is-plain-object": "^5.0.0", + "jsonparse": "^1.3.1", + "rfdc": "^1.1.4", + "through2": "^4.0.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/warehouse/node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..6eb5dac --- /dev/null +++ b/package.json @@ -0,0 +1,37 @@ +{ + "name": "hexo-site", + "version": "0.0.0", + "private": true, + "scripts": { + "build": "hexo generate", + "clean": "hexo clean", + "deploy": "hexo deploy", + "server": "hexo server" + }, + "hexo": { + "version": "6.3.0" + }, + "dependencies": { + "bulma-stylus": "^0.8.0", + "hexo": "^6.2.0", + "hexo-component-inferno": "^1.2.0", + "hexo-deployer-git": "^3.0.0", + "hexo-generator-archive": "^1.0.0", + "hexo-generator-category": "^1.0.0", + "hexo-generator-feed": "^3.0.0", + "hexo-generator-index": "^2.0.0", + "hexo-generator-searchdb": "^1.4.1", + "hexo-generator-tag": "^1.0.0", + "hexo-lazyload-image": "^1.0.13", + "hexo-pagination": "^2.0.0", + "hexo-renderer-ejs": "^2.0.0", + "hexo-renderer-inferno": "^0.1.3", + "hexo-renderer-pandoc": "^0.4.0", + "hexo-renderer-stylus": "^2.1.0", + "hexo-server": "^3.0.0", + "hexo-theme-landscape": "^0.0.3", + "inferno": "^7.3.3", + "inferno-create-element": "^7.3.3", + "semver": "^7.3.7" + } +} \ No newline at end of file diff --git a/scaffolds/draft.md b/scaffolds/draft.md new file mode 100644 index 0000000..fc8ef29 --- /dev/null +++ b/scaffolds/draft.md @@ -0,0 +1,4 @@ +--- +title: {{ title }} +tags: +--- diff --git a/scaffolds/page.md b/scaffolds/page.md new file mode 100644 index 0000000..1a1812b --- /dev/null +++ b/scaffolds/page.md @@ -0,0 +1,4 @@ +--- +title: {{ title }} +date: {{ date }} +--- diff --git a/scaffolds/post.md b/scaffolds/post.md new file mode 100644 index 0000000..9f379f7 --- /dev/null +++ b/scaffolds/post.md @@ -0,0 +1,12 @@ +--- +title: {{ title }} +date: {{ date }} +tags: +- +categories: +- +mathjax: true +toc: true +password: +id: +--- diff --git a/scaffolds/tutorial.md b/scaffolds/tutorial.md new file mode 100644 index 0000000..957b0a9 --- /dev/null +++ b/scaffolds/tutorial.md @@ -0,0 +1,29 @@ +--- +title: {{ title }} +date: {{ date }} +tags: +- +categories: +- +mathjax: true +toc: true +password: +--- + +### 题意简述: + + + +[题目链接]() + +### 解题思路: + + + +### 参考代码: + +{% spoiler "Code" %} +```cpp + +``` +{% endspoiler %} diff --git a/services/homework-ans/docs/about.md b/services/homework-ans/docs/about.md new file mode 100644 index 0000000..bca23f9 --- /dev/null +++ b/services/homework-ans/docs/about.md @@ -0,0 +1,5 @@ +~~我知道你很急但你先别急。~~ + +这些答案都是我写的,还没写完,正在整理 & 补充中。 + +如果你觉得我的解答步骤(或答案)有问题,或是你希望能够做出贡献,请 [发邮件到我的邮箱](mailto:xze22@mails.tsinghua.edu.cn)。 diff --git a/services/homework-ans/docs/calculus-1/chapter1/exercise1-1.md b/services/homework-ans/docs/calculus-1/chapter1/exercise1-1.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter1/exercise1-1.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter1/exercise1-2.md b/services/homework-ans/docs/calculus-1/chapter1/exercise1-2.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter1/exercise1-2.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter1/exercise1-3.md b/services/homework-ans/docs/calculus-1/chapter1/exercise1-3.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter1/exercise1-3.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter1/exercise1-4.md b/services/homework-ans/docs/calculus-1/chapter1/exercise1-4.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter1/exercise1-4.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter1/exercise1-5.md b/services/homework-ans/docs/calculus-1/chapter1/exercise1-5.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter1/exercise1-5.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter1/exercise1-rev.md b/services/homework-ans/docs/calculus-1/chapter1/exercise1-rev.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter1/exercise1-rev.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter2/exercise2-1.md b/services/homework-ans/docs/calculus-1/chapter2/exercise2-1.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter2/exercise2-1.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter2/exercise2-2.md b/services/homework-ans/docs/calculus-1/chapter2/exercise2-2.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter2/exercise2-2.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter2/exercise2-3.md b/services/homework-ans/docs/calculus-1/chapter2/exercise2-3.md new file mode 100644 index 0000000..aa696f9 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter2/exercise2-3.md @@ -0,0 +1,48 @@ + +## 第 1 题 +证明本节的性质1与性质2. + +**解** + +## 第 2 题 +证明定理2.3.1. + +**解** + +## 第 3 题 +设 $\lim\limits_{x \to x_0}f(x) = A$, 证明: + +(1) $\lim\limits_{x \to x_0}f^2(x) = A^2$; + +(2) $\lim\limits_{x \to x_0}\sqrt{f(x)} = \sqrt{A}(A > 0)$; + +(3) $\lim\limits_{x \to x_0}\sqrt[3]{f(x)} = \sqrt[3]{A}$ + +**解** + +## 第 4 题 +若 $\lim\limits_{x \to x_0}f(x) = A > B$, 则 $\exists \delta > 0$, 当 $x \in U(x_0, \delta)$ 时, $f(x) > B$. + +**解** + +## 第 5 题 +证明定理2.3.2. + +**解** + +## 第 6 题 +求下列极限(其中各题中的 $m$ 与 $n$ 均为正整数). + +(1) $\lim\limits_{x \to 2}(5-3x)(3x-1)$; + +(2) $\lim\limits_{x \to \frac{\pi}{2}}\frac{\sin x}{x}$; + +(3) $\lim\limits_{x \to 2}\frac{x^2 - 2x}{x^2 - 3x + 2}$; + +**解** + +(1) $\lim\limits_{x \to 2}(5-3x)(3x-1) = (5 - 3 \times 2)(3\times 2 - 1) = -5$ + +(2) $\lim\limits_{x \to \frac{\pi}{2}}\frac{\sin x}{x} = \frac{\sin \frac{\pi}{2}}{\frac{\pi}{2}} = \frac{2}{\pi}$ + +(3) $\lim\limits_{x \to 2}\frac{x^2 - 2x}{x^2 - 3x + 2} = \lim\limits_{x \to 2}\frac{x(x - 2)}{(x - 1)(x - 2)} = \lim\limits_{x \to 2}\frac{x}{x - 1} = \frac{2}{2 - 1} = 2$ diff --git a/services/homework-ans/docs/calculus-1/chapter2/exercise2-4.md b/services/homework-ans/docs/calculus-1/chapter2/exercise2-4.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter2/exercise2-4.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter2/exercise2-5.md b/services/homework-ans/docs/calculus-1/chapter2/exercise2-5.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter2/exercise2-5.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter2/exercise2-6.md b/services/homework-ans/docs/calculus-1/chapter2/exercise2-6.md new file mode 100644 index 0000000..e36680b --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter2/exercise2-6.md @@ -0,0 +1,6 @@ + +## 第 4 题 +设 $f \in C[0, 2a], f(0) = f(2a)$. 求证:$\exists \xi \in[0, a]$ 使得 $f(\xi) = f(\xi + a)$. + +**证明** +设 $F(x) = f(x) - f(x + a)$. 由 $f \in C[0, 2a]$ 知 $F \in C[0, a]$. 注意到 $F(0) = f(0) - f(a)$, $F(a) = f(a) - f(2a) = f(a) - f(0) = -F(0)$, 不妨设 $F(0) \le 0 \le F(a)$. 由介值定理知 $\exists \xi \in[0, a]$ 使得 $F(\xi) = 0$. 即得 $f(\xi) = f(\xi + a)$. diff --git a/services/homework-ans/docs/calculus-1/chapter2/exercise2-rev.md b/services/homework-ans/docs/calculus-1/chapter2/exercise2-rev.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter2/exercise2-rev.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter3/exercise3-1.md b/services/homework-ans/docs/calculus-1/chapter3/exercise3-1.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter3/exercise3-1.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter3/exercise3-2.md b/services/homework-ans/docs/calculus-1/chapter3/exercise3-2.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter3/exercise3-2.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter3/exercise3-3.md b/services/homework-ans/docs/calculus-1/chapter3/exercise3-3.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter3/exercise3-3.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter3/exercise3-rev.md b/services/homework-ans/docs/calculus-1/chapter3/exercise3-rev.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter3/exercise3-rev.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter4/exercise4-1.md b/services/homework-ans/docs/calculus-1/chapter4/exercise4-1.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter4/exercise4-1.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter4/exercise4-2.md b/services/homework-ans/docs/calculus-1/chapter4/exercise4-2.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter4/exercise4-2.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter4/exercise4-3.md b/services/homework-ans/docs/calculus-1/chapter4/exercise4-3.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter4/exercise4-3.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter4/exercise4-4.md b/services/homework-ans/docs/calculus-1/chapter4/exercise4-4.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter4/exercise4-4.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter4/exercise4-5.md b/services/homework-ans/docs/calculus-1/chapter4/exercise4-5.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter4/exercise4-5.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter4/exercise4-6.md b/services/homework-ans/docs/calculus-1/chapter4/exercise4-6.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter4/exercise4-6.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter4/exercise4-rev.md b/services/homework-ans/docs/calculus-1/chapter4/exercise4-rev.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter4/exercise4-rev.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter5/exercise5-1.md b/services/homework-ans/docs/calculus-1/chapter5/exercise5-1.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter5/exercise5-1.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter5/exercise5-2.md b/services/homework-ans/docs/calculus-1/chapter5/exercise5-2.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter5/exercise5-2.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter5/exercise5-3.md b/services/homework-ans/docs/calculus-1/chapter5/exercise5-3.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter5/exercise5-3.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter5/exercise5-4.md b/services/homework-ans/docs/calculus-1/chapter5/exercise5-4.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter5/exercise5-4.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter5/exercise5-5.md b/services/homework-ans/docs/calculus-1/chapter5/exercise5-5.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter5/exercise5-5.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter5/exercise5-6.md b/services/homework-ans/docs/calculus-1/chapter5/exercise5-6.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter5/exercise5-6.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter5/exercise5-7.md b/services/homework-ans/docs/calculus-1/chapter5/exercise5-7.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter5/exercise5-7.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter5/exercise5-rev.md b/services/homework-ans/docs/calculus-1/chapter5/exercise5-rev.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter5/exercise5-rev.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter6/exercise6-1.md b/services/homework-ans/docs/calculus-1/chapter6/exercise6-1.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter6/exercise6-1.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter6/exercise6-2.md b/services/homework-ans/docs/calculus-1/chapter6/exercise6-2.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter6/exercise6-2.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter6/exercise6-rev.md b/services/homework-ans/docs/calculus-1/chapter6/exercise6-rev.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter6/exercise6-rev.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter7/exercise7-1.md b/services/homework-ans/docs/calculus-1/chapter7/exercise7-1.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter7/exercise7-1.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter7/exercise7-2.md b/services/homework-ans/docs/calculus-1/chapter7/exercise7-2.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter7/exercise7-2.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter7/exercise7-3.md b/services/homework-ans/docs/calculus-1/chapter7/exercise7-3.md new file mode 100644 index 0000000..ffad6a8 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter7/exercise7-3.md @@ -0,0 +1,62 @@ + +\paragraph{题目} + +求解下列微分方程. + +(1) $y''=2x-\cos x, y(0)=1, y'(0)=-1$; + +(2) $xy''+(y')^2-y'=0, y(1)=1-\ln 2, y'(1)=\frac{1}{2}$; + +(3) $y''=3\sqrt{y}, y(0)=1, y'(0)=2$; + +(4) $(1+x^2)y''-2xy'=0$; + +(5) $y''+\frac{2}{1-y}(y')^2=0$; + +(6) $(y''')^2+(y'')^2=1$; + +(7) $xy''-y'\ln y'+y'=0$; + +(8) $(1+x^2)y''+(y')^2=-1$; + +(9) $(y'')^2-y'=0$. + +**解** + +(1) 等式左右两边积分, 可得 $y' = x^2-\sin x + C_1$. 由 $y'(0)=-1$ 得 $C_1 = -1$, 故 $y'=x^2-\sin x - 1$. 等式左右两边再次积分, 可得 $y=\frac{1}{3}x^3+\cos x - x + C_2$. 由 $y(0)=1$ 得 $C_2 = 0$, 故 $y = \frac{1}{3}x^3 + \cos x - x$. + +(2) 设 $p = y'$, 则有 $xp' + p^2 - p = 0$, 即 $\frac{\text{d}{p}}{p - p^2} = \frac{\text{d}{x}}{x}$. 化简为 $\left(\frac{1}{p} - \frac{1}{p - 1}\right)\text{d}{p} = \frac{\text{d}{x}}{x}$ 后, 积分得 $\ln\left|\frac{p-1}{p}\right| = \ln \left|x\right| + C_1$, 此即 $\frac{p - 1}{p} = \frac{C_2}{x}$. 由于 $p(1) = y'(1) = \frac{1}{2}$, 因此 $C_2 = -1$. 故 $p = y' = 1 - \frac{1}{x + 1}$. 再次积分得 $y = x - \ln(x + 1) + C$. 由于 $y(1) = 1 - \ln 2$, 故 $C = 0$. 所以 $y = x - \ln(x + 1)$. + +(3) 设 $p = y'$, 则有 $p\frac{\text{d}{p}}{\text{d}{y}} = 3\sqrt{y}$, 即 $p\text{d}{p} = 3\sqrt{y}\text{d}{y}$. 积分可得 $\frac{1}{2}p^2=2y^{\frac{3}{2}}+C_1$. 由 $y'(0) = p(0) = 2$ 得 $C_1 = 0$, 故 $y' = p = 2y^{\frac{3}{4}}$(负值舍去). 此即 $\frac{\text{d}{y}}{y^{\frac{3}{4}}} = 2\text{d}{x}$. 积分得 $4\sqrt[4]{y} = 2x + C_2$. 由于 $y(0) = 1$, 故 $C_2 = 4$. 所以 $y = \left(\frac{1}{2}x + 1\right)^4$. + +(4) 注意到 + +$$ +\left(\frac{y}{1 + x^2}\right)' = \frac{(1 + x^2)y'' - 2xy'}{(1 + x^2)^2} = 0 +$$ + +因此 $y' = C_1(1 + x^2)$, 积分得 $y = C_1(\frac{1}{3}x^3 + x + C)$, 这等价于 $y = C_1(\frac{1}{3}x^3 + x) + C_2$. + +(5) 设 $p = y'$, 则有 $p\frac{\text{d}{p}}{\text{d}{y}} + \frac{2}{1-y}p^2=0$. 这个方程可以化简为 $\frac{\text{d}{p}}{p} = \frac{2\text{d}{y}}{y-1}$. 积分得 $\ln \left|p\right| = 2\ln\left|y - 1\right| + C_1$ 即 $\left|p\right| = e^{C_1}(y-1)^2$. 由于 $p \equiv 0$ 也为方程的解, 故方程的解可表示为 $p = C_2(y-1)^2$. 因此 $\frac{\text{d}{y}}{\text{d}{x}} = C_2(y - 1)^2$, 即 $\frac{\text{d}{y}}{(y - 1)^2} = C_2\text{d}{x}$. 积分得 $\frac{1}{1 - y} = C_2 x + C_3$. 故原方程的解为 $y = 1 - \frac{1}{C_2 x + C_3}$. + +(6) 设 $p = y''$, 则有 $(p')^2 + p^2 = 1$, 即 $\frac{\text{d}{p}}{\sqrt{1 - p^2}} = \pm \text{d}{x}$, 或 $p^2 \equiv 1$. + +对于前者而言, 积分得 $x = \arcsin p - C_1$, 即 $y'' = p = \sin(x + C_1)$(没有正负号是因为可以取 $C_1\gets C_1 + \pi$ 得到负号). 积分得 $y' = -\cos(x + C_1) + C_2$, 再积分得 $y = -\sin(x + C_1) + C_2 x + C_3$. + +对于后者而言, 易知有解 $y = \pm \frac{1}{2}x^2 + C_1 x + C_2$. + +(7) 注意到 + +$$ +\left(\frac{\ln y' - 1}{x}\right)' = \frac{\left(\frac{y''}{y'}\right)x-\ln y' + 1}{x^2} = \frac{xy''-y'\ln y' + y'}{x^2y'} = 0 +$$ + +因此 $\frac{\ln y' - 1}{x} = C_1$, 即 $\ln y' - 1 = C_1 x$, 化简得 $\text{d}{y} = e^{C_1 x + 1}\text{d}{x}$. 积分得 $y = \frac{1}{C_1}e^{C_1 x + 1} + C_2$. + +(8) 设 $p = y'$, 则有 $1+p^2+p'(1+x)^2=0$, 即 $\frac{\text{d}{p}}{1+p^2} = -\frac{\text{d}{x}}{1+x^2}$. 积分得 $\arctan p = -\arctan x + C$, 即 $\frac{x + p}{1 - xp} = \tan C = C_1$. 化简得 $p = \frac{C_1 - x}{1 + C_1 x}$, 积分得 $y = \ln(1 + C_1 x) - \frac{1}{C_1}\cdot \frac{1}{1 + C_1 x} +C_2(C_1 \neq 0)$, 或 $y = -\frac{1}{2}x^2 + C_2(C_1 = 0)$. + +(9) 设 $p = y'$, 则有 $(p')^2 = p$, 即 $p' = \pm \sqrt{p}$, 化简得 $\frac{\text{d}{p}}{\sqrt{p}} = \pm \text{d}{x}$, 或 $p \equiv 0$. + +对于前者而言, 积分得 $x = \pm 2\sqrt{p} + C_1$, 即 $y' = p = \frac{1}{4}(x - C_1)^2$, 再次积分得 $y = \frac{1}{12}(x - C_1)^3 + C_2$. + +对于后者而言, 易知有解 $y = C_3$. diff --git a/services/homework-ans/docs/calculus-1/chapter7/exercise7-4.md b/services/homework-ans/docs/calculus-1/chapter7/exercise7-4.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter7/exercise7-4.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter7/exercise7-5.md b/services/homework-ans/docs/calculus-1/chapter7/exercise7-5.md new file mode 100644 index 0000000..9a0acea --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter7/exercise7-5.md @@ -0,0 +1,58 @@ + +## 第 1 题 + +**解** + +## 第 2 题 + +**解** + +## 第 3 题 + +**解** + +## 第 4 题 + +**解** + +## 第 5 题 + +设曲线 $y = y(x)$ 满足 $4x^2y''-4xy' - y = 0$, 过点 $(1, 4)$, 且在点 $(1, 4)$ 处与 $x$ 轴夹角为 $\frac{\pi}{4}$, 求 $y = y(x)$. + +**解** + +设 $y = x^\lambda$, 则 $4\lambda(\lambda - 1) + 4\lambda - 1 = 0$. 解得 $\lambda_1 = \frac{1}{2}, \lambda_2 = -\frac{1}{2}$. 故通解为 $y = C_1\sqrt{x} + \frac{C_2}{\sqrt{x}}$. 求导得 $y' = \frac{C_1}{2\sqrt{x}} - \frac{C_2}{2x\sqrt{x}}$. 由题 + +$$ +\begin{cases} + y(1) = 4 \\ + y'(1) = 1 +\end{cases} +\Longrightarrow +\begin{cases} + C_1 + C_2= 4 \\ + \frac{1}{2}(C_1 - C_2) = 1 +\end{cases} +$$ + +解得 $C_1 = 3, C_2 = 1$. 故 $y = 3\sqrt{x} + \frac{1}{\sqrt{x}}$. + +## 第 6 题 + +设 $y = e^{2x} + (1 + x)e^x$ 为微分方程 $y'' + ay' + by = ce^x$ 的一个解, 求常系数 $a, b, c$ 及微分方程的通解. + +**解** + +## 第 7 题 + +已知连续函数 $y = f(x)$ 满足 + +$$ +f(x) = \sin x + \int_{0}^{x}(t-x)f(t)\text{d}{t}, +$$ + +求 $y = f(x)$. + +**解** + +$f(0) = 0$. 由 $f(x) = \sin x + \int_{0}^{x}tf(t)\text{d}{t} - x\int_{0}^{x}f(t)\text{d}{t}$ 两边求导得 $f'(x) = \cos x + xf(x) - \left(xf(x) + \int_{0}^{x}f(t)\text{d}{t}\right) = \cos x - \int_{0}^{x}f(t)\text{d}{t}$. 这蕴含着 $f'(0) = 1$. 再次求导得 $f''(x) = -\sin x - f(x)$, 即 $y'' + y = -\sin x$. 考虑方程 $z'' + z = e^{-ix}$. 特征方程为 $\lambda^2 + 1 = 0$, $\lambda_1 = i, \lambda_2 = -i$. 因此 $\lambda = -i$ 为特征方程的一个根. 设其有特解 $Z(x) = Axe^{-ix}$, 代入有 $A = \frac{i}{2}$, 则 $Z(x) = \frac{i}{2}e^{-ix}, \text{Im}{Z(x)} = \frac{1}{2}x\cos x$. 故原微分方程有通解 $y = C_1\cos x + C_2\sin x + \frac{1}{2}x\cos x$. 又因为 $f(0) = 0, f(1) = 1$, 故 $C_1 = 0, C_2 = \frac{1}{2}$. 因此 $f(x) = \frac{1}{2}\sin x + \frac{1}{2}x\cos x$. diff --git a/services/homework-ans/docs/calculus-1/chapter7/exercise7-6.md b/services/homework-ans/docs/calculus-1/chapter7/exercise7-6.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter7/exercise7-6.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/chapter7/exercise7-rev.md b/services/homework-ans/docs/calculus-1/chapter7/exercise7-rev.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/chapter7/exercise7-rev.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-1/index.md b/services/homework-ans/docs/calculus-1/index.md new file mode 100644 index 0000000..a289515 --- /dev/null +++ b/services/homework-ans/docs/calculus-1/index.md @@ -0,0 +1,698 @@ +## 第1章 + +### 习题1.1 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | + +### 习题1.2 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | + +### 习题1.3 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | + +### 习题1.4 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | +| 第12题 | | | +| 第13题 | | | +| 第14题 | | | +| 第15题 | | | +| 第16题 | | | +| 第17题 | | | + +### 习题1.5 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | + +### 第1章总复习题 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | +| 第12题 | | | +| 第13题 | | | +| 第14题 | | | +| 第15题 | | | +| 第16题 | | | + +## 第2章 + +### 习题2.1 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | +| 第12题 | | | +| 第13题 | | | +| 第14题 | | | +| 第15题 | | | +| 第16题 | | | +| 第17题 | | | +| 第18题 | | | +| 第19题 | | | +| 第20题 | | | +| 第21题 | | | +| 第22题 | | | +| 第23题 | | | + +### 习题2.2 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | + +### 习题2.3 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | 已完成 | | +| 第2题 | 已完成 | | +| 第3题 | 已完成 | | +| 第4题 | 已完成 | | +| 第5题 | 已完成 | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | +| 第12题 | | | +| 第13题 | | | +| 第14题 | | | +| 第15题 | | | + +### 习题2.4 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | +| 第12题 | | | +| 第13题 | | | + +### 习题2.5 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | + +### 习题2.6 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | 已完成 | 已完成 | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | +| 第12题 | | | +| 第13题 | | | +| 第14题 | | | + +### 第2章总复习题 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | +| 第12题 | | | +| 第13题 | | | +| 第14题 | | | +| 第15题 | | | +| 第16题 | | | +| 第17题 | | | +| 第18题 | | | +| 第19题 | | | +| 第20题 | | | +| 第21题 | | | +| 第22题 | | | +| 第23题 | | | + +## 第3章 + +### 习题3.1 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | +| 第12题 | | | +| 第13题 | | | +| 第14题 | | | +| 第15题 | | | + +### 习题3.2 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | +| 第12题 | | | + +### 习题3.3 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | + +### 第3章总复习题 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | +| 第12题 | | | +| 第13题 | | | +| 第14题 | | | +| 第15题 | | | + +## 第4章 + +### 习题4.1 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | +| 第12题 | | | +| 第13题 | | | +| 第14题 | | | +| 第15题 | | | +| 第16题 | | | + +### 习题4.2 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | + +### 习题4.3 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | +| 第12题 | | | + +### 习题4.4 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | +| 第12题 | | | + +### 习题4.5 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | + +### 习题4.6 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | + +### 第4章总复习题 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | +| 第12题 | | | +| 第13题 | | | +| 第14题 | | | +| 第15题 | | | +| 第16题 | | | +| 第17题 | | | +| 第18题 | | | +| 第19题 | | | +| 第20题 | | | + +## 第5章 + +### 习题5.1 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | +| 第12题 | | | +| 第13题 | | | +| 第14题 | | | +| 第15题 | | | +| 第16题 | | | + +### 习题5.2 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | + +### 习题5.3 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | +| 第12题 | | | +| 第13题 | | | +| 第14题 | | | +| 第15题 | | | + +### 习题5.4 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | + +### 习题5.5 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | + +### 习题5.6 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | +| 第12题 | | | +| 第13题 | | | +| 第14题 | | | + +### 习题5.7 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | +| 第12题 | | | +| 第13题 | | | +| 第14题 | | | +| 第15题 | | | +| 第16题 | | | +| 第17题 | | | +| 第18题 | | | +| 第19题 | | | + +### 第5章总复习题 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | +| 第12题 | | | +| 第13题 | | | +| 第14题 | | | +| 第15题 | | | +| 第16题 | | | +| 第17题 | | | +| 第18题 | | | +| 第19题 | | | +| 第20题 | | | +| 第21题 | | | + +## 第6章 + +### 习题6.1 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | + +### 习题6.2 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | + +### 第6章总复习题 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | + +## 第7章 + +### 习题7.1 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | + +### 习题7.2 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | + +### 习题7.3 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 题目 | 已完成 | 已完成 | + +### 习题7.4 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | + +### 习题7.5 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | 已完成 | 已完成 | +| 第6题 | 已完成 | | +| 第7题 | 已完成 | 已完成 | + +### 习题7.6 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | + +### 第7章总复习题 + +| | 题面 | 答案 | +| :---------: | :--------: | :--------: | +| 第1题 | | | +| 第2题 | | | +| 第3题 | | | +| 第4题 | | | +| 第5题 | | | +| 第6题 | | | +| 第7题 | | | +| 第8题 | | | +| 第9题 | | | +| 第10题 | | | +| 第11题 | | | +| 第12题 | | | +| 第13题 | | | + diff --git a/services/homework-ans/docs/calculus-2/chapter1/exercise1-1.md b/services/homework-ans/docs/calculus-2/chapter1/exercise1-1.md new file mode 100644 index 0000000..9b1dfd2 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter1/exercise1-1.md @@ -0,0 +1,123 @@ +## 第 1 题 + +证明: $n$ 维 Euclid 空间中的距离 $\left\lVert\mathbf{X} - \mathbf{Y}\right\rVert _n$ 满足正定性、对称性与三角不等式. + +**证明** + +不妨设 $\mathbf{X} = (x_1, x_2, \cdots, x_n), \mathbf{Y} = (y_1, y_2, \cdots, y_n)$, 则 $\left\lVert\mathbf{X} - \mathbf{Y}\right\rVert _n = \sqrt{\sum_{i = 1}^n(x_i - y_i)^2}$. + +(1) 正定性: 显然 $\left\lVert\mathbf{X} - \mathbf{Y}\right\rVert _n = \sqrt{\sum_{i = 1}^n(x_i - y_i)^2} \ge 0$, 且 $\left\lVert\mathbf{X} - \mathbf{Y}\right\rVert _n = 0$ 当且仅当 $\forall i \in [1, n]$ 均有 $x_i - y_i = 0$, 此即 $\mathbf{X} = \mathbf{Y}$. + +(2) 对称性: 显然 $\left\lVert\mathbf{Y} - \mathbf{X}\right\rVert _n = \sqrt{\sum_{i = 1}^n(x_i - y_i)^2} = \left\lVert\mathbf{X} - \mathbf{Y}\right\rVert _n$ + +(3) 三角不等式: 再设 $\mathbf{Z} = (z_1, z_2, \cdots, z_n)$. 要证 $\left\lVert\mathbf{X} - \mathbf{Y}\right\rVert _n \le \left\lVert\mathbf{X} - \mathbf{Z}\right\rVert _n + \left\lVert\mathbf{Z} - \mathbf{Y}\right\rVert _n$, 只需证 $\sqrt{\sum_{i = 1}^n(x_i - y_i)^2} \le \sqrt{\sum_{i = 1}^n(x_i - z_i)^2} + \sqrt{\sum_{i = 1}^n(z_i - y_i)^2}$. 由于 + +$$ +\begin{aligned} + & \sqrt{\sum_{i = 1}^n(x_i - y_i)^2} \\ + &= \sqrt{\sum_{i = 1}^n[(x_i - z_i) + (z_i - y_i)]^2} \\ + &= \sqrt{\sum_{i = 1}^n(x_i - z_i)^2 + \sum_{i = 1}^n(z_i - y_i)^2 - 2\sum_{i = 1}^n(x_i - z_i)(z_i - y_i)} \\ + &\le \sqrt{\sum_{i = 1}^n(x_i - z_i)^2 + \sum_{i = 1}^n(z_i - y_i)^2 + 2\sqrt{\sum_{i = 1}^n(x_i - z_i)^2\sum_{i = 1}^{n}(z_i - y_i)^2}} \\ + &= \sqrt{\sum_{i = 1}^n(x_i - z_i)^2} + \sqrt{\sum_{i = 1}^n(z_i - y_i)^2} +\end{aligned} +$$ + +其中不等号由柯西不等式得到. 故三角不等式得证. + +## 第 2 题 + +求下列集合 $\Omega$ 的内部、外部、边界和闭包. + +(1) $\Omega$ 为 $\mathbb{R}^2$ 的子集, $\Omega = \{(x, y) | x^2 + y^2 = 1\}$; + +(2) $\Omega$ 为 $\mathbb{R}^3$ 的子集, $\Omega = \{(x, y, z) | 1 \le x^2 + y^2 + z^2 < 4\}$. + +**解** + +(1) 内部: $\varnothing$, 外部: $\{(x, y) | x^2 + y^2 \neq 1\}$, 边界: $\{(x, y) | x^2 + y^2 = 1\}$, 闭包: $\{(x, y) | x^2 + y^2 = 1\}$. + +(2) 内部: $\{(x, y, z) | 1 < x^2 + y^2 + z^2 < 4\}$, 外部 $\{(x, y, z) | x^2 + y^2 + z^2 < 1 \lor x^2 + y^2 + z^2 > 4\}$, 边界: $\{(x, y, z) | x^2 + y^2 + z^2 = 1 \lor x^2 + y^2 + z^2 = 4\}$, 闭包: $\{(x, y, z) | 1 \le x^2 + y^2 + z^2 \le 4\}$. + +## 第 3 题 + +证明下列命题: + +(1) 已知 $S \subset \mathbb{R}^n$, 则 $S$ 为开集 $\iff$ $S = \mathring{S}$; + +(2) 若 $S \subset \mathbb{R}^n$ 为开集, 则 $S \cap \partial S = \varnothing$; + +(3) 任意多个开集之并为开集; 有限个开集之交为开集; + +(4) 若 $A, B \subset \mathbb{R}^n$, 记 $S = A \cap B, T = A \cup B$, 则 $\mathring{S} = \mathring{A} \cap \mathring{B}, \mathring{T} \supset \mathring{A} \cup \mathring{B}$; + +(5) 若 $A \subset \mathbb{R}^n$, 则集合 $\mathring{A}$ 的内部等于 $\mathring{A}$. + +## 第 4 题 + +证明下列命题: + +(1) 已知 $S \subset \mathbb{R}^n$, 则 $S$ 为闭集 $\iff$ $S = \overline{S} \iff \partial S \subset S$; + +(2) 若 $A, B \subset \mathbb{R}^n$, 则 $\overline{A}\backslash\overline{B} \subset \overline{A \backslash B}, \overline{A}\cup\overline{B} \subset \overline{A\cup B}$ (事实上他们相等), $\overline{A}\cap\overline{B} \supset \overline{A\cap B}$; + +(3) 若 $P_1, P_2, \cdots, P_k \in \mathbb{R}^n$, 则 $\{P_1, P_2, \cdots, P_k\}$ 为闭集; + +(4) 任意多个闭集之交为闭集; 有限个闭集之并为闭集. + +**证明** + +## 第 5 题 + +证明下列命题: + +(1) 已知 $S \subset \mathbb{R}^n$, 则 $\overset{\circ}{S}$ 等于 $S$ 的余集的闭包的余集; $\overline{S}$ 等于 $S$ 的余集的内部的余集; + +(2) 若 $A \subset \mathbb{R}^n$, 则 $\overline{A} = A \cup \partial A = \overset{\circ}{A} \cup \partial A, \overset{\circ}{A} = A \backslash\partial A = \overline{A}\backslash\partial A, \partial A = \partial(\mathbb{R}^n\backslash A)$; + +(3) 若 $A \subset \mathbb{R}^n$, 则 $\partial(\overset{\circ}{A}), \partial(\overline{A}) \subset \partial A$; + +(4) 若 $A, B \subset \mathbb{R}^n$, 则 $\partial(A\cup B) \subset \partial A \cup \partial B$; + +(5) $\partial A = \varnothing$ $\iff$ $A$ 既是开集又是闭集. + +**证明** + +## 第 6 题 + +证明: $\mathbb{R}^n$ 中的点列 $\{\mathbf{X}_k\}$ 为 Cauchy 列当且仅当 $\{\mathbf{X}_k\}$ 的 $n$ 个分量构成的 $n$ 个实数列 $\{x_k^{(i)}\}_{k=1}^{+\infty}(i = 1, 2, \cdots, n)$ 均为 Cauchy 列. + +**证明** + +## 第 7 题 + +下列集合中, 哪些是连通的, 哪些是非连通的? + +(1) $D = \{(x, y) | y \neq 0\}$; + +(2) $D = \{(x, y) | 0 < x^2 + y^2 \le 2\}$; + +(3) $\Omega = \{(x, y, z) | x^2 + y^2 \neq 0\}$; + +(4) $\Omega = \{(x, y, z) | 1 < x^2 + y^2 + z^2 \le 4\}$. + +**解** + +(1) 不是. + +(2) 是. + +(3) 是. + +(4) 是. + +## 第 8 题 + +连通的闭集是否为闭区域? 如果是,请证明; 如果不是, 请举出反例. + +**解** + +## 第 9 题 + +证明: $\mathbb{R}^n$ 中的收敛点列必为有界点列. + +**证明** diff --git a/services/homework-ans/docs/calculus-2/chapter1/exercise1-2.md b/services/homework-ans/docs/calculus-2/chapter1/exercise1-2.md new file mode 100644 index 0000000..2680b75 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter1/exercise1-2.md @@ -0,0 +1,84 @@ +## 第 1 题 + +写出下列函数表达式: + +(1) 将圆锥的体积 $V$ 表示为圆锥斜高 $l$ 与高 $h$ 的函数; + +(2) 在半径为 $1$ 的球面内内接长宽高分别为 $x, y, z$ 的长方体, 将其表面积表示为 $x, y$ 的函数; + +(3) 在椭球面 $\dfrac{x^2}{a^2} +\dfrac{y^2}{b^2} + \dfrac{z^2}{c^2} = 1$ 内接长宽高分别为 $2x, 2y, 2z$ 的长方体, 将其体积表示为 $x, y$ 的函数; + +(4) 将点 $P(x, y, z)$ 到球面 $(x - 1)^2 + y^2 + (z + 1)^2 = 2$ 的最短距离表示为 $P$ 的坐标的函数. + +## 第 2 题 + +求下列函数的定义域, 并画出定义域的图形 + +(1) $f(x, y) = \sqrt{4x^2 + y^2 - 1}$; + +(2) $f(x, y) = \ln(xy)$; + +(3) $f(x, y, z) = \sqrt{y^2 - 1} + \ln(4 - x^2 - y^2 - z^2)$; + +(4) $f(x, y, z) = \arcsin\dfrac{x^2 - y^2}{x^2 + y^2}$. + +## 第 3 题 + +已知 $f\left(x + y, \frac{y}{x}\right) = x^2 - y^2$, 求 $f(x, y)$. + +**解** + +设 $\begin{cases} m = x + y, \\ n = \frac{y}{x}, \end{cases}$ 则 $\begin{cases}x = \frac{m}{n + 1}, \\ y = \frac{nm}{n + 1}.\end{cases}$ 因此 $f(m, n) = x^2 - y^2 = \frac{m^2(1-n)}{1+n} (n \neq -1)$. 而当 $n = -1$ 时显然有 $f(m, n) = 0$. 故 + +$$ +f(x, y) = \begin{cases} + \frac{x^2(1 - y)}{1 + y}, &y \neq -1, \\ + 0, &y = -1. +\end{cases} +$$ + +## 第 4 题 + +如果 $n$ 元函数 $f(x_1, x_2, \cdots, x_n)$ 对任意实数 $t$ 满足 $f(tx_1, tx_2, \cdots, tx_n) = t^kf(x_1, x_2, \cdots, x_n)$, 则称 $f$ 是 $x_1, x_2, \cdots, x_n$ 的 $k$ 次齐次式, 下列函数是否为齐次式? 若是, 求出次数 $k$. + +(1) $f(x, y, z) = \frac{x^3 + y^3 + z^3}{xyz}$; + +(2) $f(x, y, z) = \sqrt{x^3 + y^3 + z^3} + xyz$; + +(3) $f(x_1, x_2, \cdots, x_n) = \sum_{i = 1}^n\sum_{j = 1}^na_{ij}x_ix_j$. + +**解** + +(1) $f(tx, ty, yz) = \frac{(tx)^3 + (ty)^3 + (tz)^3}{(tx)(ty)(tz)} = \frac{x^3 + y^3 + z^3}{xyz} = t^0f(x, y, z)$. 因此 $k = 0$. + +(2) $f(tx, ty, tz) = \sqrt{(tx)^3 + (ty)^3 + (tz)^3} + (tx)(ty)(tz) = t^{\frac{3}{2}}\sqrt{x^3 + y^3 + z^3} + t^3xyz$. 因此不是齐次式. + +(3) $f(tx_1, tx_2, \cdots, tx_n) = \sum_{i = 1}^n\sum_{j = 1}^na_{ij}(tx_i)(tx_j) = t^{2}\sum_{i = 1}^n\sum_{j = 1}^na_{ij}x_ix_j = t^{2}f(x_1, x_2, \cdots, x_n)$. 因此 $k = 2$​. + +## 第 5 题 + +位于 $(a, b, c)$ 质量为 $M_0$ 的空间质点对于位于 $(x, y, z)$ 质量为 $m_0$ 的空间质点的引力是定义在 $\mathbb{R}^n\backslash\{a, b, c\}$ 上的一个向量值函数 $\mathbf{F}(x, y, z) = (F_x, F_y, F_z)$, 写出 $\mathbf{F}$ 及分量 $F_x, F_y, F_z$ 的函数表达式. + +## 第 6 题 + +$\mathbb{R}^2$ 的子集 $D$ 到 $\mathbb{R}^2$ 的映射 $F:(x, y)\mapsto (u, v)$ 为 $\begin{cases}u = x^2 - y^2, \\ v = xy, \end{cases}$ 其中定义域 $D$ 是由四条曲线 $x^2 - y^2 = 1, x^2 - y^2 = 4, xy = 1, xy = 2$ 围成的平面区域, 求 $F$ 的值域 $F(D)$, 并问: 在 $D$ 内的直线 $x = a$ 映射为何曲线? + +**解** + +由题知 $F(D)$ 中区域被夹在 $x^2 - y^2 = 1$ 和 $x^2 - y^2 = 4$ 之间, $xy = 1$ 和 $xy = 2$ 之间. 因此 $F(D) = \{(u, v) | 1 \le u \le 4, 1 \le v \le 2\}$. + +因为当 $x = a$ 时 $u = a^2 - y^2, v = ay$, 所以消去 $y$ 可得曲线 $a^2u + v^2 = a^4 (1 \le u \le 4, 1 \le v \le 2)$. + +## 第 7 题 + +$\mathbb{R}^2 \backslash \{(0, 0)\}$ 到 $\mathbb{R}^2$ 的映射 $F:(x, y) \mapsto (u, v)$ 为 $\begin{cases}u = \frac{x}{x^2 + y^2}, \\ v = \frac{y}{x^2 + y^2}.\end{cases}$ + +问: (1) $O-xy$ 平面上的圆 $x^2 + y^2 = R^2$ 映射为 $O-uv$ 平面上的什么曲线? + +(2) $O-xy$ 平面上的线段 $y = x(0 < x \le 1)$ 映射为 $O-uv$ 平面上的什么曲线? + +**解** + +(1) 解得 $\begin{cases}x = \frac{u}{u^2 + v^2}, \\ y = \frac{v}{u^2 + v^2}.\end{cases}$ 代入 $x^2 + y^2 = R^2$ 得 $u^2 + v^2 = \frac{1}{R^2}$. + +(2) 代入 $y = x(0 < x \le 1)$ 得 $v = u(v \ge \dfrac{1}{2})$. diff --git a/services/homework-ans/docs/calculus-2/chapter1/exercise1-3.md b/services/homework-ans/docs/calculus-2/chapter1/exercise1-3.md new file mode 100644 index 0000000..714e726 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter1/exercise1-3.md @@ -0,0 +1,160 @@ + +## 第 1 题 + +下列函数当 $(x, y) \to (0, 0)$ 时, 其极限是否存在? 若存在, 求出极限. + +(1) $\dfrac{\arcsin(x^2 + y^2)}{x^2 + y^2}$; + +(3) $(x^2 + y^2)e^{-x-y}$; + +(5) $\dfrac{x^2 - y^2}{x^2 + y^2}$; + +(7) $\dfrac{x^3 - y^3}{x + y}$; + +(9) $\dfrac{x^2}{x^2 + y^2}$; + +(11) $\dfrac{x^4y^4}{(x^2 + y^4)^3}$; + +**解** + +(1) 当 $(x, y)\to(0, 0)$ 时 $x^2 + y^2 \to 0$. 因此 $\lim\limits_{(x, y)\to(0, 0)}\dfrac{\arcsin(x^2 + y^2)}{x^2 + y^2} = \lim\limits_{u\to 0}\dfrac{\arcsin u}{u} = 1$. + +(3) $\lim\limits_{(x, y)\to(0, 0)}(x^2 + y^2)e^{-x-y} = \lim\limits_{(x, y)\to(0, 0)}(x^2 + y^2)\lim\limits_{(x, y)\to(0, 0)}e^{-x-y} = 0$. + +(5) 当 $(x, y)$ 沿直线 $x = 0$ 趋于 $(0, 0)$ 时, $f(x, y) = \frac{-y^2}{y^2} = -1$. 当 $(x, y)$ 沿直线 $y = 0$ 趋于 $(0, 0)$ 时, $f(x, y) = \frac{x^2}{x^2} = 1$. 两者不相等, 故极限不存在. + +(7) 当 $(x, y)$ 沿直线 $y = kx^3 - x$ 趋于 $(0, 0)$ 时, $f(x, y) = \dfrac{x^3 - (kx^3 - x)^3}{x + (kx^3 - x)} = \dfrac{-k^3x^9 + 3k^2x^7 - 3kx^5 + 2x^3}{kx^3} = \dfrac{-k^3x^6 + 3k^2x^4 - 3kx^2 + 2}{k} \to \dfrac{2}{k} \quad (x \to 0)$. 因此极限随着 $k$ 的变化而变化, 故极限不存在. + +(9) 当 $(x, y)$ 沿直线 $x = 0$ 趋于 $(0, 0)$ 时, $f(x, y) = \dfrac{1}{y^2} \to +\infty, \quad y \to 0$. 故极限不存在. + +(11) 当 $(x, y)$ 沿直线 $y = x$ 趋于 $(0, 0)$ 时, $f(x, y) = \dfrac{x^8}{(x^2 + x^4)^3} > \dfrac{1}{x^4} \to +\infty, \quad x \to 0$. 故极限不存在. + +## 第 2 题 + +求下列函数极限. + +(1) $\lim\limits_{x\to 3 \atop y\to 0}\dfrac{\ln(x + \sin y)}{\sqrt{x^2 + y^2}}$; + +(3) $\lim\limits_{x\to +\infty \atop y\to -\infty}(x^2 + y^2)e^{y - x}$; + +(5) $\lim\limits_{x \to \infty \atop y \to \infty}\left(\dfrac{\left|xy\right|}{x^2 + y^2}\right)^{x^2}$ + +**解** + +(1) $\lim\limits_{x\to 3 \atop y\to 0}\dfrac{\ln(x + \sin y)}{\sqrt{x^2 + y^2}} = \dfrac{\ln(x + \sin y)}{\sqrt{x^2 + y^2}}\Bigg\vert_{x = 3\atop y = 0} = \dfrac{\ln 3}{3}$. + +(3) $\lim\limits_{x\to +\infty \atop y\to -\infty}(x^2 + y^2)e^{y - x} = \lim\limits_{x\to +\infty \atop y\to -\infty}e^y\cdot\dfrac{x^2}{e^x} + \lim\limits_{x\to +\infty \atop y\to -\infty} \dfrac{1}{e^x}\cdot y^2e^y = 0 \cdot 0 + 0 \cdot 0 = 0$ + +(5) 由于 $0 \le \left(\dfrac{\left|xy\right|}{x^2 + y^2}\right)^{x^2} \le \left(\dfrac{1}{2}\right)^{x^2}$ 且 $\lim\limits_{x \to \infty}\left(\dfrac{1}{2}\right)^{x^2} = 0$, 故由夹逼准则知 $\lim\limits_{x \to \infty \atop y \to \infty}\left(\dfrac{\left|xy\right|}{x^2 + y^2}\right)^{x^2} = 0$. + +## 第 3 题 + +讨论下列累次极限与二重极限是否存在, 若存在求值. + +(1) $\lim\limits_{x\to \infty}\lim\limits_{y\to \infty}\sin \dfrac{\pi x}{2x + y}, \lim\limits_{y\to \infty}\lim\limits_{x\to \infty}\sin \dfrac{\pi x}{2x + y}, \lim\limits_{x\to \infty \atop y \to \infty}\sin \dfrac{\pi x}{2x + y};$ + +(2) $\lim\limits_{x\to +\infty}\lim\limits_{y\to 0^{+}}\dfrac{x^y}{1+x^y}, \lim\limits_{y\to 0^{+}}\lim\limits_{x\to +\infty}\dfrac{x^y}{1+x^y}, \lim\limits_{x\to +\infty \atop y \to 0^{+}}\dfrac{x^y}{1+x^y}$; + +(3) $\lim\limits_{x\to 0}\lim\limits_{y\to 0}(x+y)\sin \dfrac{1}{x}\sin \dfrac{1}{y}, \lim\limits_{y\to 0}\lim\limits_{x\to 0}(x+y)\sin \dfrac{1}{x}\sin \dfrac{1}{y}, \lim\limits_{x\to 0 \atop y \to 0}(x+y)\sin \dfrac{1}{x}\sin \dfrac{1}{y}$. + +**解** + +(2) $\lim\limits_{x\to +\infty}\lim\limits_{y\to 0^{+}}\dfrac{x^y}{1+x^y} = \lim\limits_{x\to +\infty}\dfrac{1}{1+1} = \dfrac{1}{2}$. $\lim\limits_{y\to 0^{+}}\lim\limits_{x\to +\infty}\dfrac{x^y}{1+x^y} = \lim\limits_{y\to 0^{+}}1 = 1$. 由 1.3.1 节结论知 $\lim\limits_{x\to +\infty \atop y \to 0^{+}}\dfrac{x^y}{1+x^y}$ 不存在. + +(3) 显然累次极限均不存在. 因为 $0 \le \left|(x+y)\sin\dfrac{1}{x}\sin\dfrac{1}{y}\right| \le \left|x + y\right|$, 且 $\lim\limits_{x \to 0 \atop y \to 0}\left|x+y\right| \to 0$, 故由夹逼准则知 $\lim\limits_{x\to 0 \atop y \to 0}(x+y)\sin \dfrac{1}{x}\sin \dfrac{1}{y} = 0$. + +## 第 4 题 + +(1) 举例说明累次极限存在性与二重极限的存在性互不包含; + +(2) 证明: 若二元函数 $f$ 在某一点的两个累次极限和二重极限都存在, 则这三个值相等. + +**解** + +(2) 由于 $f(x, y)$ 的二重极限存在, 不妨设 $\lim\limits_{(x, y)\to(x_0, y_0)}f(x, y) = A$. 再设 $g(x) = \lim\limits_{y\to y_0}f(x, y)$, 即证 $\lim\limits_{x \to x_0}g(x) = A$. 由定义知 $\forall \epsilon > 0, \exists \delta > 0$ 使得在 $0 < \sqrt{(x - x_0)^2 + (y - y_0)^2} < \delta$ 时有 $\left|f(x, y) - A\right| < \dfrac{\epsilon}{2}$. 左右两侧取极限可知 $\lim\limits_{y\to y_0}\left|f(x, y)- A\right| \le \dfrac{\epsilon}{2}$. 由于绝对值函数是连续函数, 因此可以转化为 $\left|\lim\limits_{y \to y_0}f(x, y) - A\right| \le \dfrac{\epsilon}{2} < \epsilon$, 即 $\left|g(x) - A\right| <\epsilon$. 观察此时 $\delta$ 的取值范围, 发现有 $0 < \left|x - x_0\right| \le \sqrt{(x - x_0)^2 + (y - y_0)^2} < \delta$. 故由定义可知 $\lim\limits_{x \to x_0}g(x) = A$. 此即 $\lim\limits_{x\to x_0}\lim\limits_{y\to y_0}f(x, y) = \lim\limits_{(x, y)\to(x_0, y_0)}f(x, y)$. 由对称性可知 $\lim\limits_{y\to y_0}\lim\limits_{x\to x_0}f(x, y) = \lim\limits_{(x, y)\to(x_0, y_0)}f(x, y)$. 命题得证. + +## 第 5 题 + +用定义证明函数 $f(x, y) = \sqrt{x^2 + y^2}$ 在 $\mathbb{R}^2$ 上连续. + +**解** + +## 第 6 题 + +判断下列函数的在 $(0, 0)$ 点的连续性. + +(1) $f(x, y) = \begin{cases}\dfrac{\sin(x^3 + y^3)}{x^2+y^2}, &x^2 + y^2 \neq 0, \\ 0, &x^2 + y^2 = 0;\end{cases}$ + +(2) $f(x, y) = \begin{cases}1, &x^2 + y^2 \neq 0, \\ 0, &x^2 + y^2 = 0;\end{cases}$ + +(3) $f(x, y) = \begin{cases}\dfrac{x^2y^2}{(x^2+y^2)^{\frac{3}{2}}}, &x^2 + y^2 \neq 0, \\ 0, &x^2 + y^2 = 0;\end{cases}$ + +(4) $f(x, y) = \begin{cases}\dfrac{xy^2}{x^2+y^4}, &x^2 + y^2 \neq 0, \\ 0, &x^2 + y^2 = 0.\end{cases}$ + +**解** + +(1) 因为 $0 \le \left|\dfrac{\sin(x^3 + y^3)}{x^2 + y^2}\right| \le \left|\dfrac{x^3 + y^3}{x^2 + y^2}\right| = \left|(x + y)\left(1 + \dfrac{xy}{x^2 + y^2}\right)\right| \le \dfrac{3}{2}(x + y)$, 且 $\lim\limits_{(x, y)\to(0, 0)}\dfrac{3}{2}(x + y) = 0$, 故由夹逼准则知 $\lim\limits_{(x, y)\to(0, 0)}f(x, y) = 0 = f(0, 0)$. 因此该函数在 $(0, 0)$ 处连续. + +(2) 因为 $\lim\limits_{(x, y)\to(0, 0)}f(x, y) = 1 \neq 0 = f(0, 0)$, 所以该函数在 $(0, 0)$ 处不连续. + +(3) 因为 $0 \le \left|\dfrac{x^2y^2}{(x^2+y^2)^{\frac{3}{2}}}\right| \le \left|\dfrac{x^2 + y^2}{(2xy)^{\frac{3}{2}}}\right| = \left|\dfrac{\sqrt{xy}}{2\sqrt{2}}\right|$, 且 $\lim\limits_{(x, y)\to(0, 0)}\dfrac{\sqrt{xy}}{2\sqrt{2}} = 0$, 故由夹逼准则知 $\lim\limits_{(x, y)\to(0, 0)}f(x, y) = 0 = f(0, 0)$. 因此该函数在 $(0, 0)$ 处连续. + +(4) 考虑极限 $\lim\limits_{(x, y)\to(0, 0)}\dfrac{xy^2}{x^2+y^4}$. 当 $(x, y)$ 沿着 $y = k\sqrt{x}$ 趋于 $(0, 0)$ 时, 有 $f(x, y) = f(x, k\sqrt{x}) = \dfrac{k^2}{1 + k^4}$ 随着 $k$ 的变化而变化. 因此该极限不存在. 故该函数在 $(0, 0)$ 处不连续. + +## 第 7 题 + +考察下列函数在平面上的连续性, 并指出在哪些点上函数是连续的. + +(1) $f(x, y) = \begin{cases}\dfrac{x - y^2}{x^3+y^3}, &x + y \neq 0, \\ 0, &x + y = 0;\end{cases}$ + +(2) $f(x, y) = \begin{cases}\dfrac{x}{y^2}e^{-\frac{x^2}{y^2}}, &y \neq 0, \\ 0, &y = 0;\end{cases}$ + +**解** + +(1) 当 $x + y \neq 0$ 的时候显然函数是连续的. 现只需考察 $x + y = 0$ 时的情况即可. 当 $x + y = 0$ 且 $(x, y)$ 不趋向于 $(0, 0)$ 时, 显然分子不为 $0$, 但分母趋向于 $0$, 极限不存在, 因此在 $x + y = 0(x \neq 0)$ 的区域内不连续. 最后再考察 $(x, y)\to (0, 0)$ 的情况. 假设 $(x, y)$ 沿着 $y = kx$ 趋于 $(0, 0)$, 则 $\lim\limits_{(x, y)\to(0, 0)}f(x, y) = \lim\limits_{x \to 0}\dfrac{x - (kx)^2}{x^3 + (kx)^3} = \lim\limits_{x \to 0}\dfrac{1 - k^2x}{(1 + k^3)x^2} = \lim\limits_{x \to 0}\dfrac{-k^2}{2x(1 + k^3)}$ 极限不存在. 因此函数在 $(0, 0)$ 处也不连续. 综上所述, 函数在除了 $x + y = 0$ 这条直线外的区域都连续. + +(2) 先固定 $x = x_0$, $f(x, y) = f(x_0, y) = \dfrac{x_0}{y^2e^{\frac{x_0^2}{y^2}}} \to 0, \quad y \to 0$. 再考虑当 $(x, y)\to(0, 0)$ 时的极限值. 不妨设 $(x, y)$ 沿着 $y = kx$ 趋于 $(0, 0)$, 则 $\lim\limits_{(x, y)\to (0, 0)}f(x, y) = \lim\limits_{x\to 0}\dfrac{x}{(kx)^2}e^\frac{1}{k^2}$ 不存在. 因此该函数在 $(0, 0)$ 处不连续, 在平面上其他区域内都连续. + +## 第 8 题 + +设 $f$ 是定义在 $\mathbb{R}^2$ 上的连续函数, 且 $\lim\limits_{x^2 + y^2 \to \infty}f(x, y) = +\infty$, 证明: $f$ 有最小值. + +**证明** + +记 $f(0, 0) = A$. 因为 $\lim\limits_{x^2 + y^2 \to \infty}f(x, y) = +\infty$, 所以 $\exists r_0 > 0$ 使得 $\forall (x, y)$ 满足 $x^2 + y^2 > r_0^2$, 都有 $f(x, y) > A$. 记 $D = \{(x, y) | x^2 + y^2 \le r_0^2\}$ 为一有界闭集, 故 $D$ 中可以取到最小值. 不妨设 $f(x_0, y_0)$ 为 $D$ 中最小值. 由于 $(0, 0) \in D$, 则 $f(x_0, y_0) \le f(0, 0) = A$. 所以 $\forall (x, y) \in \mathbb{R}^2, f(x_0, y_0) \le f(x, y)$. 所以 $f$ 在 $\mathbb{R}^2$ 上存在最小值. + +## 第 9 题 + +当 $(x, y) \to (0, 0)$ 时, $f(x, y) = o(\rho^m), g(x, y) = o(\rho^n)$, 其中 $\rho = \sqrt{x^2 + y^2}$, 证明: + +(1) $f(x, y) + g(x, y) = o(\rho^k), k = \min\{m, n\}$, + +(2) $f(x, y)g(x, y) = o(\rho^{m+n})$. + +**证明** + +(1) 由题知 $\lim\limits_{(x, y)\to(0, 0)}\dfrac{f(x, y)}{\rho^m} = 0, \lim\limits_{(x, y)\to(0, 0)}\dfrac{g(x, y)}{\rho^n} = 0$. 不妨设 $m \le n$. 因此 $\lim\limits_{(x, y)\to(0, 0)}\dfrac{f(x, y) + g(x, y)}{\rho^m} = \lim\limits_{(x, y)\to (0, 0)}\left(\dfrac{f(x, y)}{\rho^m} + \rho^{n - m}\dfrac{g(x, y)}{\rho^n}\right) = 0 + 0 = 0$. 由定义知 $f(x, y) + g(x, y) = o(\rho^k)$, 其中 $k = \min\{m, n\}$. + +(2) 由题知 $\lim\limits_{(x, y)\to(0, 0)}\dfrac{f(x, y)}{\rho^m} = 0, \lim\limits_{(x, y)\to(0, 0)}\dfrac{g(x, y)}{\rho^n} = 0$. 因此 $\lim\limits_{(x, y)\to(0, 0)}\dfrac{f(x, y)g(x, y)}{\rho^{m + n}} = \lim\limits_{(x, y)\to (0, 0)}\left(\dfrac{f(x, y)}{\rho^m} \cdot \dfrac{g(x, y)}{\rho^n}\right) = 0 \cdot 0 = 0$. 由定义知 $f(x, y)g(x, y) = o(\rho^{m+n})$. + +## 第 10 题 + +当 $(x, y)\to(0, 0)$ 时, 讨论下列无穷小的阶(若有阶, 求阶; 若无阶, 说明理由). + +(1) $\sin (x^2 + y^2)$; + +(2) $\ln(1 + \sqrt{x^2 + y^2})$; + +(3) $(x^2 + y^2)\sin\dfrac{1}{\sqrt{x^2 + y^2}}$; + +(4) $x + y + 2xy$; + +**解** + +(1) 记 $\sqrt{x^2 + y^2} = \rho$. 则 $\lim\limits_{(x, y)\to(0, 0)}\dfrac{\sin (x^2 + y^2)}{x^2 + y^2} = \lim\limits_{\rho \to 0}\dfrac{\sin\rho^2}{\rho^2} = 1$. 故为 $2$ 阶无穷小. + +(2) 记 $\sqrt{x^2 + y^2} = \rho$. 则 $\lim\limits_{(x, y)\to(0, 0)}\dfrac{\ln(1 + \sqrt{x^2 + y^2})}{\sqrt{x^2 + y^2}} = \lim\limits_{\rho \to 0}\dfrac{\ln(1 + \rho)}{\rho} = 1$. 故为 $1$ 阶无穷小. + +(3) 记 $\sqrt{x^2 + y^2} = \rho$. 则 $\lim\limits_{(x, y)\to(0, 0)}\dfrac{(x^2 + y^2)\sin\dfrac{1}{\sqrt{x^2 + y^2}}}{(\sqrt{x^2 + y^2})^k} = \lim\limits_{\rho \to 0}\dfrac{\rho^2\sin\dfrac{1}{\rho}}{\rho^k}$ 不可能为一固定常数, 所以无阶. + +(4) 由于 $\lim\limits_{(x, y)\to(0, 0)}\dfrac{x + y + 2xy}{(\sqrt{x^2 + y^2})^k}$ 不可能为一固定常数, 所以无阶. diff --git a/services/homework-ans/docs/calculus-2/chapter1/exercise1-4.md b/services/homework-ans/docs/calculus-2/chapter1/exercise1-4.md new file mode 100644 index 0000000..0453a91 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter1/exercise1-4.md @@ -0,0 +1,171 @@ + +## 第 1 题 + +求下列函数的偏导数: + +(1) $z = ax^2y + bxy^2$; + +(3) $z = \dfrac{x}{y} + \dfrac{y}{x}$; + +(5) $z = \ln(x + \sqrt{x^2 - y^2})$; + +(7) $z = \cos(1 + 2^{xy})$; + +**解** + +(1) $\dfrac{\partial z}{\partial x} = 2axy + by^2$, $\dfrac{\partial z}{\partial y} = ax^2 + 2bxy$. + +(3) $\dfrac{\partial z}{\partial x} = \dfrac{1}{y} -\dfrac{y}{x^2}$, $\dfrac{\partial z}{\partial y} = \dfrac{1}{x} -\dfrac{x}{y^2}$. + +(5) $\dfrac{\partial z}{\partial x} = \dfrac{1}{x + \sqrt{x^2 - y^2}}\cdot(1 + \dfrac{2x}{2\sqrt{x^2 - y^2}}) = \dfrac{1}{\sqrt{x^2 - y^2}}$, $\dfrac{\partial z}{\partial y} = \dfrac{1}{x + \sqrt{x^2 - y^2}}\cdot\dfrac{-2y}{2\sqrt{x^2 - y^2}} = \dfrac{y}{y^2 - x^2 - x\sqrt{x^2 - y^2}}$. + +(7) $\dfrac{\partial z}{\partial x} = -\sin(1 + 2^{xy})\cdot 2^{xy}\cdot \ln(2^y) = -2^{xy}y\sin(1 + 2^{xy})\ln 2$, $\dfrac{\partial z}{\partial y} = -\sin(1 + 2^{xy})\cdot 2^{xy}\cdot \ln(2^x) = -2^{xy}x\sin(1 + 2^{xy})\ln 2$. + +## 第 2 题 + +考察下列函数在坐标原点的可微性. + +(1) $f(x, y) = \sqrt{\left|x\right|}\cos y$; + +(2) $f(x, y) = \begin{cases}\dfrac{2xy}{\sqrt{x^2 + y^2}}, &x^2 + y^2 \neq 0, \\ 0, &x^2 + y^2 = 0;\end{cases}$ + +(3) $f(x, y) = \begin{cases}\dfrac{x^2y^2}{\left(x^2 + y^2\right)^{\frac{3}{2}}}, &x^2 + y^2 \neq 0, \\ 0, &x^2 + y^2 = 0;\end{cases}$ + +(4) $f(x, y) = \left|x - y\right|\phi(x, y)$, 其中 $\phi(x, y)$ 在原点的某个邻域内连续, 且 $\phi(0, 0) = 0$. + +**解** + +(1) 由于 $f'_x(0, 0) = \lim\limits_{\Delta x \to 0}\dfrac{f(\Delta x, 0) - f(0, 0)}{\Delta x} = \lim\limits_{\Delta x \to 0}\dfrac{\sqrt{\left|x\right|}}{\Delta x}$ 不存在, 所以该函数在原点不可微. + +(2) 由于 $f'_x(0, 0) = \lim\limits_{\Delta x \to 0}\dfrac{f(\Delta x, 0) - f(0, 0)}{\Delta x} = 0, f'_y(0, 0) = \lim\limits_{\Delta y \to 0}\dfrac{f(0, \Delta y) - f(0, 0)}{\Delta y} = 0$, 所以 $\lim\limits_{(\Delta x, \Delta y)\to (0, 0)}\dfrac{f(\Delta x, \Delta y) - f'_x(0, 0)\Delta x - f'_y(0, 0)\Delta y - f(0, 0)}{\sqrt{\Delta x^2 + \Delta y^2}} = \lim\limits_{(\Delta x, \Delta y)\to (0, 0)}\dfrac{f(\Delta x, \Delta y) - 0 - 0 - 0}{\sqrt{\Delta x^2 + \Delta y^2}} = \lim\limits_{(\Delta x, \Delta y)\to (0, 0)}\dfrac{2\Delta x\Delta y}{\Delta x^2 + \Delta y^2}$. 由于沿着 $\Delta y = k\Delta x$ 趋于 $(0, 0)$ 时极限值为 $\dfrac{2k}{1 + k^2}$ 随着 $k$ 的变化为变化, 所以该函数在原点不可微. + +(3) 由于 $f'_x(0, 0) = \lim\limits_{\Delta x \to 0}\dfrac{f(\Delta x, 0) - f(0, 0)}{\Delta x} = 0, f'_y(0, 0) = \lim\limits_{\Delta y \to 0}\dfrac{f(0, \Delta y) - f(0, 0)}{\Delta y} = 0$, 所以 $\lim\limits_{(\Delta x, \Delta y)\to (0, 0)}\dfrac{f(\Delta x, \Delta y) - f'_x(0, 0)\Delta x - f'_y(0, 0)\Delta y - f(0, 0)}{\sqrt{\Delta x^2 + \Delta y^2}} = \lim\limits_{(\Delta x, \Delta y)\to (0, 0)}\dfrac{f(\Delta x, \Delta y) - 0 - 0 - 0}{\sqrt{\Delta x^2 + \Delta y^2}} = \lim\limits_{(\Delta x, \Delta y)\to (0, 0)}\dfrac{\Delta x^2\Delta y^2}{(\Delta x^2 + \Delta y^2)^2}$. 由于沿着 $\Delta y = k\Delta x$ 趋于 $(0, 0)$ 时极限值为 $\dfrac{k^2}{(1 + k^2)^2}$ 随着 $k$ 的变化而变化, 所以该函数在原点不可微. + +(4) 由于 $f'_x(0, 0) = \lim\limits_{\Delta x \to 0}\dfrac{f(\Delta x, 0) - f(0, 0)}{\Delta x} = \lim\limits_{\Delta x \to 0}\dfrac{\left|\Delta x\right|\phi(\Delta x, 0)}{\Delta x} = 0$, $f'_y(0, 0) = \lim\limits_{\Delta y \to 0}\dfrac{f(0, \Delta y) - f(0, 0)}{\Delta y} = \lim\limits_{\Delta y \to 0}\dfrac{\left|\Delta y\right|\phi(0, \Delta y)}{\Delta y} = 0$, + +故 + +$$ +\begin{aligned} + \lim\limits_{(\Delta x, \Delta y)\to (0, 0)}\dfrac{f(\Delta x, \Delta y) - f'_x(0, 0)\Delta x - f'_y(0, 0)\Delta y - f(0, 0)}{\sqrt{\Delta x^2 + \Delta y^2}} & = \lim\limits_{(\Delta x, \Delta y)\to (0, 0)}\dfrac{\left|x - y\right|\phi(\Delta x, \Delta y)}{\sqrt{\Delta x^2 + \Delta y^2}} \\ + & \le \lim\limits_{(\Delta x, \Delta y)\to (0, 0)}\dfrac{(\left|x\right| + \left|y\right|)\phi(\Delta x, \Delta y)}{\sqrt{\Delta x^2 + \Delta y^2}} \\ + & \le \lim\limits_{(\Delta x, \Delta y)\to (0, 0)}\dfrac{\sqrt{2(x^2 + y^2)}\phi(\Delta x, \Delta y)}{\sqrt{\Delta x^2 + \Delta y^2}} \\ + & = \lim\limits_{(\Delta x, \Delta y)\to (0, 0)}\sqrt{2}\phi(\Delta x, \Delta y)\to 0 +\end{aligned} +$$ + +所以该函数在原点可微. + +## 第 4 题 + +求下列函数的全微分: + +(1) $u = \sin\dfrac{1}{x^2 + y^2 + z^2}$, 在点 $\left(\dfrac{\sqrt{2}}{2}, \dfrac{1}{2}, -\dfrac{1}{2}\right)$; + +(3) $z = (x + y)^2$; + +(5) $z = \dfrac{x - y}{x + y}$; + +(7) $u = \ln(1 + x^2 + y^2 + z^2)$; + +**解** + +(1) 记 $\mathbf{r} = \left(\dfrac{\sqrt{2}}{2}, \dfrac{1}{2}, -\dfrac{1}{2}\right)$. $\text{d}{u} = 2(x\text{d}{x} + y\text{d}{y} + z\text{d}{z})\cos\dfrac{1}{x^2 + y^2 + z^2}$. 代入得 $\text{d}{u}\big\vert_{\mathbf{r}} = (\sqrt{2}\text{d}{x} + \text{d}{y} - \text{d}{z})\cos 1$. + +(3) 由于 $z = (x + y)^2 = x^2 + 2xy + y^2$, 故 $\dfrac{\partial z}{\partial x} = \dfrac{\partial z}{\partial y} = 2x + 2y$. 所以 $\text{d}{z} = 2(x + y){\text{d}{x} + \text{d}{y}}$. + +(5) 由于 $\dfrac{\partial z}{\partial x} = \dfrac{(x + y) - (x - y)}{(x + y)^2} = \dfrac{2y}{(x + y)^2}$, $\dfrac{\partial z}{\partial y} = \dfrac{-(x + y) - (x - y)}{(x + y)^2} = -\dfrac{2x}{(x + y)^2}$, 故 $\text{d}{z} = \dfrac{2(y\text{d}{x} - x\text{d}{y})}{(x + y)^2}$. + +(7) $\text{d}{u} = \dfrac{2x\text{d}{x} + 2y\text{d}{y} + 2z\text{d}{z}}{1 + x^2 + y^2 + z^2} = \dfrac{2(x\text{d}{x} + y\text{d}{y} + z\text{d}{z})}{1 + x^2 + y^2 + z^2}$. + +## 第 7 题 + +设 $\dfrac{\partial f}{\partial x}(x_0, y_0)$ 存在, $\dfrac{\partial f}{\partial y}(x, y)$ 连续, 证明 $f(x, y)$ 在点 $(x_0, y_0)$ 处可微. + +**证明** + +考虑函数 $f$ 在点 $(x_0, y_0)$ 处的该变量 $\Delta f = f(x_0 + h, y_0 + k) - f(x_0, y_0)$. 利用一元函数的中值定理得 + +$$ +\begin{aligned} + \Delta f & = f(x_0 + h, y_0 + k) - f(x_0 + h, y_0) + f(x_0 + h, y_0) - f(x_0, y_0) \\ + & = f_y(x_0 + h, y_0 + \mu k)k + f(x_0 + h, y_0) - f(x_0, y_0), \quad \mu \in (0, 1) \\ + & = f(x_0 + h, y_0) - f(x_0, y_0) + f_y(x_0, y_0)k + \beta k, +\end{aligned} +$$ + +其中 $\beta = f_y(x_0 + h, y_0 + \mu k) - f_y(x_0, y_0)$. + +由题知 $f_y(x, y)$ 连续, 因此 $\lim\limits_{(h, k)\to(0, 0)}\beta(h, k) = 0$. 由题知 $\lim\limits_{(x, y)\to(x_0, y_0)}\dfrac{f(x_0 + h, y_0) - f(x_0, y_0)}{h} = \dfrac{\partial f}{\partial x}(x_0, y_0)$ 存在, 这说明 $f(x_0 + h, y_0) - f(x_0, y_0)$ 是关于 $h$ 的一阶无穷小. 不妨记 $f(x_0 + h, y_0) - f(x_0, y_0) = \lambda h$. 故 $\Delta f = \lambda h + f_y(x_0, y_0)k + \beta k = \lambda h + f_y(x_0, y_0)k + o(\rho)$. 此即 $f$ 在点 $(x_0, y_0)$ 处可微. 命题得证. + +## 第 8 题 + +设函数 $f(x, y) = \sqrt[3]{xy}$, 证明: 函数 $f$ 在原点处连续、偏导数存在, 但沿方向 $l = (a, b)(ab \neq 0)$ 的方向导数不存在. + +**证明** + +由于 $f$ 是初等函数的复合, 所以函数 $f$ 在原点处连续. 因为 $f'_x(0, 0) = \lim\limits_{\Delta x \to 0}\dfrac{f(\Delta x, 0) - f(0, 0)}{\Delta x} = 0, f'_y(0, 0) = \lim\limits_{\Delta y \to 0}\dfrac{f(0, \Delta y) - f(0, 0)}{\Delta y} = 0$, 所以 $f$ 在原点处的偏导数均存在. 设 $l$ 单位化得 $l_0 = (\cos\theta, \sin\theta), \theta \neq \dfrac{k\pi}{2}, k \in \mathbb{N}$. 则沿着 $l_0$ 的方向导数 $\dfrac{\partial f}{\partial l_0} = \lim\limits_{d \to 0}\dfrac{f(d\cos \theta, d\sin\theta) - f(0, 0)}{d} = \sqrt[3]{\dfrac{\cos\theta\sin\theta}{d}}$. 由于 $\theta \neq \dfrac{k\pi}{2}, k \in \mathbb{N}$, 故该极限不存在. 因此题中所表述的方向导数不存在. 命题得证. + +## 第 11 题 + +求下列函数在点 $P_0$ 处沿方向 $l$ 的方向导数. + +(1) $z = \cos (x + y), P_0 = \left(0, \dfrac{\pi}{2}\right), l = (3, -4)$; + +(3) $z = \sum\limits_{i = 1}^n\sum\limits_{j = 1}^nx_ix_j, P(1, 1, \cdots, 1), l = (-1, -1, \cdots, -1)$; + +**解** + +(1) 由于 $\dfrac{\partial z}{\partial x} = \dfrac{\partial z}{\partial y} = -\sin(x + y)$, 且将 $l$ 单位化后得到 $r = \left(\dfrac{3}{5}, -\dfrac{4}{5}\right)$, 所以 $\dfrac{\partial z}{\partial l} = -\dfrac{3}{5}\sin(0 + \dfrac{\pi}{2}) + \dfrac{4}{5}\sin(0 + \dfrac{\pi}{2}) = \dfrac{1}{5}$. + +(3) 由于 $\dfrac{\partial z}{\partial x_i} = 2\sum\limits_{j = 1}^nx_j$, 且将 $l$ 单位化后得到 $r = \left(-\dfrac{1}{\sqrt{n}}, -\dfrac{1}{\sqrt{n}}, \cdots, -\dfrac{1}{\sqrt{n}}\right)$, 所以将 $P(1, 1, \cdots, 1)$ 代入得 $\dfrac{\partial z}{\partial l} = 2\sum\limits_{j = 1}^nn\left(-\dfrac{1}{\sqrt{n}}\right) = -2n\sqrt{n}$. + +## 第 12 题 + +求下列数量场的梯度. + +(1) $u(x, y) = \sqrt{x^2 + y^2}$; + +(3) $u(x_1, x_2, \cdots, x_n) = \sum\limits_{i = 1}^nx_i$; + +**解** + +(1) 由于 $\dfrac{\partial u}{\partial x} = \dfrac{\partial u}{\partial y} = \dfrac{1}{\sqrt{x^2 + y^2}}$, 故 $\nabla u = \left(\dfrac{1}{\sqrt{x^2 + y^2}}, \dfrac{1}{\sqrt{x^2 + y^2}}\right)$. + +(3) 由于 $\forall i \in [1, n], \dfrac{\partial u}{\partial x_i} = 1$, 故 $\nabla u = (1, 1, \cdots, 1)$. + +## 第 13 题 + +已知函数 $u(x, y, z) = x^2 + y^2 + z^2 - xy - xz + yz$ 及点 $P(1, 1, 1)$, 求 $u$ 在 $P$ 点的方向导数 $\dfrac{\partial u}{\partial l}$ 的最值, 并指出取得最值时的方向, 以及哪个方向的方向导数为零. + +**解** + +$\dfrac{\partial u}{\partial x} = 2x - y - z, \dfrac{\partial u}{\partial y} = 2y - x + z, \dfrac{\partial u}{\partial z} = 2z - x + y$. 因此在 $P$ 点处梯度的方向为 $(0, 2, 2)$, 单位化可得 $l_0 = \left(0, \dfrac{\sqrt{2}}{2}, \dfrac{\sqrt{2}}{2}\right)$. 将 $P(1, 1, 1)$ 以及 $\pm l_0$ 代入可得 $\dfrac{\partial u}{\partial l}$ 的最大值为 $2\sqrt{2}$, 方向为 $\left(0, \dfrac{\sqrt{2}}{2}, \dfrac{\sqrt{2}}{2}\right)$; 最小值为 $-2\sqrt{2}$, 方向为 $\left(0, -\dfrac{\sqrt{2}}{2}, -\dfrac{\sqrt{2}}{2}\right)$. 对任意一个垂直于梯度的方向 $(k, 1, -1)(k \in \mathbb{R})$ 或 $(k, -1, 1)(k \in \mathbb{R})$,都有方向导数为 $0$. + +## 第 14 题 + +求下列函数的二阶偏导数 $\dfrac{\partial^2 u}{\partial x^2}, \dfrac{\partial^2 u}{\partial y^2}, \dfrac{\partial^2 u}{\partial x\partial y}$. + +(1) $u = \cos^2(ax - by)$; + +(3) $u = xe^{-xy}$; + +**解** + +(1) 由于 $\dfrac{\partial u}{\partial x} = 2\cos(ax - by)\cdot(-\sin(ax - by))\cdot a = -a\sin(2ax - 2by)$, $\dfrac{\partial u}{\partial y} = 2\cos(ax - by)\cdot(-\sin(ax - by))\cdot (-b) = b\sin(2ax - 2by)$, 故 $\dfrac{\partial ^2u}{\partial x^2} = -2a^2\cos(2ax - 2by), \dfrac{\partial ^2u}{\partial y^2} = -2b^2\cos(2ax - 2by), \dfrac{\partial ^2u}{\partial x\partial y} = 2ab\cos(2ax - 2by)$. + +(3) 由于 $\dfrac{\partial u}{\partial x} = e^{-xy} + -xye^{-xy} = (1 - xy)e^{-xy}$, $\dfrac{\partial u}{\partial y} = xe^{-xy}\cdot(-x) = -x^2e^{-xy}$, 故 $\dfrac{\partial ^2u}{\partial x^2} = ye^{-xy}(xy - 2), \dfrac{\partial ^2u}{\partial y^2} = x^3e^{-xy}, \dfrac{\partial ^2u}{\partial x\partial y} = xe^{-xy}(xy - 2)$. + +## 第 15 题 + +证明下列函数满足相应的等式. + +(1) $u = 2\cos^2\left(x - \dfrac{y}{2}\right)$ 满足 $2\dfrac{\partial^2u}{\partial y^2} + \dfrac{\partial^2u}{\partial x \partial y} = 0$; + +(3) $\begin{cases}u = e^x\cos y, \\ v = e^x\sin y\end{cases}$ 满足 Cauchy-Riemann 条件 $\begin{cases}\dfrac{\partial u}{\partial x} = \dfrac{\partial v}{\partial y}, \\ \dfrac{\partial u}{\partial y} = -\dfrac{\partial v}{\partial x}\end{cases}$, 且分别满足 Laplace 方程 $\dfrac{\partial^2 f}{\partial x^2} + \dfrac{\partial^2 f}{\partial y^2} = 0$; + +**证明** + +(1) 由于 $\dfrac{\partial u}{\partial y} = \sin(2x - y)$, 所以 $\dfrac{\partial ^2u}{\partial y^2} = -\cos(2x - y), \dfrac{\partial ^2u}{\partial x\partial y} = 2\cos(2x - y)$. 代入有 $2\dfrac{\partial^2u}{\partial y^2} + \dfrac{\partial^2u}{\partial x \partial y} = -2\cos(2x - y) + \cos(2x - y) = 0$. 命题得证. + +(3) $\dfrac{\partial u}{\partial x} = e^x\cos y, \dfrac{\partial u}{\partial y} = -e^x\sin y, \dfrac{\partial v}{\partial x} = e^x\sin y, \dfrac{\partial v}{\partial y} = e^x\cos y$. 代入可知其满足 Cauchy-Riemann 条件. $\dfrac{\partial ^2u}{\partial x^2} = e^x\cos y, \dfrac{\partial ^2u}{\partial y^2} = -e^x\cos y, \dfrac{\partial ^2v}{\partial x^2} = e^x\sin y, \dfrac{\partial ^2v}{\partial y^2} = -e^x\sin y$. 代入可知其分别满足 Laplace 方程. 命题得证. diff --git a/services/homework-ans/docs/calculus-2/chapter1/exercise1-5.md b/services/homework-ans/docs/calculus-2/chapter1/exercise1-5.md new file mode 100644 index 0000000..aa7ef7f --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter1/exercise1-5.md @@ -0,0 +1,241 @@ + +## 第 1 题 + +求下列变换所确定的向量值函数 $\begin{pmatrix}u \\ v\end{pmatrix} = \begin{pmatrix}f_1(x, y) \\ f_2(x, y)\end{pmatrix}$ 的 Jacobi 矩阵 $\dfrac{\partial(u, v)}{\partial(x, y)}$, 并指出在哪些区域 Jacobi 矩阵可逆. + +(1) $\begin{cases}u = \sqrt{x^2 + y^2}, \\ v = \arctan\dfrac{y}{x};\end{cases}$ + +(3) $\begin{cases}u = \dfrac{x}{x^2 + y^2}, \\ v = \dfrac{y}{x^2 + y^2};\end{cases}$ + +**解** + +(1) + +$$ +J= +\begin{pmatrix} + \dfrac{\partial u}{\partial x} & \dfrac{\partial u}{\partial y} \\ + \dfrac{\partial v}{\partial x} & \dfrac{\partial v}{\partial y} +\end{pmatrix} += +\begin{pmatrix} + \dfrac{2x}{2\sqrt{x^2 + y^2}} & \dfrac{2y}{2\sqrt{x^2 + y^2}} \\ + \dfrac{1}{1 + \left(\dfrac{y}{x}\right)^2}\cdot\left(-\dfrac{y}{x^2}\right) & \dfrac{1}{1 + \left(\dfrac{y}{x}\right)^2}\cdot\dfrac{1}{x} +\end{pmatrix} += +\begin{pmatrix} + \dfrac{x}{\sqrt{x^2 + y^2}} & \dfrac{y}{\sqrt{x^2 + y^2}} \\ + \dfrac{-y}{x^2 + y^2} & \dfrac{x}{x^2 + y^2} +\end{pmatrix} +$$ + +且 $\det{J} \neq 0 \iff x^2 + y^2 \neq 0$, 故在 $\mathbb{R}^2 \backslash \{(0, 0)\}$ 处 Jacobi 矩阵可逆. + +(3) + +$$ +J= +\begin{pmatrix} + \dfrac{\partial u}{\partial x} & \dfrac{\partial u}{\partial y} \\ + \dfrac{\partial v}{\partial x} & \dfrac{\partial v}{\partial y} +\end{pmatrix} += +\begin{pmatrix} + \dfrac{x^2 + y^2 - x\cdot 2x}{(x^2 + y^2)^2} & \dfrac{-x\cdot 2y}{(x^2 + y^2)^2} \\ + \dfrac{-y\cdot 2x}{(x^2 + y^2)^2} & \dfrac{x^2 + y^2 - y\cdot 2y}{(x^2 + y^2)^2} +\end{pmatrix} += +\begin{pmatrix} + \dfrac{y^2 - x^2}{(x^2 + y^2)^2} & \dfrac{-2xy}{(x^2 + y^2)^2} \\ + \dfrac{-2xy}{(x^2 + y^2)^2} & \dfrac{x^2 - y^2}{(x^2 + y^2)^2} +\end{pmatrix} +$$ + +且 $\det{J} \neq 0 \iff x^2 + y^2 \neq 0$, 故在 $\mathbb{R}^2 \backslash \{(0, 0)\}$ 处 Jacobi 矩阵可逆. + +## 第 2 题 + +求变换 $\begin{cases}x = r\sin\theta\cos\phi, \\ y = r\cos\theta\cos\phi, \\ z=r\sin\phi,\end{cases}r>0, 0\le\theta \le 2\pi, 0 \le \phi \le pi$ 确定的向量值函数 $\begin{pmatrix}x \\ y \\ z\end{pmatrix} = \begin{pmatrix}f_1(r, \theta, \phi) \\ f_2(r, \theta, \phi) \\ f_3(r, \theta, \phi)\end{pmatrix}$ 的 Jacobi 矩阵. + +**解** + +$$ +J = +\begin{pmatrix} + \dfrac{\partial x}{\partial r} & \dfrac{\partial x}{\partial \theta} & \dfrac{\partial x}{\partial \phi} \\ + \dfrac{\partial y}{\partial r} & \dfrac{\partial y}{\partial \theta} & \dfrac{\partial y}{\partial \phi} \\ + \dfrac{\partial z}{\partial r} & \dfrac{\partial z}{\partial \theta} & \dfrac{\partial z}{\partial \phi} +\end{pmatrix} += +\begin{pmatrix} + \sin\theta & r\cos\theta\cos\phi & -r\sin\theta\sin\phi \\ + \cos\theta\cos\phi & -r\sin\theta\cos\phi & -r\cos\theta\sin\phi \\ + \sin\phi & 0 & r\cos\phi +\end{pmatrix} +$$ + +## 第 3 题 + +求下列复合函数的偏导数 $\dfrac{\partial z}{\partial x}, \dfrac{\partial z}{\partial y}$ (已知 $f$ 为可微函数). + +(1) $z = \arctan \dfrac{u}{v}, u = x^2 + y^2, v = xy$; + +(3) $z = f(x^2 - y^2, e^{xy})$; + +(5) $z = xy + \dfrac{y}{x}f(xy)$; + +**解** + +(1) $\dfrac{\partial z}{\partial x} = \dfrac{\partial z}{\partial u}\dfrac{\partial u}{\partial x} + \dfrac{\partial z}{\partial v}\dfrac{\partial v}{\partial x} = \dfrac{\dfrac{1}{v}}{1 + \left(\dfrac{u}{v}\right)^2}\cdot 2x + \dfrac{-\dfrac{u}{v^2}}{1 + \left(\dfrac{u}{v}\right)^2}\cdot y = \dfrac{y(x^2 - y^2)}{x^4 + 3x^2y^2 + y^4}$. + +$\dfrac{\partial z}{\partial y} = \dfrac{\partial z}{\partial u}\dfrac{\partial u}{\partial y} + \dfrac{\partial z}{\partial v}\dfrac{\partial v}{\partial y} = \dfrac{\dfrac{1}{v}}{1 + \left(\dfrac{u}{v}\right)^2}\cdot 2y + \dfrac{-\dfrac{u}{v^2}}{1 + \left(\dfrac{u}{v}\right)^2}\cdot x = \dfrac{x(y^2 - x^2)}{x^4 + 3x^2y^2 + y^4}$. + +(3) $\dfrac{\partial z}{\partial x} = \dfrac{\partial z}{\partial u}\dfrac{\partial u}{\partial x} + \dfrac{\partial z}{\partial v}\dfrac{\partial v}{\partial x} = f_1'(x^2 - y^2, e^{xy})\cdot 2x + f_2'(x^2 - y^2, e^{xy})\cdot ye^{xy} = 2xf_1' + ye^{xy}f_2'$. + +$\dfrac{\partial z}{\partial y} = \dfrac{\partial z}{\partial u}\dfrac{\partial u}{\partial y} + \dfrac{\partial z}{\partial v}\dfrac{\partial v}{\partial y} = f_1'(x^2 - y^2, e^{xy})\cdot (-2y) + f_2'(x^2 - y^2, e^{xy})\cdot xe^{xy} = -2yf_1' + xe^{xy}f_2'$. + +(5) $\dfrac{\partial z}{\partial x} = \dfrac{\partial z}{\partial u}\dfrac{\partial u}{\partial x} + \dfrac{\partial z}{\partial v}\dfrac{\partial v}{\partial x} = y + \dfrac{y^2f'(xy)x-yf(xy)}{x^2} = y + \dfrac{y^2f'(xy)}{x} - \dfrac{yf(xy)}{x^2}$. + +$\dfrac{\partial z}{\partial y} = \dfrac{\partial z}{\partial u}\dfrac{\partial u}{\partial y} + \dfrac{\partial z}{\partial v}\dfrac{\partial v}{\partial y} = x + \dfrac{f(xy) + yxf'(xy)}{x} = x + yf'(xy) + \dfrac{f(xy)}{x}$. + +## 第 4 题 + +已知函数 $z = u\ln(u - v)$, 其中 $u = e^{-x}, v = \ln x$, 求 $\dfrac{\text{d}{z}}{\text{d}{x}}$. + +**解** + +$$ +\begin{aligned} + \dfrac{\text{d}{z}}{\text{d}{x}} & = \dfrac{\partial z}{\partial u}\dfrac{\text{d}{u}}{\text{d}{x}} + \dfrac{\partial z}{\partial v}\dfrac{\text{d}{v}}{\text{d}{x}} \\ + & = \left(\ln(u - v) + \dfrac{u}{u - v}\right)\cdot (-e^{-x}) + \dfrac{u}{u - v}\cdot\left(-\dfrac{1}{x}\right) \\ + & = -e^{-x}\ln(e^{-x}-\ln x) - \dfrac{e^{-2x}}{e^{-x} - \ln x} - \dfrac{e^{-x}}{x(e^{-x} - \ln x)} +\end{aligned} +$$ + +## 第 5 题 + +已知函数 $u = f(x, y)$, 其中 $x = r\cos \theta, y = r\sin\theta$, $f$ 可微, 证明: + +$$ +\left(\dfrac{\partial u}{\partial r}\right)^2 + \left(\dfrac{1}{r}\dfrac{\partial u}{\partial \theta}\right)^2 = \left(\dfrac{\partial u}{\partial x}\right)^2 + \left(\dfrac{\partial u}{\partial y}\right)^2. +$$ + +**证明** + +由于 $\dfrac{\partial u}{\partial r} = \dfrac{\partial u}{\partial x}\dfrac{\partial x}{\partial r} + \dfrac{\partial u}{\partial y}\dfrac{\partial y}{\partial r} = \cos\theta \dfrac{\partial u}{\partial x} + \sin\theta \dfrac{\partial u}{\partial y}, \dfrac{\partial u}{\partial \theta} = \dfrac{\partial u}{\partial x}\dfrac{\partial x}{\partial \theta} + \dfrac{\partial u}{\partial y}\dfrac{\partial y}{\partial \theta} = -r\sin\theta \dfrac{\partial u}{\partial \theta} + r\cos\theta \dfrac{\partial u}{\partial \theta}$, 所以代入得 + +$$ +\begin{aligned} + \left(\dfrac{\partial u}{\partial r}\right)^2 + \left(\dfrac{1}{r}\dfrac{\partial u}{\partial \theta}\right)^2 & = \left(\cos\theta \dfrac{\partial u}{\partial x} + \sin\theta \dfrac{\partial u}{\partial y}\right)^2 + \left(-\sin\theta \dfrac{\partial u}{\partial \theta} + \cos\theta \dfrac{\partial u}{\partial \theta}\right)^2 \\ + & = \left(\dfrac{\partial u}{\partial x}\right)^2 + \left(\dfrac{\partial u}{\partial y}\right)^2. +\end{aligned} +$$ + +命题得证. + +## 第 6 题 + +设 $f$ 可微, $u = xy + xf\left(\dfrac{y}{x}\right)$, 证明: $x\dfrac{\partial u}{\partial x} + y\dfrac{\partial u}{\partial y} = u + xy$. + +**证明** + +由于 $\dfrac{\partial u}{\partial x} = y + f\left(\dfrac{y}{x}\right) - \dfrac{y}{x}f'\left(\dfrac{y}{x}\right), \dfrac{\partial u}{\partial y} = x + f'\left(\dfrac{y}{x}\right)$, 所以代入得 + +$$ +\begin{aligned} + x\dfrac{\partial u}{\partial x} + y\dfrac{\partial u}{\partial y} & = xy + xf\left(\dfrac{y}{x}\right) - yf'\left(\dfrac{y}{x}\right) + xy + yf'\left(\dfrac{y}{x}\right) \\ + & = 2xy + xf\left(\dfrac{y}{x}\right) \\ + & = u + xy +\end{aligned} +$$ + +命题得证. + +## 第 7 题 + +设 $f \in C^2(\mathbb{R}^2)$ 满足 Laplace 方程 $\dfrac{\partial ^2f}{\partial x^2} + \dfrac{\partial ^2f}{\partial y^2} = 0$, 证明: $u(x, y) = f\left(\dfrac{x}{x^2 + y^2}, \dfrac{y}{x^2 + y^2}\right)$ 也满足 Laplace 方程. + +**证明** + +$\dfrac{\partial u}{\partial x} = u_1'\dfrac{y^2 - x^2}{(x^2 + y^2)^2} + u_2'\dfrac{-2xy}{(x^2 + y^2)^2}$. + +$$ +\begin{aligned} + \dfrac{\partial^2 u}{\partial x^2} & = \dfrac{\partial}{\partial x}\left(u_1'\dfrac{y^2 - x^2}{(x^2 + y^2)^2}\right) + \dfrac{\partial}{\partial x}\left(u_2'\dfrac{-2xy}{(x^2 + y^2)^2}\right) \\ + & = u_{11}'\left(\dfrac{y^2 - x^2}{(x^2 + y^2)^2}\right)^2 - (u_{12}' + u_{21}')\dfrac{2xy(y^2 - x^2)}{(x^2 + y^2)^4} + u_{22}'\left(\dfrac{-2xy}{(x^2 + y^2)^2}\right)^2 \\ + & + u_1'\dfrac{-2x(3y^2 - x^2)}{(x^2 + y^2)^3} + u_2'\dfrac{2y(3x^2 - y^2)}{(x^2 + y^2)^3} +\end{aligned} +$$ + +同理可得 + +$$ +\begin{aligned} + \dfrac{\partial^2 u}{\partial y^2} & = u_{11}'\left(\dfrac{-2xy}{(x^2 + y^2)^2}\right)^2 + (u_{12}' + u_{21}')\dfrac{2xy(y^2 - x^2)}{(x^2 + y^2)^4} + u_{22}'\left(\dfrac{y^2 - x^2}{(x^2 + y^2)^2}\right)^2 \\ + & + u_2'\dfrac{-2y(3x^2 - y^2)}{(x^2 + y^2)^3} + u_1'\dfrac{2x(3y^2 - x^2)}{(x^2 + y^2)^3} +\end{aligned} +$$ + +由题知 $f$ 满足 Laplace 方程, 则 $u_{11}' + u_{22}' = 0$. 则 + +$$ +\begin{aligned} + \dfrac{\partial^2 u}{\partial x^2} + \dfrac{\partial^2 u}{\partial y^2} & = u_{11}'\left(\dfrac{y^2 - x^2}{(x^2 + y^2)^2}\right)^2 - (u_{12}' + u_{21}')\dfrac{2xy(y^2 - x^2)}{(x^2 + y^2)^4} + u_{22}'\left(\dfrac{-2xy}{(x^2 + y^2)^2}\right)^2 \\ + & + u_1'\dfrac{-2x(3y^2 - x^2)}{(x^2 + y^2)^3} + u_2'\dfrac{2y(3x^2 - y^2)}{(x^2 + y^2)^3} \\ + & + u_{11}'\left(\dfrac{-2xy}{(x^2 + y^2)^2}\right)^2 + (u_{12}' + u_{21}')\dfrac{2xy(y^2 - x^2)}{(x^2 + y^2)^4} + u_{22}'\left(\dfrac{y^2 - x^2}{(x^2 + y^2)^2}\right)^2 \\ + & + u_2'\dfrac{-2y(3x^2 - y^2)}{(x^2 + y^2)^3} + u_1'\dfrac{2x(3y^2 - x^2)}{(x^2 + y^2)^3} \\ + & = (u_{11}' + u_{22}')\left[\left(\dfrac{-2xy}{(x^2 + y^2)^2}\right)^2 +\left(\dfrac{y^2 - x^2}{(x^2 + y^2)^2}\right)^2\right] \\ + & = 0 +\end{aligned} +$$ + +命题得证. + +## 第 8 题 + +已知变换 $\begin{cases} w=x+y+z, \\u=x, \\ v=x+y,\end{cases}$ 化简方程 $\dfrac{\partial ^2z}{\partial x^2} - 2\dfrac{\partial ^2z}{\partial x \partial y} + \dfrac{\partial ^2z}{\partial y^2} + \dfrac{\partial z}{\partial x} - \dfrac{\partial z}{\partial y} = 0$, 以 $w$ 为因变量, $u, v$ 为自变量. + +**解** + +化简得 $z = -x - y + w$. 因此 + +$$ +\begin{aligned} + \dfrac{\partial z}{\partial x} & = \dfrac{\partial w}{\partial x} - 1 = \dfrac{\partial w}{\partial u}\dfrac{\partial u}{\partial x} + \dfrac{\partial w}{\partial v}\dfrac{\partial v}{\partial x} - 1 = \dfrac{\partial w}{\partial u} + \dfrac{\partial w}{\partial v} - 1, \\ + \dfrac{\partial z}{\partial y} & = \dfrac{\partial w}{\partial y} - 1 = \dfrac{\partial w}{\partial u}\dfrac{\partial u}{\partial y} + \dfrac{\partial w}{\partial v}\dfrac{\partial v}{\partial y} - 1 = \dfrac{\partial w}{\partial v} - 1. +\end{aligned} +$$ + +故 $\dfrac{\partial^2 z}{\partial x^2} = \dfrac{\partial^2 w}{\partial u^2} + 2\dfrac{\partial^2 w}{\partial u\partial v} + \dfrac{\partial^2 w}{\partial v^2}, \dfrac{\partial^2 z}{\partial x\partial y} = \dfrac{\partial^2 w}{\partial u\partial v} + \dfrac{\partial^2 w}{\partial v^2}, \dfrac{\partial^2 z}{\partial y^2} = \dfrac{\partial^2 w}{\partial v^2}$. + +则 + +$$ +\begin{aligned} + &\; \; \; \; \; \; \; \; \dfrac{\partial ^2z}{\partial x^2} - 2\dfrac{\partial ^2z}{\partial x \partial y} + \dfrac{\partial ^2z}{\partial y^2} + \dfrac{\partial z}{\partial x} - \dfrac{\partial z}{\partial y} \\ + & = \left(\dfrac{\partial^2 w}{\partial u^2} + 2\dfrac{\partial^2 w}{\partial u\partial v} + \dfrac{\partial^2 w}{\partial v^2}\right) - 2\left(\dfrac{\partial^2 w}{\partial u\partial v} + \dfrac{\partial^2 w}{\partial v^2}\right) + \dfrac{\partial^2 w}{\partial v^2} + \left(\dfrac{\partial w}{\partial u} + \dfrac{\partial w}{\partial v} - 1\right) - \left(\dfrac{\partial w}{\partial v} - 1\right) \\ + & = \dfrac{\partial^2w}{\partial u^2} + \dfrac{\partial w}{\partial u} +\end{aligned} +$$ + +所以化简为 $\dfrac{\partial^2w}{\partial u^2} + \dfrac{\partial w}{\partial u} = 0$. + +## 第 9 题 + +向量值函数 $\mathbf{Y} = \mathbf{f}(\mathbf{U}), \mathbf{U} = \mathbf{g}(\mathbf{X})$ 均可微, 求复合函数 $\mathbf{Y} = \mathbf{f} \circ \mathbf{g}(\mathbf{X})$ 的 Jacobi 矩阵和全微分. + +(1) $\begin{cases} y_1 = u_1 + u_2 \\ y_2 = u_1u_2 \\ y_3 = \dfrac{u_2}{u_1},\end{cases}\begin{cases}u_1 = \dfrac{x}{x^2 + y^2}, \\ u_2 = \dfrac{y}{x^2 + y^2};\end{cases}$ + +**解** + +(1) 因为 + +$$ +J_{\mathbf{g}} = \begin{pmatrix}\dfrac{\partial u_1}{\partial x} & \dfrac{\partial u_1}{\partial y} \\ \dfrac{\partial u_2}{\partial x} & \dfrac{\partial u_2}{\partial y}\end{pmatrix} = \begin{pmatrix}\dfrac{y^2 - x^2}{x^2 + y^2} & \dfrac{-2xy}{x^2 + y^2} \\ \dfrac{-2xy}{x^2 + y^2} & \dfrac{x^2 - y^2}{x^2 + y^2}\end{pmatrix}, +$$ + +$$ +J_{\mathbf{f}} = \begin{pmatrix}\dfrac{\partial y_1}{\partial u_1} & \dfrac{\partial y_1}{\partial u_2} \\ \dfrac{\partial y_2}{\partial u_1} & \dfrac{\partial y_2}{\partial u_2} \\ \dfrac{\partial y_3}{\partial u_1} & \dfrac{\partial y_3}{\partial u_2}\end{pmatrix} = \begin{pmatrix}1 & 1 \\ \dfrac{y}{x^2 + y^2} & \dfrac{x}{x^2 + y^2} \\ -\dfrac{y}{x} & \dfrac{x^2 + y^2}{x}\end{pmatrix}, +$$ + +所以 $J = J_{\mathbf{f}}J_{\mathbf{g}} = \begin{pmatrix}1 & 1 \\ \dfrac{y}{x^2 + y^2} & \dfrac{x}{x^2 + y^2} \\ -\dfrac{y}{x} & \dfrac{x^2 + y^2}{x}\end{pmatrix}\begin{pmatrix}\dfrac{y^2 - x^2}{x^2 + y^2} & \dfrac{-2xy}{x^2 + y^2} \\ \dfrac{-2xy}{x^2 + y^2} & \dfrac{x^2 - y^2}{x^2 + y^2}\end{pmatrix}$, 且全微分 $\text{d}{\mathbf{Y}} = J\begin{pmatrix}\text{d}{x} \\ \text{d}{y}\end{pmatrix}$. diff --git a/services/homework-ans/docs/calculus-2/chapter1/exercise1-6.md b/services/homework-ans/docs/calculus-2/chapter1/exercise1-6.md new file mode 100644 index 0000000..bd4e785 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter1/exercise1-6.md @@ -0,0 +1,106 @@ + +## 第 2 题 + +下列方程中, 在哪些点附近可以确定一个函数 $y = y(x)$ 或 $z = z(x, y)$, 并求出相应的 $\dfrac{\text{d}{y}}{\text{d}{x}}$ 或 $\dfrac{\partial z}{\partial x}, \dfrac{\partial z}{\partial y}$. + +(1) $(x^2 + y^2)^2 = a^2(y^2 - x^2)$; + +(2) $e^{-(x + y + z)} = x + y + z$; + +**解** + +(1) 设 $F(x, y) = (x^2 + y^2)^2 - a^2(y^2 - x^2)$. 在满足 $y_0 \neq 0, x_0^2 + y_0^2 \neq \dfrac{a^2}{2}$ 的点附近可以确定 $y = y(x)$, 且 $\dfrac{\text{d}{y}}{\text{d}{x}} = -\dfrac{\dfrac{\partial F}{\partial x}}{\dfrac{\partial F}{\partial y}} = -\dfrac{2x^3 + (2y^2 + a^2)x}{2y^3 + (2x^2 - a^2)y}$. + +(2) 设 $F(x, y, z) = e^{-(x + y + z)} - (x + y + z)$. 在 $\mathbb{R}^2$ 上的所有点附近都可以确定 $z = z(x, y)$, 且 $\dfrac{\partial z}{\partial x} = -\dfrac{\dfrac{\partial F}{\partial x}}{\dfrac{\partial F}{\partial z}} = -\dfrac{-e^{-(x + y + z)} - 1}{-e^{-(x + y + z)} - 1} = -1, \dfrac{\partial z}{\partial y} = -\dfrac{\dfrac{\partial F}{\partial y}}{\dfrac{\partial F}{\partial z}} = -\dfrac{-e^{-(x + y + z)} - 1}{-e^{-(x + y + z)} - 1} = -1$. + +## 第 3 题 + +下列方程均确定了函数 $z = z(x, y)$, 分别求解下列各表达式的值. + +(1) $f(ax - cz, ay - bz) = 0$, $f$ 可微, 计算: $c\dfrac{\partial z}{\partial x} + b\dfrac{\partial z}{\partial y}$; + +(3) $f(x, x + y, x + y + z) = 0$, $f$ 二阶可微, 计算: $\dfrac{\partial z}{\partial x}, \dfrac{\partial z}{\partial y}, \dfrac{\partial ^2z}{\partial x^2}$. + +**解** + +(1) $\dfrac{\partial z}{\partial x} = -\dfrac{\dfrac{\partial f}{\partial x}}{\dfrac{\partial f}{\partial z}} = -\dfrac{f_1'\cdot a}{f_1'\cdot (-c) + f_2'\cdot (-b)} = \dfrac{f_1'\cdot a}{f_1'\cdot c + f_2'\cdot b}$. 同理 $\dfrac{\partial z}{\partial y} = \dfrac{f_2'\cdot a}{f_1'\cdot c + f_2'\cdot b}$. 故 $c\dfrac{\partial z}{\partial x} + b\dfrac{\partial z}{\partial y} = \dfrac{f_1'\cdot ac}{f_1'\cdot c + f_2'\cdot b} + \dfrac{f_2'\cdot ab}{f_1'\cdot c + f_2'\cdot b} = a$. + +(3) $\dfrac{\partial z}{\partial x} = -\dfrac{\dfrac{\partial f}{\partial x}}{\dfrac{\partial f}{\partial z}} = -\dfrac{f_1' + f_2' + f_3'}{f_3'}$, $\dfrac{\partial z}{\partial y} = -\dfrac{\dfrac{\partial f}{\partial y}}{\dfrac{\partial f}{\partial z}} = -\dfrac{f_2' + f_3'}{f_3'}$. 故 + +$$ +\begin{aligned} + \dfrac{\partial ^2z}{\partial x^2} &= \dfrac{\partial }{\partial x}\left(\dfrac{\partial z}{\partial x}\right) \\ + & = -\dfrac{[(f_{11}'' + f_{12}'' + f_{13}''\cdot\dfrac{\partial z}{\partial x}) + (f_{21}'' + f_{22}'' + f_{23}''\cdot\dfrac{\partial z}{\partial x}) + (f_{31}'' + f_{32}'' + f_{33}''\cdot\dfrac{\partial z}{\partial x})]\cdot f_3'}{(f_3')^2} \\ + & - \dfrac{(f_1' + f_2' + f_3')(f_{31}'' + f_{32}'' + f_{33}''\dfrac{\partial z}{\partial x})}{(f_3')^2} \\ + & = - \dfrac{(f_{11}'' + 2f_{12}'' + f_{22}'')}{f_3'} + \dfrac{2(f_1' + f_2')(f_{13}'' + f_{23}'')}{(f_3')^2} - \dfrac{(f_1' + f_2')^2f_{33}''}{(f_3')^3} +\end{aligned} +$$ + +## 第 4 题 + +设方程 $f(u^2 - x^2, u^2 - y^2, u^2 - z^2) = 0$ 确定了函数 $u = u(x, y, z)$, 其中 $f$ 可微, 证明: + +$$ +\dfrac{1}{x}\dfrac{\partial u}{\partial x} + \dfrac{1}{y}\dfrac{\partial u}{\partial y} + \dfrac{1}{z}\dfrac{\partial u}{\partial z} = \dfrac{1}{u}. +$$ + +**证明** + +$$ +\dfrac{\partial u}{\partial x} = -\dfrac{\dfrac{\partial f}{\partial x}}{\dfrac{\partial f}{\partial u}} = -\dfrac{f_x'\cdot(-2x)}{f_x'\cdot (2u) + f_y'\cdot (2u) + f_z'\cdot (2u)} = \dfrac{x}{u}\cdot\dfrac{f_x'}{f_x' + f_y' + f_z'} +$$ + +同理有 $\dfrac{\partial u}{\partial y} = \dfrac{y}{u}\cdot\dfrac{f_y'}{f_x' + f_y' + f_z'}, \dfrac{\partial u}{\partial z} = \dfrac{z}{u}\cdot\dfrac{f_z'}{f_x' + f_y' + f_z'}$. 故 $\dfrac{1}{x}\dfrac{\partial u}{\partial x} + \dfrac{1}{y}\dfrac{\partial u}{\partial y} + \dfrac{1}{z}\dfrac{\partial u}{\partial z} = \dfrac{1}{u}\cdot\dfrac{f_x' + f_y' + f_z'}{f_x' + f_y' + f_z'} = \dfrac{1}{u}$. 命题得证. + +## 第 5 题 + +方程组 $\begin{cases}x = u + v, \\ y = u - v, \\ z = u^2v^2\end{cases}$ 能否确定 $z$ 是 $x, y$ 的函数? 如果能, 求 $\dfrac{\partial z}{\partial x}, \dfrac{\partial z}{\partial y}$; 如果不能, 说明理由. + +**解** + +由方程组可解得 + +$$ +\begin{cases} + u = \dfrac{x + y}{2}, \\ + v = \dfrac{x - y}{2}. +\end{cases} +$$ + +因此 $z = u^2v^2 = \dfrac{1}{16}(x^4 - 2x^2y^2 + y^4)$ 是 $x, y$ 的函数. $\dfrac{\partial z}{\partial x} = \dfrac{1}{4}(x^3 - xy^2)$, $\dfrac{\partial z}{\partial y} = \dfrac{1}{4}(y^3 - x^2y)$. + +## 第 6 题 + +方程组 $\begin{cases}x + y + z + z^2 = 0, \\ x + y^2 + z + z^3 = 0\end{cases}$ 在点 $P(-1, 1, 0)$ 附近能否确定向量值函数 $\begin{pmatrix}y\\z\end{pmatrix}=\mathbf{f}(x)$, 如果能确定, 求出 $y'(-1), z'(-1)$. + +**解** + +记 $F(x, y, z) = x + y + z + z^2, G(x, y, z) = x + y^2 + z + z^3$. 计算得 $\dfrac{\partial(F, G)}{\partial(y, z)} = \begin{pmatrix}1 & 1 + 2z \\ 2y & z + 3z^2\end{pmatrix}$. 由于 $\dfrac{\partial(F, G)}{\partial(y, z)}\bigg\vert_{(1, 0)} = \begin{pmatrix}1 & 1 \\ 2 & 0\end{pmatrix}$ 可逆, 故能确定向量值函数 $\mathbf{f}(x)$. 且有 $y(-1) = 1, z(-1) = 0$. 对 $\begin{cases}F(x, y, z) = 0, \\ G(x, y, z) = 0\end{cases}$ 求导得 $\begin{cases}1 + y'(x) + z'(x) + 2z(x)z'(x) = 0, \\ 1 + 2y(x)y'(x) + z'(x) + 3z^2(x)z'(x) = 0.\end{cases}$ 将 $x = 1$ 代入有 $\begin{cases}1 + y'(-1) + z'(-1) = 0, \\1 + 2y'(-1) + z'(-1) = 0.\end{cases}$ 解得 $y'(-1) = 0, z'(-1) = -1$. + +## 第 9 题 + +求下列向量值函数的逆映射的 Jacobi 矩阵以及 Jacobi 行列式. + +(1) $\begin{cases}u = x^2 - y^2, \\ v = 2xy;\end{cases}$ + +(3) $\begin{cases}u = x^3 - y^3, \\ v = xy^2;\end{cases}$ + +**解** + +(1) $J = \begin{pmatrix}\dfrac{\partial u}{\partial x} & \dfrac{\partial u}{\partial y} \\ \dfrac{\partial v}{\partial x} & \dfrac{\partial v}{\partial y}\end{pmatrix}^{-1} = \begin{pmatrix}2x & -2y \\ 2y & 2x\end{pmatrix}^{-1} = \dfrac{1}{2(x^2 + y^2)}\begin{pmatrix}x & y \\ -y & x\end{pmatrix}$. $\left|J\right| = \dfrac{1}{4(x^2 + y^2)}$. + +(3) $J = \begin{pmatrix}\dfrac{\partial u}{\partial x} & \dfrac{\partial u}{\partial y} \\ \dfrac{\partial v}{\partial x} & \dfrac{\partial v}{\partial y}\end{pmatrix}^{-1} = \begin{pmatrix}3x^2 & -3y^2 \\ y^2 & 2xy\end{pmatrix}^{-1} = \dfrac{1}{6x^3y + 3y^4}\begin{pmatrix}2xy & 3y^2 \\ -y^2 & 3x^2\end{pmatrix}$. $\left|J\right| = \dfrac{1}{6x^3y + 3y^4}$. + +## 第 10 题 + +下列由可微向量值函数 $\mathbf{g}:(\xi, \eta)\mapsto(u, v)$ 和 $\mathbf{f}:(x, y)\mapsto(\xi, \eta)$ 复合而成的复合向量值函数 $\mathbf{g}\circ\mathbf{f}$ 在 $(x_0, y_0)$ 的邻域内能否确定可微的逆向量值函数 $(\mathbf{g}\circ\mathbf{f})^{-1}$? + +(1) $\begin{cases}u = \xi^2 - \eta^2, \\ v = 2\xi\eta,\end{cases}\begin{cases}\xi = e^x\cos y,\\ \eta = e^x\sin y,\end{cases}(x_0, y_0) = (1, 0)$; + +(3) $\begin{cases}u = \xi^5 + \eta, \\ v = \eta^5 - \xi,\end{cases}\begin{cases}\xi = x^3-y^3,\\ \eta = x^2+2y^2,\end{cases}(x_0, y_0) = (1, 0)$. + +**解** + +(1) $\mathbf{g}$ 的逆映射的 Jacobi 矩阵为 $J_g = \begin{pmatrix}\dfrac{\partial u}{\partial \xi} & \dfrac{\partial u}{\partial \eta} \\ \dfrac{\partial v}{\partial \xi} & \dfrac{\partial v}{\partial \eta}\end{pmatrix}^{-1} = \begin{pmatrix}2\xi & -2\eta \\ 2\eta & 2\xi\end{pmatrix}^{-1} = \dfrac{1}{2(\xi^2 + \eta^2)}\begin{pmatrix}\xi & \eta \\ -\eta & \xi\end{pmatrix}$. $\mathbf{f}$ 的逆映射的 Jacobi 矩阵为 $J_f = \begin{pmatrix}\dfrac{\partial \xi}{\partial x} & \dfrac{\partial \xi}{\partial y} \\ \dfrac{\partial \eta}{\partial x} & \dfrac{\partial \eta}{\partial y}\end{pmatrix}^{-1} = \begin{pmatrix}e^x\cos y & -e^x\sin y \\ e^x\sin y & e^x\cos y\end{pmatrix}^{-1} = \dfrac{1}{e^{2x}}\begin{pmatrix}e^x\cos y & e^x\sin y \\ -e^x\sin y & e^x\cos y\end{pmatrix}$. 当 $x = x_0 = 1, y = y_0 = 0$ 时, $\left|J_f\right| \neq 0, \left|J_g\right| \neq 0$, 故能确定. 且 $(\mathbf{g}\circ\mathbf{f})^{-1}$ 的 Jacobi 矩阵为 $J_fJ_g$. + +(3) $\mathbf{g}$ 的逆映射的 Jacobi 矩阵为 $J_g = \begin{pmatrix}\dfrac{\partial u}{\partial \xi} & \dfrac{\partial u}{\partial \eta} \\ \dfrac{\partial v}{\partial \xi} & \dfrac{\partial v}{\partial \eta}\end{pmatrix}^{-1} = \begin{pmatrix}5\xi^4 & 1 \\ -1 & 5\eta^4\end{pmatrix}^{-1} = \dfrac{1}{25\xi^4\eta^4 + 1}\begin{pmatrix}5\eta^4 & -1 \\ 1 & 5\xi^4\end{pmatrix}$. $\mathbf{f}$ 的逆映射的 Jacobi 矩阵为 $J_f = \begin{pmatrix}\dfrac{\partial \xi}{\partial x} & \dfrac{\partial \xi}{\partial y} \\ \dfrac{\partial \eta}{\partial x} & \dfrac{\partial \eta}{\partial y}\end{pmatrix}^{-1} = \begin{pmatrix}3x^2 & -3y^2 \\ 2x & 4y\end{pmatrix}^{-1} = \dfrac{1}{12x^2y + 6xy^2}\begin{pmatrix}4y & 3y^2 \\ -2x & 3x^2\end{pmatrix}$. 当 $x = x_0 = 1, y = y_0 = 0$ 时, $J_f$ 前的系数分母为 $0$, 故 $J_f$ 不存在, 不能确定. diff --git a/services/homework-ans/docs/calculus-2/chapter1/exercise1-7.md b/services/homework-ans/docs/calculus-2/chapter1/exercise1-7.md new file mode 100644 index 0000000..c3747fe --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter1/exercise1-7.md @@ -0,0 +1,114 @@ + +## 第 1 题 + +求下列曲面在给定点的切平面方程和法线方程. + +(1) $z = x^2 + y^2$, 点 $P(1, 2, 5)$; + +(3) $(2a^2 - z^2)x^2 = a^2y^2$, 点 $P(a, a, a)(a \neq 0)$; + +(5) $\begin{cases}x = u\cos v, \\ y = u\sin v, \\ z = av,\end{cases}$ 点 $(u, v) = (u_0, v_0)$; + +**解** + +(1) 因为 $\dfrac{\partial z}{\partial x} = 2x, \dfrac{\partial z}{\partial y} = 2y$, 所以切平面的表达式为 $z = z_0 + 2x_0(x - x_0) + 2y_0(y - y_0)$. 将 $P(1, 2, 5)$ 代入得 $z = 2x + 4y - 5$. 法线的表达式为 $\dfrac{x - 1}{2} = \dfrac{y - 2}{4} = \dfrac{z - 5}{-1}$. + +(3) 记 $F(x, y, z) = (2a^2 - z^2)x^2 - a^2y^2$. 则 $\dfrac{\partial F}{\partial x} = 2x(2a^2 - z^2), \dfrac{\partial F}{\partial y} = -2a^2y, \dfrac{\partial F}{\partial z} = -2x^2z$. 代入 $P(a, a, a)$ 得切平面表达式为 $x - y - z + a = 0$, 法线表达式为 $x - a = a - y = a - z$. + +(5) + +$$ +\begin{aligned} + A &= \begin{vmatrix} + \dfrac{\partial y}{\partial u} & \dfrac{\partial y}{\partial v} \\ + \dfrac{\partial z}{\partial u} & \dfrac{\partial z}{\partial v} + \end{vmatrix} + = \begin{vmatrix} + \sin v & u\cos v \\ + 0 & a + \end{vmatrix} = a\sin v\\ + B &= \begin{vmatrix} + \dfrac{\partial z}{\partial u} & \dfrac{\partial z}{\partial v} \\ + \dfrac{\partial x}{\partial u} & \dfrac{\partial x}{\partial v} + \end{vmatrix} + = \begin{vmatrix} + 0 & a \\ + \cos v & -u\sin v + \end{vmatrix} = -a\cos v\\ + C &= \begin{vmatrix} + \dfrac{\partial x}{\partial u} & \dfrac{\partial x}{\partial v} \\ + \dfrac{\partial y}{\partial u} & \dfrac{\partial y}{\partial v} + \end{vmatrix} + = \begin{vmatrix} + \cos v & -u\sin v \\ + \sin v & u\cos v + \end{vmatrix} = u +\end{aligned} +$$ + +代入 $(u_0, v_0)$ 可得切平面为 $a\sin v_0(x - u_0\cos v_0) - a\cos v_0(y - u_0\sin v_0) + u_0(z - av_0) = 0$, 法线为 $\dfrac{x - u_0\cos v_0}{a\sin v_0} = \dfrac{y - u_0\sin v_0}{-a\cos v_0} = \dfrac{z - av_0}{u_0}$. + +## 第 2 题 + +在椭球面 $\dfrac{x^2}{a^2} + \dfrac{y^2}{b^2} + \dfrac{z^2}{c^2} = 1$ 上求一点 $P$, 使得过 $P$ 点的法线与坐标轴正方向成等角. + +**解** + +记 $F(x, y, z) = \dfrac{x^2}{a^2} + \dfrac{y^2}{b^2} + \dfrac{z^2}{c^2} - 1$. 则 $\dfrac{\partial F}{\partial x} = \dfrac{2x}{a^2}, \dfrac{\partial F}{\partial y} = \dfrac{2y}{b^2}, \dfrac{\partial F}{\partial z} = \dfrac{2z}{c^2}$. 因此在 $(x_0, y_0, z_0)$ 处的法向量为 $\left(\dfrac{2x_0}{a^2}, \dfrac{2y_0}{b^2}, \dfrac{2z_0}{c^2}\right)$. 由于与三个坐标轴的正方向成等角, 因此有 $\dfrac{2x_0}{a^2} = \dfrac{2y_0}{b^2} = \dfrac{2z_0}{c^2}$. 结合 $F(x_0, y_0, z_0) = 0$ 解得满足条件的点 $P$ 有两个, $P_1 = \left(\dfrac{a^2}{\sqrt{a^2 + b^2 + c^2}}, \dfrac{b^2}{\sqrt{a^2 + b^2 + c^2}}, \dfrac{c^2}{\sqrt{a^2 + b^2 + c^2}}\right), P_2 = \left(-\dfrac{a^2}{\sqrt{a^2 + b^2 + c^2}}, -\dfrac{b^2}{\sqrt{a^2 + b^2 + c^2}}, -\dfrac{c^2}{\sqrt{a^2 + b^2 + c^2}}\right)$. + +## 第 3 题 + +求曲面 $x^2 + 2y^2 + 3z^2 = 21$ 上平行于 $x + 4y + 6z = 0$ 的切平面. + +**解** + +设切点为 $P(x_0, y_0, z_0)$. 记 $F(x, y, z) = x^2 + 2y^2 + 3z^2 = 21$. 因为 $\dfrac{\partial F}{\partial x} = 2x, \dfrac{\partial F}{\partial y} = 4y, \dfrac{\partial F}{\partial z} = 6z$, 所以切平面的法向量为 $(2x_0, 4y_0, 6z_0)$. 因为改平面平行于 $x + 4y + 6z = 0$, 所以 $\dfrac{2x_0}{1} = \dfrac{4y_0}{4} = \dfrac{6z_0}{6}$. 解得法平面为 $x + 4y + 6z = 21$ 或 $x + 4y + 6z = -21$. + +## 第 4 题 + +(1) 曲面 $xyz = a^3$ 上的任一点的切平面与坐标平面围成的四面体的体积为定值; + +(3) 曲面 $z = x^2 + y^2$ 与直线 $l:\begin{cases}x + 2z = 1, \\ y + 2z = 2\end{cases}$ 垂直的切平面; + +(5) 设 $f$ 可微, 曲面 $z = yf\left(\dfrac{x}{y}\right)$ 的所有切平面相交于一个定点. + +**证明** + +(1) 设 $F(x, y, z) = xyz - a^3$. 则 $\dfrac{\partial F}{\partial x} = yz, \dfrac{\partial F}{\partial y} = xz, \dfrac{\partial F}{\partial z} = xy$. 假设切点为 $(x_0, y_0, z_0)$, 则切平面的表达式为 $y_0z_0(x - x_0) + x_0z_0(y - y_0) + x_0y_0(z - z_0) = 0$ 与坐标轴交点分别为 $(x_0, 0, 0), (0, y_0, 0), (0, 0, z_0)$. 体积即为 $\dfrac{1}{6}x_0y_0z_0 = \dfrac{1}{12}a^3$ 为定值. + +(3) 由于 $\dfrac{\partial z}{\partial x} = 2x, \dfrac{\partial z}{\partial y} = 2y$, 所以设切点为 $(x_0, y_0, z_0)$, 则法向量为 $(2x_0, 2y_0, -1)$. 而该直线能被表示为 $\dfrac{x - 1}{2} = \dfrac{y - 2}{2} = \dfrac{z}{-1}$, 因此有 $2x_0 = 2y_0 = 2$. 解得切点为 $(1, 1, 2)$. 所以切平面为 $2(x - 1) + 2(y - 1) - (z - 2) = 0$. + +(5) $\dfrac{\partial z}{\partial x} = yf'\left(\dfrac{x}{y}\right)\cdot \dfrac{1}{y} = f'\left(\dfrac{x}{y}\right), \dfrac{\partial z}{\partial y} = f\left(\dfrac{x}{y}\right) + y\cdot f'\left(\dfrac{x}{y}\right)\cdot\left(-\dfrac{x}{y^2}\right) = f\left(\dfrac{x}{y}\right) - \dfrac{xf'\left(\dfrac{x}{y}\right)}{y}$. 因此在 $(x_0, y_0)$ 处的切平面的表达式为 $f'\left(\dfrac{x_0}{y_0}\right)(x - x_0) + [f\left(\dfrac{x_0}{y_0}\right) - \dfrac{x_0f'\left(\dfrac{x_0}{y_0}\right)}{y_0}](y - y_0) + y_0f'\left(\dfrac{x_0}{y_0}\right) - z = 0$, 过定点 $(0, 0, 0)$. + +## 第 5 题 + +求曲线 $l:\begin{cases}x^2 + y^2 + z^2 = 6, \\ x + y + z = 0\end{cases}$ 在点 $P(1, -2, 1)$ 处的切线方程与法平面方程. + +**解** + +记 $F(x, y, z) = x^2 + y^2 + z^2 - 6, G(x, y, z) = x + y + z$. 则 $\dfrac{\partial F}{\partial x} = 2x, \dfrac{\partial F}{\partial y} = 2y, \dfrac{\partial F}{\partial z} = 2z$, $\dfrac{\partial G}{\partial x} = \dfrac{\partial G}{\partial y} = \dfrac{\partial G}{\partial z} = 1$. 因此代入 $P(1, -2, 1)$, 有切线方程满足 + +$$ +\begin{cases} + 2(x - 1) - 4(y + 2) + 2(z - 1) = 0, \\ + (x - 1) + (y + 2) + (z - 1) = 0. +\end{cases} +$$ + +法平面的方程则为 $-(x - 1) + (z - 1) = 0$, 即为 $x - z = 0$. + +## 第 6 题 + +证明: 螺旋线 $\begin{cases}x = a\cos t, \\ y = a\sin t, \\ z = bt\end{cases}$ 的切线与 $z$ 轴形成定角. + +**证明** + +设切点在 $t = t_0$ 处. 则切向量为 $\mathbf{n} = (-a\sin t_0, a\cos t_0, b)$, 记沿着 $z$ 轴正方向的单位向量为 $\mathbf{k} = (0, 0, 1)$. 该切线与 $z$ 轴正方向所夹角度 $\theta$ 满足 $\cos\theta = \dfrac{\mathbf{n}\cdot \mathbf{k}}{\left|\mathbf{n}\right|} = \dfrac{b}{\sqrt{a^2 + b^2}}$ 为定值. + +## 第 7 题 + +已知函数 $f$ 可微, 若 $T$ 为曲面 $S:f(x, y, z) = 0$ 在点 $P(x_0, y_0, z_0)$ 处的切平面, $l$ 为 $T$ 上任意一条过 $P$ 的曲线, 求证: 在 $S$ 上存在一条曲线, 该曲线在 $P$ 处的切线恰好为 $l$. + +**证明** + +不妨设要求的曲线为 $L$. 现在构造 $L$ 如下: 过 $P(x_0, y_0, z_0)$ 有法向量 $\mathbf{n}$, 由于 $\mathbf{n}$ 和 $l$ 相互垂直, 因此张成了一个平面 $Q$. 取 $L$ 为 $Q$ 和 $S$ 的交线, 则 $L$ 与平面 $Q$ 相切, 且它在 $P$ 处的切线恰好为 $l$. 因此命题得证. diff --git a/services/homework-ans/docs/calculus-2/chapter1/exercise1-8.md b/services/homework-ans/docs/calculus-2/chapter1/exercise1-8.md new file mode 100644 index 0000000..0f87585 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter1/exercise1-8.md @@ -0,0 +1,28 @@ + +## 第 1 题 + +分别写出下列函数在点 $O$ 处带有二阶 Peano 余项和 Lagrange 余项的 Taylor 公式. + +(1) $z = \cos(x^2 + y^2)$; + +(2) $z = e^{x^2 - y^2}$; + +(3) $u = \ln(1 + x + y + z)$. + +**解** + +(1) 由于 $\dfrac{\partial z}{\partial x} = -2x\sin(x^2 + y^2), \dfrac{\partial z}{\partial y} = -2y(x^2 + y^2)$, 所以 $\dfrac{\partial^2 z}{\partial x^2} = -4x^2\cos(x^2 + y^2) - 2\sin(x^2 + y^2), \dfrac{\partial^2 z}{\partial y^2} = -4y^2\cos(x^2 + y^2) - 2\sin(x^2 + y^2), \dfrac{\partial^2 z}{\partial x\partial y} = -4xy\cos(x^2 + y^2)$. 因此带有二阶 Peano 余项的 Taylor 公式为 $z = 1 + o(x^2 + y^2)$, 因此带有二阶 Lagrange 余项的 Taylor 公式为 $z = 1 - (x^2 + y^2)\sin(\theta^2(x^2 + y^2)) - 2\theta^2(x^2 + y^2)^2\cos(\theta^2(x^2 + y^2)), \theta \in (0, 1)$. + +(2) 由于 $\dfrac{\partial z}{\partial x} = 2xe^{x^2 - y^2}, \dfrac{\partial z}{\partial y} = -2ye^{x^2-y^2}$, 所以 $\dfrac{\partial^2 z}{\partial x^2} = (4x^2+2)e^{x^2-y^2}, \dfrac{\partial^2 z}{\partial y^2} = (4y^2-2)e^{x^2-y^2}, \dfrac{\partial^2 z}{\partial x\partial y} = -4xye^{x^2-y^2}$. 因此带有二阶 Peano 余项的 Taylor 公式为 $z = 1 + x^2 - y^2 + o(x^2 + y^2)$, 带有二阶 Lagrange 余项的 Taylor 公式为 $z = 1 + (x^2-y^2)e^{\theta^2(x^2-y^2)}(1+2\theta^2(x^2-y^2)), \theta \in (0, 1)$. + +(3) 由于 $\dfrac{\partial u}{\partial x} = \dfrac{\partial u}{\partial y} = \dfrac{\partial u}{\partial z} = \dfrac{1}{1 + x + y + z}$, 所以 $\dfrac{\partial^2 u}{\partial x^2} = \dfrac{\partial ^2u}{\partial x\partial y} = \dfrac{\partial^2 u}{\partial x\partial z} = \dfrac{\partial^2u}{\partial y^2} = \dfrac{\partial^2u}{\partial y\partial z} = \dfrac{\partial^2u}{\partial z^2} = -\dfrac{1}{(1 + x + y + z)^2}$. 因此带有二阶 Peano 余项的 Taylor 公式为 $z = x + y + z - \dfrac{1}{2}(x + y + z)^2 + o(x^2 + y^2 + z^2)$, 带有二阶 Lagrange 余项的 Taylor 公式为 $z = x + y + z - \dfrac{1}{2(1 + \theta x + \theta y + \theta z)^2}(x + y + z)^2, \theta \in (0, 1)$. + +## 第 2 题 + +写出下列函数在指定点处的 Taylor 公式 + +(2) $z = \dfrac{\cos x}{\cos y}$ 在点 $(0, 0)$ 处的二阶 Taylor 多项式; + +**解** + +(2) $\dfrac{\partial z}{\partial x} = -\dfrac{\sin x}{\cos y}, \dfrac{\partial z}{\partial y} = \dfrac{\cos x\sin y}{\cos^2y}$. 因此 $\dfrac{\partial^2z}{\partial x^2} = -\dfrac{\cos x}{\cos y}, \dfrac{\partial^2z}{\partial x\partial y} = -\dfrac{\sin x\sin y}{\cos^2y}, \dfrac{\partial^2z}{\partial y^2} = \dfrac{(\sin^2 y + \cos y)\cos x}{\cos^3 y}$. 故 $R_{2}(x, y) = \dfrac{1}{2}(\dfrac{\partial^2z}{\partial x^2}\bigg\vert_{(0, 0)}x^2 + 2\dfrac{\partial^2z}{\partial x\partial y}\bigg\vert_{(0, 0)}xy + \dfrac{\partial^2z}{\partial y^2}\bigg\vert_{(0, 0)}y^2) = -\dfrac{1}{2}x^2 + \dfrac{1}{2}y^2$. 因此在 $(0, 0)$ 处的二阶 Taylor 多项式为 $z = 1 - \dfrac{1}{2}x^2 + \dfrac{1}{2}y^2$. diff --git a/services/homework-ans/docs/calculus-2/chapter1/exercise1-9.md b/services/homework-ans/docs/calculus-2/chapter1/exercise1-9.md new file mode 100644 index 0000000..d7d8b53 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter1/exercise1-9.md @@ -0,0 +1,232 @@ + +## 第 1 题 + +研究下列函数的极值. + +(1) $z = x^3 + y^3 - 3x^2 - 3y^2$; + +(2) $z = e^{2x}(x + y^2 + 2y)$; + +(4) $z = x_1 + \dfrac{x_2}{x_1} + \dfrac{x_3}{x_2} + \cdots + \dfrac{x_n}{x_{n - 1}} + \dfrac{2}{x_n}, \quad x_i > 1$; + +(5) $u = x + \dfrac{y^2}{4x} + \dfrac{z^2}{y} + \dfrac{2}{z}, \quad x, y, z > 0$. + +**解** + +(1) $\dfrac{\partial z}{\partial x} = 3x^2 - 6x, \dfrac{\partial z}{\partial y} = 3y^2 - 6y$. Hesse 矩阵为 $H = \begin{pmatrix}6x - 6 & 0\\ 0 & 6y - 6\end{pmatrix}$. 驻点有 $(0, 0), (0, 2), (2, 0), (2, 2)$. 代入 Hesse 矩阵判断正定性、负定性知极小值点为 $(2, 2)$, 极大值点为 $(0, 0)$. 因此极小值为 $z(2, 2) = -8$, 极大值为 $z(0, 0) = 0$. + +(2) $\dfrac{\partial z}{\partial x} = e^{2x}(2x + 2y^2 + 4y + 1), \dfrac{\partial z}{\partial y} = e^{2x}(2y + 2)$. Hesse 矩阵为 $H = \begin{pmatrix}e^{2x}(4x + 4y^2 + 8y + 4) & (4y+4)e^{2x}\\ (4y+4)e^{2x} & 2e^{2x}\end{pmatrix}$. 驻点为 $(\dfrac{1}{2}, -1)$. 代入 Hesse 矩阵, 为正定的. 因此有极小值为 $z\left(\dfrac{1}{2}, -1\right) = -\dfrac{e}{2}$. + +(4) $\dfrac{\partial z}{\partial x_1} = 1 - \dfrac{x_2}{x_1}$, $\dfrac{\partial z}{\partial x_i} = \dfrac{1}{x_{i - 1}} - \dfrac{x_{i + 1}}{x_i^2}, \quad (2 \le i \le n - 1)$, $\dfrac{\partial z}{\partial x_n} = \dfrac{1}{x_{n - 1}} - \dfrac{2}{x_n^2}$. 因此 Hesse 矩阵为 + +$$ +\begin{pmatrix} + \dfrac{2x_2}{x_1^3} & -\dfrac{1}{x_1^2} & 0 & 0 & \cdots & 0 \\ + -\dfrac{1}{x_1^2} & \dfrac{2x_3}{x_2^3} & -\dfrac{1}{x_2^2} & 0 & \cdots & 0 \\ + 0 & -\dfrac{1}{x_2^2} & \dfrac{2x_4}{x_3^3} & -\dfrac{1}{x_3^2} & \cdots & 0 \\ + 0 & 0 & -\dfrac{1}{x_3^2} & \dfrac{2x_5}{x_4^3} & \cdots & 0 \\ + \vdots & \vdots & \vdots & \vdots & \ddots & \vdots \\ + 0 & 0 & 0 & 0 & \cdots & \dfrac{4}{x_n^3} +\end{pmatrix} +$$ + +驻点为 $(2^{\frac{1}{n+1}}, 2^{\frac{2}{n+1}}, \cdots, 2^{\frac{n}{n+1}})$. 代入 Hesse 矩阵知其为正定的, 因此有极小值 $z(2^{\frac{1}{n+1}}, 2^{\frac{2}{n+1}}, \cdots, 2^{\frac{n}{n+1}}) = (n+1)2^{\frac{1}{n+1}}$. + +(5) $\dfrac{\partial u}{\partial x} = 1 - \dfrac{y^2}{4x^2}, \dfrac{\partial u}{\partial y} = \dfrac{y}{2x} - \dfrac{z^2}{y^2}, \dfrac{\partial u}{\partial z} = \dfrac{2z}{y} - \dfrac{2}{z^2}$. Hesse 矩阵为 $\begin{pmatrix}\dfrac{y^2}{2x^3} & -\dfrac{y}{2x^2} & 0\\ -\dfrac{y}{2x^2} & \dfrac{1}{2x} + \dfrac{2z^2}{y^3} & -\dfrac{2z}{y^2} \\ 0 & -\dfrac{2z}{y^2} & \dfrac{2}{y} + \dfrac{4}{z^3}\end{pmatrix}$. 驻点为 $\left(\dfrac{1}{2}, 1, 1\right)$ 和 $\left(-\dfrac{1}{2}, -1, -1\right)$. 代入 Hesse 矩阵知极小值点为 $(\dfrac{1}{2}, 1, 1)$. 因此极小值为 $u(\dfrac{1}{2}, 1, 1) = 4$. + +## 第 2 题 + +函数 $z = z(x, y)$ 由 $2x^2 + 2y^2 + z^2 + 8xz - z + 8 = 0$ 确定, 求 $z = z(x, y)$ 的极值. + +**解** + +记 $F(x, y, z) = 2x^2 + 2y^2 + z^2 + 8xz - z + 8$. 因此 $\dfrac{\partial z}{\partial x} = -\dfrac{\dfrac{\partial F}{\partial x}}{\dfrac{\partial F}{\partial z}} = -\dfrac{4x + 8z}{2z + 8x - 1}, \dfrac{\partial z}{\partial y} = -\dfrac{\dfrac{\partial F}{\partial y}}{\dfrac{\partial F}{\partial z}} = \dfrac{4y}{2z + 8x - 1}$. 因此在极值点有 $\begin{cases}4x_0 + 8z_0 = 0, \\ y_0 = 0.\end{cases}$ 代入方程有 $2(-2z_0)^2 + z_0^2 + 8(-2z_0)z_0 - z_0 + 8 = 0$, 化简得 $7z_0^2 + z_0 - 8 = 0$. 解得 $z_{01} = 1. z_{02} = -\dfrac{8}{7}$. 经检验 Hesse 矩阵也满足条件, 所以极小值为 $1$, 极大值为 $-\dfrac{8}{7}$. + +## 第 4 题 + +求下列函数在给定区域的最值. + +(2) $z = xy(4 - x - y), (x, y) \in \{x + y \le 6, y \ge 0, x \ge 1\}$. + +**解** + +由于 $\dfrac{\partial z}{\partial x} = 4y - y^2 - 2xy, \dfrac{\partial z}{\partial y} = 4x - x^2 - 2xy$, 所以驻点满足方程 + +$$ +\begin{cases} + 4y - y^2 - 2xy = 0 \\ + 4x - x^2 - 2xy = 0 +\end{cases} +$$ + +解得 $(x, y) = (0, 0), (0, 4), \left(\dfrac{4}{3}, \dfrac{4}{3}\right), (4, 0)$. 再加上 $x \ge 1$ 的条件后, 只剩下 $z\left(\dfrac{4}{3}, \dfrac{4}{3}\right) = \dfrac{64}{27}$ 和 $z(4, 0) = 0$. + +再考虑边界上的极值. 当 $y = 0$ 时 $z \equiv 0$. 当 $x = 1$ 时 $z = y(3 - y) \in \left[0, \dfrac{9}{4}\right]$. 当 $x + y = 6$ 时 $z = -2xy \in [-18, 0]$. + +综上可得 $z$ 有最大值 $\dfrac{64}{27}$, 最小值 $-18$. + +## 第 5 题 + +证明下列各题 + +(1) 设 $D$ 为 $\mathbb{R}^2$ 中的有界闭区域. $f(x, y)$ 在 $D$ 上连续, 在 $D$ 内可微, 且满足方程 $\dfrac{\partial f}{\partial x} + \dfrac{\partial f}{\partial y} = kf(x, y)(k > 0)$, 若在 $D$ 的边界上有 $f(x, y) = 0$, 试证 $f(x, y)$ 在 $D$ 上恒为 $0$. + +(2) 设 $u(x, y)$ 在 $x^2 + y^2 \le 1$ 上连续, 在 $x^2 + y^2 < 1$ 满足 $\dfrac{\partial^2 u}{\partial x^2} + \dfrac{\partial^2u}{\partial y^2} = u$. 且在 $x^2 + y^2 = 1$ 上, $u(x, y) \ge 0$. 证明: 当 $x^2 + y^2 \le 1$ 时, $u(x, y) \ge 0$. + +**证明** + +(1) 反证法. 假设 $\exists P(x_0, y_0)$ 使得 $f(x_0, y_0) \neq 0$. 不妨设 $f(x_0, y_0) > 0$. 则由题知 $\dfrac{\partial f}{\partial x}\bigg\vert_P + \dfrac{\partial f}{\partial y}\bigg\vert_P = kf(x_0, y_0) > 0$. 因此 $\dfrac{\partial f}{\partial x}\bigg\vert_P$ 和 $\dfrac{\partial f}{\partial y}\bigg\vert_P$ 中至少有一个为正数. 不妨设 $\dfrac{\partial f}{\partial x}\bigg\vert_P> 0$. 则 $f(x, y)$ 从 $f(x_0, y_0)$ 沿着 $x$ 方向单调递增. 而 $f(x_0, y_0) > 0$, 所以沿着该方向到边界时, 有边界点函数值也为正数, 矛盾. 因此 $f(x, y) \equiv 0$. + +(2) 反证法. 假设 $\exists P(x_0, y_0)$ 使得 $u(x_0, y_0) < 0$, 且 $u$ 在 $P(x_0, y_0)$ 处取得极小值. 则在极小值点 $P(x_0, y_0)$ 处的 Hesse 矩阵的迹为 $\dfrac{\partial^2 u}{\partial x^2}\bigg\vert_P + \dfrac{\partial^2u}{\partial y^2}\bigg\vert_P > 0$. 这与题目 $\dfrac{\partial^2 u}{\partial x^2}\bigg\vert_P + \dfrac{\partial^2u}{\partial y^2}\bigg\vert_P = u(x_0, y_0) < 0$ 矛盾. 因此当 $x^2 + y^2 \le 1$ 时, $u(x, y) \ge 0$. + +## 第 6 题 + +证明函数 $z(x, y) = (1 + e^y)\cos x - ye^y$ 有无穷多个极大值点而无极小值. + +**证明** + +由于 $\dfrac{\partial z}{\partial x} = -(1 + e^y)\sin x, \dfrac{\partial z}{\partial y} = (\cos x - 1 - y)e^y$, 所以 Hesse 矩阵为 + +$$ +H = \begin{pmatrix}\dfrac{\partial^2 z}{\partial x^2} & \dfrac{\partial ^2z}{\partial x\partial y} \\ \dfrac{\partial^2z}{\partial x\partial y} & \dfrac{\partial^2z}{\partial y^2}\end{pmatrix} = \begin{pmatrix}-(1+e^y)\cos x & -e^y\sin x \\ -e^y\sin x & (\cos x - y - 2)e^y\end{pmatrix} +$$ + +且驻点为 $(2k\pi, 0)$ 和 $((2k+1)\pi, 2)$, 其中 $k \in \mathbb{Z}$. 将 $(2k\pi, 0)$ 代入 $H$, 有 $H_1 = \begin{pmatrix}-2 & 0 \\ 0 & -1\end{pmatrix}$ 负定. 因此 $(2k\pi, 0), k \in \mathbb{Z}$ 为极大值点, 且有无穷多个. 将 $((2k + 1)\pi, 2)$ 代入 $H$, 有 $H_2 = \begin{pmatrix}e^2 + 1 & 0 \\ 0 & -5e^2\end{pmatrix}$ 不定. 因此 $((2k + 1)\pi, 2), k \in \mathbb{Z}$ 不为极值点. 所以没有极小值点. + +## 第 7 题 + +求下列函数在给定条件下的条件极值. + +(1) $\begin{cases}z = x^2 + y^2, \\ \text{s.t.} \dfrac{x}{a} + \dfrac{y}{b} = 1;\end{cases}$ + +(2) $\begin{cases}u = x - 2y + 2z, \\ \text{s.t.} x^2 + y^2 + z^2 = 1;\end{cases}$ + +**解** + +(1) $L = x^2 + y^2 + \lambda\left(\dfrac{x}{a} + \dfrac{y}{b} - 1\right)$. $L_x' = 2x + \dfrac{\lambda}{a}, L_y' = 2y + \dfrac{\lambda}{b}$. 因此有方程组 $\begin{cases}2x + \dfrac{\lambda}{a} = 0 \\2y + \dfrac{\lambda}{b} = 0 \\\dfrac{x}{a} + \dfrac{y}{b} = 1\end{cases}$, 解得 $\begin{cases}x = \dfrac{ab^2}{a^2 + b^2} \\y = \dfrac{a^2b}{a^2 + b^2} \\\lambda = -\dfrac{2a^2b}{a^2 + b^2}\end{cases}$. 此时有 $z = \dfrac{a^2b^2}{a^2 + b^2}$ 为极小值. + +(2) $L = x - 2y + 2z + \lambda(x^2 + y^2 + z^2 - 1)$. $L_x' = 1 + 2\lambda x, L_y' = -2 + 2\lambda y, L_z' = 2 + 2\lambda z$. 因此有方程组 $\begin{cases}1 + 2\lambda x = 0 \\ -2 + 2\lambda y = 0 \\ 2 + 2\lambda z = 0 \\ x^2 + y^2 + z^2 = 1\end{cases}$. 解得 $\begin{cases}x = -\dfrac{1}{3} \\ y = \dfrac{2}{3} \\ z = -\dfrac{2}{3} \\ \lambda = \dfrac{3}{2}\end{cases}$ 或 $\begin{cases}x = \dfrac{1}{3} \\ y = -\dfrac{2}{3} \\ z = \dfrac{2}{3} \\ \lambda = -\dfrac{3}{2}\end{cases}$. 因此有极小值 $u\left(-\dfrac{1}{3}, \dfrac{2}{3}, -\dfrac{2}{3}\right) = -3$, 极大值 $u\left(\dfrac{1}{3}, -\dfrac{2}{3}, \dfrac{2}{3}\right) = 3$. + +## 第 8 题 + +求函数 $u = x^2 + 2y^2 + z^2 - 2xy - 2yz$ 在区域 $x^2 + y^2 + z^2 \le 4$ 内的最值. + +**解** + +\begin{enumerate} + \item 考虑内点处的极值. $\dfrac{\partial u}{\partial x} = 2x - 2y, \dfrac{\partial u}{\partial y} = 4y - 2x - 2z, \dfrac{\partial u}{\partial z} = 2z - 2y$. 因此驻点满足 $x = y = z$. 此时 $u = 0$. + \item 考虑边界点处的极值. $L = x^2 + 2y^2 + z^2 - 2yz - 2xy + \lambda(x^2 + y^2 + z^2 - 4)$. $L_x' = 2x - 2y + 2\lambda x, L_y' = 4y - 2z - 2z + 2\lambda y, L_z' = 2z - 2y + 2\lambda z$. 因此有方程组 $\begin{cases}2x - 2y + 2\lambda x = 0 \\ 4y - 2z - 2z + 2\lambda y = 0 \\ 2z - 2y + 2\lambda z = 0 \\ x^2 + y^2 + z^2 = 4\end{cases}$. 解得 $(x, y, z) = (0, 0, 0), \left(\dfrac{2\sqrt{3}}{3}, \dfrac{2\sqrt{3}}{3}, \dfrac{2\sqrt{3}}{3}\right), \left(\pm\dfrac{\sqrt{6}}{3}, \mp\dfrac{2\sqrt{6}}{3}, \pm\dfrac{\sqrt{6}}{3}\right), (\pm\sqrt{2}, 0, \mp\sqrt{2}),$. 故有最大值 $u\left(\pm\dfrac{\sqrt{6}}{3}, \mp\dfrac{2\sqrt{6}}{3}, \pm\dfrac{\sqrt{6}}{3}\right) = 12$, 最小值 $u(k, k, k)(k \in \mathbb{R}) \equiv 0$. +\end{enumerate} + +## 第 9 题 + +求解下列问题. + +(1) 求椭圆 $x^2 + \dfrac{y^2}{4} = 1$ 上的点到直线 $x + y = 4$ 的距离的最值; + +(3) 求椭圆面 $\dfrac{x^2}{a^2} + \dfrac{y^2}{b^2} + \dfrac{z^2}{c^2} = 1$ 内接长方体的体积最值; + +**解** + +(1) 设椭圆上的某一点为 $P(\cos \theta, 2\sin \theta), \theta \in (-\pi, \pi]$. 距离为 $d = \dfrac{\left|\cos \theta + 2\sin \theta - 4\right|}{\sqrt{2}} = \dfrac{\left|4 - \sqrt{5}\cos\varphi\right|}{\sqrt{2}} \in [\dfrac{4\sqrt{2} - \sqrt{10}}{2}, \dfrac{4\sqrt{2} + \sqrt{10}}{2}]$. 因此最大值为 $\dfrac{4\sqrt{2} + \sqrt{10}}{2}$, 最小值为 $\dfrac{4\sqrt{2} - \sqrt{10}}{2}$. + +(3) 易知该长方体关于原点中心对称. 设长方体的某一个顶点为 $P(a\cos\theta\cos\varphi, b\cos\theta\sin\varphi, c\sin\theta)$. 则体积为 $V = 8\left|xyz\right| = 8abc\cos^2\theta\sin\theta\sin\varphi\cos\varphi = 4abc\sin\theta(1 - \sin^2\theta)\sin2\varphi \in (0, \dfrac{2\sqrt{3}}{9}abc]$. 因此体积最大值为 $\dfrac{8\sqrt{3}}{9}abc$, 无最小值. + +## 第 10 题 + +求解下列问题. + +(3) 已知矩形的周长为 $2p$, 将它绕其一边旋转成的圆柱体的体积最大值为多少? + +**解** + +设矩形的一边长为 $x$, 则邻边长为 $p - x$. 绕长为 $p - x$ 的边旋转而成的圆柱体体积为 $\pi x^2 (p-x) = \dfrac{\pi}{2}x \cdot x \cdot (2p - 2x) \le \dfrac{\pi}{2}\left(\dfrac{x + x + 2p - 2x}{3}\right)^3 = \dfrac{4p^3\pi}{27}$. 因此圆柱体的体积最大值为 $\dfrac{4p^3\pi}{27}$. + +## 第 11 题 + +求解下列问题. + +(1) 求函数 $u = x^2y^2z^2$ 在约束条件 $x^2 + y^2 + z^2 = a^2$ 下的最大值, 并证明: + +$$ +\sqrt[3]{x^2y^2z^2} \le \dfrac{x^2 + y^2 + z^2}{3}; +$$ + +(2) 类似 (1), 证明: $a_1, a_2, \cdots, a_n > 0$ 有 + +$$ +\sqrt{\dfrac{a_1^2 + a_2^2 + \cdots + a_n^2}{n}} \ge \dfrac{a_1 + a_2 + \cdots + a_n}{n} \ge \sqrt[n]{a_1a_2\cdots a_n} \ge \dfrac{n}{\dfrac{1}{a_1} + \dfrac{1}{a_2} + \cdots + \dfrac{1}{a_n}}. +$$ + +**证明** + +(1) 设 $L = x^2y^2z^2 + \lambda(x^2 + y^2 + z^2 - a^2)$, 则 + +$$ +\begin{aligned} + L_x' & = 2xy^2z^2 + 2x\lambda = 0 \\ + L_y' & = 2x^2yz^2 + 2y\lambda = 0 \\ + L_z' & = 2x^2y^2z + 2z\lambda = 0 +\end{aligned} +$$ + +解得有极大值点满足 $x^2 = y^2 = z^2 = \dfrac{a^2}{3}$, 因此有 $x^2y^2z^2 \le \left(\dfrac{a^2}{3}\right)^3 = \left(\dfrac{x^2 + y^2 + z^2}{3}\right)^3$. 此即 $\sqrt[3]{x^2y^2z^2} \le \dfrac{x^2 + y^2 + z^2}{3}$. + +(2) 同理, 拓展至 $n$ 元, 有 $\sqrt{\dfrac{a_1^2 + a_2^2 + \cdots + a_n^2}{n}} \ge \dfrac{a_1 + a_2 + \cdots + a_n}{n}$. 而由 $n$ 元均值不等式有 $\dfrac{a_1 + a_2 + \cdots + a_n}{n} \ge \sqrt[n]{a_1a_2\cdots a_n}$. 将 $a_1 = \dfrac{1}{b_1}, a_2 = \dfrac{1}{b_2}, \cdots, a_n = \dfrac{1}{b_n}$ 代入有 $\dfrac{\dfrac{1}{b_1} + \dfrac{1}{b_2} + \cdots + \dfrac{1}{b_n}}{n}\ge \dfrac{1}{\sqrt[n]{b_1b_2\cdots b_n}}$, 不等式两边同时取倒数, 有 $\sqrt[n]{b_1b_2\cdots b_n} \ge \dfrac{n}{\dfrac{1}{b_1} + \dfrac{1}{b_2} + \cdots + \dfrac{1}{b_n}}$. 此即 $\sqrt[n]{a_1a_2\cdots a_n} \ge \dfrac{n}{\dfrac{1}{a_1} + \dfrac{1}{a_2} + \cdots + \dfrac{1}{a_n}}$. 命题得证. + +## 第 13 题 + +弹簧在弹性限度内的伸长 $x$ 与所受拉力 $y$ 满足关系式 $y = a + bx$, 试根据下列数据确定弹性系数 $b$. + +\begin{table}[H] + \centering + %\caption{} + \vspace{1em} + \begin{tabular}{|c|c|c|c|c|} + \hline + $x_i/\text{cm}$ & 2.6 & 3.0 & 3.5 & 4.3 \\ + \hline + $y_i/\text{kg}$ & 0 & 1 & 2 & 3 \\ + \hline + \end{tabular} + %\label{} +\end{table} + +**解** + +由题可列出方程组 $A\mathbf{x}=\mathbf{b}$: + +$$ +\begin{pmatrix} + 1 & 2.6 \\ + 1 & 3.0 \\ + 1 & 3.5 \\ + 1 & 4.3 +\end{pmatrix} +\begin{pmatrix} + a \\ b +\end{pmatrix} += +\begin{pmatrix} + 0 \\ 1 \\ 2 \\ 3 +\end{pmatrix} +$$ + +则 $A^{\top}A = \begin{pmatrix}1 & 1 & 1 & 1 \\ 2.6 & 3.0 & 3.5 & 4.3\end{pmatrix}\begin{pmatrix}1 & 2.6 \\1 & 3.0 \\1 & 3.5 \\1 & 4.3\end{pmatrix}=\begin{pmatrix}4 & 13.4 \\ 13.4 & 46.5\end{pmatrix}$, $A^{\top}\mathbf{b} = \begin{pmatrix}1 & 1 & 1 & 1 \\ 2.6 & 3.0 & 3.5 & 4.3\end{pmatrix}\begin{pmatrix}0 \\ 1 \\ 2 \\ 3\end{pmatrix}=\begin{pmatrix}6 \\ 22.9\end{pmatrix}$ + +因此方程即 + +$$ +\begin{pmatrix} + 4 & 13.4 \\ 13.4 & 46.5 +\end{pmatrix} +\begin{pmatrix} + a \\ b +\end{pmatrix} += +\begin{pmatrix} + 6 \\ 22.9 +\end{pmatrix} +$$ + +解得 $a = -4.326, b = 1.739$. diff --git a/services/homework-ans/docs/calculus-2/chapter1/exercise1-rev.md b/services/homework-ans/docs/calculus-2/chapter1/exercise1-rev.md new file mode 100644 index 0000000..851bb57 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter1/exercise1-rev.md @@ -0,0 +1,38 @@ + +## 第 15 题 + +设 $f(x, y)$ 是可微函数, 且满足以下条件: $\lim\limits_{x^2 + y^2 \to +\infty}\dfrac{f(x, y)}{\sqrt{x^2 + y^2}} = +\infty$, 试证明: 对于任意的 $\mathbf{v} = (v_1, v_2)$, 都存在点 $(x_0, y_0)$, 使得 $\nabla f(x_0, y_0) = \mathbf{v}$. + +**证明** + +作辅助函数 $g(x, y) = f(x, y) - v_1 x - v_2 y$, 则 + +$$ +\lim\limits_{x^2 + y^2 \to +\infty}\dfrac{g(x, y)}{\sqrt{x^2 + y^2}} = \lim\limits_{x^2 + y^2 \to +\infty}\dfrac{f(x, y)}{\sqrt{x^2 + y^2}} - \lim\limits_{x^2 + y^2 \to +\infty}\dfrac{v_1 x}{\sqrt{x^2 + y^2}} - \lim\limits_{x^2 + y^2 \to +\infty}\dfrac{v_2 y}{\sqrt{x^2 + y^2}} = +\infty +$$ + +考虑 $g(x, y)$ 在 $\mathbb{R}^2$ 上的极小值点 $P(x_0, y_0)$, 有 $\nabla g(x_0, y_0) = \mathbf{0}$, 此即 $\nabla f(x_0, y_0) = \mathbf{v}$. + +## 第 17 题 + +已知点 $P(a, b)$ 在曲线 $f(x, y) = 0$ 上, 点 $Q(c, d)$ 在曲线 $g(x, y) = 0$ 上, 其中 $f, g$ 可微, 证明: 若 $|PQ|$ 为两条曲线的距离, 则 $\dfrac{a - c}{b - d} = \dfrac{f_1'(a, b)}{f_2'(a, b)} = \dfrac{g_1'(c, d)}{g_2'(c, d)}$. 利用此结论求椭圆 $x^2 + 2xy + 5y^2 - 16y = 0$ 与直线 $x - y - 8 = 0$ 的距离. + +**解** + +由于 $|PQ|$ 为两条曲线间的距离, 故由题知 $\vec{PQ} \parallel \nabla f(a, b) \parallel \nabla g(c, d)$. 此即 + +$$ +\dfrac{a - c}{b - d} = \dfrac{f_1'(a, b)}{f_2'(a, b)} = \dfrac{g_1'(c, d)}{g_2'(c, d)} +$$ + +在此例中, $f_1'(x, y) = 2x + 2y, f_2'(x, y) = 2x + 10y - 16, g_1'(x, y) = 1, g_2'(x, y) = -1$. 代入有方程 + +$$ +\begin{cases} + \dfrac{a - c}{b - d} = \dfrac{2a + 2b}{2a + 10b - 16} = \dfrac{1}{-1}, \\ + a^2 + 2ab + 5b^2 - 16b = 0, \\ + c - d - 8 = 0. +\end{cases} +$$ + +解得 $|PQ| = \min\{6\sqrt{2} + 4, 6\sqrt{2} - 4\} = 6\sqrt{2} - 4$. diff --git a/services/homework-ans/docs/calculus-2/chapter2/exercise2-1.md b/services/homework-ans/docs/calculus-2/chapter2/exercise2-1.md new file mode 100644 index 0000000..ca6b57a --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter2/exercise2-1.md @@ -0,0 +1,80 @@ + +## 第 1 题 + +证明: $f(x, y) = \sin(x^2 + y^2)$ 在 $\mathbb{R}^2$ 上非一致连续. + +**证明** + +反证法. 假设 $f(x, y) = \sin(x^2 + y^2)$ 在 $\mathbb{R}^2$ 上一致连续, 那么对任意 $\epsilon > 0$, 比如 $\epsilon = \dfrac{1}{3}$, 则存在 $\delta > 0$, 使得只要 $\|(x_1, y_1) - (x_2, y_2)\| < \delta$, 就有 $\left|\sin(x_1^2 + y_1^2) - \sin(x_2^2 + y_2^2)\right| < \epsilon = \dfrac{1}{3}$. 取 $(x_1, y_1) = (0, \sqrt{n\pi}), (x_2, y_2) = (0, \sqrt{n\pi + \dfrac{\pi}{2}})$, 则当 $n$ 足够大时可以保证 $\|(x_1, y_1) - (x_2, y_2)\| < \delta$. 但此时 + +$$ +\begin{aligned} + \left|\sin(x_1^2 + y_1^2) - \sin(x_2^2 + y_2^2)\right| & = \left|\sin(n\pi) - \sin\left(n\pi + \dfrac{\pi}{2}\right)\right| \\ + & = \cos\left(n\pi + \dfrac{\pi}{4}\right)\sin\left(\dfrac{\pi}{4}\right) \\ + & = \dfrac{\sqrt{2}}{2}\cos\left(n\pi + \dfrac{\pi}{4}\right) +\end{aligned} +$$ + +当 $n$ 取 $2$ 的倍数的时候有 $\left|\sin(x_1^2 + y_1^2) - \sin(x_2^2 + y_2^2)\right| = \dfrac{1}{2} > \dfrac{1}{3} = \epsilon$. 矛盾. 因此 $f(x, y) = \sin(x^2 + y^2)$ 在 $\mathbb{R}^2$ 上非一致连续. + +## 第 2 题 + +已知函数 $f:\mathbb{R}^n\to\mathbb{R}$ 连续, 且 $\lim\limits_{\| X\|\to +\infty}f(X)$ 存在, 求证: $f$ 在 $\mathbb{R}^n$ 上一致连续. + +**证明** + +记 $L = \lim\limits_{\| X\|\to +\infty}f(X)$, 则 $\exists M_0 > 0$, 使得 $\forall \epsilon > 0, \|X\| > M_0$, 都有 $\left|f(X) - L\right| < \dfrac{\epsilon}{2}$. 对于 $\|X\| \le M_0$ 的有界闭区域, $f$ 在上面是一致连续的, 现只需要考虑 $\|X\| > M_0$ 的区域. 由于 $\forall X, X'$ 满足 $\|X\|, \|X'\| > M_0, \|X - X'\| < \delta$, 有 $\left|f(X) - f(X')\right| \le \left|f(X) - L\right| + \left|f(X') - L\right| < \dfrac{\epsilon}{2} + \dfrac{\epsilon}{2} = \epsilon$, 所以 $f$ 在 $\|X\| > M_0$ 的区域上也是一致连续的. 故 $f$ 在 $\mathbb{R}^2$ 上一致连续. + +## 第 3 题 + +证明: 函数 $f(X)$ 在 $\Omega \subset \mathbb{R}^n$ 上一致连续的充要条件是: 对 $\Omega \subset \mathbb{R}^n$ 上的任何两个点列 $\{X_n\}$ 和 $\{Y_n\}$, 当 $\lim\limits_{n\to\infty}\|X_n-Y_n\| = 0$ 时, 有 $\lim\limits_{n\to\infty}(f(X_n)-f(Y_n)) = 0$. + +**证明** + +先证必要性: 假设 $f(X)$ 在 $\Omega \subset \mathbb{R}^n$ 上一致连续, 则对于任意点列 $\{X_n\}, \{Y_n\}$: $\forall \epsilon > 0, \exists \delta_0 > 0$ 使得 $\forall X, X'' \in \Omega, \|X - X'\| < \delta_0$ 有 $\|f(X) - f(X')\| < \epsilon$. 由于 $\lim\limits_{n \to \infty}\|X_n - Y_n\| = 0$, 故按定义展开有 $\exists M > 0, \forall n > M$, 有 $\|X_n - Y_n\| < \delta_0$ 从而 $\|f(X_n) - f(Y_n)\| < \epsilon$. 故由定义知 $\lim\limits_{n \to \infty}\|f(X_n)-f(Y_n)\| = 0$. + +再证充分性: 反证法. 假设 $f(X)$ 不一致连续, 则 $\exists \epsilon_0 > 0, \forall delta > 0, \exists X_0, X_0' \in \Omega$ 满足 $\|X_0 - X_0'\| < \delta$ 但 $\|f(X_0) - f(X_0')\| \ge \epsilon_0$. 取 $\delta_n = \dfrac{1}{n}$, 则 $\exists X_n, Y_n$ 使得 $\|X_n - Y_n\| < \delta_n = \dfrac{1}{n}$, 则由条件知 $\|f(X_n) - f(Y_n)\| \ge \epsilon_0$. 由此, $\lim\limits_{n \to \infty}\|X_n - Y_n\| = 0$ 但 $\|f(X_n) - f(Y_n)\| \ge \epsilon_0$ 恒成立, 说明其极限不为 $0$. 与 $\lim\limits_{n \to \infty}\|f(X_n) - f(Y_n)\| = 0$ 矛盾. 故假设错误, $f(X)$ 在 $\Omega \subset \mathbb{R}^n$ 上一致连续. + +## 第 4 题 + +讨论下列积分在所给区间上的一致收敛性. + +(2) $\int_{-\infty}^{+\infty}\dfrac{\cos yx}{1 + x^2}\text{d}{x}(-\infty < y < +\infty)$; + +(4) $\int_{0}^{+\infty}e^{-tx^2}\sin x\text{d}{x}(0 < t_0 \le t < +\infty)$; + +(6) $\int_{0}^{+\infty}\dfrac{\text{d}{x}}{1 + (x + t)^2}(0 \le t < +\infty)$; + +**解** + +(2) 考虑 $f(x) = \cos (yx), g(x) = \dfrac{1}{1 + x^2}$, 则对任意 $A<0, B>0, y \in \mathbb{R}$ 均有 $\left|\int_{A}^{B}f(x)\text{d}{x}\right| \le 1$ 有界, 且 $g(x) = \dfrac{1}{1 + x^2}$ 关于 $x$ 单调递减. 由于不含 $y$, 所以 $\lim\limits_{x \to +\infty} g(x) = 0$ 对于 $y$ 一致成立. 由 Dirichlet 判别法知 $\int_{-\infty}^{+\infty}\dfrac{\cos yx}{1 + x^2}\text{d}{x}$ 在 $\mathbb{R}$ 上一致收敛. + +(4) 考虑 $f(x) = \sin x, g(x) = e^{-tx}$, 则对任意 $A > 0, t \in [t_0, +\infty)$ 有 $\left|\int_{0}^{A}f(x)\text{d}{x}\right| \le 1$ 有界, 且 $g(x) = e^{-tx}$ 单调递减, 且 $\lim\limits_{x \to +\infty}g(x) = 0$ 对于任意 $t \in [t_0, +\infty)$ 一致成立. 有 Dirichlet 判别法知 $\int_{0}^{+\infty}e^{-tx^2}\sin x\text{d}{x}$ 在 $[t_0, +\infty)$ 上一致收敛. + +(6) 考虑含参积分 $I(t) = \int_{0}^{+\infty}\dfrac{\text{d}{x}}{1 + (x + t)^2}$, 则 $I(t) = \int_{0}^{+\infty}\dfrac{\text{d}{(x + t)}}{1 + (x + t)^2} = \arctan(x + t)\bigg\vert_{0}^{+\infty} = \dfrac{\pi}{2} - \arctan t$ 在 $[0, +\infty)$ 一致收敛. + +## 第 5 题 + +证明: 积分 $\int_{0}^{+\infty}e^{-tx}\dfrac{\sin 3x}{x + t}\text{d}{x}(0 \le t < +\infty)$ 一致收敛. + +**证明** + +先证明函数 $\int_{0}^{+\infty}f(x, t)\text{d}{x} = \int_{0}^{+\infty}\dfrac{\sin 3x}{x + t}\text{d}{x}$ 关于 $t>0$ 一致收敛. 由于 $\int_{0}^{A}\sin 3x\text{d}{x}$ 不含 $t$ 且对充分大的 $A$ 均有界, 并且 $\dfrac{1}{x + t}$ 关于 $x$ 单调递减且趋于 $0$ 对于任意 $t > 0$ 一致成立, 故由 Dirichlet 判别法知 $f(x, t) = \int_{0}^{+\infty}\dfrac{\sin 3x}{x + t}\text{d}{x}$ 关于 $t > 0$ 一致收敛. + +再考虑 $g(x, t) = e^{-tx}$, 它关于 $x$ 单调递减且趋于 $0$ 对于任意 $t > 0$ 一致成立. 由 Dirichlet 判别法知 $\int_{0}^{+\infty}e^{-tx}\dfrac{\sin 3x}{x + t}\text{d}{x} = \int_{0}^{+\infty}f(x, t)g(x, t)\text{d}{x}$ 对于 $t > 0$ 一致收敛. + +## 第 6 题 + +设 $f(x, y)$ 在 $[a, +\infty) \times [\alpha, \beta]$ 中连续, 如果对于每一个 $t \in [\alpha, \beta)$, $\int_{a}^{+\infty}f(x, t)\text{d}{x}$ 均收敛, 但 $\int_{a}^{+\infty}f(x, \beta)\text{d}{x}$ 均发散, 证明: $\int_{a}^{+\infty}f(x, y)\text{d}{x}$ 在 $[\alpha, \beta)$ 上非一致收敛. + +**证明** + +反证法. 假设 $\int_{0}^{+\infty} f(x, t) \text{d}{x}$ 在 $[\alpha, \beta)$ 上一致收敛, 则由定义知 $\forall \epsilon > 0, \exists A > 0, \forall A', A'' > A, \forall t \in [\alpha, \beta)$, 有 $\left|\int_{A'}^{A''}f(x, t)\text{d}{x}\right| < \epsilon$. 考虑数列 $\{t_n\} = \{\beta - \dfrac{1}{n}\} \to \beta, n \to +\infty$, 由于 $f(x, t)$ 在 $[a, +\infty)\times[\alpha, \beta]$ 上连续, 因此对 $\left|\int_{A'}^{A''}f(x, t_n)\text{d}{x}\right| < \epsilon$ 取 $n \to +\infty$ 的极限, 有 $\left|\int_{A'}^{A''}f(x, \beta)\text{d}{x}\right| \le \epsilon$. 但这与 $\int_{a}^{+\infty}f(x, \beta)\text{d}{x}$ 发散矛盾. 因此假设不成立. 命题得证. + +## 第 8 题 + +证明: 积分 $\int_{0}^{+\infty}\dfrac{\sin tx}{x}\text{d}{x}$ 在包含 $t = 0$ 的区间上不一致收敛. + +**证明** + +反证法. 假设积分 $I(t) = \int_{0}^{+\infty}\dfrac{\sin tx}{x}\text{d}{x}$ 在包含 $t = 0$ 的区间上一致收敛, 不妨设该区间为 $[a, b]$, 其中 $0 \in [a, b]$. 由于 $\dfrac{\sin tx}{x}$ 在带状域 $[0, +\infty)\times[a, b]$ 上连续, 且广义积分 $\int_{0}^{+\infty}\dfrac{\sin tx}{x}\text{d}{x}$ 在包含 $t = 0$ 的区间上一致收敛, 则该广义积分 $I(t)$ 是连续的. 但 $I(t) = \begin{cases}0, t = 0, \\ \dfrac{\pi}{2}, t \neq 0 \end{cases}$ 并不连续, 矛盾. 因此积分 $\int_{0}^{+\infty}\dfrac{\sin tx}{x}\text{d}{x}$ 在包含 $t = 0$ 的区间上不一致收敛. diff --git a/services/homework-ans/docs/calculus-2/chapter2/exercise2-2.md b/services/homework-ans/docs/calculus-2/chapter2/exercise2-2.md new file mode 100644 index 0000000..d06ef27 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter2/exercise2-2.md @@ -0,0 +1,83 @@ + +## 第 1 题 + +求下列极限: + +(1) $\lim\limits_{a \to 0}\int_{-1}^{1}\sqrt{x^2 + a^2}\text{d}{x}$; + +(2) $\lim\limits_{a \to 0}\int_{0}^{3}x^2\cos ax \text{d}{x}$. + +**解** + +(1) $\lim\limits_{a \to 0}\int_{-1}^{1}\sqrt{x^2 + a^2}\text{d}{x} = \int_{-1}^{1}\lim\limits_{a \to 0}\sqrt{x^2 + a^2}\text{d}{x} = \int_{-1}^{1}\left|x\right|\text{d}{x} = 1$. + +(2) $\lim\limits_{a \to 0}\int_{0}^{3}x^2\cos ax \text{d}{x} = \int_{0}^{3}\lim\limits_{a \to 0}x^2\cos ax \text{d}{x} = \int_{0}^{3}x^2\text{d}{x} = \dfrac{1}{3}x^3\bigg\vert_0^3 = 9$. + +## 第 2 题 + +求下列函数的导函数. + +(1) $F(x) = \int_{x}^{x^2}e^{-xy^2}\text{d}{y}$; + +(3) $F(x) = \int_{0}^{t}\dfrac{\ln(1 + tx)}{x}\text{d}{x}$; + +**解** + +(1) $F'(x) = \int_{x}^{x^2}-y^2e^{-xy^2}\text{d}{y} + e^{-x^5}\cdot 2x - e^{-x^3} = 2xe^{-x^5} - e^{-x^3} - \int_{x}^{x^2}y^2e^{-xy^2}\text{d}{y}$. + +(3) $F'(t) = \int_{0}^t\dfrac{1}{1 + tx}\text{d}{x} + \dfrac{\ln (1 + t^2)}{t}$. + +## 第 3 题 + +设 $f(x)$ 可微, 且 $F(x) = \int_{0}^{x}(x + y)f(y)\text{d}{y}$, 求 $F''(x)$. + +**解** + +由于 $F'(x) = \int_{0}^xf(y)\text{d}{y} + 2xf(x)$, 所以 $F''(x) = f(x) + 2f(x) + 2xf'(x) = 3f(x) + 2xf'(x)$. + +## 第 4 题 + +证明: $u(x, t) = \dfrac{1}{2}(\varphi(x + at) + \varphi(x - at)) + \dfrac{1}{2a}\int_{x - at}^{x + at}\psi(s)\text{d}{s}$ 是弦振动方程 $\dfrac{\partial^2u}{\partial t^2} = a^2 \dfrac{\partial^2u}{\partial x^2}$ 的解, 其中 $\varphi \in C^2, \psi \in C^1$. + +**证明** + +由题知 + +$$ +\begin{aligned} + \dfrac{\partial u}{\partial t} &= \dfrac{a}{2}[\varphi'(x + at) - \varphi'(x - at)] + \dfrac{1}{2}[\psi'(x + at) + \psi'(x - at)], \\ + \dfrac{\partial^2 u}{\partial t^2} &= \dfrac{a^2}{2}[\varphi''(x + at) + \varphi''(x - at)] + \dfrac{a}{2}[\psi''(x + at) - \psi''(x - at)]. +\end{aligned} +$$ + +且有 + +$$ +\begin{aligned} + \dfrac{\partial u}{\partial x} &= \dfrac{1}{2}[\varphi'(x + at) + \varphi'(x - at)] + \dfrac{1}{2a}[\psi'(x + at) - \psi'(x - at)], \\ + \dfrac{\partial^2 u}{\partial x^2} &= \dfrac{1}{2}[\varphi''(x + at) + \varphi''(x - at)] + \dfrac{1}{2a}[\psi''(x + at) - \psi''(x - at)]. +\end{aligned} +$$ + +代入则可验证 $\dfrac{\partial^2u}{\partial t^2} = a^2 \dfrac{\partial^2u}{\partial x^2}$. + +## 第 5 题 + +计算下列积分. + +(1) $\int_{0}^{1}\dfrac{\arctan x}{x}\dfrac{1}{\sqrt{1 - x^2}}\text{d}{x}$ (提示: $\dfrac{\arctan x}{x} = \int_{0}^{1}\dfrac{1}{1 + x^2y^2}\text{d}{y}$); + +**解** + +$$ +\begin{aligned} + \int_{0}^{1}\dfrac{\arctan x}{x}\dfrac{1}{\sqrt{1 - x^2}}\text{d}{x} &= \int_{0}^{1}\int_{0}^1\dfrac{1}{1 + x^2y^2}\text{d}{y}\dfrac{1}{\sqrt{1 - x^2}}\text{d}{x} \\ + & = \int_{0}^{\frac{\pi}{2}}\text{d}{\sin\theta}\int_{0}^1\dfrac{1}{1 + \sin^2\theta y^2}\text{d}{y}\dfrac{1}{\sqrt{1 - \sin^2\theta}} \\ + & = \int_{0}^{\frac{\pi}{2}}\text{d}{\tan \theta}\int_{0}^1\dfrac{1}{1 + (y^2 + 1)\tan^2\theta}\text{d}{y} \\ + & = \int_0^1\text{d}{y}\int_{0}^{+\infty}\dfrac{\text{d}{\theta}}{1 + (y^2 + 1)\theta^2} \\ + & = \int_0^{1}\text{d}{y}\dfrac{1}{y^2 + 1}\arctan(\theta\sqrt{y^2 + 1})\bigg\vert_{\theta = 0}^{\theta = +\infty} \\ + & = \int_0^1\dfrac{\pi}{2}\dfrac{1}{\sqrt{y^2 + 1}}\text{d}{y} \\ + & = \dfrac{\pi}{2}\ln(y + \sqrt{y^2 + 1})\big\vert_{0}^1 \\ + & = \dfrac{\pi}{2}\ln(\sqrt{2} + 1). +\end{aligned} +$$ diff --git a/services/homework-ans/docs/calculus-2/chapter2/exercise2-3.md b/services/homework-ans/docs/calculus-2/chapter2/exercise2-3.md new file mode 100644 index 0000000..b23da1e --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter2/exercise2-3.md @@ -0,0 +1,79 @@ + +## 第 1 题 + +计算下列积分. + +(1) $\int_{0}^{+\infty}\dfrac{e^{-ax^2}-e^{-bx^2}}{x}\text{d}{x}(a, b > 0)$; + +(2) $\int_{0}^{+\infty}xe^{-ax^2}\sin yx \text{d}{x}(a > 0)$; + +(3) $\int_{0}^{+\infty}\dfrac{\cos ax - \cos bx}{x^2}\text{d}{x}(a, b > 0)$(提示: 将 $\cos ax - \cos bx$ 写成积分的形式, 并且 $\int_{0}^{+\infty}\dfrac{\sin x}{x} = \dfrac{\pi}{2}$). + +**解** + +(1) 因为 $\dfrac{e^{-ax^2}-e^{-bx^2}}{x} = x\int_a^be^{-x^2y}\text{d}{y}$, 故 + +$$ +\begin{aligned} + \int_{0}^{+\infty}\dfrac{e^{-ax^2}-e^{-bx^2}}{x}\text{d}{x} & = \int_{0}^{+\infty}x\text{d}{x}\int_a^be^{-x^2y}\text{d}{y} \\ + & = \dfrac{1}{2}\int_{0}^{+\infty}\text{d}{x^2}\int_a^be^{-x^2y}\text{d}{y} \\ + & = \dfrac{1}{2}\text{d}{\theta}\int_a^be^{-\theta y}\text{d}{y} \\ + & = \dfrac{1}{2}\int_a^b\dfrac{1}{y}\text{d}{y} \\ + & = \dfrac{1}{2}\ln\dfrac{b}{a}. +\end{aligned} +$$ + +(2) + +$$ + \begin{aligned} + \int_{0}^{+\infty}xe^{-ax^2}\sin yx \text{d}{x} & = -\dfrac{1}{2a}\left(e^{-ax^2}\sin(yx)\bigg\vert^{+\infty}_{0} - y\int_{0}^{+\infty}e^{-ax^2}\cos(yx)\text{d}{x}\right) \\ + & = \dfrac{y}{2a}\int_{0}^{+\infty}e^{-ax^2}\cos(yx)\text{d}{x} \\ + & = \dfrac{y}{4a}\sqrt{\dfrac{\pi}{a}}e^{-\frac{y^2}{4a}} + \end{aligned} +$$ + +(3) 由于 $\cos ax - \cos bx = x\int_a^b\sin yx\text{d}{y}$, 故 + +$$ +\begin{aligned} + \int_{0}^{+\infty}\dfrac{\cos ax - \cos bx}{x^2}\text{d}{x} & = \int_0^{+\infty}\dfrac{1}{x}\text{d}{x}\int_a^b\sin(yx)\text{d}{y} \\ + & = \int_{0}^{+\infty}\dfrac{\sin yx}{yx}\text{d}{(yx)}\int_a^b\text{d}{y} \\ + & = \dfrac{\pi}{2}(b - a). +\end{aligned} +$$ + +## 第 2 题 + +利用对参变量的求导, 求下列积分. + +(1) $\int_{0}^{+\infty}e^{-tx^2}x^{2n}\text{d}{x}(t > 0)$(提示: 利用 $\int_{0}^{+\infty}e^{-x^2}\text{d}{x} = \dfrac{\sqrt{\pi}}{2}$); + +(2) $\int_{0}^{+\infty}\dfrac{\text{d}{x}}{(y + x^2)^{n+1}} = \dfrac{\pi(2n - 1)!!}{2(2n)!!}y^{-\left(n + \frac{1}{2}\right)}(y > 0)$(提示: 利用 $\int_{0}^{+\infty}\dfrac{\text{d}{x}}{y + x^2}$ 的值). + +**解** + +(1) 考虑 $I(t) = \int_{0}^{+\infty}e^{-tx^2}\text{d}{x}$, 则其 $n$ 阶导数为 $I^{(n)}(t) = \int_{0}^{+\infty}e^{-tx^2}x^{2n}\text{d}{x}$ 即为所求. 注意到 + +$$ +\begin{aligned} + I(t) & = \int_{0}^{+\infty}e^{-tx^2}\text{d}{x} \\ + & = \dfrac{1}{\sqrt{t}}\int_{0}^{+\infty}e^{-(\sqrt{t}x)^2}\text{d}{(\sqrt{t}x)} \\ + & = \dfrac{\sqrt{\pi}}{2}\cdot t^{-\frac{1}{2}} +\end{aligned} +$$ + +因此有 $\int_{0}^{+\infty}e^{-tx^2}x^{2n}\text{d}{x} = I^{(n)}(t) = \dfrac{\sqrt{\pi}}{2}\cdot\dfrac{(2n-1)!!}{2^n}(-1)^nt^{-\left(n+\frac{1}{2}\right)}$. + +(2) 考虑 $I(y) = \int_{0}^{+\infty}\dfrac{\text{d}{x}}{y + x^2}$, 则 $\dfrac{(-1)^n}{n!}I^{(n)}(y) = \int_{0}^{+\infty}\dfrac{\text{d}{x}}{(y + x^2)^{n+1}}$ 即为所求. 由于 + +$$ +\begin{aligned} + I(y) & = \int_{0}^{+\infty}\dfrac{\text{d}{x}}{y + x^2} \\ + & = \int_{0}^{+\infty}\dfrac{\sqrt{y}\text{d}{\left(\dfrac{x}{\sqrt{y}}\right)}}{y\left(1 + \left(\dfrac{x}{\sqrt{y}}\right)^2\right)} \\ + & = y^{-\frac{1}{2}}\arctan\left(\dfrac{x}{\sqrt{y}}\right)\bigg\vert_{x = 0}^{x = +\infty} \\ + & = \dfrac{\pi}{2}y^{-\frac{1}{2}} +\end{aligned} +$$ + +因此 $I^{(n)}(y) = \dfrac{\pi}{2}\cdot\dfrac{(2n-1)!!}{2^n}(-1)^ny^{-\left(n + \frac{1}{2}\right)}$. 故 $\int_{0}^{+\infty}\dfrac{\text{d}{x}}{(y + x^2)^{n+1}} = \dfrac{(-1)^n}{n!}I^{(n)}(y) = \dfrac{\pi(2n - 1)!!}{2(2n)!!}y^{-\left(n + \frac{1}{2}\right)}$. diff --git a/services/homework-ans/docs/calculus-2/chapter2/exercise2-rev.md b/services/homework-ans/docs/calculus-2/chapter2/exercise2-rev.md new file mode 100644 index 0000000..b8e474e --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter2/exercise2-rev.md @@ -0,0 +1,81 @@ + +## 第 1 题 + +证明: $f(x, y) = \sin (xy)$ 在 $\mathbb{R}^2$ 上不一致连续. + +**证明** + +取点列 $\{X_n\} = \left(\sqrt{n\pi}, \sqrt{n\pi}\right), \{Y_n\} = \left(\sqrt{n\pi + \dfrac{\pi}{2}}, \sqrt{n\pi + \dfrac{\pi}{2}}\right)$. 对于足够大的 $n$, $\forall \delta > 0$, 都能有 $\|X_n - Y_n\| = \sqrt{2}\left(\sqrt{n\pi + \dfrac{\pi}{2}} - \sqrt{n\pi}\right)< \delta$, 但取 $\epsilon_0 = 1$, 有 + +$$ + \begin{aligned} + \left|f(X_n) - f(Y_n)\right| & = \left|\sin(n\pi) - \sin\left(n\pi + \dfrac{\pi}{2}\right)\right| \\ + & = 1 + \ge \epsilon_0 + \end{aligned} +$$ + +因此 $f(x, y) = \sin(xy)$ 在 $\mathbb{R}^2$ 上不一致连续. + +## 第 4 题 + +利用对参变量的微分, 求下列积分. + +(1) $\int_{0}^{\frac{\pi}{2}}\ln(a^2\sin^2x + b^2\cos^2x)\text{d}{x}$; + +(2) $\int_{0}^{\frac{\pi}{2}}\dfrac{\arctan(a\tan x)}{\tan x}\text{d}{x}$. + +**解** + +(1) 不妨设 $a, b > 0$. 记 $I(b) = \int_{0}^{\frac{\pi}{2}}\ln(a^2\sin^2x + b^2\cos^2x)\text{d}{x}$ 为关于 $b$ 的函数, $a$ 为常数. 则 + +$$ +\begin{aligned} + I'(b) & = \int_{0}^{\frac{\pi}{2}}\dfrac{2b\cos^2x}{a^2\sin^2 x + b^2\cos^2 x}\text{d}{x} \\ + & = \int_{0}^{\frac{\pi}{2}}\dfrac{2b}{a^2\tan^2x + b^2}\text{d}{x} \\ + & = \int_{0}^{+\infty}\dfrac{2b}{a^2u^2 + b^2}\text{d}{\arctan u} \\ + & = \int_{0}^{+\infty}\dfrac{2b}{(a^2u^2 + b^2)(1 + u^2)}\text{d}{u} \\ + & = 2b\cdot \dfrac{\arctan u - \dfrac{a}{b}\arctan\left(\dfrac{a}{b}u\right)}{b^2 - a^2} \bigg\vert_{u=0}^{u=+\infty} \\ + & = \dfrac{\pi}{a + b} +\end{aligned} +$$ + +因此 $I(b) = \pi\ln(a + b) + C$, 其中 $C$ 为某一待定常数. 由于 $I(a) = \dfrac{\pi}{2}\ln(a^2) = \pi\ln a$, 所以 $C = \pi\ln a - \pi\ln(a + a) = -\pi\ln 2$. 故 $\int_{0}^{\frac{\pi}{2}}\ln(a^2\sin^2x + b^2\cos^2x)\text{d}{x} = I(b) = \pi\ln\left(\dfrac{a + b}{2}\right)$. + +(2) 设 $I(a) = \int_{0}^{\frac{\pi}{2}}\dfrac{\arctan(a\tan x)}{\tan x}\text{d}{x}$. 则 + +$$ +\begin{aligned} + I'(a) & = \int_{0}^{\frac{\pi}{2}}\dfrac{\tan x}{1 + (a\tan x)^2}\cdot\dfrac{1}{\tan x}\text{d}{x} \\ + & = \int_{0}^{\frac{\pi}{2}}\dfrac{1}{1 + (a\tan x)^2}\text{d}{x} \\ + & = \int_{0}^{+\infty}\dfrac{1}{1 + (ax)^2}\cdot\dfrac{1}{1 + x^2}\text{d}{x} \\ + & = \dfrac{1}{1 - a^2}\int_{0}^{+\infty}\left[\dfrac{1}{1 + x^2}-\dfrac{a^2}{1 + (ax)^2}\right]\text{d}{x} \\ + & = \dfrac{1}{1 - a^2}(\arctan x - a\arctan (ax))\bigg\vert_{x=0}^{x=+\infty} \\ + & = \dfrac{\pi}{2(a + 1)} +\end{aligned} +$$ + +因此 $I(a) = \dfrac{\pi}{2}\ln(a + 1) + C$. 由于 $I(0) = 0$, 所以 $C = 0$. 故 $\int_{0}^{\frac{\pi}{2}}\dfrac{\arctan(a\tan x)}{\tan x}\text{d}{x} = I(a) = \dfrac{\pi}{2}\ln(a + 1)$. + +## 第 6 题 + +计算下列积分的值. + +(1) $\int_{0}^{+\infty}\dfrac{\arctan xy}{x(1 + x^2)}\text{d}{x}(y \ge 0)$; + +**解** + +(1) 设 $I(y) = \int_{0}^{+\infty}\dfrac{\arctan xy}{x(1 + x^2)}\text{d}{x}$, 则 + +$$ +\begin{aligned} + I'(y) & = \int_{0}^{+\infty}\dfrac{\D}{\text{d}{y}}\dfrac{\arctan xy}{x(1 + x^2)}\text{d}{x} \\ + & = \int_{0}^{+\infty}\dfrac{1}{1 + x^2}\cdot\dfrac{x}{1 + (xy)^2}\text{d}{x} \\ + & = \int_{0}^{+\infty}\dfrac{1}{(1 + x^2)(1 + x^2y^2)}\text{d}{x} \\ + & = \dfrac{1}{1 - y^2}\int_{0}^{+\infty}\left(\dfrac{1}{1 + x^2}-\dfrac{y^2}{1 + x^2y^2}\right)\text{d}{x} \\ + & = \dfrac{1}{1 - y^2}\left(\arctan(x) - y\arctan (yx)\right)\bigg\vert_{x=0}^{x=+\infty} \\ + & = \dfrac{\pi}{2(1 + y)} +\end{aligned} +$$ + +因此 $I(y) = \dfrac{\pi}{2}\ln(1 + y) + C$. 由 $I(0) = 0$ 知 $C = 0$. 因此 $I(y) = \dfrac{\pi}{2}\ln(1 + y)$. diff --git a/services/homework-ans/docs/calculus-2/chapter3/exercise3-1.md b/services/homework-ans/docs/calculus-2/chapter3/exercise3-1.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter3/exercise3-1.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-2/chapter3/exercise3-2.md b/services/homework-ans/docs/calculus-2/chapter3/exercise3-2.md new file mode 100644 index 0000000..227e5b7 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter3/exercise3-2.md @@ -0,0 +1,46 @@ + +## 第 2 题 + +证明: $1.96<\iint\limits_{\left|x\right| + \left|y\right| \le 10}\dfrac{\text{d}{x}\text{d}{y}}{100 + \cos^2 x + \cos^2 y}<2$. + +**证明** + +由于 $\cos^2 x + \cos^2 y \in [0, 2]$, 因此 + +$$ +1.96<\dfrac{200}{102} < \iint\limits_{\left|x\right| + \left|y\right| \le 10}\dfrac{\text{d}{x}\text{d}{y}}{100 + \cos^2 x + \cos^2 y}<\dfrac{200}{100} = 2. +$$ + +## 第 3 题 + +比较下列各组积分值的大小. + +(1) $\iint\limits_{D}(x + y)^2\text{d}{x}\text{d}{y}$ 与 $\iint\limits_{D}(x + y)^3\text{d}{x}\text{d}{y}$, 其中 $D = \{(x, y) | (x - 2)^2 + (y - 2)^2 \le 2\}$; + +(2) $\iint\limits_{D}\ln(x + y)\text{d}{x}\text{d}{y}$ 与 $\iint\limits_{D}xy\text{d}{x}\text{d}{y}$, 其中 $D$ 由直线 $x = 0, y = 0, x + y = \dfrac{1}{2}, x + y = 1$ 围成. + +**解** + +(1) 由于在 $D$ 上有 $x + y \ge 1$, 因此 $\iint\limits_{D}(x + y)^2\text{d}{x}\text{d}{y} \le \iint\limits_{D}(x + y)^3\text{d}{x}\text{d}{y}$. + +(2) 由于在 $D$ 上有 $xy \ge \ln(x + y)$, 因此 $\iint\limits_{D}\ln(x + y)\text{d}{x}\text{d}{y} \le \iint\limits_{D}xy\text{d}{x}\text{d}{y}$. + +## 第 4 题 + +设 $D \subset \mathbb{R}^2$ 为有界闭矩形, 非负函数 $f(x, y) \in C(D)$, 证明: 若 $\iint\limits_{D}f(x, y)\text{d}{x}\text{d}{y} = 0$, 则 $f(x, y) = 0, \forall (x, y) \in D$. + +**证明** + +反证法. 假设 $\exists P_0(x_0, y_0)$ 使得 $f(x_0, y_0) \neq 0$, 则 $\exists \delta > 0$, 使得 $\forall (x, y) \in B(P_0, \delta)$, 均有 $f(x, y) > 0$. 因此 $\iint\limits_{B(P_0, \delta)\subset D}f(x, y)\text{d}{x}\text{d}{y} > 0$. 而其他区域上 $f(x, y)$ 非负, 所以 $\iint\limits_{D}f(x, y)\text{d}{x}\text{d}{y} \ge \iint\limits_{B(P_0, \delta)\subset D}f(x, y)\text{d}{x}\text{d}{y} > 0$. 与题目条件矛盾. 故 $f(x, y) = 0, \forall (x, y) \in D$. + +## 第 5 题 + +函数 $f(x, y)$ 在 $(0, 0)$ 的某个邻域内连续, 计算极限 $\lim\limits_{r \to 0^{+}}\dfrac{1}{r^2}\iint\limits_{x^2 + y^2 \le r^2}f(x, y)\text{d}{x}\text{d}{y}$. + +**证明** + +由于 $f(x, y)$ 在 $O(0, 0)$ 的某个邻域内连续, 不妨记为 $B(O, \delta)$, 因此由多元函数的中值定理可得 $\exists \xi, \eta \in (0, \min\{\delta, r\})$ 使得 $\iint\limits_{x^2 + y^2 \le r^2}f(x, y)\text{d}{x}\text{d}{y} = f(\xi, \eta)\iint\limits_{x^2 + y^2 \le r^2}\text{d}{x}\text{d}{y} = \pi r^2 f(\xi, \eta)$. 故 + +$$ +\lim\limits_{r \to 0^{+}}\dfrac{1}{r^2}\iint\limits_{x^2 + y^2 \le r^2}f(x, y)\text{d}{x}\text{d}{y} = \lim\limits_{r \to 0^{+}}\dfrac{f(\xi, \eta)}{r^2}\pi r^2 = \pi f(0, 0) +$$ diff --git a/services/homework-ans/docs/calculus-2/chapter3/exercise3-3.md b/services/homework-ans/docs/calculus-2/chapter3/exercise3-3.md new file mode 100644 index 0000000..056f2e3 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter3/exercise3-3.md @@ -0,0 +1,593 @@ + +## 第 1 题 + +用二重积分的几何意义求下列二重积分的值. + +(1) $\iint\limits_{D}\sqrt{R^2 - x^2 - y^2}\text{d}{x}\text{d}{y}, D = \{(x, y) | x^2 + y^2 \le R^2\}$; + +(2) $\iint\limits_{D}\sqrt{x^2 + y^2}\text{d}{x}\text{d}{y}, D = \{(x, y) | x^2 + y^2 \le R^2\}$; + +(3) $\iint\limits_{D}\text{d}{x}\text{d}{y}, D = \{(x, y) | \left|x\right| + \left|y\right| \le 1\}$; + +**解** + +(1) 这个积分是半径为 $R$ 的上半球的体积, 因此 $\iint\limits_{D}\sqrt{R^2 - x^2 - y^2}\text{d}{x}\text{d}{y} = \dfrac{2}{3}\pi R^3$. + +(2) 这个积分是底面半径为 $R$, 高度为 $R$ 的圆锥的体积, 因此 $\iint\limits_{D}\sqrt{x^2 + y^2}\text{d}{x}\text{d}{y} = \dfrac{2}{3}\pi R^3$. + +(3) 这个积分是一个对角线长度为 $2$ 的正方形的面积, 因此 $\iint\limits_{D}\text{d}{x}\text{d}{y} = 2$. + +## 第 2 题 + +计算下列二重积分. + +(1) $\iint\limits_{I}\dfrac{x^2}{1 + y^2}\text{d}{x}\text{d}{y}, I = [0, 1]^2$; + +(2) $\iint\limits_{I}x\cos(xy)\text{d}{x}\text{d}{y}, I = \left[0, \dfrac{\pi}{2}\right] \times [0, 1]$; + +(3) $\iint\limits_{I}\sin(x + y)\text{d}{x}\text{d}{y}, I = [0, \pi]^2$. + +**解** + +(1) + +$$ +\begin{aligned} + \iint\limits_{I}\dfrac{x^2}{1 + y^2}\text{d}{x}\text{d}{y} & = \int_{0}^{1}\text{d}{x}\int_{0}^{1}\dfrac{x^2}{1 + y^2}\text{d}{y} \\ + & = \int_{0}^{1}x^2\arctan y\bigg\vert_{y=0}^{y=1}\text{d}{x} \\ + & = \dfrac{\pi}{4}\int_{0}^{1}x^2\text{d}{x} \\ + & = \dfrac{\pi}{4}\cdot \dfrac{1}{3}x^3\bigg\vert_{0}^{1} \\ + & = \dfrac{\pi}{12} +\end{aligned} +$$ + +(2) + +$$ +\begin{aligned} + \iint\limits_{I}x\cos(xy)\text{d}{x}\text{d}{y} & = \int_{0}^{\frac{\pi}{2}}\text{d}{x}\int_{0}^{1}x\cos(xy)\text{d}{y} \\ + & = \int_{0}^{\frac{\pi}{2}}\sin(xy)\bigg\vert_{y=0}^{y=1}\text{d}{x} \\ + & = \int_{0}^{\frac{\pi}{2}}\sin x\text{d}{x} \\ + & = -\cos x\bigg\vert_{0}^{\frac{\pi}{2}} \\ + & = 1 +\end{aligned} +$$ + +(3) + +$$ +\begin{aligned} + \iint\limits_{I}\sin(x + y)\text{d}{x}\text{d}{y} & = \int_{0}^{\pi}\text{d}{x}\int_{0}^{\pi}\sin(x + y)\text{d}{y} \\ + & = \int_{0}^{\pi}-\cos(x + y)\bigg\vert_{y=0}^{y=\pi}\text{d}{x} \\ + & = 0 +\end{aligned} +$$ + +## 第 3 题 + +设函数 $f(x, y)$ 在 $I = [a, b] \times [c, d]$ 上有连续的二阶偏导数, 计算$\iint\limits_{I}\dfrac{\partial ^2 f}{\partial x\partial y}\text{d}{x}\text{d}{y}$. + +**解** + +$$ +\begin{aligned} + \iint\limits_{I}\dfrac{\partial ^2 f}{\partial x\partial y}\text{d}{x}\text{d}{y} & = \int_{a}^{b}\text{d}{x}\int_{c}^{d}\dfrac{\partial ^2 f}{\partial x\partial y}\text{d}{y} \\ + & = \int_{a}^{b}\dfrac{\partial f}{\partial x}(x, y)\bigg\vert_{y=c}^{y=d}\text{d}{x} \\ + & = \int_{a}^{b}\left(\dfrac{\partial f(x,d)}{\partial x} - \dfrac{\partial f(x, c)}{\partial x}\right)\text{d}{x} \\ + & = f(x, d)\bigg\vert_{a}^{b} - f(x, c)\bigg\vert_{a}^{b} \\ + & = f(b, d) - f(a, d) - f(b, c) + f(a, c) +\end{aligned} +$$ + +## 第 4 题 + +将二重积分 $\iint\limits_{D}f(x, y)\text{d}{x}\text{d}{y}$ 化为累次积分. + +(1) $D = \{(x, y) | x + y \le 1, y - x \le 1, y \ge 0\}$; + +(2) $D = \{(x, y) | y \ge x - 2, x \ge y^2\}$; + +(3) $D = \{(x, y) | \dfrac{2}{x} \le y \le 2x, 1 \le x \le 2\}$. + +**解** + +(1) 由题知 $y-1\le x \le 1-y$, 因此 $y \in [0, 1]$. 故 $\iint\limits_{D}f(x, y)\text{d}{x}\text{d}{y} = \int_{0}^{1}\text{d}{y}\int_{y-1}^{1-y}f(x, y)\text{d}{x}$. + +(2) 由题知 $y^2 \le x \le y + 2$, 因此 $y \in [-1, 2]$. 故 $\iint\limits_{D}f(x, y)\text{d}{x}\text{d}{y} = \int_{-1}^{2}\text{d}{y}\int_{y^2}^{y+2}f(x, y)\text{d}{x}$. + +(3) 按题目所给约束, 有 $\iint\limits_{D}f(x, y)\text{d}{x}\text{d}{y} = \int_{1}^{2}\text{d}{x}\int_{\frac{2}{x}}^{2x}f(x, y)\text{d}{y}$. + +## 第 5 题 + +在直角坐标系中画出下列积分的积分区域, 并交换积分次序. + +(1) $\int_{-1}^{0}\text{d}{x}\int_{0}^{1 + x}f(x, y)\text{d}{y} + \int_{0}^{1}\text{d}{x}\int_{0}^{1 - x}f(x, y)\text{d}{y}$; + +(2) $\int_{0}^{1}\text{d}{x}\int_{2\sqrt{1-x}}^{\sqrt{4-x^2}}f(x, y)\text{d}{y} + \int_{1}^{2}\text{d}{x}\int_{0}^{\sqrt{4-x^2}}f(x, y)\text{d}{y}$; + +(3) $\int_{0}^{1}\text{d}{x}\int_{0}^{\sqrt{2x-x^2}}f(x, y)\text{d}{y} + \int_{1}^{2}\text{d}{x}\int_{0}^{2-x}f(x, y)\text{d}{y}$; + +**解** + +(1) + +\begin{figure}[!htbp] + \centering + \begin{tikzpicture} + \begin{axis}[ + axis lines=middle, + samples=100, + %grid, + thick, + domain=-1:1, + %legend pos=outer north east, + smooth, + xmin=-1.1, xmax=1.1, ymin=0, ymax=1.1, + xlabel={$x$}, + ylabel={$y$}, + mark=halfcircle*, + mark size=2.9pt, + ] + \addplot+[no marks,domain=0:1]{1-x}; + \addplot+[no marks,domain=-1:0]{1+x}; + %\addplot+[sharp plot] coordinates {(3, 5.6569)}; + %\addplot+[sharp plot] coordinates {(3, -5.6569)}; + \end{axis} + \end{tikzpicture} + %\put(0, 0){O} + \caption{习题3.3第5题(1)} + %\label{} +\end{figure} + +由图知 $\int_{-1}^{0}\text{d}{x}\int_{0}^{1 + x}f(x, y)\text{d}{y} + \int_{0}^{1}\text{d}{x}\int_{0}^{1 - x}f(x, y)\text{d}{y} = \int_{0}^{1}\text{d}{y}\int_{y-1}^{1-y}f(x, y)\text{d}{x}$. + +(2) + +\begin{figure}[!htbp] + \centering + \begin{tikzpicture} + \begin{axis}[ + axis lines=middle, + samples=100, + %grid, + thick, + domain=-0.1:2.1, + %legend pos=outer north east, + smooth, + xmin=0, xmax=2.1, ymin=0, ymax=2.1, + xlabel={$x$}, + ylabel={$y$}, + mark=halfcircle*, + mark size=2.9pt, + ] + \addplot+[no marks,domain=0:2]{sqrt(4-x^2)}; + \addplot+[no marks,domain=0:1]{2*sqrt(1-x)}; + %\addplot+[sharp plot] coordinates {(3, 5.6569)}; + %\addplot+[sharp plot] coordinates {(3, -5.6569)}; + \end{axis} + \end{tikzpicture} + %\put(0, 0){O} + \caption{习题3.3第5题(2)} + %\label{} +\end{figure} + +由图知 $\int_{0}^{1}\text{d}{x}\int_{2\sqrt{1-x}}^{\sqrt{4-x^2}}f(x, y)\text{d}{y} + \int_{1}^{2}\text{d}{x}\int_{0}^{\sqrt{4-x^2}}f(x, y)\text{d}{y} = \int_{0}^{2}\text{d}{y}\int_{1-\frac{1}{4}y^2}^{\sqrt{4-y^2}}f(x,y)\text{d}{x}$. + +(3) + +\begin{figure}[!htbp] + \centering + \begin{tikzpicture} + \begin{axis}[ + axis lines=middle, + samples=100, + %grid, + thick, + domain=0:2, + %legend pos=outer north east, + smooth, + xmin=0, xmax=2.1, ymin=0, ymax=1.1, + xlabel={$x$}, + ylabel={$y$}, + mark=halfcircle*, + mark size=2.9pt, + ] + \addplot+[no marks,domain=1:2]{2-x}; + \addplot+[no marks,domain=0:1]{sqrt(2*x-x^2)}; + %\addplot+[sharp plot] coordinates {(3, 5.6569)}; + %\addplot+[sharp plot] coordinates {(3, -5.6569)}; + \end{axis} + \end{tikzpicture} + %\put(0, 0){O} + \caption{习题3.3第5题(3)} + %\label{} +\end{figure} + +由图知 $\int_{0}^{1}\text{d}{x}\int_{0}^{\sqrt{2x-x^2}}f(x, y)\text{d}{y} + \int_{1}^{2}\text{d}{x}\int_{0}^{2-x}f(x, y)\text{d}{y} = \int_{0}^{1}\text{d}{y}\int_{1-\sqrt{1-y^2}}^{2-y}f(x,y)\text{d}{x}$. + +## 第 6 题 + +计算下列二重积分. + +(1) $\iint\limits_{D}xy^2\text{d}{x}\text{d}{y}, D = \{(x, y) | 4x \ge y^2, x \le 1\}$; + +(3) $\iint\limits_{D}\left|xy\right|\text{d}{x}\text{d}{y}, D = \{(x, y) | x^2+y^2\le R^2\}$; + +(5) $\iint\limits_{D}(x^2 + y^2)\text{d}{x}\text{d}{y}$, $D$ 是以 $y=x, y=x+1, y=1, y=4$ 为边的平行四边形区域; + +(7) $\iint\limits_{D}\cos(x+y)\text{d}{x}\text{d}{y}, D = \{(x, y) | 0 \le x, y \le \pi\}$; + +(9) $\iint\limits_{D}y^2\text{d}{x}\text{d}{y}$, $D$ 由 $\begin{cases}x=a(t-\sin t), \\ y = a(1-\cos t),\end{cases}0\le t \le 2\pi$ 以及 $x$ 轴围成; + +**解** + +(1) + +$$ +\begin{aligned} + \iint\limits_{D}xy^2\text{d}{x}\text{d}{y} & = \int_{-2}^{2}\text{d}{y}\int_{\frac{1}{4}y^2}^{1}xy^2\text{d}{x} \\ + & = \int_{-2}^{2}\dfrac{1}{2}x^2y^2\bigg\vert_{x=\frac{1}{4}y^2}^{x=1}\text{d}{y} \\ + & = \int_{-2}^{2}\left(\dfrac{1}{2}y^2-\dfrac{1}{32}y^6\right)\text{d}{y} \\ + & = \left(\dfrac{1}{6}y^3 - \dfrac{1}{224}y^7\right)\bigg\vert_{-2}^2 \\ + & = \dfrac{32}{21} +\end{aligned} +$$ + +(2) 考虑 $D_{\rho, \varphi} = \{(\rho, \varphi) | 0 \le \rho \le R, 0 \le \phi \le \dfrac{\pi}{2}\}$, 则由对称性可知 $\iint\limits_{D}\left|xy\right|\text{d}{x}\text{d}{y} = 4\iint\limits_{D_{\rho,\varphi}}\rho^2\sin\varphi\cos\varphi\rho\text{d}{\rho}\text{d}{\varphi}$. + +$$ +\begin{aligned} + \iint\limits_{D_{\rho,\varphi}}\rho^2\sin\varphi\cos\varphi\rho\text{d}{\rho}\text{d}{\varphi} & = \int_{0}^{\frac{\pi}{2}}\dfrac{1}{8}\sin2\varphi\rho^4\bigg\vert_{\rho = 0}^{\rho = R}\text{d}{\varphi} \\ + & = \dfrac{R^4}{8}\int_{0}^{\frac{\pi}{2}}\sin2\varphi\text{d}{\varphi} \\ + & = \dfrac{R^4}{16}(-\cos2\varphi)\bigg\vert_{0}^{\frac{\pi}{2}} \\ + & = \dfrac{R^4}{8} +\end{aligned} +$$ + +故 $\iint\limits_{D}\left|xy\right|\text{d}{x}\text{d}{y} = 4\iint\limits_{D_{\rho,\varphi}}\rho^2\sin\varphi\cos\varphi\rho\text{d}{\rho}\text{d}{\varphi} = \dfrac{R^4}{2}$. + +(5) + +$$ +\begin{aligned} + \iint\limits_{D}(x^2 + y^2)\text{d}{x}\text{d}{y} & = \int_{1}^{4}text{d}{y}\int_{y-1}^{y}(x^2+y^2)\text{d}{x} \\ + & = \int_{1}^{4}\left(\dfrac{1}{3}x^3+xy^2\right)\bigg\vert_{x=y-1}^{x=y}\text{d}{y} \\ + & = \int_{1}^{4}\left(2y^2-y + \dfrac{1}{3}\right)\text{d}{y} \\ + & = \left(\dfrac{2}{3}y^3 - \dfrac{1}{2}y^2 + \dfrac{1}{3}y\right)\bigg\vert_{1}^{4} \\ + & = \dfrac{71}{2} +\end{aligned} +$$ + +(7) + +$$ +\begin{aligned} + \iint\limits_{D}\cos(x+y)\text{d}{x}\text{d}{y} & = \int_{0}^{\pi}\text{d}{x}\int_{0}^{\pi}\cos(x + y)\text{d}{y} \\ + & = \int_{0}^{\pi}\sin(x + y)\bigg\vert_{y=0}^{y=\pi}\text{d}{x} \\ + & = \int_{0}^{\pi}2\sin x\text{d}{x} \\ + & = 2\cos x\bigg\vert_{0}^{\pi} \\ + & = -4 +\end{aligned} +$$ + +(9) + +$$ +\begin{aligned} + \iint\limits_{D}y^2\text{d}{x}\text{d}{y} & = \int_{0}^{2\pi a}\text{d}{x}\int_{0}^{y(x)}y^2\text{d}{y} \\ + & = \int_{0}^{2\pi a}\dfrac{1}{3}{y^3}\bigg\vert_{y=0}^{y=y(x)}\text{d}{x} \\ + & = \dfrac{1}{3}\int_{0}^{2\pi a}y^3(x)\text{d}{x} \\ + & = \dfrac{1}{3}\int_{0}^{2\pi}a^3(1-\cos t)^3a(1-\cos t)\text{d}{t} \\ + & = \dfrac{16a^4}{3}\int_{0}^{2\pi}\sin^8\dfrac{t}{2}\text{d}{t} \\ + & = \dfrac{32a^4}{3}\int_{0}^{2\pi}\sin^8 u\text{d}{u} \\ + & = \dfrac{64a^4}{3}\int_{0}^{\frac{\pi}{2}}\sin^8 u\text{d}{u} \\ + & = \dfrac{64a^4}{3}\cdot\dfrac{\pi}{2}\cdot\dfrac{7!!}{8!!} \\ + & = \dfrac{35}{12}\pi a^4 +\end{aligned} +$$ + +## 第 8 题 + +利用第7题结论, 计算积分 + +$\iint\limits_{D}x^2y^3\text{d}{x}\text{d}{y}$, $\iint\limits_{D}\sqrt{R^2-x^2}\sin y\text{d}{x}\text{d}{y}$, $D = \{(x, y) | x^2+y^2\le R^2\}$. + +**解** + +由于 $D$ 关于 $x$ 轴对称且关于 $y$ 轴对称, 且第一个被积函数关于 $y$ 为奇函数, 所以第一个积分式为 $0$. 同理, 第二个被积函数关于 $y$ 也为奇函数, 所以第二个积分式也为 $0$. 此即 $\iint\limits_{D}x^2y^3\text{d}{x}\text{d}{y} = \iint\limits_{D}\sqrt{R^2-x^2}\sin y\text{d}{x}\text{d}{y} = 0$. + +## 第 9 题 + +分别求出由平面 $z=x-y,z=0$ 与圆柱面 $x^2+y^2=2x$ 所围成的两个空间几何体的体积. + +**解** + +记 $D_1 = \{x^2+y^2\le 2x, y \ge x\}, D_2 = \{0 \le x \le 1, 0 \le y \le x\}, D_3 = \{x^2+y^2\le 2x, x\ge1\lor y \le 0\}$. 容易验证总积分区域 $D = D_1 + D_2 + D_3$. + +$$ +\begin{aligned} + \iint\limits_{D_2}z\text{d}{x}\text{d}{y} & = \int_{0}^{1}\text{d}{x}\int_{0}^{x}(x-y)\text{d}{y} \\ + & = \dfrac{1}{2}\int_{0}^{1}x^2\text{d}{x} \\ + & = \dfrac{1}{6} +\end{aligned} +$$ + +$$ +\begin{aligned} + \iint\limits_{D_1+D_2}z\text{d}{x}\text{d}{y} & = \int_{\frac{\pi}{2}}^{\pi}\text{d}{\theta}\int_{0}^{1}r(1+r\cos\theta-r\sin\theta)\text{d}{r} \\ + & = \int_{\frac{\pi}{2}}^{\pi}\left(\dfrac{1}{2} + \dfrac{1}{3}\cos\theta - \dfrac{1}{3}\sin\theta\right)\text{d}{\theta} \\ + & = \dfrac{\pi}{4} -\dfrac{2}{3} +\end{aligned} +$$ + +$$ +\begin{aligned} + \iint\limits_{D_3}z\text{d}{x}\text{d}{y} & = \int_{-\pi}^{\frac{\pi}{2}}\text{d}{\theta}\int_{0}^{1}r(1+r\cos\theta-r\sin\theta)\text{d}{r} \\ + & = \int_{-\pi}^{\frac{\pi}{2}}\left(\dfrac{1}{2} + \dfrac{1}{3}\cos\theta - \dfrac{1}{3}\sin\theta\right)\text{d}{\theta} \\ + & = \dfrac{2}{3} + \dfrac{3\pi}{4} +\end{aligned} +$$ + +因此 $V_1 = \int\limits_{D_1}z\text{d}{x}\text{d}{y} = \int\limits_{D_1+D_2}z\text{d}{x}\text{d}{y} - \iint\limits_{D_2}z\text{d}{x}\text{d}{y} = \dfrac{5}{6} - \dfrac{\pi}{4}, V_2 = \int\limits_{D_2+D_3}z\text{d}{x}\text{d}{y} = \int\limits_{D_2}z\text{d}{x}\text{d}{y} + \iint\limits_{D_3}z\text{d}{x}\text{d}{y} = \dfrac{5}{6} + \dfrac{3\pi}{4}$. + +## 第 10 题 + +求由旋转抛物面 $z = x^2+y^2$, 柱面 $y=x^2$ 及平面 $y=1,z=0$ 围成的空间几何体的体积. + +**解** + +体积为 + +$$ +\begin{aligned} + V & = \int_{-1}^{1}\text{d}{x}\int_{x^2}^{1}(x^2+y^2)\text{d}{y} \\ + & = \int_{-1}^{1}\left(\dfrac{1}{3} + x^2 - x^4 - \dfrac{1}{3}x^6\right)\text{d}{x} \\ + & = \dfrac{88}{105} +\end{aligned} +$$ + +## 第 11 题 + +画出下列积分区域的图形, 并将二重积分 $\iint\limits_{D}f(x, y)\text{d}{x}\text{d}{y}$ 化为极坐标下的累次积分. + +(1) $D = \{(x, y) | x^2 + y^2 \le 1, x^2 + (y-1)^2 \le 1\}$; + +(2) $D = \{(x, y) | x^2 + (y-a)^2 \le a^2, (x - a)^2 + y^2 \le a^2\}$. + +**解** + +(1) 由图知 $\iint\limits_{D}f(x, y)\text{d}{x}\text{d}{y} = \int_{0}^{\frac{\pi}{6}}\text{d}{\theta}\int_{0}^{2\sin\theta}f(r\cos\theta, r\sin\theta)r\text{d}{r} + \int_{\frac{\pi}{6}}^{\frac{\pi}{2}}\text{d}{\theta}\int_{0}^{2}f(r\cos\theta, r\sin\theta)r\text{d}{r}$. + +\begin{figure}[!htbp] + \centering + \begin{tikzpicture} + \begin{axis}[ + axis lines=middle, + samples=100, + %grid, + thick, + domain=-0.1:1.1, + %legend pos=outer north east, + smooth, + xmin=0, xmax=1.1, ymin=0, ymax=1.1, + xlabel={$x$}, + ylabel={$y$}, + mark=halfcircle*, + mark size=2.9pt, + ] + \addplot+[no marks,domain=0:sqrt(3)/2]{sqrt(1-x^2)}; + \addplot+[no marks,domain=0:sqrt(3)/2]{1-sqrt(1-x^2)}; + %\addplot+[sharp plot] coordinates {(3, 5.6569)}; + %\addplot+[sharp plot] coordinates {(3, -5.6569)}; + \end{axis} + \end{tikzpicture} + %\put(0, 0){O} + \caption{习题3.3第11题(1)} + %\label{} +\end{figure} + +(2) 由图知 $\iint\limits_{D}f(x, y)\text{d}{x}\text{d}{y} = \int_{0}^{\frac{\pi}{4}}\text{d}{\theta}\int_{0}^{2a\sin\theta}f(r\cos\theta, r\sin\theta)r\text{d}{r} + \int_{\frac{\pi}{4}}^{\frac{\pi}{2}}\text{d}{\theta}\int_{0}^{2\cos\theta}f(r\cos\theta, r\sin\theta)r\text{d}{r}$. + +\begin{figure}[!htbp] + \centering + \begin{tikzpicture} + \begin{axis}[ + axis lines=middle, + samples=100, + %grid, + thick, + domain=-0.1:1.1, + %legend pos=outer north east, + smooth, + xmin=0, xmax=1.1, ymin=0, ymax=1.1, + xlabel={$x$}, + ylabel={$y$}, + mark=halfcircle*, + mark size=2.9pt, + ] + \addplot+[no marks,domain=0:1]{1-sqrt(1-x^2)}; + \addplot+[no marks,domain=0:1]{sqrt(1-(x-1)^2)}; + %\addplot+[sharp plot] coordinates {(3, 5.6569)}; + %\addplot+[sharp plot] coordinates {(3, -5.6569)}; + \end{axis} + \end{tikzpicture} + %\put(0, 0){O} + \caption{习题3.3第11题(2), 此时取 a=1} + %\label{} +\end{figure} + +## 第 12 题 + +计算下列二重积分. + +(1) $\iint\limits_{D}(x^2 + y^2)\text{d}{x}\text{d}{y}, D = \{(x, y) | 2x \le x^2 + y^2 \le 4x\}$; + +(3) $\iint\limits_{D}(x+y)\text{d}{x}\text{d}{y}$, $D$ 是由 $x^2+y^2=x+y$ 围成的平面区域; + +(5) $\iint\limits_{D}\arctan\dfrac{y}{x}\text{d}{x}\text{d}{y}, D = \{(x, y) | x^2 + y^2 \le 1, x \le 0, y \le 0\}$; + +**解** + +(1) 代换 $x = r\cos\theta, y = r\sin\theta$, 则区域变为 $D_{r, \theta} = \{2\cos\theta \le r \le 4\cos\theta, \theta \in [0, \pi]\}$. 则 + +$$ +\begin{aligned} + \iint\limits_{D}(x^2 + y^2)\text{d}{x}\text{d}{y} & = \iint\limits_{D_{r,\theta}}r^2\cdot r\text{d}{r}\text{d}{\theta} \\ + & = \int_{0}^{\pi}\text{d}{\theta}\int_{2\cos\theta}^{4\cos\theta}r^3\text{d}{r} \\ + & = \int_{0}^{\pi}60\cos^4\theta\text{d}{\theta} \\ + & = 120 \int_{0}^{\frac{\pi}{2}}\cos^4\theta\text{d}{\theta} \\ + & = 120\cdot\dfrac{\pi}{2}\cdot\dfrac{3\cdot 1}{4\cdot 2} \\ + & = \dfrac{45}{2}\pi +\end{aligned} +$$ + +(3) 做坐标变换 $\begin{cases}x = r\cos\theta, \\ y = r\sin\theta,\end{cases}$ 则有 + +$$ +\begin{aligned} + \iint\limits_{D}(x+y)\text{d}{x}\text{d}{y} & = \int_{-\frac{\pi}{4}}^{\frac{3\pi}{4}}\int_{0}^{\sin\theta + \cos\theta}r^2(\sin\theta + \cos\theta)\text{d}{r} \\ + & = \dfrac{1}{3}\int_{-\frac{\pi}{4}}^{\frac{3\pi}{4}}(\sin\theta + \cos\theta)^4\text{d}{\theta} \\ + & = \dfrac{1}{3}\int_{-\frac{\pi}{4}}^{\frac{3\pi}{4}}\left(\dfrac{3-\cos4\theta}{2} + 2\sin2\theta\right)\text{d}{\theta} \\ + & = \dfrac{1}{3}\cdot\dfrac{3\pi}{2} \\ + & = \dfrac{\pi}{2} +\end{aligned} +$$ + +(5) 做坐标变换 $\begin{cases}x = r\cos\theta, \\ y = r\sin\theta,\end{cases}$ 则有 + +$$ +\begin{aligned} + \iint\limits_{D}\arctan\dfrac{y}{x}\text{d}{x}\text{d}{y} & = \int_{0}^{1}r\text{d}{r}\int_{0}^{\frac{\pi}{2}}\theta\text{d}{\theta} \\ + & = \dfrac{1}{2}\cdot\dfrac{\pi^2}{8} \\ + & = \dfrac{\pi^2}{16} +\end{aligned} +$$ + +## 第 13 题 + +求下列曲线所围图形的面积. + +(1) 双纽线 $(x^2 + y^2)^2 = 2a^2(x^2-y^2)$ 与圆 $x^2 + y^2 = a^2$ 所围图形 (圆外部分) 的面积 $(a > 0)$; + +(2) 心脏线 $r = a(1 + \cos\theta)$ 与圆 $x^2 + y^2 = \sqrt{3}ay$ 所围图形 (心脏线内部) 的面积 $(a > 0)$. + +**解** + +(1) 考虑 $D = \{a \le \rho \le a\sqrt{2\cos 2\theta}, -\dfrac{\pi}{6} \le \theta \le \dfrac{\pi}{6} \lor \dfrac{5\pi}{6} \le \theta \le \dfrac{7\pi}{6}\}$. 则面积 + +$$ +\begin{aligned} + S & = \iint\limits_{D}\rho\text{d}{\rho}\text{d}{\theta} \\ + & = \int_{-\frac{\pi}{6}}^{\frac{\pi}{6}}\text{d}{\theta}\int_{a}^{a\sqrt{2\cos2\theta}}\rho \text{d}{\rho}\text{d}{\theta} + \int_{\frac{5\pi}{6}}^{\frac{7\pi}{6}}\text{d}{\theta}\int_{a}^{a\sqrt{2\cos2\theta}}\rho \text{d}{\rho}\text{d}{\theta} \\ + & = \left(\sqrt{3} - \dfrac{\pi}{3}\right)a^2 +\end{aligned} +$$ + +(2) 考虑 $D = \{0 \le \rho \le \sqrt{3}a\sin\theta, 0 \le \theta \le \dfrac{\pi}{3}\} \bigcup \{0 \le \rho \le a(1 + \cos\theta), \dfrac{\pi}{3} \le \theta \le \pi\}$. 则面积 + +$$ +\begin{aligned} + S & = \iint\limits_{D}\rho\text{d}{\rho}\text{d}{\theta} \\ + & = \int_{0}^{\frac{\pi}{3}}\text{d}{\theta}\int_{0}^{\sqrt{3}a\sin\theta}\rho \text{d}{\rho}\text{d}{\theta} + \int_{\frac{\pi}{3}}^{\pi}\text{d}{\theta}\int_{0}^{a(1+\cos\theta)}\rho \text{d}{\rho}\text{d}{\theta} \\ + & = \dfrac{3\pi - 3\sqrt{3}}{4}a^2 +\end{aligned} +$$ + +## 第 14 题 + +通过恰当的变量代换, 计算下列二重积分. + +(1) $\iint\limits_{D}x^2y^2\text{d}{x}\text{d}{y}$, $D$ 是由 $xy = 2, xy = 4, y=x, y=3x$ 在第一象限所围成的平面区域; + +(2) $\iint\limits_{D}(x^2 + y^2)\text{d}{x}\text{d}{y}$, $D$ 是由 $xy=1, xy=2, x^2-y^2=1, x^2-y^2=2$ 所围成的平面区域; + +**解** + +(1) 做坐标变换 $(u, v) = (xy, \dfrac{y}{x})$, 则 $\dfrac{D(x, y)}{D(u, v)} = \dfrac{1}{4v}$. 因此 + +$$ +\begin{aligned} + \iint\limits_{D}x^2y^2\text{d}{x}\text{d}{y} & = \int_{1}^{3}\text{d}{v}\int_{2}^{4}\dfrac{D(x, y)}{D(u, v)}u^2\text{d}{u} \\ + & = \int_{1}^{3}\dfrac{1}{4v}\text{d}{v}\int_{2}^{4}u^2\text{d}{u} \\ + & = \dfrac{\ln3}{4}\cdot\dfrac{56}{3} \\ + & = \dfrac{28\ln3}{3} +\end{aligned} +$$ + +(2) 做坐标变换 $(u, v) = (x^2-y^2, xy)$, 则 $\dfrac{D(x, y)}{D(u, v)} = \dfrac{1}{2\sqrt{u^2+4v^2}}$. 因此 + +$$ +\begin{aligned} + \iint\limits_{D}(x^2 + y^2)\text{d}{x}\text{d}{y} & = \int_{1}^{2}\text{d}{v}\int_{1}^{2}\dfrac{D(x, y)}{D(u, v)}\sqrt{u^2+4v^2}\text{d}{u} \\ + & = \dfrac{1}{2}\int_{1}^{2}\text{d}{v}\int_{1}^{2}\text{d}{u} \\ + & = \dfrac{1}{2} +\end{aligned} +$$ + +## 第 15 题 + +求下列图形围成区域的面积. + +(1) $(a_1x + b_1y + c_1)^2 + (a_2x + b_2y + c_2)^2 = 1$, 其中 $a_1b_2 \neq a_2b_1$; + +(2) $\sqrt{x} + \sqrt{y} = \sqrt{a}$ 与 $x = 0, y = 0$. + +**解** + +(1) 做坐标变换 $(u, v) = (a_1x + b_1y + c_1, a_2x, b_2y, c_2)$, 则 $\dfrac{D(x, y)}{D(u, v)} = \dfrac{1}{a_1b_2 - a_2b_1}$. 因此 $S = \iint\limits_{u^2 + v^2 \le 1}\left|\dfrac{D(x, y)}{D(u, v)}\right|\text{d}{u}\text{d}{v} = \dfrac{\pi}{\left|a_1b_2 - a_2b_1\right|}$. + +(2) 做坐标变换 $(u, v) = (\sqrt{x}, \sqrt{y})$, 则 $\dfrac{D(x, y)}{D(u, v)} = 4uv$. 因此 $S = \iint\limits_{u+v\le \sqrt{a}, u,v\ge 0}\left|\dfrac{D(x, y)}{D(u, v)}\right|\text{d}{u}\text{d}{v} = \iint\limits_{u+v\le\sqrt{a}, u, v\ge 0}4uv\text{d}{u}\text{d}{v} = \dfrac{1}{6}a^2$. + +## 第 16 题 + +设函数 $f(t)$ 连续, 证明: + +(1) $\iint\limits_{\left|x\right| + \left|y\right| \le 1}f(x+y)\text{d}{x}\text{d}{y} = \int_{-1}^{1}f(t)\text{d}{t}$. + +(2) $\iint\limits_{D}f(xy)\text{d}{x}\text{d}{y} = \ln 2\int_{1}^{2}f(t)\text{d}{t}$, $D$ 是由 $xy = 1, xy = 2, y = x, y = 4x$ 所围成的第一象限的区域. + +**证明** + +(1) 做坐标变换 $(u, v) = (x+y, x-y)$, 则 $\dfrac{D(x, y)}{D(u, v)} = -\dfrac{1}{2}$. 因此 + +$$ +\begin{aligned} + \iint\limits_{\left|x\right| + \left|y\right| \le 1}f(x+y)\text{d}{x}\text{d}{y} & = \int_{-1}^{1}\text{d}{v}\int_{-1}^{1}\left|\dfrac{D(x, y)}{D(u, v)}\right|f(u)\text{d}{u} \\ + & = \int_{-1}^{1}f(u)\text{d}{u} \\ + & = \int_{-1}^{1}f(t)\text{d}{t} +\end{aligned} +$$ + +(2) 做坐标变换 $(u, v) = (xy, \dfrac{y}{x})$, 则 $\dfrac{D(x, y)}{D(u, v)} = \dfrac{1}{4v}$. 因此 + +$$ +\begin{aligned} + \iint\limits_{D}f(xy)\text{d}{x}\text{d}{y} & = \int_{1}^{4}\dfrac{D(x, y)}{D(u, v)}\text{d}{v}\int_{1}^{2}f(u)\text{d}{u} \\ + & = \int_{1}^{4}\dfrac{1}{4v}\text{d}{v}\int_{1}^{2}f(u)\text{d}{u} \\ + & = \ln2\int_{1}^{2}f(t)\text{d}{t} +\end{aligned} +$$ + +## 第 17 题 + +设函数 $f(t)$ 连续, $f(t) > 0$, 求积分 $\iint\limits_{x^2 + y^2 \le R^2}\dfrac{af(x) + bf(y)}{f(x) + f(y)}\text{d}{x}\text{d}{y}$. + +**解** + +由对称性, 记 $S = \iint\limits_{x^2 + y^2 \le R^2}\dfrac{f(x)}{f(x) + f(y)}\text{d}{x}\text{d}{y} = \iint\limits_{x^2 + y^2 \le R^2}\dfrac{f(y)}{f(x) + f(y)}\text{d}{x}\text{d}{y}$, 则 $2S = \iint\limits_{x^2 + y^2 \le R^2}\dfrac{f(x) + f(y)}{f(x) + f(y)}\text{d}{x}\text{d}{y} = \pi R^2$. 故 $S = \dfrac{1}{2}\pi R^2$. 因此 $\iint\limits_{x^2 + y^2 \le R^2}\dfrac{af(x) + bf(y)}{f(x) + f(y)}\text{d}{x}\text{d}{y} = aS + bS = \dfrac{a+b}{2}\pi R^2$. + +## 第 18 题 + +设函数 $f(t, s)$ 连续, 求 $F(x) = \int_{0}^{x}\int_{t^2}^{x^2}f(t, s)\text{d}{s}\text{d}{t}$ 的导函数. + +**解** + +记 $g(x, t) = \int_{t^2}^{x^2}f(t, s)\text{d}{s}$, 则 $F(x) = \int_{0}^{x}g(x, t)\text{d}{t}$. + +$$ +\begin{aligned} + F'(x) & = \int_{0}^{x}\dfrac{\partial g}{\partial x}(x, t)\text{d}{t} + g(x, x) \\ + & = \int_{0}^{x} f(t, x^2)\cdot 2x\text{d}{t} + \int_{x^2}^{x^2}f(x, s)\text{d}{s} \\ + & = 2x\int_{0}^{x}f(t, x^2)\text{d}{t} +\end{aligned} +$$ diff --git a/services/homework-ans/docs/calculus-2/chapter3/exercise3-4.md b/services/homework-ans/docs/calculus-2/chapter3/exercise3-4.md new file mode 100644 index 0000000..f014dd4 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter3/exercise3-4.md @@ -0,0 +1,216 @@ + +## 第 3 题 + +利用三重积分的几何意义, 求下列三重积分的值. + +(1) $\iiint\limits_{\Omega}1\text{d}{x}\text{d}{y}\text{d}{z}, \Omega = \{(x, y, z) | \sqrt{x^2 + y^2} \le z \le H\}$; + +(2) $\iiint\limits_{\Omega}1\text{d}{x}\text{d}{y}\text{d}{z}, \Omega = \{(x, y, z) | 0 \le z \le 1 - x - y, 0 \le y \le 1 - x, 0 \le x \le 1\}$. + +**解** + +(1) 由题知, 这个积分的值是一个底面半径为 $H$ 高为 $H$ 的圆锥的体积, 因此为 $\dfrac{1}{3}\pi H^3$. + +(2) 由题知, 这个积分的值是一个由三条两两垂直的长为 $1$ 的边构成的正四面体的体积, 因此为 $\dfrac{1}{6}$. + +## 第 4 题 + +将三重积分 $\iiint\limits_{\Omega}f(x, y, z)\text{d}{x}\text{d}{y}\text{d}{z}$ 化为直角坐标下的累次积分. + +(1) $\Omega = \{(x, y, z) | \sqrt{x^2 + y^2} \le z \le 1\}$; + +(2) $\Omega = \{(x, y, z) | 0 \le z \le x^2 + y^2, x + y \le 1, x \ge 0, y \ge 0\}$. + +**解** + +(1) 由 $\sqrt{x^2 + y^2} \le 1$ 得 $-\sqrt{1-x^2} \le y \le \sqrt{1-x^2}$. 因此 $\iiint\limits_{\Omega}f(x, y, z)\text{d}{x}\text{d}{y}\text{d}{z} = \int_{0}^{1}\text{d}{x}\int_{-\sqrt{1-x^2}}^{\sqrt{1-x^2}}\text{d}{y}\int_{\sqrt{x^2+y^2}}^{1}f(x, y, z)\text{d}{z}$. + +(2) 由 $x + y \le 1, x \ge 0, y \ge 0$ 得到 $1 - x \le y \le 1, 0 \le x \le 1$. 因此 $\iiint\limits_{\Omega}f(x, y, z)\text{d}{x}\text{d}{y}\text{d}{z} = \int_{0}^{1}\text{d}{x}\int_{1-x}^{1}\text{d}{y}\int_{0}^{x^2+y^2}f(x, y, z)\text{d}{z}$. + +## 第 5 题 + +计算下列三重积分的值. + +(1) $\iiint\limits_{\Omega}xy^2z^3\text{d}{x}\text{d}{y}\text{d}{z}$, $\Omega$ 是由马鞍面 $z = xy$ 与平面 $y = x, x = 1, z = 0$ 所围成的空间区域; + +(3) $\iiint\limits_{\Omega}x\cos(y + z)\text{d}{x}\text{d}{y}\text{d}{z}$, $\Omega$ 是由曲面 $x = \sqrt{y}$ 与平面 $x = 0, z = 0, y + z = \dfrac{\pi}{2}$ 围成的区域. + +**解** + +(1) 由题知 $\Omega = \{(x, y, z) | 0 \le x \le 1, 0 \le y \le x, 0 \le z \le xy\}$. 因此 + +$$ +\begin{aligned} + \iiint\limits_{\Omega}xy^2z^3\text{d}{x}\text{d}{y}\text{d}{z} & = \int_{0}^{1}\text{d}{x}\int_{0}^{x}\text{d}{y}\int_{0}^{xy}xy^2z^3\text{d}{z} \\ + & = \int_{0}^{1}\text{d}{x}\int_{0}^{x}\dfrac{1}{4}x^5y^6\text{d}{y} \\ + & = \int_{0}^{1}\dfrac{1}{28}x^{12}\text{d}{x} \\ + & = \dfrac{1}{364} +\end{aligned} +$$ + +(3) 由题知 $\Omega = \{(x, y, z) | 0 \le z \le \dfrac{\pi}{2}, 0 \le y \le \dfrac{\pi}{2} - z, 0 \le x \le \sqrt{y}\}$. 因此 + +$$ +\begin{aligned} + \iiint\limits_{\Omega}x\cos(y + z)\text{d}{x}\text{d}{y}\text{d}{z} & = \int_{0}^{\frac{\pi}{2}}\text{d}{z}\int_{0}^{\frac{\pi}{2}-z}\text{d}{y}\int_{0}^{\sqrt{y}}x\cos(y+z)\text{d}{x} \\ + & = \dfrac{1}{2}\int_{0}^{\frac{\pi}{2}}\text{d}{z}\int_{0}^{\frac{\pi}{2}-z}y\cos(y+z)\text{d}{y} \\ + & = \dfrac{1}{2}\int_{0}^{\frac{\pi}{2}}\left(\dfrac{\pi}{2} - z - \cos z\right)\text{d}{z} \\ + & = \dfrac{\pi^2}{16} - \dfrac{1}{2} +\end{aligned} +$$ + +## 第 6 题 + +计算累次积分 $I = \int_{0}^{1}\text{d}{x}\int_{0}^{x}\text{d}{y}\int_{0}^{y}\dfrac{\cos z}{(1 - z)^2}\text{d}{z}$ 的值. + +**解** + +积分区域为 $\Omega = \{0 \le z \le y \le x \le 1\}$. 因此 + +$$ +\begin{aligned} + I & = \int_{0}^{1}\text{d}{x}\int_{0}^{x}\text{d}{y}\int_{0}^{y}\dfrac{\cos z}{(1 - z)^2}\text{d}{z} \\ + & = \int_{0}^{1}\text{d}{z}\int_{z}^{1}\text{d}{y}\int_{y}^{1}\dfrac{\cos z}{(1-z)^2}\text{d}{x} \\ + & = \int_{0}^{1}\text{d}{z}\int_{z}^{1}(1-y)\dfrac{\cos z}{(1-z)^2}\text{d}{y} \\ + & = \dfrac{1}{2}\int_{0}^{1}\cos z\text{d}{z} \\ + & = \dfrac{\sin 1}{2} +\end{aligned} +$$ + +## 第 7 题 + +计算下列三重积分的值. + +(1) $\iiint\limits_{\Omega}\sqrt{x^2 + y^2}\text{d}{x}\text{d}{y}\text{d}{z}, \Omega = \{\sqrt{x^2 + y^2} \le z \le 1\}$; + +(3) $\iiint\limits_{\Omega}\dfrac{z}{x^2 + y^2}\text{d}{x}\text{d}{y}\text{d}{z}, \Omega = \{(x, y, z) | 0 \le z \le x^2 + y^2, x + y \le 1, x, y \ge 0\}$; + +(5) $\iiint\limits_{\Omega}xyz\text{d}{x}\text{d}{y}\text{d}{z}, \Omega = \{(x, y, z) | x^2 + y^2 + z^2 \le 4, x^2 + y^2 + (z - 2)^2\le 4, x \ge 0, y \ge 0\}$; + +**解** + +(1) 做坐标变换 $\begin{cases}x = r\cos \theta, \\ y = r\sin \theta, \\ z = z,\end{cases}$ 则 + +$$ +\begin{aligned} + \iiint\limits_{\Omega}\sqrt{x^2 + y^2}\text{d}{x}\text{d}{y}\text{d}{z} & = \int_{0}^{1}\text{d}{r}\int_{0}^{2\pi}\text{d}{\theta}\int_{r}^{1}r^2\text{d}{z} \\ + & = \int_{0}^{1}\text{d}{r}\int_{0}^{2\pi}r^2(1-r)\text{d}{\theta} \\ + & = 2\pi\int_{0}^{1}r^2(1-r)\text{d}{r} \\ + & = \dfrac{\pi}{6} +\end{aligned} +$$ + +(3) + +$$ +\begin{aligned} + \iiint\limits_{\Omega}\dfrac{z}{x^2 + y^2}\text{d}{x}\text{d}{y}\text{d}{z} & = \int_{0}^{1}\text{d}{x}\int_{0}^{1-x}\text{d}{y}\int_{0}^{x^2+y^2}\dfrac{z}{x^2 + y^2}\text{d}{z} \\ + & = \dfrac{1}{2}\int_{0}^{1}\text{d}{x}\int_{0}^{1-x}(x^2+y^2)\text{d}{y} \\ + & = \dfrac{1}{2}\int_{0}^{1}\left(x^2(1-x) + \dfrac{1}{3}(1-x)^3\right)\text{d}{x} \\ + & = \dfrac{1}{12} +\end{aligned} +$$ + +(5) + +做坐标变换 $\begin{cases}x = r\sin\varphi\cos\theta, \\ y = r\sin\varphi\sin\theta, \\ z = r\cos\varphi, \end{cases}$ 则 $\Omega = \Omega_1 + \Omega_2$, 其中 + +$$ +\begin{aligned} + \Omega_1 & = \{0 \le r \le 2, 0 \le \varphi \le \dfrac{\pi}{4}, 0 \le \theta \le \dfrac{\pi}{2}\}, \\ + \Omega_2 & = \{0 \le r \le 4\cos\varphi, \dfrac{\pi}{4} \le \varphi \le \dfrac{\pi}{2}, 0 \le \theta \le \dfrac{\pi}{2}\}. +\end{aligned} +$$ + +因此 + +$$ +\begin{aligned} + \iiint\limits_{\Omega_1}xyz\text{d}{x}\text{d}{y}\text{d}{z} & = \int_{0}^{2}r^5\text{d}{r}\int_{0}^{\frac{\pi}{4}}\sin^3\varphi \cos\varphi\text{d}{\varphi}\int_{0}^{\frac{\pi}{2}}\sin\theta\cos\theta\text{d}{\theta} \\ + & = \int_{0}^{2}r^5\text{d}{r}\int_{0}^{\frac{\pi}{4}}\sin^3\varphi \text{d}{\sin\varphi}\int_{0}^{\frac{\pi}{2}}\sin\theta\text{d}{\sin\theta} \\ + & = \dfrac{32}{3}\cdot\dfrac{1}{16}\cdot\dfrac{1}{2} \\ + & = \dfrac{1}{3} +\end{aligned} +$$ + +且 + +$$ +\begin{aligned} + \iiint\limits_{\Omega_2}xyz\text{d}{x}\text{d}{y}\text{d}{z} & = \int_{\frac{\pi}{4}}^{\frac{\pi}{2}}\sin^3\varphi \cos\varphi\text{d}{\varphi}\int_{0}^{4\cos\varphi}r^5\text{d}{r}\int_{0}^{\frac{\pi}{2}}\sin\theta\cos\theta\text{d}{\theta} \\ + & = \dfrac{1}{2}\int_{\frac{\pi}{4}}^{\frac{\pi}{2}}\sin^3\varphi \cos\varphi\text{d}{\varphi}\int_{0}^{4\cos\varphi}r^5\text{d}{r} \\ + & = \dfrac{1024}{3}\int_{\frac{\pi}{4}}^{\frac{\pi}{2}}\sin^3\varphi\cos^7\varphi\text{d}{\varphi} \\ + & = -\dfrac{1024}{3}\int_{\frac{\pi}{4}}^{\frac{\pi}{2}}(1-\cos^2\varphi)\cos^7\varphi\text{d}{\cos\varphi} \\ + & = \dfrac{1024}{3}\int_{0}^{\frac{\sqrt{2}}{2}}(u^7-u^9)\text{d}{u} \\ + & = \dfrac{8}{5} +\end{aligned} +$$ + +故 + +$$ +\begin{aligned} + \iiint\limits_{\Omega}xyz\text{d}{x}\text{d}{y}\text{d}{z} & = \iiint\limits_{\Omega_1}xyz\text{d}{x}\text{d}{y}\text{d}{z} + \iiint\limits_{\Omega_2}xyz\text{d}{x}\text{d}{y}\text{d}{z} \\ + & = \dfrac{1}{3} + \dfrac{8}{5} \\ + & = \dfrac{29}{15} +\end{aligned} +$$ + +## 第 8 题 + +做适当的变量代换, 计算下列三重积分. + +(1) $\iiint\limits_{\Omega}\sqrt{1 - \dfrac{x^2}{a^2} - \dfrac{y^2}{b^2} - \dfrac{z^2}{c^2}}\text{d}{x}\text{d}{y}\text{d}{z}, \Omega = \{(x, y, z) | \dfrac{x^2}{a^2} + \dfrac{y^2}{b^2} + \dfrac{z^2}{c^2} \le 1\}$; + +**解** + +(1) 作代换 $\begin{cases}x = ar\sin\varphi\cos\theta, \\ y = br\sin\varphi\sin\theta, \\ z = cr\sin\varphi,\end{cases}$ 有 + +$$ +\begin{aligned} + \iiint\limits_{\Omega}\sqrt{1 - \dfrac{x^2}{a^2} - \dfrac{y^2}{b^2} - \dfrac{z^2}{c^2}}\text{d}{x}\text{d}{y}\text{d}{z} & = abc\int_{0}^{2\pi}\text{d}{\theta}\int_{0}^{\pi}\sin\varphi\text{d}{\varphi}\int_{0}^{1}\sqrt{1-r^2}r^2\text{d}{r} \\ + & = 4\pi abc\int_{0}^{1}r^2\sqrt{1-r^2}\text{d}{r} \\ + & = 4\pi abc\int_{0}^{\frac{\pi}{2}}\sin^2\alpha\cos\alpha\text{d}{\sin\alpha} \\ + & = 4\pi abc \int_{0}^{\frac{\pi}{2}}(\sin^2\alpha - \sin^4\alpha)\text{d}{\alpha} \\ + & = 4\pi abc\cdot (\dfrac{1}{2} - \dfrac{3\cdot 1}{4\cdot 2})\cdot\dfrac{\pi}{2} \\ + & = \dfrac{\pi^2 abc}{4} +\end{aligned} +$$ + +## 第 10 题 + +设 $f(t)$ 在 $(-\infty, +\infty)$ 上连续, $f(t) = 3\iiint\limits_{x^2 + y^2 + z^2 \le t^2}f(\sqrt{x^2 + y^2 + z^2})\text{d}{x}\text{d}{y}\text{d}{z} + \left|t^3\right|$, 求 $f(t)$. + +**解** + +注意到 $f(t)$ 为偶函数, 因此暂时先考虑 $t\ge 0$ 时的情况, 此时 $f(t) = 3\iiint\limits_{x^2 + y^2 + z^2 \le t^2}f(\sqrt{x^2 + y^2 + z^2})\text{d}{x}\text{d}{y}\text{d}{z} + t^3$. 作变换 $\begin{cases}x = r\sin\varphi\cos\theta, \\ y = r\sin\varphi\sin\theta, \\ z = r\sin\varphi,\end{cases}$, 则 + +$$ +\begin{aligned} + f(t) & = 3\iiint\limits_{x^2 + y^2 + z^2 \le t^2}f(\sqrt{x^2 + y^2 + z^2})\text{d}{x}\text{d}{y}\text{d}{z} + t^3 \\ + & = t^3 + \int_{0}^{\pi}\sin\varphi\text{d}{\varphi}\int_{0}^{2\pi}\text{d}{\theta}\int_{-t}^{t}r^2f(r)\text{d}{r} \\ + & = t^3 + 12 \pi \int_{-t}^{t}r^2f(r)\text{d}{r} \\ + & = t^3 + 24 \pi \int_{0}^{t}r^2f(r)\text{d}{r} +\end{aligned} +$$ + +对等式左右两侧求导, 有 $f'(t) = 3t^2 + t^2f(t)$. 解得 $f(t) = Ce^{8\pi t^3}-\dfrac{1}{8\pi}(t\ge 0)$. 又因为 $f(0) = 0$ 且 $f(t)$ 为偶函数, 因此 + +$$ +f(t) = \dfrac{1}{8\pi}e^{8\pi \left|t^3\right|}-\dfrac{1}{8\pi} +$$ + +## 第 11 题 + +函数 $f(x, y, z)$ 连续, 计算极限 $\lim\limits_{r \to 0^{+}}\dfrac{1}{r^3}\iiint\limits_{x^2 + y^2 + z^2 \le r^2}f(x, y, z)\text{d}{x}\text{d}{y}\text{d}{z}$. + +**解** + +将积分中值定理推广到三维, 有 $\exists \xi, \eta, \zeta \in (0, r)$ 使得 $\iiint\limits_{x^2+y^2+z^2\le r^2}f(x, y, z)\text{d}{x}\text{d}{y}\text{d}{z} = \dfrac{4}{3}\pi r^3f(\xi, \eta, \zeta)$. 代入则有 + +$$ +\begin{aligned} + \lim\limits_{r \to 0^{+}}\dfrac{1}{r^3}\iiint\limits_{x^2 + y^2 + z^2 \le r^2}f(x, y, z)\text{d}{x}\text{d}{y}\text{d}{z} & = \lim\limits_{r \to 0^{+}}\dfrac{1}{r^3}\dfrac{4}{3}\pi r^3f(\xi, \eta, \zeta) \quad \xi, \eta, \zeta \in (0, r) \\ + & = \dfrac{4}{3}\pi f(0, 0, 0) +\end{aligned} +$$ diff --git a/services/homework-ans/docs/calculus-2/chapter3/exercise3-5.md b/services/homework-ans/docs/calculus-2/chapter3/exercise3-5.md new file mode 100644 index 0000000..a6cf21a --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter3/exercise3-5.md @@ -0,0 +1,147 @@ + +## 第 1 题 + +求下列曲面的面积. + +(1) 柱面 $x^2 + z^2 = a^2$ 在柱面 $x^2 + y^2 = a^2$ 内的部分; + +(2) 锥面 $z = \sqrt{x^2 + y^2}$ 在柱面 $z^2 = 2x$ 内的部分; + +(3) 由曲面 $x^2 + y^2 = az$ 与 $z = 2a - \sqrt{x^2 + y^2}$ 所包围的空间几何体的表面积. + +**解** + +(1) 只考虑 $z \ge 0$ 部分的面积 $S_1$. 由于 $\dfrac{\partial z}{\partial x} = -\dfrac{x}{\sqrt{a^2-x^2}}, \dfrac{\partial z}{\partial y} = 0$, 因此 $\sqrt{1 + \left(\dfrac{\partial z}{\partial x}\right)^2 + \left(\dfrac{\partial z}{\partial y}\right)^2} = \sqrt{1 + \dfrac{x^2}{a^2-x^2}} = \dfrac{a}{\sqrt{a^2-x^2}}$. + +$$ +\begin{aligned} + S_1 & = \iint\limits_{x^2+y^2\le a^2}\dfrac{a}{\sqrt{a^2-x^2}}\text{d}{x}\text{d}{y} \\ + & = \int_{-a}^{a}\text{d}{x}\int_{-\sqrt{a^2-x^2}}^{\sqrt{a^2-x^2}}\dfrac{a}{\sqrt{a^2-x^2}}\text{d}{y} \\ + & = \int_{-a}^{a}2a\text{d}{x} \\ + & = 4a^2 +\end{aligned} +$$ + +由对称性知 $S = 2S_1 = 8a^2$. + +(2) 在 $xy$ 面上的投影为 $D_{xy} = \{(x, y) | x^2 + y^2 \le 2x\}$, 是一个以 $(1, 0)$ 为圆心, $1$ 为半径的圆, 面积为 $\pi$. 由于 $\dfrac{\partial z}{\partial x} = \dfrac{x}{\sqrt{x^2 + y^2}}, \dfrac{\partial z}{\partial y} = \dfrac{y}{\sqrt{x^2 + y^2}}$, 故 $\sqrt{1 + \left(\dfrac{\partial z}{\partial x}\right)^2 + \left(\dfrac{\partial z}{\partial y}\right)^2} = \sqrt{2}$. 因此 + +$$ +S = \iint\limits_{D_{xy}}\sqrt{2}\text{d}{x}\text{d}{y} = \sqrt{2}\pi +$$ + +(3) 两者的交线为 $x^2 + y^2 = a(2a-\sqrt{x^2+y^2})$. 积分区域为 $\{(x, y) | x^2+y^2 \le a(2a - \sqrt{x^2+y^2})\}$, 化简后即为 $\{(x, y) | x^2 + y^2 \le a^2\}$. 先考虑 $z = 2a - \sqrt{x^2 + y^2}$ 带来的上表面面积 $S_1$. 由于 $\dfrac{\partial z}{\partial x} = -\dfrac{x}{\sqrt{x^2 + y^2}}, \dfrac{\partial z}{\partial y} = -\dfrac{y}{\sqrt{x^2 + y^2}}$, 故 $\sqrt{1 + \left(\dfrac{\partial z}{\partial x}\right)^2 + \left(\dfrac{\partial z}{\partial y}\right)^2} = \sqrt{2}$. + +$$ +\begin{aligned} + S_1 & = \iint\limits_{x^2+y^2\le a^2}\sqrt{1 + \left(\dfrac{\partial z}{\partial x}\right)^2 + \left(\dfrac{\partial z}{\partial y}\right)^2}\text{d}{x}\text{d}{y} \\ + & = \sqrt{2}\iint\limits_{x^2+y^2\le a^2}\text{d}{x}\text{d}{y} \\ + & = \sqrt{2}\pi a^2 +\end{aligned} +$$ + +再考虑 $x^2 + y^2 = az$ 带来的下表面面积 $S_2$. 由于 $\dfrac{\partial z}{\partial x} = \dfrac{2x}{a}, \dfrac{\partial z}{\partial y} = \dfrac{2y}{a}$, 故 $\sqrt{1 + \left(\dfrac{\partial z}{\partial x}\right)^2 + \left(\dfrac{\partial z}{\partial y}\right)^2} = \sqrt{\dfrac{a^2 + 4(x^2 + y^2)}{a^2}}$. 极坐标变换后, 有 + +$$ +\begin{aligned} + S_2 & = \iint\limits_{x^2 + y^2 \le a^2}\sqrt{1 + \left(\dfrac{\partial z}{\partial x}\right)^2 + \left(\dfrac{\partial z}{\partial y}\right)^2}\text{d}{x}\text{d}{y} \\ + & = \int_{0}^{2\pi}\text{d}{\theta}\int_{0}^{a}r\cdot\sqrt{1+\dfrac{4r^2}{a^2}}\text{d}{r} \\ + & = \dfrac{2\pi}{a}\int_{0}^{a}r\sqrt{a^2 + 4r^2}\text{d}{r} \\ + & = \dfrac{\pi}{4a}\int_{a^2}^{5a^2}\sqrt{u}\text{d}{u} \\ + & = \dfrac{\pi}{6}(5\sqrt{5} - 1)a^2 +\end{aligned} +$$ + +因此表面积为 $S = S_1 + S_2 = \dfrac{\pi}{6}(6\sqrt{2} + 5\sqrt{5} - 1)a^2$. + +## 第 2 题 + +求下列曲面所包围的均匀物体的质心. + +(1) $\dfrac{x^2}{a^2} + \dfrac{y^2}{b^2} + \dfrac{z^2}{c^2} = 1, x \ge 0, y \ge 0, z \ge 0$; + +**解** + +(1) 积分区域为 $\Omega = \{(x, y, z) | \dfrac{x^2}{a^2} + \dfrac{y^2}{b^2} + \dfrac{z^2}{c^2} \le 1, x \ge 0, y \ge 0, z \ge 0\}$. 做坐标变换 $\begin{cases}x = ar\sin\varphi\cos\theta, \\ x = br\sin\varphi\sin\theta, \\ z = cr\cos\varphi, \end{cases}$, 则 $\left|\dfrac{D(x, y, z)}{D(r, \varphi, \theta)}\right| = abcr^2\sin\varphi$. 因此 + +$$ +\begin{aligned} + M & = \iiint\limits_{\Omega}\text{d}{x}\text{d}{y}\text{d}{z} \\ + & = \int_{0}^{\frac{\pi}{2}}\text{d}{\theta}\int_{0}^{\frac{\pi}{2}}\text{d}{\varphi}\int_{0}^{1}\left|\dfrac{D(x, y, z)}{D(r, \varphi, \theta)}\right|\text{d}{r} \\ + & = \int_{0}^{\frac{\pi}{2}}\text{d}{\theta}\int_{0}^{\frac{\pi}{2}}\text{d}{\varphi}\int_{0}^{1}abcr^2\sin\varphi\text{d}{r} \\ + & = \int_{0}^{\frac{\pi}{2}}\text{d}{\theta}\int_{0}^{\frac{\pi}{2}}\sin\varphi\text{d}{\varphi}\int_{0}^{1}abcr^2\text{d}{r} \\ + & = \dfrac{\pi}{2}\cdot 1\cdot \dfrac{1}{3}abc \\ + & = \dfrac{\pi}{6}abc +\end{aligned} +$$ + +对 $xy$ 平面的静力矩为 + +$$ +\begin{aligned} + M_{xy} & = \iiint\limits_{\Omega}z\text{d}{x}\text{d}{y}\text{d}{z} \\ + & = \int_{0}^{\frac{\pi}{2}}\text{d}{\theta}\int_{0}^{\frac{\pi}{2}}\text{d}{\varphi}\int_{0}^{1}\left|\dfrac{D(x, y, z)}{D(r, \varphi, \theta)}\right|cr\cos\varphi\text{d}{r} \\ + & = \int_{0}^{\frac{\pi}{2}}\text{d}{\theta}\int_{0}^{\frac{\pi}{2}}\text{d}{\varphi}\int_{0}^{1}abc^2r^3\sin\varphi\cos\varphi\text{d}{r} \\ + & = \int_{0}^{\frac{\pi}{2}}\text{d}{\theta}\int_{0}^{\frac{\pi}{2}}\sin\varphi\cos\varphi\text{d}{\varphi}\int_{0}^{1}abc^2r^3\text{d}{r} \\ + & = \dfrac{\pi}{2}\cdot \dfrac{1}{2}\cdot \dfrac{1}{4}abc^2 \\ + & = \dfrac{\pi}{16}abc^2 +\end{aligned} +$$ + +由对称性知 $M_{yz} = \dfrac{\pi}{16}a^2bc, M_{xz} = \dfrac{\pi}{16}ab^2c$. 因此质心坐标为 $\left(\dfrac{3a}{8}, \dfrac{3b}{8}, \dfrac{3c}{8}\right)$. + +## 第 3 题 + +求解下列问题. + +(1) 物体在 $P(x, y, z)$ 的点密度为 $\rho = \dfrac{1}{\sqrt{x^2+y^2+z^2}}, \Omega = \{(x, y, z) | 0 \le x, y, z \le 1\}$, 求物体的质心; + +**解** + +(1) 总质量为 + +$$ +\begin{aligned} + M & = \iiint\limits_{\Omega}(x+y+z)\text{d}{x}\text{d}{y}\text{d}{z} \\ + & = \int_{0}^{1}\text{d}{x}\int_{0}^{1}\text{d}{y}\int_{0}^{1}(x+y+z)\text{d}{z} \\ + & = \int_{0}^{1}\text{d}{x}\int_{0}^{1}(x+y+\dfrac{1}{2})\text{d}{y} \\ + & = \int_{0}^{1}(x+1)\text{d}{x} \\ + & = \dfrac{3}{2} +\end{aligned} +$$ + +对 $xy$ 平面的静力矩为 + +$$ +\begin{aligned} + M_{xy} & = \iiint\limits_{\Omega}z(x+y+z)\text{d}{x}\text{d}{y}\text{d}{z} \\ + & = \int_{0}^{1}\text{d}{x}\int_{0}^{1}\text{d}{y}\int_{0}^{1}z(x+y+z)\text{d}{z} \\ + & = \int_{0}^{1}\text{d}{x}\int_{0}^{1}\left(\dfrac{1}{2}(x+y)+\dfrac{1}{3}\right)\text{d}{y} \\ + & = \int_{0}^{1}\left(\dfrac{1}{2}x + \dfrac{7}{12}\right)\text{d}{x} \\ + & = \dfrac{5}{6} +\end{aligned} +$$ + +因此 $\bar{z} = \dfrac{M_{xy}}{M} = \dfrac{5}{9}$. 由对称性知 $\bar{x} = \bar{y} = \bar{z} = \dfrac{5}{9}$. 因此质心坐标为 $\left(\dfrac{5}{9}, \dfrac{5}{9}, \dfrac{5}{9}\right)$. + +## 第 4 题 + +求下列曲面所包围的均匀物体关于 $z$ 轴的转动惯量. + +(1) $z = x^2+y^2, x+y = \pm 1, x - y = \pm 1, z = 0$; + +**解** + +(1) 设积分区域为 $\Omega = \{(x, y, z) | z \le x^2 + y^2, x+y\le 1, x\ge 0, y \ge 0, z \ge 0\}$. + +$$ +\begin{aligned} + J_z' & = \iiint\limits_{\Omega}(x^2+y^2)\text{d}{x}\text{d}{y}\text{d}{z} \\ + & = \int_{0}^{1}\text{d}{x}\int_{0}^{1-x}\text{d}{y}\int_{0}^{x^2+y^2}(x^2+y^2)\text{d}{z} \\ + & = \int_{0}^{1}\text{d}{x}\int_{0}^{1-x}(x^2+y^2)^2\text{d}{y} \\ + & = \int_{0}^{1}\left(-\dfrac{28}{15}x^5+4x^4-4x^3+\dfrac{8}{3}x^2-x+\dfrac{1}{5}\right)\text{d}{x} \\ + & = \dfrac{7}{90} +\end{aligned} +$$ + +由对称性知 $J_z = 4J_z' = 4\cdot\dfrac{7}{90} = \dfrac{14}{45}$. diff --git a/services/homework-ans/docs/calculus-2/chapter3/exercise3-rev.md b/services/homework-ans/docs/calculus-2/chapter3/exercise3-rev.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter3/exercise3-rev.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-2/chapter4/exercise4-1.md b/services/homework-ans/docs/calculus-2/chapter4/exercise4-1.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter4/exercise4-1.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-2/chapter4/exercise4-2.md b/services/homework-ans/docs/calculus-2/chapter4/exercise4-2.md new file mode 100644 index 0000000..a287ced --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter4/exercise4-2.md @@ -0,0 +1,266 @@ + +## 第 1 题 + +计算下列曲线积分. + +(1) $\int_L(x+y)\text{d}{l}$, 其中 $L$ 为 $O(0, 0), A(1, 0), B(0, 1)$ 为顶点的三角形的三条边; + +(2) $\int_L\sqrt{x^2+y^2}\text{d}{l}$, 其中 $L$ 为圆周 $x^2+y^2=2x$; + +(3) $\int_Ly^2\text{d}{l}$, 其中 $L$ 为摆线 $\begin{cases}x = a(t - \sin t), \\ y = a(1 - \cos t),\end{cases}0 \le t \le 2\pi$; + +(4) $\int_L(x^{\frac{4}{3}}+y^{\frac{4}{3}})\text{d}{l}$, 其中 $L$ 为星形线 $\begin{cases}x = a\cos^3t, \\ y = a\sin^3t,\end{cases}0 \le t \le 2\pi$. + +**解** + +(1) $L = L_1 + L_2 + L_3$, 其中 $L_1 = \begin{cases}x = x, \\ y = 0, \end{cases}L_2 = \begin{cases}x = x, \\ y = 1-x, \end{cases}L_3 = \begin{cases}x = 0, \\ y = y, \end{cases}(0 \le x \le 1, 0 \le y \le 1)$. 因此 + +$$ +\begin{aligned} + \int_L (x+y)\text{d}{l} & = \int_{L_1} (x+y)\text{d}{l} + \int_{L_2} (x+y)\text{d}{l} + \int_{L_3} (x+y)\text{d}{l} \\ + & = \int_{0}^{1}x\text{d}{x} + \int_{0}^{1}\sqrt{2}\text{d}{x} + \int_{0}^{1}y\text{d}{y} \\ + & = \dfrac{1}{2} + \sqrt{2} + \dfrac{1}{2} \\ + & = \sqrt{2} + 1 +\end{aligned} +$$ + +(2) 设 $\begin{cases}x=1+\cos\theta, \\ y = \sin\theta, \end{cases}$ 则 $\text{d}{l} = \sqrt{(\text{d}{x})^2 + (\text{d}{y})^2} = \sqrt{(-\sin\theta)^2+(\cos\theta)^2}\text{d}{\theta} = \text{d}{\theta}$. + +$$ +\begin{aligned} + \int_L\sqrt{x^2+y^2}\text{d}{l} & = \int_{-\pi}^{\pi}\sqrt{(1+\cos\theta)^2 + \sin^2\theta}\text{d}{\theta} \\ + & = \int_{-\pi}^{\pi}2\cos\dfrac{\theta}{2}\text{d}{\theta} \\ + & = 4\int_{-\frac{\pi}{2}}^{\frac{\pi}{2}}\cos u\text{d}{u} \\ + & = 8 +\end{aligned} +$$ + +(3) $\text{d}{l} = \sqrt{(\text{d}{x})^2 + (\text{d}{y})^2} = \sqrt{a^2(a-\cos t)^2 + (a\sin t)^2} = \sqrt{2}a\sin\dfrac{t}{2}$. 因此 + +$$ +\begin{aligned} + \int_Ly^2\text{d}{l} & = \int_{0}^{2\pi}a^2(1-\cos t)^2\cdot\sqrt{2}a\sin\dfrac{t}{2} \text{d}{t} \\ + & = 4\sqrt{2}a^3\int_{0}^{2\pi}\sin^3\dfrac{t}{2}\text{d}{t} \\ + & = 8\sqrt{2}a^3\int_{0}^{2\pi}\sin^3u\text{d}{u} \\ + & = 32\sqrt{2}a^3\int_{0}^{\frac{\pi}{2}}\sin^5u\text{d}{u} \\ + & = 32\sqrt{2}a^3\cdot\dfrac{4 \cdot 2}{5\cdot 3} \\ + & = \dfrac{256}{15}a^3 +\end{aligned} +$$ + +(4) $\text{d}{l} = \sqrt{(\text{d}{x})^2+(\text{d}{y})^2} = \sqrt{(3a\cos^2t\sin t)^2 + (3a\sin^2t\cos t)^2}\text{d}{t} = 3a\left|\sin t\cos t\right|\text{d}{t}$. 只考虑 $0 \le t \le \dfrac{\pi}{2}$ 的情况. + +$$ +\begin{aligned} + \int_{L'}(x^{\frac{4}{3}}+y^{\frac{4}{3}})\text{d}{l} & = \int_{0}^{\frac{\pi}{2}}a^{\frac{4}{3}}(\cos^4t+\sin^4t)\cdot 3a(\sin t\cos t)\text{d}{t} \\ + & = 3a^{\frac{7}{3}}\int_{0}^{\frac{\pi}{2}}(\cos^4t+\sin^4t)\sin t\cos t\text{d}{t} \\ + & = 3a^{\frac{7}{3}}\left(\dfrac{1}{6}\sin^6t - \dfrac{1}{6}\cos^6t\right)\bigg\vert_{0}^{\frac{\pi}{2}} \\ + & = a^{\frac{7}{3}} +\end{aligned} +$$ + +由对称性知 $\int_{L}(x^{\frac{4}{3}}+y^{\frac{4}{3}})\text{d}{l} = 4\int_{L'}(x^{\frac{4}{3}}+y^{\frac{4}{3}})\text{d}{l} = 4a^{\frac{7}{3}}$. + +## 第 2 题 + +计算下列曲线积分. + +(1) $\int_L x\sqrt{x^2-y^2}\text{d}{l}$, 其中 $L$ 为双纽线右半支 $r^2 = a^2\cos2\theta(-\dfrac{\pi}{4} \le \theta \le \dfrac{\pi}{4}, a > 0)$; + +(2) $\int_L(x^2+y^2+z^2)\text{d}{l}$, 其中 $L$ 为螺线 $x=2\cos t, y=2\sin t, z=3t(0\le t \le 2\pi)$; + +(3) $\int_L xyz \text{d}{l}$, 其中 $L$ 的参数方程为 $x=t, y=\dfrac{2}{3}\sqrt{2}t^{\frac{3}{2}}, z=\dfrac{1}{2}t^2(0 \le t \le 1)$; + +(4) $\int_L x\text{d}{l}$, 其中 $L$ 为球面 $x^2+y^2+z^2=4$ 在第一象限部分的边界. + +**解** + +(1) 由题知 $\sqrt{x^2-y^2}=\sqrt{(r\cos\theta)^2-(r\sin\theta)^2} = \sqrt{r^2\cos2\theta} = \dfrac{r^2}{a}$. 而 + +$$ +\begin{aligned} + \text{d}{l} & = \sqrt{(\text{d}{x})^2+(\text{d}{y})^2} \\ + & = \sqrt{(-r\sin\theta)^2+(r\cos\theta)^2} \\ + & = \sqrt{(\cos\theta\text{d}{r} - r\sin\theta\text{d}{\theta})^2 + (\sin\theta\text{d}{r} + r\cos\theta\text{d}{\theta})^2} \\ + & = \sqrt{(\text{d}{r})^2 + r^2(\text{d}{\theta})^2} +\end{aligned} +$$ + +对 $r^2 = a^2\cos2\theta$ 微分得到 $\text{d}{r} = -\dfrac{a^2\sin2\theta}{r}\text{d}{\theta}$, 代入有 $\text{d}{l} = \sqrt{\left(-\dfrac{a^2\sin2\theta}{r}\text{d}{\theta}\right)^2+r^2(\text{d}{\theta})^2} = \dfrac{1}{r}\sqrt{r^4 - (a^2\sin2\theta)^2}\text{d}{\theta}$. 结合 $r^2 = a^2\cos2\theta$ 知 $\text{d}{l} = \dfrac{a^2}{r}\text{d}{\theta}$. 因此 + +$$ +\begin{aligned} + \int_L x\sqrt{x^2-y^2}\text{d}{l} & = \int_{-\frac{\pi}{4}}^{\frac{\pi}{4}}r\cos\theta\cdot \dfrac{r^2}{a}\cdot \dfrac{a^2}{r}\text{d}{\theta} \\ + & = a\int_{-\frac{\pi}{4}}^{\frac{\pi}{4}}r^2\cos\theta\text{d}{\theta} \\ + & = a\int_{-\frac{\pi}{4}}^{\frac{\pi}{4}}a^2\cos2\theta\cos\theta\text{d}{\theta} \\ + & = a^3\int_{-\frac{\pi}{4}}^{\frac{\pi}{4}}(1-2\sin^2\theta)\cos\theta\text{d}{\theta} \\ + & = a^3\left(\sin\theta - \dfrac{2}{3}\sin^3\theta\right)\bigg\vert_{-\frac{\pi}{4}}^{\frac{\pi}{4}} \\ + & = \dfrac{2\sqrt{2}a^3}{3} +\end{aligned} +$$ + +(2) $\text{d}{l} = \sqrt{(\text{d}{x})^2+(\text{d}{y})^2+(\text{d}{z})^2} = \sqrt{(-2\sin t)^2+(2\cos t)^2 + 3^2} = \sqrt{13}$. 因此 + +$$ +\begin{aligned} + \int_L(x^2+y^2+z^2)\text{d}{l} & = \int_{0}^{2\pi}(4 + 9t^2)\cdot\sqrt{13}\text{d}{t} \\ + & = \sqrt{13}(4t + 3t^3)\bigg\vert_{0}^{2\pi} \\ + & = 24\sqrt{13}\pi^3+8\sqrt{13}\pi +\end{aligned} +$$ + +(3) $\text{d}{l} = \sqrt{(\text{d}{x})^2+(\text{d}{y})^2+(\text{d}{z})^2} = \sqrt{1^2+(\sqrt{2t})^2 + t^2} = (t+1)\text{d}{t}$. 因此 + +$$ +\begin{aligned} + \int_Lxyz\text{d}{l} & = \int_{0}^{1}\dfrac{\sqrt{2}}{3}t^{\frac{9}{2}}\cdot(t+1)\text{d}{t} \\ + & = \dfrac{2\sqrt{2}}{3}t^{\frac{11}{2}}\left(\dfrac{1}{13}t + \dfrac{1}{11}\right)\bigg\vert_{0}^{1} \\ + & = \dfrac{16\sqrt{2}}{143} +\end{aligned} +$$ + +(4) $L = L_1 + L_2 + L_3$, 其中 $L_1 = \begin{cases}x = 0, \\ y = 2\cos\theta, \\ z = 2\sin\theta, \end{cases}L_2 = \begin{cases}x = 2\cos\theta, \\ y = 0, \\ z = 2\sin\theta, \end{cases} L_3 = \begin{cases}x = 2\cos\theta, \\ y = 2\sin\theta, \\ z = 0, \end{cases}(0 \le \theta \le \dfrac{\pi}{2})$. 因此 + +$$ +\begin{aligned} + \int_L x\text{d}{l} & = \int_{L_1} x\text{d}{l} + \int_{L_2} x\text{d}{l} + \int_{L_3} x\text{d}{l} \\ + & = 0 + 2\int_{0}^{\frac{\pi}{2}}2\cos\theta\cdot4\text{d}{\theta} \\ + & = 8 +\end{aligned} +$$ + +## 第 4 题 + +曲线 $y=\ln x$ 的线密度 $\rho(x, y) = x^2$, 试求曲线在 $x = \sqrt{3}$ 与 $x = \sqrt{15}$ 之间的质量. + +**解** + +$M = \int_L\rho(x, y)\text{d}{l}$, 其中 $L$ 是 $y=\ln x(\sqrt{3} \le x \le \sqrt{15})$. 而 $\text{d}{l} = \sqrt{(\text{d}{x})^2+(\text{d}{y})^2} = \sqrt{1 + \dfrac{1}{x^2}}\text{d}{x}$, 因此 + +$$ +\begin{aligned} + M & = \int_L\rho(x, y)\text{d}{l} \\ + & = \int_{\sqrt{3}}^{\sqrt{15}}x^2\cdot \sqrt{1 + \dfrac{1}{x^2}}\text{d}{x} \\ + & = \int_{\sqrt{3}}^{\sqrt{15}}x\sqrt{x^2+1}\text{d}{x} \\ + & = \dfrac{1}{3}(x^2+1)^{\frac{3}{2}}\bigg\vert_{\sqrt{3}}^{\sqrt{15}} \\ + & = \dfrac{56}{3} +\end{aligned} +$$ + +## 第 5 题 + +求圆柱面 $x^2+y^2=a^2$ 介于曲面 $z = a+\dfrac{x^2}{a}$ 与 $z=0$ 之间的面积 ($a > 0$). + +**解** + +积分区域为 $L = \{(x, y) | x^2+y^2=a^2\} = \{(x, y) | x = a\cos\theta, b=a\sin\theta, 0 \le \theta \le 2\pi\}$. 而 $\text{d}{l} = \sqrt{(\text{d}{x})^2+(\text{d}{y})^2} = \sqrt{(-a\sin\theta)^2 + (a\cos\theta)^2}\text{d}{\theta} = a\text{d}{\theta}$, 因此 + +$$ +\begin{aligned} + S & = \int_{L}z\text{d}{l} \\ + & = \int_{0}^{2\pi}(a+a\cos^2\theta)a\text{d}{\theta} \\ + & = \dfrac{1}{2}a^2\int_{0}^{2\pi}(3+\cos2\theta)\text{d}{\theta} \\ + & = 3\pi a^2 +\end{aligned} +$$ + +## 第 6 题 + +求摆线 $\begin{cases}x = a(t - \sin t), \\ y = a(1 - \cos t),\end{cases}0 \le t \le \pi$ 的形心. + +**解** + +$\text{d}{l} = \sqrt{(\text{d}{x})^2 + (\text{d}{y})^2} = \sqrt{a^2(a-\cos t)^2 + (a\sin t)^2} = \sqrt{2}a\sin\dfrac{t}{2}$. + +总质量 + +$$ +\begin{aligned} + M & = \int_{L}\text{d}{l} \\ + & = \int_{0}^{\pi}\sqrt{2}a\sin\dfrac{t}{2}\text{d}{t} \\ + & = \sqrt{2}a\int_{0}^{\pi}\sin\dfrac{t}{2}\text{d}{t} \\ + & = 2\sqrt{2}a\int_{0}^{\frac{\pi}{2}}\sin u\text{d}{u} \\ + & = 2\sqrt{2}a +\end{aligned} +$$ + +对 $x$ 轴的静力矩 + +$$ +\begin{aligned} + M_{x} & = \int_{L}y\text{d}{l} \\ + & = \int_{0}^{\pi}a(1-\cos t)\cdot\sqrt{2}a\sin\dfrac{t}{2}\text{d}{t} \\ + & = 2\sqrt{2}a^2\int_{0}^{\pi}\sin^2\dfrac{t}{2}\cdot\sin\dfrac{t}{2}\text{d}{t} \\ + & = 4\sqrt{2}a^2\int_{0}^{\frac{\pi}{2}}\sin^3u\text{d}{u} \\ + & = 4\sqrt{2}a^2\cdot\dfrac{2}{3} \\ + & = \dfrac{8\sqrt{2}a^2}{3} +\end{aligned} +$$ + +对 $y$ 轴的静力矩 + +$$ +\begin{aligned} + M_y & = \int_{L}x\text{d}{l} \\ + & = \int_{0}^{\pi}a(t-\sin t)\cdot\sqrt{2}a\sin\dfrac{t}{2}\text{d}{t} \\ + & = \sqrt{2}a^2\int_{0}^{\pi}t\sin\dfrac{t}{2}\text{d}{t} -\sqrt{2}a^2\int_{0}^{\pi}\sin t\sin\dfrac{t}{2}\text{d}{t} \\ + & = 4\sqrt{2}a^2\int_{0}^{\frac{\pi}{2}}u\sin u\text{d}{u} - 4\sqrt{2}a^2\int_{0}^{\frac{\pi}{2}}sin^2u\cos u\text{d}{u} \\ + & = 4\sqrt{2}a^2(-u\cos u + \sin u)\bigg\vert_{0}^{\frac{\pi}{2}} - \dfrac{4\sqrt{2}a^2}{3}\sin^3u\bigg\vert_{0}^{\frac{\pi}{2}} \\ + & = 4\sqrt{2}a^2 - \dfrac{4\sqrt{2}a^2}{3} \\ + & = \dfrac{8\sqrt{2}a^2}{3} +\end{aligned} +$$ + +因此形心在 $\left(\dfrac{M_x}{M}, \dfrac{M_y}{M}\right)$ 即 $(\dfrac{4a}{3}, \dfrac{4a}{3})$ 处. + +## 第 7 题 + +求螺线 $x = a\cos t, y = a\sin t, z = \dfrac{b}{2\pi}t(0 \le t \le 2\pi)$ 绕 $x$ 轴旋转的转动惯量 (线密度为 $1$). + +**解** + +$\text{d}{l} = \sqrt{(\text{d}{x})^2+(\text{d}{y})^2+(\text{d}{z})^2} = \sqrt{(a\sin t)^2+(a\cos t)^2 + \left(\dfrac{b}{2\pi}\right)^2}\text{d}{t} = \dfrac{\sqrt{b^2+4\pi^2a^2}}{2\pi}\text{d}{t}$. 因此 + +$$ +\begin{aligned} + J_{x} & = \int_{L}(y^2 + z^2)\text{d}{l} \\ + & = \int_{0}^{2\pi}\left(a^2\sin^2t + \left(\dfrac{b}{2\pi}t\right)^2\right)\dfrac{\sqrt{b^2+4\pi^2a^2}}{2\pi}\text{d}{t} \\ + & = \dfrac{\sqrt{b^2+4\pi^2a^2}}{2\pi}\int_{0}^{2\pi}\left(a^2\cdot\dfrac{1-2\cos2t}{2} + \dfrac{b^2}{4\pi^2}\cdot t^2\right)\text{d}{t} \\ + & = \dfrac{\sqrt{b^2+4\pi^2a^2}}{2\pi}\cdot\left(\pi a^2 + \dfrac{2\pi b^2}{3}\right) \\ + & = \left(\dfrac{a^2}{2} + \dfrac{b^2}{3}\right)\sqrt{b^2+4\pi^2a^2} +\end{aligned} +$$ + +## 第 8 题 + +圆周 $L:x^2+y^2=-2y$ 上每点的质量线密度等于 $\sqrt{x^2+y^2}$, 求曲线 $L$ 的质量与曲线 $L$ 对 $x$ 轴的静力矩. + +**解** + +设 $\begin{cases}x = \cos\theta, \\ y = -1 + \sin\theta,\end{cases}(-\dfrac{3\pi}{2} \le \theta \le \dfrac{\pi}{2})$, 此时恒有 $\cos\dfrac{\theta}{2} \ge \sin\dfrac{\theta}{2}$. + +曲线 $L$ 的质量为 + +$$ +\begin{aligned} + M & = \int_{L}\sqrt{x^2+y^2}\text{d}{l} \\ + & = \int_{-\frac{3\pi}{2}}^{\frac{\pi}{2}}\sqrt{2 - 2\sin\theta}\text{d}{\theta} \\ + & = \sqrt{2}\int_{-\frac{3\pi}{2}}^{\frac{\pi}{2}}(\cos\dfrac{\theta}{2} - \sin\dfrac{\theta}{2})\text{d}{\theta} \\ + & = 2\sqrt{2}\int_{-\frac{3\pi}{4}}^{\frac{\pi}{4}}(\cos\varphi - \sin\varphi)\text{d}{\varphi} \\ + & = 2\sqrt{2}(\sin\varphi + \cos\varphi)\bigg\vert_{-\frac{3\pi}{4}}^{\frac{\pi}{4}} \\ + & = 8 +\end{aligned} +$$ + +对 $x$ 轴的静力矩为 + +$$ +\begin{aligned} + M_{x} & = \int_{L}y\sqrt{x^2+y^2}\text{d}{l} \\ + & = \sqrt{2}\int_{-\frac{3\pi}{2}}^{\frac{\pi}{2}}(\sin\theta - 1)(\cos\dfrac{\theta}{2} - \sin\dfrac{\theta}{2})\text{d}{\theta} \\ + & = \sqrt{2}\int_{-\frac{3\pi}{2}}^{\frac{\pi}{2}}(2\cos^2\dfrac{\theta}{2}\sin\dfrac{\theta}{2} - 2\sin^2\dfrac{\theta}{2}\cos\dfrac{\theta}{2} + \sin\dfrac{\theta}{2} - \cos\dfrac{\theta}{2})\text{d}{\theta} \\ + & = 2\sqrt{2}\int_{-\frac{3\pi}{4}}^{\frac{\pi}{4}}(2\cos^2\varphi\sin\varphi - 2\sin^2\varphi\cos\varphi + \sin\varphi - \cos\varphi)\text{d}{\varphi} \\ + & = 2\sqrt{2}\left(-\dfrac{2}{3}\cos^2\varphi - \dfrac{2}{3}\sin^3\varphi - \cos\varphi - \sin\varphi\right)\bigg\vert_{-\frac{3\pi}{4}}^{\frac{\pi}{4}} \\ + & = -\dfrac{32}{3} +\end{aligned} +$$ diff --git a/services/homework-ans/docs/calculus-2/chapter4/exercise4-3.md b/services/homework-ans/docs/calculus-2/chapter4/exercise4-3.md new file mode 100644 index 0000000..366a8b8 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter4/exercise4-3.md @@ -0,0 +1,136 @@ + +## 第 1 题 + +计算下列第一类曲面积分. + +(1) $\iint\limits_{S}(x+y+z)\text{d}{S}$, 其中 $S$ 是上半球面 $x^2 + y^2 + z^2 = a^2(z \ge 0)$; + +(3) $\iint\limits_{S}\dfrac{\text{d}{S}}{(1 + x + y)^2}$, 其中 $S$ 是四面体 $x + y + z \le 1, x \ge 0, y \ge 0, z \ge 0$ 的边界面; + +**解** + +(1) 做坐标变换 $\begin{cases}x = a\sin\varphi\cos\theta, \\ y = a\sin\varphi\sin\theta, \\ z = a\cos\varphi\end{cases}$, 则积分区域变为 $D = \{(a\sin\varphi\cos\theta, a\sin\varphi\sin\theta, a\cos\varphi) | 0 \le \varphi \le \dfrac{\pi}{2}, 0 \le \theta \le 2\pi\}$. $\text{d}{S} = a^2\sin\varphi\text{d}{\varphi}\text{d}{\theta}$. 由对称性知 $\iint\limits_{S}(x+y)\text{d}{S} = 0$. 因此 + +$$ +\begin{aligned} + \iint\limits_{S}(x+y+z)\text{d}{S} & = \iint\limits_{S}z\text{d}{S} \\ + & = \iint\limits_{S}a\cos\varphi\cdot a^2\sin\varphi\text{d}{\varphi}\text{d}{\theta} \\ + & = a^3\int_{0}^{2\pi}\text{d}{\theta}\int_{0}^{\frac{\pi}{2}}\sin\varphi\cos\varphi\text{d}{\varphi} \\ + & = 2\pi a^3\int_{0}^{\frac{\pi}{2}}\sin\varphi\cos\varphi\text{d}{\varphi} \\ + & = -\dfrac{\pi a^3}{2}\cos2\varphi \bigg\vert_{0}^{\frac{\pi}{2}} \\ + & = \pi a^3 +\end{aligned} +$$ + +(3) 将 $S$ 分解为 + +$$ +\begin{aligned} + S_1 & = \{(x, y, z) | x + y + z = 1 , x \ge 0, y \ge 0, z \ge 0\}, \\ + S_2 & = \{(x, y, z) | x + y + z \le 1, x = 0, y \ge 0, z \ge 0\}, \\ + S_3 & = \{(x, y, z) | x + y + z \le 1, x \ge 0, y = 0, z \ge 0\}, \\ + S_4 & = \{(x, y, z) | x + y + z \le 1, x \ge 0, y \ge 0, z = 0\}. +\end{aligned} +$$ + +对于 $S_1$, 由于 $x + y + z = 1$, 所以 $\text{d}{S} = \sqrt{1 + \left(\dfrac{\partial z}{\partial x}\right)^2 + \left(\dfrac{\partial z}{\partial y}\right)^2}\text{d}{x}\text{d}{y} = \sqrt{3}\text{d}{x}\text{d}{y}$. + +$$ +\begin{aligned} + \iint\limits_{S_1}\dfrac{\text{d}{S}}{(1 + x + y)^2} & = \iint\limits_{S_1}\dfrac{\sqrt{3}\text{d}{x}\text{d}{y}}{(1 + x + y)^2} \\ + & = \sqrt{3}\int_{0}^{1}\text{d}{x}\int_{0}^{1 - x}\dfrac{\text{d}{y}}{(1 + x + y)^2} \\ + & = \sqrt{3}\int_{0}^{1}\left(\dfrac{1}{1 + x} - \dfrac{1}{2}\right)\text{d}{x} \\ + & = \sqrt{3}\left(\ln(x + 1) - \dfrac{x}{2}\right)\bigg\vert_{0}^{1} \\ + & = \sqrt{3}\left(\ln 2 - \dfrac{1}{2}\right) +\end{aligned} +$$ + +同理 $\iint\limits_{S_4}\dfrac{\text{d}{S}}{(1 + x + y)^2} = \ln2 - \dfrac{1}{2}$, 再考虑 $S_2$: + +$$ +\begin{aligned} + \iint\limits_{S_2}\dfrac{\text{d}{S}}{(1 + x + y)^2} & = \iint\limits_{S_2}\dfrac{\text{d}{y}\text{d}{z}}{(1 + y)^2} \\ + & = \int_{0}^{1}\text{d}{y}\int_{0}^{1 - y}\dfrac{\text{d}{z}}{(1 + y)^2} \\ + & = \int_{0}^{1}\dfrac{1 - x}{(1 + x)^2}\text{d}{x} \\ + & = -\left(\ln(1 +x) + \dfrac{2}{1 + x}\right)\bigg\vert_{0}^{1} \\ + & = 1 - \ln 2 +\end{aligned} +$$ + +同理 $\iint\limits_{S_3}\dfrac{\text{d}{S}}{(1 + x + y)^2} = 1 - \ln 2$. 因此总和为 + +$$ +\begin{aligned} + S & = S_1 + S_2 + S_3 + S_4 \\ + & = \sqrt{3}\left(\ln 2 - \dfrac{1}{2}\right) + (1 - \ln 2) + (1 - \ln 2) + \ln2 - \dfrac{1}{2} \\ + & = \dfrac{3 - \sqrt{3}}{2} + (\sqrt{3} - 1)\ln 2 +\end{aligned} +$$ + +## 第 2 题 + +计算圆柱面 $x^2 + y^2 = ax$ 被球面 $x^2 + y^2 + z^2 = a^2$ 所截部分的面积 $(a > 0)$. + +**解** + +进行坐标变换 $\begin{cases}x = \dfrac{a}{2} + \dfrac{a}{2}\cos\theta, \\ y = \dfrac{a}{2}\sin\theta,\end{cases}$ 则积分区域变为 $L = \{(x, y) | x = \dfrac{a}{2} + \dfrac{a}{2}\cos\theta, y = \dfrac{a}{2}\sin\theta, 0 \le \theta \le 2\pi\}$. 同时 $\text{d}{l} = \dfrac{a}{2}\text{d}{\theta},z^2 = a^2 - ax = \dfrac{a^2}{2}(1-\cos\theta)$. 不妨只考虑 $z > 0$ 的部分. + +$$ +\begin{aligned} + \int_{L}z\text{d}{l} & = \int_{0}^{2\pi}\sqrt{\dfrac{a^2}{2}(1 - \cos\theta)}\cdot\dfrac{a}{2}\text{d}{\theta} \\ + & = \dfrac{a^2}{2}\int_{0}^{2\pi}\sin\dfrac{\theta}{2}\text{d}{\theta} \\ + & = -a^2\cos\dfrac{\theta}{2}\bigg\vert_{0}^{2\pi} \\ + & = 2a^2 +\end{aligned} +$$ + +由对称性, $z < 0$ 的区域所截面积也为 $2a^2$, 因此全面积为 $4a^2$. + +## 第 3 题 + +求抛物面 $2z = x^2 + y^2$ 在 $z \in [0, 1]$ 部分的质量, 其中质量面密度为 $\sigma = z$. + +**解** + +抛物面的面积元素为 + +$$ +\begin{aligned} + \text{d}{S} & = \sqrt{1 + \left(\dfrac{\partial z}{\partial x}\right)^2 + \left(\dfrac{\partial z}{\partial y}\right)^2}\text{d}{x}\text{d}{y} \\ + & = \sqrt{1 + x^2 + y^2}\text{d}{x}\text{d}{y} \\ +\end{aligned} +$$ + +进行坐标变换 $\begin{cases}x = r\cos\theta, \\ y = r\sin\theta,\end{cases}$ 则有 + +$$ +\begin{aligned} + \iint\limits_{0 \le x^2 + y^2 \le 2}\sigma\text{d}{S} & = \iint\limits_{0 \le x^2 + y^2 \le 2}\dfrac{x^2 + y^2}{2}\cdot\sqrt{1 + x^2 + y^2}\text{d}{x}\text{d}{y} \\ + & = \int_{0}^{\sqrt{2}}\text{d}{r}\int_{0}^{2\pi}\dfrac{r^3}{2}\sqrt{1 + r^2}\text{d}{r} \\ + & = \pi\int_{0}^{\sqrt{2}}r^3\sqrt{1 + r^2}\text{d}{r} \\ + & = \dfrac{\pi}{2}\int_{0}^{2}u\sqrt{1 + u}\text{d}{u} \\ + & = \dfrac{\pi}{15}(3u-2)(u+1)^{\frac{3}{2}}\bigg\vert_{0}^{2} \\ + & = \dfrac{12\sqrt{3} + 2}{15}\pi +\end{aligned} +$$ + +## 第 8 题 + +求锥面 $z = \sqrt{x^2 + y^2}$ 在柱面 $z^2 = 2x$ 内的面积. + +**解** + +锥面的面积元素为 + +$$ +\begin{aligned} + \text{d}{S} & = \sqrt{1 + \left(\dfrac{\partial z}{\partial x}\right)^2 + \left(\dfrac{\partial z}{\partial y}\right)^2}\text{d}{x}\text{d}{y} \\ + & = \sqrt{2}\text{d}{x}\text{d}{y} \\ +\end{aligned} +$$ + +锥面被柱面所截部分记作 $S$ (其面积也记为 $S$), 它在 $xy$ 平面上的投影区域是圆域 $D_{xy} = \{(x, y) | x^2 + y^2 \le 2x\}$, 所以 + +$$ +S = \iint\limits_{S}1\text{d}{S} = \iint_{D_{xy}}\sqrt{2}\text{d}{x}\text{d}{y} = \sqrt{2}\pi +$$ diff --git a/services/homework-ans/docs/calculus-2/chapter4/exercise4-4.md b/services/homework-ans/docs/calculus-2/chapter4/exercise4-4.md new file mode 100644 index 0000000..9f85f4d --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter4/exercise4-4.md @@ -0,0 +1,177 @@ + +## 第 1 题 + +计算下列第二类曲线积分. + +(1) $\int_{L^{+}}\dfrac{x^2\text{d}{y}-y^2\text{d}{x}}{x^{\frac{5}{3}}+y^{\frac{5}{3}}}$, 其中 $L^{+}$ 是星形线在第一象限中的弧段 $\begin{cases}x = a\cos^3t, \\ y = a\sin^3t,\end{cases}0 \le t \le \dfrac{\pi}{2}$, 正向为 $(0, a)$ 到 $(a, 0)$; + +(2) $\int_{\bar{AB}}x\text{d}{x}+y\text{d}{y}+z\text{d}{z}$, 其中路径是从点 $A(1, 1, 1)$ 到 $B(2, 3, 4)$ 的直线段; + +(3) $\int_{L^{+}}\dfrac{-y\text{d}{x}+x\text{d}{y}}{x^2+y^2}+b\text{d}{z}$, 其中 $L^{+}$ 是螺旋线 $x=a\cos t, y=a\sin t, z = bt$ 上由参数 $t=0$ 到 $t=2\pi$ 的一段有向弧段. + +**解** + +(1) $\text{d}{x} = -3a\cos^2t\sin t, \text{d}{y} = 3a\sin^2t\cos t$, 正向参数值为 $t$ 从 $\dfrac{\pi}{2}$ 到 $0$. 因此 + +$$ +\begin{aligned} + \int_{L^{+}}\dfrac{x^2\text{d}{y}-y^2\text{d}{x}}{x^{\frac{5}{3}}+y^{\frac{5}{3}}} & = \int_{\frac{\pi}{2}}^{0}\dfrac{a^2\cos^6t\cdot 3a\sin^2t\cos t - a^2\sin^6t\cdot (-3a\cos^2t\sin t)}{a^{\frac{5}{3}}(\cos^5t + \sin^5t)}\text{d}{t} \\ + & = 3a^{\frac{4}{3}}\int_{\frac{\pi}{2}}^{0}\cos^2t\sin^2t\text{d}{t} \\ + & = 3a^{\frac{4}{3}}\cdot\dfrac{1}{8}\left(t - \dfrac{1}{4}\sin4t\right)\bigg\vert_{\frac{\pi}{2}}^{0} \\ + & = -\dfrac{3\pi}{16}a^{\frac{4}{3}} +\end{aligned} +$$ + +(2) 设路径上的任意一点 $P$ 可被表示为 $P(1 + t, 1 + 2t, 1 + 3t)$, 正向参数值为 $t$ 从 $0$ 到 $1$, 则 + +$$ +\begin{aligned} + \int_{\bar{AB}}x\text{d}{x}+y\text{d}{y}+z\text{d}{z} & = \int_{0}^{1}[(1 + t) + 2(1 + 2t) + 3(1 + 3t)]\text{d}{t} \\ + & = \int_{0}^{1}(14t + 6)\text{d}{t} \\ + & = (7t^2 + 6t)\bigg\vert_{0}^{1} \\ + & = 13 +\end{aligned} +$$ + +(3) $\text{d}{x} = -a\sin t\text{d}{t}, \text{d}{y} = a\cos t\text{d}{t}, \text{d}{z} = b\d{t}$. 因此 + +$$ +\begin{aligned} + \int_{L^{+}}\dfrac{-y\text{d}{x}+x\text{d}{y}}{x^2+y^2}+b\text{d}{z} & = \int_{0}^{2\pi}\left(\dfrac{-a\sin t\cdot (-a\sin t) + a\cos t \cdot a\cos t}{(a\cos t)^2 + (a\sin t)^2} + b^2\right)\text{d}{t} \\ + & = \int_{0}^{2\pi}(1 + b^2)\text{d}{t} \\ + & = 2\pi(1 + b^2) +\end{aligned} +$$ + +## 第 2 题 + +计算下列第二类曲线积分. + +(1) $\int_{L^{+}}(x^2-y^2)\text{d}{x}$, 其中 $L^{+}$ 是抛物线 $y=x^2$ 从点 $(0, 0)$ 到点 $(2, 4)$ 的弧段; + +(3) $\oint_{L^{+}}\dfrac{\text{d}{x} + \text{d}{y}}{\left|x\right| + \left|y\right|}$, 其中 $L^+$ 是 $x^2+y^2=a^2$, 逆时针为正向; + +(5) $\int_{L^+}xyz\text{d}{z}$, 其中 $L$ 为 $\begin{cases}x^2+y^2+z^2=1, \\ z=y,\end{cases}$ 从 $z$ 轴正向看去是逆时针方向. + +**解** + +(1) 将 $y = x^2$ 代入, 有 + +$$ +\begin{aligned} + \int_{L^{+}}(x^2-y^2)\text{d}{x} & = \int_{0}^{2}(x^2 - x^4)\text{d}{x} \\ + & = \left(\dfrac{1}{3}x^3 - \dfrac{1}{5}x^5\right)\bigg\vert_{0}^{2} \\ + & = -\dfrac{56}{15} +\end{aligned} +$$ + +(3) 设 $\begin{cases}x = a\cos t, \\ y = a\sin t, \end{cases}$, 正向参数值为 $t$ 从 $0$ 到 $2\pi$, 则 $\text{d}{x} + \text{d}{y} = -a\sin t + a\cos t$. 故 + +$$ +\begin{aligned} + \oint_{L^{+}}\dfrac{\text{d}{x} + \text{d}{y}}{\left|x\right| + \left|y\right|} & = \int_{0}^{2\pi}\dfrac{-a\sin t + a\cos t}{a\cos t + a\sin t}\text{d}{t} \\ + & = \int_{0}^{2\pi}\dfrac{\cos t - \sin t}{\cos t + \sin t}\text{d}{t} \\ + & = \ln\left|\cos x + \sin x\right|\bigg\vert_{0}^{2\pi} \\ + & = 0 +\end{aligned} +$$ + +(5) 设 $\begin{cases}x = \cos t, \\ y = z = \dfrac{\sqrt{2}}{2}\sin t, \end{cases}$, 正向参数值为 $t$ 从 $0$ 到 $\dfrac{\pi}{2}$, 则 $\text{d}{z} = \dfrac{\sqrt{2}}{2}\cos t\text{d}{t}$. 故 + +$$ +\begin{aligned} + \int_{L^+}xyz\text{d}{z} & = \int_{0}^{2\pi}\left(\cos t\cdot \dfrac{\sqrt{2}}{2}\sin t\cdot\dfrac{\sqrt{2}}{2}\sin t\right) \cdot \dfrac{\sqrt{2}}{2}\cos t\text{d}{t} \\ + & = \dfrac{\sqrt{2}}{4}\int_{0}^{2\pi}\cos^2t\sin^2t\text{d}{t} \\ + & = \dfrac{\sqrt{2}}{4}\cdot\dfrac{1}{8}\left(t - \dfrac{1}{4}\sin4t\right)\bigg\vert_{0}^{2\pi} \\ + & = \dfrac{\sqrt{2}\pi}{16} +\end{aligned} +$$ + +## 第 3 题 + +计算 $\int_{L^+}\mathbf{F}\cdot\text{d}{\mathbf{r}}$. + +(1) $\mathbf{F} = -y\mathbf{i}+x\mathbf{j}$, $L$ 是由 $x=y, x=1, y=0$ 围成的三角形的边界, 逆时针为正向; + +(3) $\mathbf{F} = F\mathbf{i}$, $L$ 是由 $\dfrac{x^2}{a^2}+\dfrac{y^2}{b^2}=1$ 在第一象限由点 $(0, b)$ 到点 $(a, 0)$ 的弧段; + +**解** + +(1) 将 $L^{+}$ 拆成 $3$ 段: $L_1^+ = \begin{cases}x = t, \\ y = 0,\end{cases} L_2^+ = \begin{cases}x = 1, \\ y = t,\end{cases} L_3^+ = \begin{cases}x = 1 - t, \\ y = 1 - t,\end{cases}$, 正向参数值均为 $t$ 从 $0$ 到 $1$, 则 + +$$ +\begin{aligned} + \int_{L^+}\mathbf{F}\cdot\text{d}{\mathbf{r}} & = \int_{L_1^+}\mathbf{F}\cdot\text{d}{\mathbf{r}} + \int_{L_2^+}\mathbf{F}\cdot\text{d}{\mathbf{r}} + \int_{L_3^+}\mathbf{F}\cdot\text{d}{\mathbf{r}} \\ + & = \int_{0}^{1}(0, t)\cdot(1, 0)\text{d}{t} + \int_{0}^{1}(-t, 1)\cdot(0, 1)\text{d}{t} + \int_{0}^{1}(t - 1, 1 - t) \cdot (-1, -1)\text{d}{t} \\ + & = 0 + 1 + 0 \\ + & = 1 +\end{aligned} +$$ + +(3) 设 $\begin{cases}x = a\sin\theta, \\ y = b\cos\theta, \end{cases}$, 正向参数值为 $\theta$ 从 $0$ 到 $\dfrac{\pi}{2}$, 则 + +$$ +\begin{aligned} + \int_{L^+}\mathbf{F}\cdot\text{d}{\mathbf{r}} & = \int_{0}^{\frac{\pi}{2}}(F, 0)\cdot(a\cos\theta, -b\sin\theta)\text{d}{\theta} \\ + & = \int_{0}^{\frac{\pi}{2}}aF\cos\theta\text{d}{\theta} \\ + & = aF +\end{aligned} +$$ + +## 第 4 题 + +今有一平面力场 $\mathbf{F}$, 大小等于点 $(x, y)$ 到坐标原点的距离, 方向指向坐标原点. + +(1) 计算单位质量的质点 $P$ 沿椭圆 $\dfrac{x^2}{a^2} + \dfrac{y^2}{b^2} = 1$ 在第一象限中的弧段从点 $(a, 0)$ 移动到点 $(0, b)$ 时, 力 $\mathbf{F}$ 所做的功; + +(2) 计算质点 $P$ 沿上述椭圆逆时针绕一圈时, 力 $\mathbf{F}$ 所做的功. + +**解** + +(1) 设 $\mathbf{r} = (a\cos\theta, b\sin\theta)$, 则 $\mathbf{F} = (-a\cos\theta, -b\sin\theta)$. 所求的功 + +$$ +\begin{aligned} + W_1 & = \int_{L^+}\mathbf{F}\cdot\text{d}{\mathbf{r}} \\ + & = \int_{0}^{\frac{\pi}{2}}(-a\cos\theta, -b\sin\theta)\cdot(-a\sin\theta, b\cos\theta)\text{d}{\theta} \\ + & = \int_{0}^{\frac{\pi}{2}}(a^2\sin\theta\cos\theta - b^2\sin\theta\cos\theta)\text{d}{\theta} \\ + & = \dfrac{a^2-b^2}{2}\int_{0}^{\frac{\pi}{2}}\sin2\theta\text{d}{\theta} \\ + & = \dfrac{b^2-a^2}{4}\cos2\theta\bigg\vert_{0}^{\frac{\pi}{2}} \\ + & = \dfrac{a^2 - b^2}{2} +\end{aligned} +$$ + +(2) 同理可得 + +$$ +\begin{aligned} + W_2 & = \int_{L^+}\mathbf{F}\cdot\text{d}{\mathbf{r}} \\ + & = \int_{0}^{2\pi}(-a\cos\theta, -b\sin\theta)\cdot(-a\sin\theta, b\cos\theta)\text{d}{\theta} \\ + & = \int_{0}^{2\pi}(a^2\sin\theta\cos\theta - b^2\sin\theta\cos\theta)\text{d}{\theta} \\ + & = \dfrac{a^2-b^2}{2}\int_{0}^{2\pi}\sin2\theta\text{d}{\theta} \\ + & = 0 +\end{aligned} +$$ + +## 第 5 题 + +解答下列各题. + +(1) 设一力场的力的大小与作用点到 $z$ 轴的距离成反比, 方向垂直 $z$ 轴且指向 $z$ 轴, 一质点沿圆周 $\begin{cases}x^2 + z^2 = 1, \\ y = 1,\end{cases}$ 由点 $(1, 1, 0)$ 经四分之一圆弧到达点 $(0, 1, 1)$ 时, 求该力场所做的功; + +**解** + +(1) 设 $\mathbf{F} = k\left(-\dfrac{x}{x^2 + y^2}, -\dfrac{y}{x^2 + y^2}, 0\right)$. 设 $\mathbf{r} = (\cos\theta, 1, \sin\theta)$, 则 $\mathbf{F} = k\left(-\dfrac{\cos\theta}{1 + \cos^2\theta}, -\dfrac{1}{1 + \cos^2\theta}, 0\right)$. + +因此总功 + +$$ +\begin{aligned} + W & = \int_{L^{+}}\mathbf{F}\cdot\text{d}{\mathbf{r}} \\ + & = \int_{0}^{\frac{\pi}{2}}k\left(-\dfrac{\cos\theta}{1 + \cos^2\theta}, -\dfrac{1}{1 + \cos^2\theta}, 0\right)\cdot(-\sin\theta, 0, \cos\theta)\text{d}{\theta} \\ + & = k\int_{0}^{\frac{\pi}{2}}\dfrac{\sin\theta\cos\theta}{1 + \cos^2\theta}\text{d}{\theta} \\ + & = k\int{0}^{1}\dfrac{t}{1 + t^2}\text{d}{t} \\ + & = \dfrac{k}{2}\ln(1 + t^2)\bigg\vert_{0}^{1} \\ + & = \dfrac{k\ln 2}{2} +\end{aligned} +$$ diff --git a/services/homework-ans/docs/calculus-2/chapter4/exercise4-5.md b/services/homework-ans/docs/calculus-2/chapter4/exercise4-5.md new file mode 100644 index 0000000..01a67b5 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter4/exercise4-5.md @@ -0,0 +1,130 @@ + +## 第 1 题 + +计算下列第二类曲面积分, 其中 $S^{+}$ 是球面 $x^2 + y^2 + (z-R)^2 = R^2$ 的外侧. + +(1) $\oint\limits_{S^{+}} \text{d}{x}\wedge\text{d}{y}$; % 这里有问题, 应该是 \oiint + +(2) $\oint\limits_{S^{+}} z\text{d}{x}\wedge\text{d}{y}$; % 这里有问题, 应该是 \oiint + +(3) $\oint\limits_{S^{+}} z^2\text{d}{x} \wedge \text{d}{y}$. % 这里有问题, 应该是 \oiint + +**解** + +(1) 由对称性知 $\oint\limits_{S^{+}} \text{d}{x}\wedge\text{d}{y} = 0$. % 这里有问题, 应该是 \oiint + +(2) 记上半球面为 $S_1^{+}$, 满足 $z = R + \sqrt{R^2 - x^2 - y^2}$, $\text{d}{x}\wedge\text{d}{y} = \text{d}{x}\text{d}{y}$, 下半球面为 $S_2^{+}$, 满足 $z = R - \sqrt{R^2 - x^2 - y^2}$, $\text{d}{x} \wedge\text{d}{y} = -\text{d}{x}\text{d}{y}$. 则 $D_{xy} = \{(x, y) | x^2 + y^2 \le R^2\}$. 换元 $\begin{cases}x = r\cos\theta, \\ y = r\sin\theta\end{cases}$, 则 $D_{r\theta} = \{(r, \theta) | 0 \le r \le R, 0 \le \theta \le 2\pi\}$. 因此 + +$$ +I_1 = \int_{0}^{R}r\text{d}{r}\int_{0}^{2\pi}(R + \sqrt{R^2-r^2})\text{d}{\theta} +$$ + +$$ +I_2 = \int_{0}^{R}r\text{d}{r}\int_{0}^{2\pi}(-R + \sqrt{R^2 - r^2})\text{d}{\theta} +$$ + +$$ +\begin{aligned} + I & = I_1 + I_2 \\ + & = 4\pi\int_{0}^{R}r\sqrt{R^2 -r^2}\text{d}{r} \\ + & = -\dfrac{4\pi}{3}(R^2 - r^2)^{\frac{3}{2}}\bigg\vert_{0}^{R} \\ + & = \dfrac{4\pi R^3}{3} +\end{aligned} +$$ + +(3) 同 (2) 可知 + +$$ +\begin{aligned} + I & = I_1' + I_2' \\ + & = 8\pi\int_{0}^{R}r\sqrt{R^2 -r^2}\text{d}{r} \\ + & = \dfrac{8\pi R^3}{3} +\end{aligned} +$$ + +## 第 3 题 + +计算下列曲面积分. + +(1) $\iint_{S^{+}}x\text{d}{y}\wedge\text{d}{z} + y\text{d}{z}\wedge\text{d}{x} + z\text{d}{x}\wedge\text{d}{y}$, 其中 $S^{+}$ 为平面 $x = 0, y = 0, z = 0, x = 1, y = 1, z = 1$ 所围立方体表面的外侧; + +(2) $\iint\limits_{S^{+}} x^2\text{d}{y} \wedge \text{d}{z} + y^2\text{d}{z}\wedge\text{d}{x}+z^2\text{d}{x}\wedge\text{d}{y}$, 其中 $S^{+}$ 是柱面 $x^2 + y^2 = 1$ 被平面 $z = 0, z = 3$ 所截部分的外侧; + +**解** + +(1) 设 $S_1 = \{(x, y, z) | 0 \le x, y \le 1, z = 0\}$. 由对称性知 $\iint_{S^{+}}x\text{d}{y}\wedge\text{d}{z} + y\text{d}{z}\wedge\text{d}{x} + z\text{d}{x}\wedge\text{d}{y} = 3\iint\limits_{S_1}\text{d}{x}\text{d}{y} = 3$. + +(2) 将 $S^{+}$ 分为三个部分: $S_1^{+}$ 上底面, $S_2^{+}$ 下底面, $S_3^{+}$ 侧面. + +$$ +\begin{aligned} + \quad & \iint\limits_{S_1^{+}}x^2\text{d}{y} \wedge \text{d}{z} + y^2\text{d}{z}\wedge\text{d}{x}+z^2\text{d}{x}\wedge\text{d}{y} \\ + & = \iint\limits_{S_1^{+}}z^2\text{d}{x}\wedge\text{d}{y} \\ + & = \iint\limits_{S_1^{+}}9\text{d}{x}\wedge\text{d}{y} \\ + & = 9\pi +\end{aligned} +$$ + +由对称性知 $\iint\limits_{S_2^{+}}x^2\text{d}{y} \wedge \text{d}{z} + y^2\text{d}{z}\wedge\text{d}{x}+z^2\text{d}{x}\wedge\text{d}{y} = \iint\limits_{S_3^{+}}x^2\text{d}{y} \wedge \text{d}{z} + y^2\text{d}{z}\wedge\text{d}{x}+z^2\text{d}{x}\wedge\text{d}{y} = 0$. + +故 $\iint\limits_{S^{+}} x^2\text{d}{y} \wedge \text{d}{z} + y^2\text{d}{z}\wedge\text{d}{x}+z^2\text{d}{x}\wedge\text{d}{y} = 9\pi$. + +## 第 4 题 + +计算 $\iint\limits_{S^{+}}\mathbf{A}\cdot\text{d}{\mathbf{S}}$, 其中 $\mathbf{A} = \dfrac{x\mathbf{i} + y\mathbf{j} + z\mathbf{k}}{\sqrt{x^2 + y^2 + z^2}}$, $S^{+}$ 是上半球面 $z = \sqrt{R^2 - x^2 - y^2}$ 的下侧. + +**解** + +做坐标变换 $\begin{cases}x = R\sin\varphi\cos\theta, \\ y = R\sin\varphi\sin\theta, \\ z = R\cos\varphi, \end{cases}$ 则 $A = \dfrac{D(y, z)}{D(\varphi, \theta)} = R^2\sin^2\varphi\cos\theta$, $B = \dfrac{D(z, x)}{D(\varphi, \theta)} = R^2\sin^2\varphi\sin\theta$, $C = \dfrac{D(x, y)}{D(\varphi, \theta)} = R^2\sin\varphi\cos\varphi$. 积分区域为 $D_{\varphi\theta} = \{(\varphi, \theta) | -\dfrac{\pi}{2} \le \varphi \le 0, 0 \le \theta \le 2\pi\}$. 因此 + +$$ +\begin{aligned} + \iint\limits_{S^{+}}\mathbf{A}\cdot\text{d}{\mathbf{S}} & = \iint\limits_{D_{\varphi\theta}}(\sin\varphi\cos\theta, \sin\varphi\sin\theta, \cos\varphi)\cdot(R^2\sin^2\varphi\cos\theta, R^2\sin^2\varphi\sin\theta, R^2\sin\varphi\cos\varphi)\text{d}{\varphi}\text{d}{\theta} \\ + & = R^2\iint\limits_{D_{\varphi\theta}}(\sin^3\varphi\cos^2\theta + \sin^3\varphi\sin^2\theta+\sin\varphi\cos^2\varphi)\text{d}{\varphi}\text{d}{\theta} \\ + & = R^2\int_{0}^{2\pi}\text{d}{\theta}\int_{-\frac{\pi}{2}}^{0}\sin\varphi\text{d}{\varphi} \\ + & = -2\pi R^2 +\end{aligned} +$$ + +## 第 5 题 + +求流速场 $\mathbf{V} = xy\mathbf{i} + yz\mathbf{j} + zx\mathbf{k}$ 由里往外穿过球面 $x^2 + y^2 + z^2 = 1$ 在第一象限部分的流量. + +**解** + +做坐标变换 $\begin{cases}x = \sin\varphi\cos\theta, \\ y = \sin\varphi\sin\theta, \\ z = \cos\varphi, \end{cases}$ 则 $A = \dfrac{D(y, z)}{D(\varphi, \theta)} = \sin^2\varphi\cos\theta$, $B = \dfrac{D(z, x)}{D(\varphi, \theta)} = \sin^2\varphi\sin\theta$, $C = \dfrac{D(x, y)}{D(\varphi, \theta)} = \sin\varphi\cos\varphi$. 积分区域为 $D_{\varphi\theta} = \{(\varphi, \theta) | 0 \le \varphi \le \dfrac{\pi}{2}, 0 \le \theta \le \dfrac{\pi}{2}\}$. 因此 + +$$ +\begin{aligned} + \iint\limits_{S^{+}}\mathbf{V}\cdot\text{d}{\mathbf{S}} & = \iint\limits_{D_{\varphi\theta}}(\sin^2\varphi\sin\theta\cos\theta, \sin\varphi\cos\varphi\sin\theta, \sin^2\varphi\cos^2\varphi\cos\varphi)\cdot(\sin^2\varphi\cos\theta, \sin^2\varphi\sin\theta, \sin\varphi\cos\varphi)\text{d}{\varphi}\text{d}{\theta} \\ + & = \iint\limits_{D_{\varphi\theta}}(\sin^4\varphi\sin\theta\cos^2\theta + \sin^3\varphi\cos\varphi\sin^2\theta+\sin^2\varphi\cos^2\varphi\cos\theta)\text{d}{\varphi}\text{d}{\theta} \\ + & = \int_{0}^{\frac{\pi}{2}}\sin^4\varphi\text{d}{\varphi}\int_{0}^{\frac{\pi}{2}}\cos^2\theta\sin\theta\text{d}{\theta} + \int_{0}^{\frac{\pi}{2}}\sin^3\varphi\cos\varphi\text{d}{\varphi}\int_{0}^{\frac{\pi}{2}}\sin^2\theta\text{d}{\theta} + \int_{0}^{\frac{\pi}{2}}\sin^2\varphi\cos^2\varphi\text{d}{\varphi}\int_{0}^{\frac{\pi}{2}}\cos\theta\text{d}{\theta} \\ + & = \dfrac{3\cdot 1}{4\cdot 2}\cdot \dfrac{\pi}{2} \cdot \dfrac{1}{3} + \dfrac{1}{4} \cdot \dfrac{1}{2} \cdot \dfrac{\pi}{2} + 1\cdot\dfrac{\pi}{16} \\ + & = \dfrac{3\pi}{16} +\end{aligned} +$$ + +## 第 7 题 + +$\iint\limits_{S^{+}}(x^2 + y^2)\text{d}{x}\wedge\text{d}{y} + y^2\text{d}{y}\wedge\text{d}{z}+z^2\text{d}{z}\wedge\text{d}{x}$, 其中 $S$ 是螺旋面 $x = u\cos v, y = u\sin v, z = av$ 在 + +$$ +D_{uv} = \{(u, v) | 0 \le u \le 1, 0 \le v \le 2\pi\} +$$ + +的部分, 上侧为正. + +**解** + +$A = \dfrac{D(y, z)}{D(u, v)} = a\sin v$, $B = \dfrac{D(z, x)}{D(u, v)} = -a\cos v$, $C = \dfrac{D(x, y)}{D(u, v)} = u$. 因此 + +$$ +\begin{aligned} + \quad & \iint\limits_{S^{+}}(x^2 + y^2)\text{d}{x}\wedge\text{d}{y} + y^2\text{d}{y}\wedge\text{d}{z}+z^2\text{d}{z}\wedge\text{d}{x} \\ + & = \iint\limits_{D_{uv}}(u^2, u^2\sin^2v, a^2v^2)\cdot(a\sin v, -a\cos v, u)\text{d}{u}\text{d}{v} \\ + & = \iint\limits_{D_{uv}}(au^2\sin v - au^2\sin^2v\cos v + a^2uv^2)\text{d}{u}\text{d}{v} \\ + & = \int_{0}^{1}u^2\text{d}{u}\int_{0}^{2\pi}a\sin v\text{d}{v} + \int_{0}^{1}u^2\text{d}{u}\int_{0}^{2\pi}\sin^2v\cos v\text{d}{v} + \int_{0}^{1}u\text{d}{u}\int_{0}^{2\pi}a^2v^2\text{d}{v} \\ + & = 0 + 0 + \dfrac{4\pi^3a^2}{3} \\ + & = \dfrac{4\pi^3a^2}{3} +\end{aligned} +$$ diff --git a/services/homework-ans/docs/calculus-2/chapter4/exercise4-6.md b/services/homework-ans/docs/calculus-2/chapter4/exercise4-6.md new file mode 100644 index 0000000..d94ecf2 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter4/exercise4-6.md @@ -0,0 +1,240 @@ + +## 第 1 题 + +利用 Green 公式计算下列曲线积分. + +(1) $\oint_{L^{+}}(x+y)^2\text{d}{x} - (x^2 + y^2)\text{d}{y}$, 其中 $L^{+}$ 是以 $(0, 0), (1, 0), (0, 1)$ 为顶点的三角形的边界, 逆时针为正; + +(3) $\oint_{L^{+}}(x^2+y)\text{d}{x} - (x-y^2)\text{d}{y}$, 其中 $L$ 是椭圆 $\dfrac{x^2}{a^2} + \dfrac{y^2}{b^2} = 1$ 的正向边界; + +**解** + +(1) $X = (x + y)^2, Y = -(x^2 + y^2)$, 因此由 Green 定理 + +$$ +\begin{aligned} + \oint_{L^{+}}(x+y)^2\text{d}{x} - (x^2 + y^2)\text{d}{y} & = \oint_{L^{+}}X\text{d}{x}+Y\text{d}{y} \\ + & = \iint\limits_{D}\left(\dfrac{\partial Y}{\partial x} - \dfrac{\partial X}{\partial y}\right)\text{d}{x}\text{d}{y} \\ + & = \iint\limits_{D}(-2x - 2x - 2y)\text{d}{x}\text{d}{y} \\ + & = -\int_{0}^{1}\text{d}{x}\int_{0}^{1 - x}(4x + 2y)\text{d}{y} \\ + & = \int_{0}^{1}(3x^2 - 2x - 1)\text{d}{x} \\ + & = -1 +\end{aligned} +$$ + +(3) $X = x^2 + y, Y = y^2 - x$. 由 Green 定理知 + +$$ +\oint_{L^{+}}(x^2+y)\text{d}{x} - (x-y^2)\text{d}{y} = \oint_{L^{+}}X\text{d}{x} + Y\text{d}{y} = \iint\limits_{D}\left(\dfrac{\partial Y}{\partial x} - \dfrac{\partial X}{\partial y}\right)\text{d}{x}\text{d}{y} = \iint\limits_{D}(-2)\text{d}{x}\text{d}{y} = -2\pi ab +$$ + +## 第 2 题 + +计算 $\int_{L^{+}}\dfrac{(x+y)\text{d}{x} + (y-x)\text{d}{y}}{x^2 + y^2}$, 其中 $L^{+}$ 为 + +(1) 区域 $D = \{(x, y) | a^2 \le x^2 + y^2 \le b^2\}$ 的正向边界 $(b > a > 0)$; + +(3) 正方形 $D = \{(x, y) | \left|x\right| + \left|y\right| \le 1\}$ 的逆时针方向; + +**解** + +(1) $X = \dfrac{x + y}{x^2 + y^2}, Y = \dfrac{y - x}{x^2 + y^2}$, 因此 $\dfrac{\partial Y}{\partial x} = \dfrac{x^2 - 2xy - y^2}{(x^2 + y^2)^2} = \dfrac{\partial X}{\partial y}$. 由 Green 定理知 $\int_{L^{+}}\dfrac{(x+y)\text{d}{x} + (y-x)\text{d}{y}}{x^2 + y^2} = 0$. + +(3) 考虑 $D^* = \{(x, y) | x = \epsilon\cos\theta, y = \epsilon\sin\theta, 0 \le \theta \le 2\pi\}$, 正方向为 $\theta$ 从 $2\pi$ 到 $0$. 因此 $\int_{\partial D\cup D^{*}}\dfrac{(x+y)\text{d}{x} + (y-x)\text{d}{y}}{x^2 + y^2} = 0$. 而 + +$$ +\begin{aligned} + \int_{\partial D^{*}}\dfrac{(x+y)\text{d}{x} + (y-x)\text{d}{y}}{x^2 + y^2} & = \int_{2\pi}^{0}\dfrac{\epsilon^2(\sin\theta + \cos\theta)\cdot(-\sin\theta) + \epsilon^2(\sin\theta - \cos\theta)\cdot\cos\theta}{\epsilon^2}\text{d}{\theta} \\ + & = \int_{2\pi}^{0}\text{d}{\theta} \\ + & = 2\pi +\end{aligned} +$$ + +因此 + +$$ +\int_{L^{+}}\dfrac{(x+y)\text{d}{x} + (y-x)\text{d}{y}}{x^2 + y^2} = \int_{D\cup D^*}\dfrac{(x+y)\text{d}{x} + (y-x)\text{d}{y}}{x^2 + y^2} - \int_{D^*}\dfrac{(x+y)\text{d}{x} + (y-x)\text{d}{y}}{x^2 + y^2} = -2\pi +$$ + +## 第 3 题 + +计算下列曲线积分. + +(1) $\int_{L^{+}}(1+xe^{2y})\text{d}{x} + (x^2e^{2y}-y^2)\text{d}{y}$, 其中 $L$ 是从点 $(0, 0)$ 经上半圆周 $(x - 2)^2 + y^2 = 4$ 到点 $(4, 0)$ 的弧段; + +(3) $\int_{L^{+}}\left(\ln\dfrac{y}{x} - 1\right)\text{d}{x} + \dfrac{x}{y}\text{d}{y}$, 其中 $L$ 是从点 $(1, 1)$ 出发到点 $(3, 3e)$ 的任何一条不与坐标轴相交的简单曲线. + +**解** + +(1) $X = 1 + xe^{2y}, Y = x^2e^{2y} - y^2$. 设 $A(0, 0), B(4, 0)$, 正方向由 $B$ 到 $A$. 则 $AB$ 和 $L$ 围成的图形 $D$ 满足: $\iint\limits_{D}\left(\dfrac{\partial Y}{\partial x} - \dfrac{\partial X}{\partial y}\right)\text{d}{x}\text{d}{y} = \iint\limits_{D}(2xe^{2y} - 2xe^{2y})\text{d}{x}\text{d}{y} = 0$. 由于 $\int_{BA}X\text{d}{x} = \int_{4}^{0}(1 + x)\text{d}{x} = -12$, 故由 Green 定理 + +$$ +\int_{L^{+}}(1+xe^{2y})\text{d}{x} + (x^2e^{2y}-y^2)\text{d}{y} = \iint\limits_{D}\left(\dfrac{\partial Y}{\partial x} - \dfrac{\partial X}{\partial y}\right)\text{d}{x}\text{d}{y} - \int_{BA}X\text{d}{x} = 12 +$$ + +(3) $X = \ln\dfrac{y}{x} - 1, Y = \dfrac{x}{y}$, 因此 $\dfrac{\partial Y}{\partial x} = \dfrac{1}{y} = \dfrac{\partial X}{\partial y}$. 所以这个曲线积分与路径无关, 此时可以先沿着 $x$ 轴正方向, 再沿着 $y$ 轴正方向的路径来计算这个积分. + +$$ +\begin{aligned} + \int_{L^{+}}\left(\ln\dfrac{y}{x} - 1\right)\text{d}{x} + \dfrac{x}{y}\text{d}{y} & = \int_{1}^{3}\left(\ln\dfrac{1}{x} - 1\right)\text{d}{x} + \int_{1}^{3e}\dfrac{3}{y}\text{d}{y} \\ + & = -x\ln x\bigg\vert_{1}^{3} + 3\ln y\bigg\vert_{1}^{3e} \\ + & = 3 +\end{aligned} +$$ + +## 第 4 题 + +计算下列区域的面积. + +(1) 星形线 $\begin{cases}x = a\cos^3t, \\ y = a\sin ^3t,\end{cases} 0 \le t \le 2\pi$ 所围区域 $(a > 0)$; + +**解** + +$$ +\begin{aligned} + S & = 4\int_{L}y\text{d}{x} \\ + & = 4\int_{0}^{\frac{\pi}{2}}(a\sin^3t)\cdot(-3a^2\cos^2t\sin t)\text{d}{t} \\ + & = 12a^2\left(\int_{0}^{\frac{\pi}{2}}\sin^4t\text{d}{t} - \int_{0}^{\frac{\pi}{2}}\sin^6t\text{d}{t}\right) \\ + & = 12a^2\cdot\left(\dfrac{3\cdot 1}{4\cdot 2} - \dfrac{5\cdot 3\cdot 1}{6\cdot 4\cdot 2}\right)\cdot\dfrac{\pi}{2} \\ + & = \dfrac{3}{8}\pi a^2 +\end{aligned} +$$ + +## 第 5 题 + +已知 $f(u)$ 连续可微, $L$ 为任意一条分段光滑曲线, 证明: + +(1) $\oint_{L^{+}}f(xy)(y\text{d}{x} + x\text{d}{y}) = 0$; + +(2) $\oint_{L^{+}}f(x^2 + y^2)(x\text{d}{x} + y\text{d}{y}) = 0$. + +**证明** + +(1) $X = yf(xy), Y = xf(xy)$, 因此 $\dfrac{\partial Y}{\partial x} = f(xy) + xyf'(xy) = \dfrac{\partial X}{\partial y}$. 由定理 4.6.3 和定理 4.6.4 得 $\oint_{L^{+}}f(xy)(y\text{d}{x} + x\text{d}{y}) = 0$. + +(2) $X = xf(x^2 + y^2), Y = yf(x^2 + y^2)$, 因此 $\dfrac{\partial Y}{\partial x} = 2xyf'(x^2 + y^2) = \dfrac{\partial X}{\partial y}$. 由定理 4.6.3 和定理 4.6.4 得 $\oint_{L^{+}}f(x^2 + y^2)(x\text{d}{x} + y\text{d}{y}) = 0$. + +## 第 6 题 + +设 $D$ 是平面区域, $\partial D$ 为逐段光滑曲线, $(\bar{x}, \bar{y})$ 为 $D$ 的形心, $\sigma(D)$ 是 $D$ 的面积, 证明: + +(1) $\oint_{\partial D}x^2\text{d}{y} = 2\sigma(D)\bar{x}$; + +(2) $\oint_{\partial D}xy\text{d}{y} = \sigma(D)\bar{y}$. + +**证明** + +(1) 由 Green 定理 $\oint_{\partial D}x^2\text{d}{y} = \iint\limits_{D}2x\text{d}{x}\text{d}{y}$. 由定义 $\bar{x} = \dfrac{\iint\limits_{D}x\text{d}{x}\text{d}{y}}{\iint\limits_{D}\text{d}{x}\text{d}{y}} = \dfrac{\iint\limits_{D}x\text{d}{x}\text{d}{y}}{\sigma(S)}$. 因此 $\oint_{\partial D}x^2\text{d}{y} = 2\sigma(D)\bar{x}$. + +(2) 由 Green 定理 $\oint_{\partial D}xy\text{d}{y} = \iint\limits_{D}y\text{d}{x}\text{d}{y}$. 由定义 $\bar{y} = \dfrac{\iint\limits_{D}y\text{d}{x}\text{d}{y}}{\iint\limits_{D}\text{d}{x}\text{d}{y}} = \dfrac{\iint\limits_{D}y\text{d}{x}\text{d}{y}}{\sigma(S)}$. 因此 $\oint_{\partial D}xy\text{d}{y} = \sigma(D)\bar{y}$. + +## 第 8 题 + +设 $D$ 是平面区域, $\partial D$ 为逐段光滑曲线, $\mathbf{n}$ 为 $D$ 的单位外法向, $u, v \in C^2(D)$, 证明: + +(1) $\oint_{\partial D}\dfrac{\partial u}{\partial \mathbf{n}}\text{d}{l} = \iint\limits_{D}\Delta u\text{d}{x}\text{d}{y}$; + +(2) $\oint_{\partial D}v\dfrac{\partial u}{\partial \mathbf{n}}\text{d}{l} = \iint\limits_{D}v\Delta u\text{d}{x}\text{d}{y} + \iint\limits_{D}\nabla u\cdot \nabla v\text{d}{x}\text{d}{y}$; + +(3) $\oint_{\partial D}\begin{vmatrix}\dfrac{\partial u}{\partial \mathbf{n}} & \dfrac{\partial v}{\partial \mathbf{n}} \\ u & v\end{vmatrix}\text{d}{l} = \iint\limits_{D}\begin{vmatrix}\Delta u & \Delta v \\ u & v\end{vmatrix}\text{d}{x}\text{d}{y}$. + +其中 $\Delta = \dfrac{\partial^2}{\partial x^2} + \dfrac{\partial^2}{\partial y^2}, \nabla = \dfrac{\partial}{\partial x}\mathbf{i} + \dfrac{\partial}{\partial y}\mathbf{j}$. + +**证明** + +$\text{d}{\mathbf{l}} = (\text{d}{x}, \text{d}{y}), \mathbf{n} = \left(\dfrac{\text{d}{y}}{\left|\text{d}{\mathbf{l}}\right|}, -\dfrac{\text{d}{x}}{\left|\text{d}{\mathbf{l}}\right|}\right)$. + +(1) 由 Green 定理, + +$$ +\begin{aligned} + \oint_{\partial D}\dfrac{\partial u}{\partial \mathbf{n}}\text{d}{l} & = \oint_{\partial D}\dfrac{\partial u}{\partial x}\text{d}{y} - \dfrac{\partial u}{\partial y}\text{d}{x} \\ + & = \iint\limits_{D}\left(\dfrac{\partial^2u}{\partial x^2} + \dfrac{\partial^2u}{\partial y^2}\right)\text{d}{x}\text{d}{y} \\ + & = \iint\limits_{D}\Delta u\text{d}{x}\text{d}{y} +\end{aligned} +$$ + +(2) 由 Green 定理, + +$$ +\begin{aligned} + \oint_{\partial D}v\dfrac{\partial u}{\partial \mathbf{n}}\text{d}{l} & = \oint_{\partial D}v\dfrac{\partial u}{\partial x}\text{d}{y} - v\dfrac{\partial u}{\partial y}\text{d}{x} \\ + & = \iint\limits_{D}\left(\dfrac{\partial v}{\partial x}\dfrac{\partial u}{\partial x} + v\dfrac{\partial^2u}{\partial x^2} + v\dfrac{\partial^2u}{\partial y^2} + \dfrac{\partial v}{\partial y}\dfrac{\partial u}{\partial y}\right)\text{d}{x}\text{d}{y} \\ + & = \iint\limits_{D}v\Delta u\text{d}{x}\text{d}{y} + \iint\limits_{D}\nabla u\cdot \nabla v\text{d}{x}\text{d}{y} +\end{aligned} +$$ + +(3) 由 (2) 知, + +$$ +\begin{aligned} + \oint_{\partial D}\begin{vmatrix}\dfrac{\partial u}{\partial \mathbf{n}} & \dfrac{\partial v}{\partial \mathbf{n}} \\ u & v\end{vmatrix}\text{d}{l} & = \oint_{\partial D}v\dfrac{\partial u}{\partial \mathbf{n}}\text{d}{l} - \oint_{\partial D}u\dfrac{\partial v}{\partial \mathbf{n}}\text{d}{l} \\ + & = \left(\iint\limits_{D}v\Delta u\text{d}{x}\text{d}{y} + \iint\limits_{D}\nabla u\cdot \nabla v\text{d}{x}\text{d}{y}\right) - \left(\iint\limits_{D}u\Delta v\text{d}{x}\text{d}{y} + \iint\limits_{D}\nabla v\cdot \nabla u\text{d}{x}\text{d}{y}\right) \\ + & = \iint\limits_{D}v\Delta u\text{d}{x}\text{d}{y} - \iint\limits_{D}u\Delta v\text{d}{x}\text{d}{y} \\ + & = \iint\limits_{D}\begin{vmatrix}\Delta u & \Delta v \\ u & v\end{vmatrix}\text{d}{x}\text{d}{y} +\end{aligned} +$$ + +## 第 9 题 + +设 $L$ 为逐段光滑曲线, $\mathbf{n}$ 为 $L$ 所围区域的单位外法向, $\left<\mathbf{n}, \mathbf{i}\right>, \left<\mathbf{n}, \mathbf{j}\right>$ 分别表示 $\mathbf{n}$ 与 $x$ 轴、$y$ 轴正向的夹角, 计算: $\oint_{L}(x\cos\left<\mathbf{n}, \mathbf{i}\right> + y\cos\left<\mathbf{n}, \mathbf{j}\right>)\text{d}{l}$. + +**解** + +设 $L$ 所围区域为 $D$, 面积为 $S$. $\text{d}{\mathbf{l}} = (\text{d}{x}, \text{d}{y})$, 则 $\mathbf{n} = \left(\dfrac{\text{d}{y}}{\text{d}{l}}, -\dfrac{\text{d}{x}}{\text{d}{l}}\right)$. 由 Green 定理, + +$$ +\begin{aligned} + \oint_{L}(x\cos\left<\mathbf{n}, \mathbf{i}\right> + y\cos\left<\mathbf{n}, \mathbf{j}\right>)\text{d}{l} & = \oint_{L}x\text{d}{y} - y\text{d}{x} \\ + & = \iint\limits_{D}2\text{d}{x}\text{d}{y} \\ + & = 2S +\end{aligned} +$$ + +## 第 10 题 + +求解下列常微分方程. + +(1) $(x^2 - y)\text{d}{x} - (x + \sin^2y)\text{d}{y} = 0$; + +(2) $e^{y}\text{d}{x} + (xe^{y}-2y)\text{d}{y} = 0$; + +(3) $\dfrac{x\text{d}{x} + y\text{d}{y}}{\sqrt{x^2 + y^2}} = \dfrac{y\text{d}{x} - x\text{d}{y}}{x^2}$; + +(4) $\left(\cos x + \dfrac{1}{y}\right)\text{d}{x} + \left(\dfrac{1}{y} - \dfrac{x}{y^2}\right)\text{d}{y} = 0$. + +**解** + +(1) 原方程可化为 $\text{d}{\left(\dfrac{1}{3}x^3 - xy - \dfrac{1}{2}y + \dfrac{1}{4}\sin2y\right)} = 0$, 因此解为 $\dfrac{1}{3}x^3 - xy - \dfrac{1}{2}y + \dfrac{1}{4}\sin2y = C$. + +(2) 原方程可化为 $\text{d}{(xe^y - y^2)} = 0$, 因此解为 $xe^y - y^2 = C$. + +(3) 原方程可化为 $\text{d}{\sqrt{x^2 + y^2}} = -\text{d}{\left(\dfrac{y}{x}\right)}$, 因此解为 $\sqrt{x^2 + y^2} + \dfrac{y}{x} = C$. + +(4) 原方程可化为 $\text{d}{\left(\sin x + \dfrac{x}{y} + \ln y\right)} = 0$, 因此解为 $\sin x + \dfrac{x}{y} + \ln y = C$. + +## 第 11 题 + +解下列方程. + +(1) $(y\cos x - x\sin x)\text{d}{x} + (y\sin x + x\cos x)\text{d}{y} = 0$​; + +(2) $(x + y)\text{d}x + (y - x)\text{d}y = 0$; + +(3) $(3x^2 + y)\text{d}{x} + (2x^2y - x)\text{d}{y} = 0$; + +(4) $(x + y)(\text{d}x - \text{d}y) = \text{d}x + \text{d}y$; + +(5) $(x^2 - \sin^2 y)\text{d}{x} + x\sin 2y\text{d}{y} = 0$. + +**解** + +(1) 有积分因子 $e^{y}$. 原方程可化为 $\text{d}{(e^{y}(y\sin x + x\cos x - \sin x))} = 0$. 因此解为 $e^{y}(y\sin x + x\cos x - \sin x) = C$. + +(2) 由题知 $\dfrac{\text{d}y}{\text{d}x} = \dfrac{1 + \frac{y}{x}}{1 - \frac{y}{x}}$. 令 $u = \dfrac{y}{x}$, 即 $y = ux$, 则 $\dfrac{\text{d}y}{\text{d}x} = u + x\dfrac{\text{d}u}{\text{d}x}$. 方程可改写为 $u + x\dfrac{\text{d}u}{\text{d}x} = \dfrac{1 + u}{1 - u}$. 分离变量得 $\dfrac{u + 1}{u^2 + 1}\text{d}u = -\dfrac{1}{x}\text{d}x$. 拆为 $\dfrac{u}{u^2 + 1}\text{d}u + \dfrac{1}{u^2 + 1}\text{d}u = -\dfrac{1}{x}\text{d}x$, 则积分可得 $\dfrac{1}{2}\ln(u^2 + 1) + \arctan u = -\ln|x| + C$. 将 $u = \dfrac{y}{x}$ 代入可得解为 $\dfrac{1}{2}\ln(x^2 + y^2) + \arctan \dfrac{y}{x} = C$. + +(3) 有积分因子 $\dfrac{1}{x^2}$. 原方程可化为 $\text{d}{\left(3x - \dfrac{y}{x} + y^2\right)} = 0$. 同时, $x = 0$ 也是原方程的解. 因此解为 $3x^3 - xy + x^2y^2 = Cx^2$​. + +(4) 有积分因子 $\dfrac{1}{x + y}$. 原方程可化简为 $\text{d}(x - y) = \text{d}\ln(x +y)$. 因此解为 $x - y = \ln(x + y) + C$. + +(5) 有积分因子 $\dfrac{1}{x^2}$. 原方程可化为 $\text{d}{\left(x + \dfrac{\sin^2y}{x}\right)} = 0$. 同时, $x = 0$ 也是原方程的解. 因此解为 $x^3 + x^2\sin^2y = Cx^2$. diff --git a/services/homework-ans/docs/calculus-2/chapter4/exercise4-7.md b/services/homework-ans/docs/calculus-2/chapter4/exercise4-7.md new file mode 100644 index 0000000..fc6d62a --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter4/exercise4-7.md @@ -0,0 +1,236 @@ + +## 第 2 题 + +计算曲面积分 $\oint\limits_{S^{+}}\dfrac{x\text{d}{y}\wedge\text{d}{z} + y\text{d}{z}\wedge\text{d}{x} + z\text{d}{x}\wedge\text{d}{y}}{(x^2 + y^2 + z^2)^{\frac{3}{2}}}$, 其中 $S^{+}$ 为: % 这里符号有问题, 应该是 \oiint + +(1) 不包含也不经过原点的半径为 $R$ 的球面外侧; + +(2) 不包含也不经过原点的任意封闭曲面的外侧; + +(3) 球面 $x^2 + y^2 + z^2 = \epsilon^2(\epsilon > 0)$; + +(4) 包含原点在其内部的任意封闭曲面的外侧. + +**解** + +$X = \dfrac{x}{(x^2 + y^2 + z^2)^{\frac{3}{2}}}, Y = \dfrac{y}{(x^2 + y^2 + z^2)^{\frac{3}{2}}}, Z = \dfrac{z}{(x^2 + y^2 + z^2)^{\frac{3}{2}}}$. 因此 $\dfrac{\partial X}{\partial x} = \dfrac{y^2 + z^2 - 2x^2}{(x^2 + y^2 + z^2)^{\frac{5}{2}}}, \dfrac{\partial Y}{\partial y} = \dfrac{x^2 + z^2 - 2y^2}{(x^2 + y^2 + z^2)^{\frac{5}{2}}}, \dfrac{\partial Z}{\partial z} = \dfrac{x^2 + y^2 - 2z^2}{(x^2 + y^2 + z^2)^{\frac{5}{2}}}$. + +(1) 由 Gauss 公式, 该积分值为 $0$. + +(2) 由 Gauss 公式, 该积分值为 $0$. + +(3) 设此球面为 $\Gamma$, 该积分值为 $J$. 由对称性知 $J = 3\oint\limits_{\Gamma^{+}}Z\text{d}{x}\wedge\text{d}{y}$. 对于 $z > 0$, $\text{d}{x}\wedge\text{d}{y} = \text{d}{x}\text{d}{y}, z = \sqrt{\epsilon^2 - x^2 - y^2}$. 对于 $z < 0$, $\text{d}{x}\wedge\text{d}{y} = -\text{d}{x}\text{d}{y}, z = -\sqrt{\epsilon^2 - x^2 - y^2}$. 因此 + +$$ +\begin{aligned} + J & = \dfrac{6}{\epsilon^3}\iint\limits_{D}\sqrt{\epsilon^2 - x^2 - y^2}\text{d}{x}\text{d}{y} \\ + & = \dfrac{6}{\epsilon^3}\int_{0}^{\epsilon}r\sqrt{\epsilon^2 - r^2}\text{d}{r}\int_{0}^{2\pi}\text{d}{\theta} \\ + & = 2\pi \cdot\dfrac{9}{2}(\epsilon^2 - r^2)^{\frac{3}{2}}\bigg\vert_{0}^{\epsilon} \\ + & = 4\pi +\end{aligned} +$$ + +(4) 设积分区域为 $A$, 则由 Gauss 公式, $\oint\limits_{\Gamma^{-}\cup A^{+}}\dfrac{x\text{d}{y}\wedge\text{d}{z} + y\text{d}{z}\wedge\text{d}{x} + z\text{d}{x}\wedge\text{d}{y}}{(x^2 + y^2 + z^2)^{\frac{3}{2}}} = 0$. 因此 % 这里符号有问题, 应该是 \oiint + +$$ +\begin{aligned} + \quad & \oint\limits_{A^{+}}\dfrac{x\text{d}{y}\wedge\text{d}{z} + y\text{d}{z}\wedge\text{d}{x} + z\text{d}{x}\wedge\text{d}{y}}{(x^2 + y^2 + z^2)^{\frac{3}{2}}} \\ % 这里符号有问题, 应该是 \oiint + & = -\oint\limits_{\Gamma^{-}}\dfrac{x\text{d}{y}\wedge\text{d}{z} + y\text{d}{z}\wedge\text{d}{x} + z\text{d}{x}\wedge\text{d}{y}}{(x^2 + y^2 + z^2)^{\frac{3}{2}}} \\ % 这里符号有问题, 应该是 \oiint + & = \oint\limits_{\Gamma^{+}}\dfrac{x\text{d}{y}\wedge\text{d}{z} + y\text{d}{z}\wedge\text{d}{x} + z\text{d}{x}\wedge\text{d}{y}}{(x^2 + y^2 + z^2)^{\frac{3}{2}}} \\ % 这里符号有问题, 应该是 \oiint + & = 4\pi +\end{aligned} +$$ + +## 第 3 题 + +利用 Gauss 公式计算下列曲面积分. + +(1) $\oint\limits_{S^{+}}x^3\text{d}{y}\wedge\text{d}{z} + y^3\text{d}{z}\wedge\text{d}{x} + z^3\text{d}{x}\wedge\text{d}{y}$, 其中 $S^{+}$ 为球面 $x^2 + y^2 + z^2 = a^2(a > 0)$ 的外侧; % 这里符号有问题, 应该是 \oiint + +(3) $\oint\limits_{S^{+}}(x + 2y + 3z)\text{d}{x}\wedge\text{d}{y} + (y+2z)\text{d}{y}\wedge\text{d}{z} + (z^2 - 1)\text{d}{z}\wedge\text{d}{x}$, 其中 $S^{+}$ 为平面 $x + y + z = 1$ 及与三个坐标平面所围四面体的表面, 外侧为正; % 这里符号有问题, 应该是 \oiint + +(5) $\oint\limits_{S^{+}}\mathbf{A}\cdot\text{d}{\mathbf{S}}$, 其中 $\mathbf{A} = \dfrac{\mathbf{r}}{r^3}, \mathbf{r} = x\mathbf{i} + y\mathbf{j} + z\mathbf{k}, r = ||\mathbf{r}||$, $S$ 为椭球面 $\dfrac{x^2}{a^2} + \dfrac{y^2}{b^2} + \dfrac{z^2}{c^2} = 1$, 外侧为正; % 这里符号有问题, 应该是 \oiint + +**解** + +(1) $X = x^3, Y = y^3, Z = z^3$, 且 $x^2 + y^2 + z^2 = R^2$. 由 Gauss 公式 + +$$ +\begin{aligned} + \oint\limits_{S^{+}}\mathbf{A}\cdot\text{d}{\mathbf{S}} & = \iiint\limits_{\Omega}\left(\dfrac{\partial X}{\partial x} + \dfrac{\partial Y}{\partial y} + \dfrac{\partial Z}{\partial z}\right)\text{d}{x}\text{d}{y}\text{d}{z} \\ % 这里符号有问题, 应该是 \oiint + & = \iiint\limits_{\Omega}3R^2\text{d}{x}\text{d}{y}\text{d}{z} \\ + & = 4\pi +\end{aligned} +$$ + +(3) $X = x + 2y + 3z, Y = y + 2z, Z = z^2 - 1$. 由 Gauss 公式 + +$$ +\begin{aligned} + \quad & \oint\limits_{S^{+}}(x + 2y + 3z)\text{d}{x}\wedge\text{d}{y} + (y+2z)\text{d}{y}\wedge\text{d}{z} + (z^2 - 1)\text{d}{z}\wedge\text{d}{x} \\ % 这里符号有问题, 应该是 \oiint + & = \iiint\limits_{\Omega}\left(\dfrac{\partial X}{\partial x} + \dfrac{\partial Y}{\partial y} + \dfrac{\partial Z}{\partial z}\right)\text{d}{x}\text{d}{y}\text{d}{z} \\ + & = \iiint\limits_{\Omega}(0 + 0 + 3)\text{d}{x}\text{d}{y}\text{d}{z} \\ + & = \dfrac{1}{2} +\end{aligned} +$$ + +(5) 由第2题 (4) 得 $\oint\limits_{S^{+}}\mathbf{A}\cdot\text{d}{\mathbf{S}} = 4\pi$. % 这里符号有问题, 应该是 \oiint + +## 第 4 题 + +求向量场 $\mathbf{A}$ 通过闭曲面 $S$ (从里向外) 的通量 $\Phi = \oint\limits_{S^{+}}\mathbf{A}\cdot\text{d}{\mathbf{S}}$. + +(1) $\mathbf{A} = x^3\mathbf{i} + y^3\mathbf{j} + z^3\mathbf{k}$, $S$ 为球面 $x^2 + y^2 + z^2 = R^2$; + +(2) $\mathbf{A} = (x - y + z)\mathbf{i} + (y - z + x)\mathbf{j} + (z - x + y)\mathbf{k}$, $S$ 为椭球面 $\dfrac{x^2}{a^2} + \dfrac{y^2}{b^2} + \dfrac{z^2}{c^2} = 1$. + +**解** + +(1) 由第3题 (1) 得 $\Phi = \dfrac{12}{5}\pi R^5$. + +(2) $X = x - y - z, Y = y - z + x, Z = z - x + y$. 由 Gauss 公式 + +$$ +\begin{aligned} + \Phi & = \oint\limits_{S^{+}}\mathbf{A}\cdot\text{d}{\mathbf{S}} \\ + & = \iiint\limits_{\Omega}\left(\dfrac{\partial X}{\partial x} + \dfrac{\partial Y}{\partial y} + \dfrac{\partial Z}{\partial z}\right)\text{d}{x}\text{d}{y}\text{d}{z} \\ + & = \iiint\limits_{\Omega}(1 + 1 + 1)\text{d}{x}\text{d}{y}\text{d}{z} \\ + & = 4\pi abc +\end{aligned} +$$ + +## 第 5 题 + +利用 Stokes 公式计算下列积分. + +(1) $\oint_{L^{+}}y\text{d}{x} + z\text{d}{y} + x\text{d}{z}$, 其中 $L$ 是球面 $x^2 + y^2 + z^2 = R^2$ 与平面 $x + y + z = 0$ 的交线, 从 $z$ 轴正向看上去, 为逆时针方向; + +(3) $\oint_{L^{+}}y^2\text{d}{x}+z^2\text{d}{y} + x^2\text{d}{z}$, 其中 $L$ 是以 $A(a, 0, 0), B(0, b, 0), C(0, 0, c)(a, b, c > 0)$ 为顶点的三角形的边界, 方向为 $A \to B \to C \to A$. + +**解** + +(1) 取 $\mathbf{n} = \left(\dfrac{\sqrt{3}}{3}, \dfrac{\sqrt{3}}{3}, \dfrac{\sqrt{3}}{3}\right)$. 记 $D$ 为球 $x^2 + y^2 + z^2 \le R^2$ 被平面 $x + y + z = 0$ 所截的截面. 由 Stokes 公式 + +$$ +\oint_{L^{+}}y\text{d}{x} + z\text{d}{y} + x\text{d}{z} = \iint\limits_{D}(-1, -1, -1)\cdot\mathbf{n}\text{d}{S} +$$ + +故 $\oint_{L^{+}}y\text{d}{x} + z\text{d}{y} + x\text{d}{z} = \sqrt{3}\iint\limits_{D}\text{d}{S} = -\sqrt{3}\pi R^2$. + +(3) 由 Stokes 公式 + +$$ +\oint_{L^{+}}y^2\text{d}{x} + z^2\text{d}{y} + x^2\text{d}{z} = \iint\limits_{S^{+}}-2z\text{d}{y}\wedge\text{d}{z} - 2x\text{d}{z}\wedge\text{d}{x} - 2y\text{d}{x}\wedge\text{d}{y} +$$ + +考虑其中的 $\oint_{L^{+}}y^2\text{d}{x} = \iint\limits_{S^{+}}2y\text{d}{x}\wedge\text{d}{y}$, 在 $xy$ 平面内的投影 $D_{xy} = \{(x, y) | 0 \le x \le a, 0 \le y \le b - \dfrac{b}{a}x\}$. + +$$ +\begin{aligned} + \oint_{L^{+}}y^2\text{d}{x} & = \iint\limits_{D}2y\text{d}{x}\text{d}{y} \\ + & = \int_{0}^{a}\text{d}{x}\int_{0}^{b - \frac{b}{a}x}2y\text{d}{y} \\ + & = \int_{0}^{a}\left(b - \dfrac{b}{a}x\right)^2\text{d}{x} \\ + & = \dfrac{a}{3b}\left(\dfrac{b}{a}x - b\right)^3\bigg\vert_{0}^{a} \\ + & = \dfrac{ab^2}{3} +\end{aligned} +$$ + +由对称性知 $\oint_{L^{+}}y^2\text{d}{x}+z^2\text{d}{y} + x^2\text{d}{z} = \dfrac{ab^2 + bc^2 + ca^2}{3}$. + +## 第 6 题 + +试验证下列微分式为某个三元函数 $u(x, y, z)$ 的全微分, 并求出该函数. + +(1) $\dfrac{1}{x^2}(yz\text{d}{x} - zx\text{d}{y} - xy\text{d}{z})$; + +(2) $\dfrac{1}{(x + z)^2 + y^2}[y\text{d}{x} - (z + x)\text{d}{y} + y\text{d}{z}]$. + +**解** + +(1) 记 $u(x, y, z) = -\dfrac{yz}{x} + C$, 则 $\text{d}{u} = \dfrac{1}{x^2}(yz\text{d}{x} - zx\text{d}{y} - xy\text{d}{z})$. + +(2) 记 $u(x, y, z) = \arctan{\dfrac{x + z}{y}} + C$, 则 $\text{d}{u} = \dfrac{1}{\left(\frac{x+z}{y}\right)^2 + 1}\text{d}{\left(\dfrac{x + z}{y}\right)} = \dfrac{1}{(x + z)^2 + y^2}[y\text{d}{x} - (z + x)\text{d}{y} + y\text{d}{z}]$. + +## 第 7 题 + +证明下列曲线积分与路径无关, 并求积分值. + +(1) $\int_{(0, 0, 0)}^{(1, 2, 1)}(y + z)\text{d}{x} + (z + x)\text{d}{y} + (x + y)\text{d}{z}$; + +(2) $\int_{(1, -1, 1)}^{(1, 1, -1)}y^2z\text{d}{x} + 2xyz\text{d}{y} + xy^2\text{d}{z}$; + +**解** + +(1) 记 $u(x, y, z) = xy + yz + zx$, 则 $\int_{(0, 0, 0)}^{(1, 2, 1)}(y + z)\text{d}{x} + (z + x)\text{d}{y} + (x + y)\text{d}{z} = u(1, 2, 1) - u(0, 0, 0) = 5$. + +(2) 记 $u(x, y, z) = xy^2z$, 则 $\int_{(1, -1, 1)}^{(1, 1, -1)}y^2z\text{d}{x} + 2xyz\text{d}{y} + xy^2\text{d}{z} = u(1, 1, -1) - u(1, -1, 1) = -2$. + +## 第 8 题 + +求向量场 $\mathbf{A} = \dfrac{-y\mathbf{i} + x\mathbf{j}}{x^2 + y^2} + a\mathbf{k}$ 沿下列曲线的环量 $\Gamma = \oint_{L^{+}}\mathbf{A}\cdot\text{d}{\mathbf{r}}$. + +(1) 圆周 $\begin{cases}x^2 + y^2 = \epsilon^2, \\ z = 0, \end{cases}\epsilon > 0$; + +(2) 圆周 $\begin{cases}(x-1)^2 + y^2 = r^2, \\ z = 2,\end{cases}r > 2$. + +**解** + +(1) 做坐标变换 $\begin{cases}x = \epsilon\cos\theta, \\ y = \epsilon\sin\theta, \end{cases}$ 则 + +$$ +\begin{aligned} + \Gamma & = \oint_{L^{+}}\mathbf{A}\cdot\text{d}{\mathbf{r}} \\ + & = \int_{0}^{2\pi}\dfrac{-\epsilon\sin\theta\cdot(-\epsilon\sin\theta) + \epsilon\cos\theta\cdot\epsilon\cos\theta}{\epsilon^2}\text{d}{\theta} \\ + & = 2\pi +\end{aligned} +$$ + +(2) $X = \dfrac{-y}{x^2 + y^2}, Y = \dfrac{x}{x^2 + y^2}$. 设 (1) 中环路为 $L_1$, 本题环路为 $L_2$, $L_1$ 与 $L_2$ 构成的区域为 $D$. 由于 $\dfrac{\partial X}{\partial y} = \dfrac{y^2 - x^2}{(x^2 + y^2)^2} = \dfrac{\partial Y}{\partial x}$, 故由 Stokes 定理, + +$$ +\begin{aligned} + \oint_{L_1^{-}}\mathbf{A}\cdot\text{d}{\mathbf{r}} + \oint_{L_2^{+}}\mathbf{A}\cdot\text{d}{\mathbf{r}} = \iint\limits_{D}\left(\dfrac{\partial X}{\partial y} - \dfrac{\partial Y}{\partial x}\right)\text{d}{x}\text{d}{y} = 0 +\end{aligned} +$$ + +故 $\oint_{L_2^{+}}\mathbf{A}\cdot\text{d}{\mathbf{r}} = -\oint_{L_1^{-}}\mathbf{A}\cdot\text{d}{\mathbf{r}} = \oint_{L_1^{+}}\mathbf{A}\cdot\text{d}{\mathbf{r}} = 2\pi$. + +## 第 12 题 + +若向量场的积分与路径无关, 就称向量场为保守场, 考察下列向量场是否为保守场, 如果是, 求出相应的势函数, 并计算积分 $\int_{(4, 0, 1)}^{(2, 1, -1)}\mathbf{V}\cdot\text{d}{\mathbf{r}}$: + +(1) $\mathbf{V} = y\cos(xy)\mathbf{i} + x\cos(xy)\mathbf{j} + \sin z\mathbf{k}$; + +(3) $\mathbf{V} = (6xy + z^2)\mathbf{i} + (3x^2 - z)\mathbf{j} + (3xz^2 - y)\mathbf{k}$; + +**解** + +(1) $X = y\cos(xy), Y = x\cos(xy), Z = \sin z$, 则 + +$$ +\begin{aligned} + \rot{X, Y, Z} & = \begin{vmatrix}\mathbf{i} & \mathbf{j} & \mathbf{k} \\ \dfrac{\partial}{\partial x} & \dfrac{\partial}{\partial y} & \dfrac{\partial}{\partial z} \\ X & Y & Z\end{vmatrix} \\ + & = 0 +\end{aligned} +$$ + +因此该向量场是保守场, 且 $u(x, y, z) = \sin(xy) - \cos z$. 故 + +$$ +\begin{aligned} + \int_{(4, 0, 1)}^{(2, 1, -1)}\mathbf{V}\cdot\text{d}{\mathbf{r}} & = u(2, 1, -1) - u(4, 0, 1) \\ + & = \sin 2 +\end{aligned} +$$ + +(3) $X = 6xy + z^2, Y = 3x^2 - z, Z = 3xz^2 - y$, 则 + +$$ +\begin{aligned} + \rot{X, Y, Z} & = \begin{vmatrix}\mathbf{i} & \mathbf{j} & \mathbf{k} \\ \dfrac{\partial}{\partial x} & \dfrac{\partial}{\partial y} & \dfrac{\partial}{\partial z} \\ X & Y & Z\end{vmatrix} \\ + & = (2z - 3z^2)\mathbf{j} \\ + & \neq 0 +\end{aligned} +$$ + +因此该向量场不是保守场. diff --git a/services/homework-ans/docs/calculus-2/chapter4/exercise4-rev.md b/services/homework-ans/docs/calculus-2/chapter4/exercise4-rev.md new file mode 100644 index 0000000..e6deba3 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter4/exercise4-rev.md @@ -0,0 +1,125 @@ + +## 第 1 题 + +证明: $\left|\int_L\mathbf{V}\cdot\text{d}{\mathbf{r}}\right| \le \int_{L}\|\mathbf{V}\|\text{d}{l}$. + +**证明** + +设 $\mathbf{n}$ 为 $\mathbf{V}$ 的单位法向量, $\mathbf{t}$ 为 $\mathbf{r}$ 的切向量. 由于 $\mathbf{V}\cdot \text{d}{\mathbf{r}} = \|\mathbf{V}\|\text{d}{l}\cdot\cos\left<\mathbf{n}, \mathbf{t}\right> \le \|\mathbf{V}\|\text{d}{l}$, 故 $\left|\int_L\mathbf{V}\cdot\text{d}{\mathbf{r}}\right| \le \int_{L}\|\mathbf{V}\|\text{d}{l}$. + +## 第 2 题 + +设曲面 $S:z = f(x, y), (x, y) \in D$, $S^{+}$ 的法方向向上, $F \in C(\mathbb{R}^3)$, 求证: + +(1) $\iint\limits_{S^{+}}F(x, y, z)\text{d}{y}\wedge\text{d}{z} = -\iint\limits_{D}F(x, y, f(x, y))\dfrac{\partial f}{\partial x}\text{d}{x}\text{d}{y}$; + +(2) $\iint\limits_{S^{+}}F(x, y, z)\text{d}{z}\wedge\text{d}{x} = -\iint\limits_{D}F(x, y, f(x, y))\dfrac{\partial f}{\partial y}\text{d}{x}\text{d}{y}$. + +**证明** + +(1) $\mathbf{n} = (-f_x, -f_y, 1)$ 为 $S^{+}$ 的法向量. + +$$ +\begin{aligned} + \iint\limits_{S^{+}}F(x, y, z)\text{d}{y}\wedge\text{d}{z} & = \iint\limits_{D}(F, 0, 0)\cdot \dfrac{\mathbf{n}}{\left|\mathbf{n}\right|}\text{d}{S} \\ + & = \iint\limits_{D}F\cdot\dfrac{-f_x}{\left|\mathbf{n}\right|}\cdot \left|\mathbf{n}\right|\text{d}{x}\text{d}{y} \\ + & = -\iint\limits_{D}F(x, y, f(x, y))\dfrac{\partial f}{\partial x}\text{d}{x}\text{d}{y} +\end{aligned} +$$ + +(2) 由 (1) 的对称性知命题得证. + +## 第 3 题 + +设闭曲线 $L:x=x(t), y = y(t), t\in[\alpha, \beta]$, $L^{+}$ 的方向为 $t$ 增大的方向, 证明: 由 $L$ 围成区域的面积可以表示成 $S = \dfrac{1}{2}\int_{\alpha}^{\beta}\begin{vmatrix}x(t) & y(t) \\ x'(t) & y'(t)\end{vmatrix}\text{d}{t}$. + +**证明** + +由于 + +$$ +\begin{aligned} + S & = \oint_{L^{+}}x\text{d}{y} - y\text{d}{x} \\ + & = \int_{\alpha}^{\beta}(x(t)y'(t) - y(t)x'(t))\text{d}{t} \\ + & = \dfrac{1}{2}\int_{\alpha}^{\beta}\begin{vmatrix}x(t) & y(t) \\ x'(t) & y'(t)\end{vmatrix}\text{d}{t} +\end{aligned} +$$ + +故命题得证. + +## 第 4 题 + +设 $L\subset \mathbb{R}^2$ 为光滑闭曲线, 逆时针为正向, $\mathbf{n}$ 为 $L$ 的外法线单位向量, $\mathbf{a}$ 为一固定向量, 求证: $\oint_{L}\cos\left<\mathbf{n}, \mathbf{a}\right>\text{d}{l} = 0$. + +**证明** + +不妨设 $\mathbf{a} = (a_x, a_y)$ 为单位向量. 设 $L$ 围成的区域为 $D$. $\mathbf{n} = \left(-\dfrac{\text{d}{y}}{\left|\text{d}{l}\right|}, \dfrac{text{d}{x}}{\left|\text{d}{l}\right|}\right)$. 由 Green 定理 + +$$ +\begin{aligned} + \oint_{L}\cos\left<\mathbf{n}, \mathbf{a}\right>\text{d}{l} & = \oint_{L}a_y\text{d}{x} - a_x\text{d}{y} \\ + & = \iint\limits_{D}0\text{d}{x}\text{d}{y} \\ + & = 0 +\end{aligned} +$$ + +## 第 5 题 + +设 $S$ 为闭曲面, $\mathbf{a}$ 为常向量, $\mathbf{n} = (\cos\alpha, \cos\beta, \cos\gamma)$ 为 $S$ 的单位法向量, 证明: $\oint_{S}\cos\left<\mathbf{n}, \mathbf{a}\right>\text{d}{S} = 0$. % 这里符号有问题, 应该是 $\oiint$ + +**证明** + +不妨设 $\mathbf{a} = (a_x, a_y)$ 为单位向量. 设 $S$ 为成的区域为 $\Omega$. 由 Gauss 定理 + +$$ +\begin{aligned} + \oint_{S}\cos\left<\mathbf{n}, \mathbf{a}\right>\text{d}{S} & = \oint_{S}(a_x\cos\alpha, a_y\cos\beta, a_z\cos\gamma)\cdot\text{d}{S} \\ + & = \iiint\limits_{\Omega}0\text{d}{x}\text{d}{y}\text{d}{z} \\ + & = 0 +\end{aligned} +$$ + +## 第 8 题 + +设 $\Omega \subset \mathbb{R}^3$ 是一空间区域, $\partial\Omega$ 为逐段光滑曲线, $\mathbf{n}$ 为 $\Omega$ 的单位外法向, $u, v \in C^2(\Omega)$, 证明: + +(1) $\oint\limits_{\partial\Omega}\dfrac{\partial u}{\partial \mathbf{n}}\text{d}{S} = \iiint\limits_{\Omega}\Delta u\text{d}{x}\text{d}{y}\text{d}{z}$; % 这里符号有问题, 应该是 $\oiint$ + +(2) $\oint\limits_{\partial\Omega} v\dfrac{\partial u}{\partial \mathbf{n}}\text{d}{S} = \iiint\limits_{\Omega}v\Delta u\text{d}{x}\text{d}{y}\text{d}{z} + \iiint\limits_{\Omega}\nabla u\cdot \nabla v\text{d}{x}\text{d}{y}\text{d}{z}$ % 这里符号有问题, 应该是 $\oiint$ + +(3) $\oint\limits_{\partial\Omega}\begin{vmatrix}\dfrac{\partial u}{\partial \mathbf{n}} & \dfrac{\partial v}{\partial \mathbf{n}} \\ u & v\end{vmatrix}\text{d}{S} = \iiint\limits_{\Omega}\begin{vmatrix}\Delta u & \Delta v \\ u & v\end{vmatrix}\text{d}{x}\text{d}{y}\text{d}{z}$, % 这里符号有问题, 应该是 $\oiint$ + +其中 $\Delta = \dfrac{\partial^2}{\partial x^2} + \dfrac{\partial^2}{\partial y^2} + \dfrac{\partial^2}{\partial z^2}, \nabla = \dfrac{\partial}{\partial x}\mathbf{i} + \dfrac{\partial}{\partial y}\mathbf{j} + \dfrac{\partial}{\partial z}\mathbf{k}$. + +**证明** % 这里符号有问题, 应该是 $\oiint$ + +(1) 设 $\mathbf{n} = (\cos\alpha, \cos\beta, \cos\gamma)$. 由 Gauss 定理, + +$$ +\begin{aligned} + \oint_{\partial D}\dfrac{\partial u}{\partial \mathbf{n}}\text{d}{S} & = \oint_{\partial D}(\dfrac{\partial u}{\partial x}\cos\alpha, \dfrac{\partial u}{\partial y}\cos\beta, \dfrac{\partial u}{\partial z}\cos\gamma) \cdot\text{d}{S} \\ + & = \iiint\limits_{D}\left(\dfrac{\partial^2u}{\partial x^2} + \dfrac{\partial^2u}{\partial y^2} + \dfrac{\partial^2u}{\partial z^2}\right)\text{d}{x}\text{d}{y}\text{d}{z} \\ + & = \iiint\limits_{D}\Delta u\text{d}{x}\text{d}{y}\text{d}{z} +\end{aligned} +$$ + +(2) 由 Gauss 定理, + +$$ +\begin{aligned} + \oint_{\partial D}v\dfrac{\partial u}{\partial \mathbf{n}}\text{d}{S} & = \oint_{\partial D}(v\dfrac{\partial u}{\partial x}\cos\alpha, v\dfrac{\partial u}{\partial y}\cos\beta, v\dfrac{\partial u}{\partial z}\cos\gamma) \cdot\text{d}{S} \\ + & = \iint\limits_{D}\left(\dfrac{\partial v}{\partial x}\dfrac{\partial u}{\partial x} + v\dfrac{\partial^2u}{\partial x^2} + \dfrac{\partial v}{\partial y}\dfrac{\partial u}{\partial y} + v\dfrac{\partial^2u}{\partial y^2} + \dfrac{\partial v}{\partial z}\dfrac{\partial u}{\partial z} + v\dfrac{\partial^2u}{\partial z^2}\right)\text{d}{x}\text{d}{y}\text{d}{z} \\ + & = \iiint\limits_{\Omega}v\Delta u\text{d}{x}\text{d}{y}\text{d}{z} + \iiint\limits_{\Omega}\nabla u\cdot \nabla v\text{d}{x}\text{d}{y}\text{d}{z} +\end{aligned} +$$ + +(3) 由 (2) 知, + +$$ +\begin{aligned} + \oint_{\partial D}\begin{vmatrix}\dfrac{\partial u}{\partial \mathbf{n}} & \dfrac{\partial v}{\partial \mathbf{n}} \\ u & v\end{vmatrix}\text{d}{l} & = \oint_{\partial D}v\dfrac{\partial u}{\partial \mathbf{n}}\text{d}{l} - \oint_{\partial D}u\dfrac{\partial v}{\partial \mathbf{n}}\text{d}{l} \\ + & = \left(\iint\limits_{D}v\Delta u\text{d}{x}\text{d}{y}\text{d}{z} + \iint\limits_{D}\nabla u\cdot \nabla v\text{d}{x}\text{d}{y}\text{d}{z}\right) - \left(\iint\limits_{D}u\Delta v\text{d}{x}\text{d}{y}\text{d}{z} + \iint\limits_{D}\nabla v\cdot \nabla u\text{d}{x}\text{d}{y}\text{d}{z}\right) \\ + & = \iint\limits_{D}v\Delta u\text{d}{x}\text{d}{y}\text{d}{z} - \iint\limits_{D}u\Delta v\text{d}{x}\text{d}{y}\text{d}{z} \\ + & = \iint\limits_{D}\begin{vmatrix}\Delta u & \Delta v \\ u & v\end{vmatrix}\text{d}{x}\text{d}{y}\text{d}{z} +\end{aligned} +$$ diff --git a/services/homework-ans/docs/calculus-2/chapter5/exercise5-1.md b/services/homework-ans/docs/calculus-2/chapter5/exercise5-1.md new file mode 100644 index 0000000..86b6b7c --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter5/exercise5-1.md @@ -0,0 +1,93 @@ + +## 第 2 题 + +级数 $\sum\limits_{n = 1}^{\infty}u_n$ 的部分和序列 $S_n$ 满足 $\lim\limits_{n \to \infty}S_{2n + 1}$ 存在, $\lim\limits_{n\to \infty}u_n = 0$, 证明: $\sum\limits_{n = 1}^{\infty}u_n$ 收敛. + +**证明** + +设 $\lim\limits_{n\to\infty}S_{2n + 1} = L$. 由于 $\lim\limits_{n\to\infty}S_{2n} = \lim\limits_{n \to \infty}(S_{2n + 1} - u_{2n + 1}) = \lim\limits_{n \to \infty}S_{2n + 1} - \lim\limits_{n \to \infty}u_{2n + 1} = L$, 故 $\sum\limits_{n = 1}^{\infty}u_n = \lim\limits_{n\to\infty}S_{2n + 1} = \lim\limits_{n\to\infty}S_{2n} = L$, 级数收敛. + +## 第 3 题 + +已知级数 $\sum\limits_{n = 1}^{\infty}u_n$ 的部分和序列 $S_n = \dfrac{2n}{n + 1}, n = 1, 2, \cdots$, 求: + +(1) $u_n$ 的通项公式; + +(2) 判断 $\sum\limits_{n = 1}^{\infty}u_n$ 的收敛性. + +**解** + +(1) 当 $n = 1$ 时, $u_1 = S_1 = 1$. 当 $n \ge 2$ 时, $u_n = S_{n} - S_{n - 1} = \dfrac{2n}{n + 1} - \dfrac{2(n - 1)}{n} = \dfrac{2}{n(n + 1)}$. 因此 $u_n = \dfrac{2}{n(n + 1)}(n \in \mathbb{N^*})$. + +(2) 由题知 $\sum\limits_{n = 1}^{\infty}u_n = \lim\limits_{n \to \infty}S_n = \lim\limits_{n \to \infty}\dfrac{2n}{n + 1} = 2$. 该级数收敛. + +## 第 4 题 + +已知级数 $\sum\limits_{n = 1}^{\infty}u_n$ 中 $u_n > 0$, 证明: + +(1) $\sum\limits_{n = 1}^{\infty}u_n$ 收敛 $\iff$ 级数 $(u_1 + \cdots + u_{n_1}) + (u_{n_1 + 1} + \cdots + u_{n_2}) + \cdots + (u_{n_{k-1} + 1} + \cdots + u_{n_k}) + \cdots$ 收敛; + +(2) $\sum\limits_{n = 1}^{\infty}u_n$ 收敛 $\implies$ $\sum\limits_{n = 1}^{\infty}u_{2n + 1}$ 收敛. + +**证明** + +(1) $\implies$: 设 $\sum\limits_{n = 1}^{\infty}u_n$ 的部分和数列为 $\{S_n\}$, 则新的级数的部分和数列为 $\{S_{n_k}\}$, $\{S_{n_k}\}$ 为 $\{S_n\}$ 的子列, 有相同的收敛性, 且收敛到同一数. + +$\impliedby$: 取 $n_k = k$, 则得证. + +(2) 由于 $\sum\limits_{n = 1}^{\infty}u_n$ 收敛, 所以 $\forall \epsilon > 0, \exists N \in \mathbb{N^*}, \forall n > N, \forall p \in \mathbb{N^*}$, 有 $\left|\sum\limits_{k = n + 1}^{n + p}u_k\right| < \epsilon$. 对 $n'= 2n+2 > N, p' = 2p - 1 > 0$, 有 $\left|\sum\limits_{k = 2n + 3}^{2n + 2p + 1}u_k\right| < \epsilon$. 因此 $\left|\sum\limits_{k = n + 1}^{n + p}u_{2k + 1}\right| < \left|\sum\limits_{k = 2n + 3}^{2n + 2p + 1}u_k\right| < \epsilon$. 因此 $\sum\limits_{n = 1}^{\infty}u_{2n + 1}$ 收敛. + +## 第 5 题 + +设数列 $\{u_n\}$ 满足 $\lim\limits_{n \to \infty}nu_n = 0$, 证明: 级数 $\sum\limits_{n = 1}^{\infty}(n+1)(u_{n+1}-u_n)$ 收敛等价于 $\sum\limits_{n = 1}^{\infty}u_n$ 收敛. + +**证明** + +由于 $\lim\limits_{n \to \infty}nu_n = 0$, 故 $\exists N \in \mathbb{N}$, $\forall \epsilon > 0, \forall n \ge N$, 有 $\left|nu_n\right| < \dfrac{\epsilon}{3}$. $\forall p > 0$, 显然 $n + p \ge N$, 因此也有 $\left|(n + p + 1)u_{n + p + 1}\right| < \dfrac{\epsilon}{3}$. 对上述 $\epsilon > 0$, 考虑 $\left|\sum\limits_{k = n + 1}^{n + p}(k + 1)(u_{k + 1} - u_k)\right| = \left|(n + p + 1)u_{n + p + 1} - (n + 1)u_{n + 1} - \sum\limits_{k = n + 1}^{n + p}u_k\right|$. + +若 $\sum\limits_{n = 1}^{\infty}(n+1)(u_{n+1}-u_n)$ 收敛, 则 $\left|\sum\limits_{k = n + 1}^{n + p}(k + 1)(u_{k + 1} - u_k)\right| = \left|(n + p + 1)u_{n + p + 1} - (n + 1)u_{n + 1} - \sum\limits_{k = n + 1}^{n + p}u_k\right| < \epsilon$, 则 $\left|\sum\limits_{k = n + 1}^{n + p}u_k\right| < 3\epsilon$. 这说明 $\sum\limits_{n = 1}^{\infty}u_n$ 收敛. + +反之, 若 $\sum\limits_{n = 1}^{\infty}u_n$ 收敛, 则 $\left|\sum\limits_{k = n + 1}^{n + p}(k + 1)(u_{k + 1} - u_k)\right| = \left|(n + p + 1)u_{n + p + 1} - (n + 1)u_{n + 1} - \sum\limits_{k = n + 1}^{n + p}u_k\right| < 3\epsilon$, 这说明 $\sum\limits_{n = 1}^{\infty}(n+1)(u_{n+1}-u_n)$ 收敛. + +命题得证. + +## 第 6 题 + +利用定义判断下列级数的敛散性, 对收敛的级数求和. + +(1) $\sum\limits_{n = 1}^{\infty}100\left(\dfrac{1}{4}\right)^{n-1}$; + +(3) $\sum\limits_{n = 1}^{\infty}\dfrac{1}{(2n-1)(2n + 3)}$; + +(5) $\sum\limits_{n = 1}^{\infty}\dfrac{(-1)^{n}n^3}{2n^3 + n}$; + +(7) $\sum\limits_{n = 1}^{\infty}\arctan{\dfrac{1}{2n^2}}$; + +(9) $\sum\limits_{n = 1}^{\infty}\dfrac{1}{\sqrt[n]{n}}$. + +**解** + +(1) 由于 $S_n = 100 \times 1 \times\dfrac{1 - \left(\frac{1}{4}\right)^{n}}{1 - \frac{1}{4}} = \dfrac{400}{3}\left(1 - 4^{-n}\right)$, 因此 $\sum\limits_{n = 1}^{\infty}100\left(\dfrac{1}{4}\right)^{n-1} = \lim\limits_{n \to \infty}S_n = \dfrac{400}{3}$. + +(3) 由于 $S_n = \dfrac{1}{4}\sum\limits_{k = 1}^{n}\left(\dfrac{1}{2k - 1} - \dfrac{1}{2k + 3}\right) = \dfrac{1}{4}\left(\dfrac{4}{3} - \dfrac{1}{2n + 1} - \dfrac{1}{2n + 3}\right)$, 因此 $\sum\limits_{n = 1}^{\infty}\dfrac{1}{(2n-1)(2n + 3)} = \lim\limits_{n\to\infty}S_n = \dfrac{1}{3}$. + +(5) 由于 $\lim\limits_{n \to \infty}u_n$ 不存在, 所以该级数发散. + +(7) 由于 $\arctan{\dfrac{1}{2n^2}} = \arctan{\dfrac{1}{2n - 1}} - \arctan{\dfrac{1}{2n + 1}}$, 所以 $S_n = \sum\limits_{k = 1}^{n}\left(\arctan\dfrac{1}{2k - 1} - \arctan\dfrac{1}{2k + 1}\right) = \arctan 1 - \arctan\dfrac{1}{2n + 1} = \dfrac{\pi}{4} - \arctan\dfrac{1}{2n + 1}$. 故 $\sum\limits_{n = 1}^{\infty}\arctan{\dfrac{1}{2n^2}} = \lim\limits_{n \to \infty}S_n = \dfrac{\pi}{4}$. + +(9) 由于 $\sum\limits_{n = 1}^{\infty}\dfrac{1}{\sqrt[n]{n}} \ge \sum\limits_{n = 1}^{\infty}\dfrac{1}{n}$, 且后者发散, 故级数发散. + +## 第 7 题 + +求级数 $\sum\limits_{n = 1}^{\infty}\dfrac{1}{n(n+m)}(m > 0, m \in \mathbb{Z})$ 的和. + +**解** + +$$ +\begin{aligned} + \sum\limits_{n = 1}^{\infty}\dfrac{1}{n(n+m)} & = \dfrac{1}{m}\sum\limits_{n = 1}^{\infty}\left(\dfrac{1}{n} - \dfrac{1}{n + m}\right) \\ + & = \dfrac{1}{m}\lim\limits_{n \to \infty}\sum\limits_{k = 1}^{n}\left(\dfrac{1}{n} - \dfrac{1}{n + m}\right) \\ + & = \dfrac{1}{m}\lim\limits_{n \to \infty}\left(1 + \dfrac{1}{2} + \cdots + \dfrac{1}{m} - \dfrac{1}{n + 1} - \dfrac{1}{n + 2} - \cdots - \dfrac{1}{n + m}\right) \\ + & = \dfrac{1}{m}\sum\limits_{k = 1}^{m}\dfrac{1}{k} +\end{aligned} +$$ diff --git a/services/homework-ans/docs/calculus-2/chapter5/exercise5-2.md b/services/homework-ans/docs/calculus-2/chapter5/exercise5-2.md new file mode 100644 index 0000000..2ed9a04 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter5/exercise5-2.md @@ -0,0 +1,126 @@ + +## 第 1 题 + +判断下列级数的敛散性. + +(1) $\sum\limits_{n = 1}^{\infty}\dfrac{1}{(2n - 1)2^{n-1}}$; + +(3) $\sum\limits_{n = 2}^{\infty}\dfrac{1}{\ln n}$; + +(5) $\sum\limits_{n = 1}^{\infty}\left(\dfrac{1 + n^2}{1 + n^3}\right)^2$; + +(7) $\sum\limits_{n = 1}^{\infty}\dfrac{1}{\sqrt{n}}\ln\left(\dfrac{n + 1}{n - 1}\right)$; + +**解** + +(1) 由于 $\lim\limits_{n \to \infty}\dfrac{u_{n + 1}}{u_n} = \dfrac{2n - 1}{2(2n + 1)} = \dfrac{1}{2} < 1$, 故由比值判别法知 $\sum\limits_{n = 1}^{\infty}\dfrac{1}{(2n - 1)2^{n-1}}$ 收敛. + +(3) 由于 $\ln n \ge n - 1$, 因此 $\sum\limits_{n = 2}^{\infty}\dfrac{1}{\ln n} \ge \sum\limits_{n = 1}^{\infty}\dfrac{1}{n}$. 显然 $\sum\limits_{n = 1}^{\infty}\dfrac{1}{n}$ 发散. 故由比较判别法知 $\sum\limits_{n = 2}^{\infty}\dfrac{1}{\ln n}$ 发散. + +(5) 由于 $\dfrac{1 + n^2}{1 + n^3} \le \dfrac{1}{n - 1}, \forall n \ge 2$, 所以 $\sum\limits_{n = 1}^{\infty}\left(\dfrac{1 + n^2}{1 + n^3}\right)^2 \ge 1 + \sum\limits_{n = 2}^{\infty}\dfrac{1}{(n - 1)^2}$. 显然 $\sum\limits_{n = 2}^{\infty}\dfrac{1}{(n - 1)^2}$ 收敛. 故由比较判别法知 $\sum\limits_{n = 1}^{\infty}\left(\dfrac{1 + n^2}{1 + n^3}\right)^2$ 收敛. + +(7) 由于 $\lim\limits_{n \to \infty}n^{\frac{3}{2}} \cdot u_n = \lim\limits_{n \to \infty}n^{\frac{3}{2}} \cdot \dfrac{1}{\sqrt{n}}\ln\left(\dfrac{n + 1}{n - 1}\right) = \lim\limits_{n \to \infty}n\ln\left(\dfrac{n + 1}{n - 1}\right) = 2$, 故由推论 5.2.1 知 $\sum\limits_{n = 1}^{\infty}\dfrac{1}{\sqrt{n}}\ln\left(\dfrac{n + 1}{n - 1}\right)$ 收敛. + +## 第 2 题 + +判断下列级数的敛散性. + +(1) $\sum\limits_{n = 1}^{\infty}\dfrac{2^n}{(2n - 1)!}$; + +(3) $\sum\limits_{n = 1}^{\infty}\dfrac{3^nn}{n^n}$; + +(5) $\sum\limits_{n = 1}^{\infty}n^3\sin\dfrac{\pi}{3^n}$; + +**解** + +(1) 由于 $\lim\limits_{n \to \infty}\dfrac{u_{n + 1}}{u_n} = \lim\limits_{n \to \infty}\dfrac{2}{2n + 1} = 0 < 1$, 故由比值判别法知 $\sum\limits_{n = 1}^{\infty}\dfrac{2^n}{(2n - 1)!}$ 收敛. + +(3) 由于 $\lim\limits_{n \to \infty}\sqrt[n]{u_n} = \dfrac{3}{n}\sqrt[n]{n} = 0 < 1$, 故由根值判别法知 $\sum\limits_{n = 1}^{\infty}\dfrac{3^nn}{n^n}$ 收敛. + +(5) 由于 $\sum\limits_{n = 1}^{\infty}n^3\sin\dfrac{\pi}{3^n} < \sum\limits_{n = 1}^{\infty}\dfrac{\pi n^3}{3^n}$, 且显然 $\sum\limits_{n = 1}^{\infty}\dfrac{\pi n^3}{3^n}$ 收敛, 故由比较判别法知 $\sum\limits_{n = 1}^{\infty}n^3\sin\dfrac{\pi}{3^n}$ 收敛. + +## 第 3 题 + +判断下列级数的敛散性. + +(2) $\sum\limits_{n = 1}^{\infty}\dfrac{1}{3^n}\left(1 + \dfrac{1}{n}\right)^{n^2}$; + +(4) $\sum\limits_{n = 1}^{\infty}\dfrac{1}{\sqrt[3]{n+1}}\ln\dfrac{n + 2}{n}$; + +(6) $\sum\limits_{n = 1}^{\infty}\dfrac{\ln n!}{n!}$; + +**解** + +(2) 由于 $\sum\limits_{n = 1}^{\infty}\dfrac{1}{3^n}\left(1 + \dfrac{1}{n}\right)^{n^2} \le \sum\limits_{n = 1}^{\infty}\left(\dfrac{e}{3}\right)^n$ 且显然 $\sum\limits_{n = 1}^{\infty}\left(\dfrac{e}{3}\right)^n$ 收敛, 故由比较判别法知 $\sum\limits_{n = 1}^{\infty}\dfrac{1}{3^n}\left(1 + \dfrac{1}{n}\right)^{n^2}$ 收敛. + +(4) 由于 $\lim\limits_{n \to \infty}n^{\frac{4}{3}}\cdot u_n = \lim\limits_{n \to \infty}\sqrt[3]{\dfrac{n}{n + 1}}\cdot n\ln\dfrac{n + 2}{n} = \lim\limits_{n \to \infty}\sqrt[3]{\dfrac{n}{n + 1}}\cdot \lim\limits_{n \to \infty}n\ln\dfrac{n + 2}{n} = 2$. 故由推论 5.2.1 知 $\sum\limits_{n = 1}^{\infty}\dfrac{1}{\sqrt[3]{n+1}}\ln\dfrac{n + 2}{n}$ 收敛. + +(6) 由于 $\sum\limits_{n = 1}^{\infty}\dfrac{\ln n!}{n!} < \sum\limits_{n = 1}^{\infty}\dfrac{n}{n!} < 2 + \sum\limits_{n = 3}^{\infty}\dfrac{1}{(n - 1)(n - 2)}$, 且显然 $\sum\limits_{n = 3}^{\infty}\dfrac{1}{(n - 1)(n - 2)}$ 收敛, 故由比较判别法知 $\sum\limits_{n = 1}^{\infty}\dfrac{\ln n!}{n!}$ 收敛. + +## 第 4 题 + +设 $u_n, v_n > 0$, $\dfrac{u_{n + 1}}{u_n} \le \dfrac{v_{n + 1}}{v_n}$, 证明: $\sum\limits_{n = 1}^{\infty}v_n$ 收敛, 则 $\sum\limits_{n = 1}^{\infty}u_n$ 收敛. + +**证明** + +由于 $\dfrac{u_{n + 1}}{u_n} \le \dfrac{v_{n + 1}}{v_n}$, 故将左式从 $n = 1$ 连续乘到 $n = k$ 得到 $\dfrac{u_{k + 1}}{u_1} \le \dfrac{v_{k + 1}}{v_1}$. 由于 $\sum\limits_{n = 1}^{\infty}v_n$ 收敛, 故 $\sum\limits_{n = 1}^{\infty}\dfrac{u_1}{v_1}v_n$ 收敛. 而 $\sum\limits_{n = 1}^{\infty}u_{n} \le \sum\limits_{n = 1}^{\infty}\dfrac{u_1}{v_1}v_n$. 由比较判别法知 $\sum\limits_{n = 1}^{\infty}u_n$ 收敛. + +## 第 5 题 + +设 $u_n > 0$, 数列 $\{nu_n\}$ 有界, 证明: $\sum\limits_{n = 1}^{\infty}\dfrac{u_n}{n}$ 收敛. + +**证明** + +设 $nu_n \le M, \forall n \in \mathbb{N}^{*}$, 因此 $u_n \le \dfrac{M}{n}$. 则 $\sum\limits_{n = 1}^{\infty}\dfrac{u_n}{n} \le \sum\limits_{n = 1}^{\infty}\dfrac{M}{n^2}$. 显然 $\sum\limits_{n = 1}^{\infty}\dfrac{M}{n^2}$ 收敛. 由比较判别法知 $\sum\limits_{n = 1}^{\infty}\dfrac{u_n}{n}$ 收敛. + +## 第 6 题 + +设 $u_n, v_n > 0$, 且 $\sum\limits_{n = 1}^{\infty}v_n, \sum\limits_{n = 1}^{\infty}u_n$ 均发散, 考察 $\sum\limits_{n = 1}^{\infty}\max\{v_n, u_n\}$ 和 $\sum\limits_{n = 1}^{\infty}\min\{v_n, u_n\}$ 的敛散性. + +**解** + +由于 $\sum\limits_{n = 1}^{\infty}\max\{v_n, u_n\} \ge \sum\limits_{n = 1}^{\infty}u_n$ 且 $\sum\limits_{n = 1}^{\infty}\max\{v_n, u_n\} \ge \sum\limits_{n = 1}^{\infty}v_n$, 故由比较判别法知 $\sum\limits_{n = 1}^{\infty}\max\{v_n, u_n\}$ 发散. + +取 $u_n = v_n = n$, 则此时 $\sum\limits_{n = 1}^{\infty}\min\{v_n, u_n\} = \sum\limits_{n = 1}^{\infty}n$ 发散. 取 $u_n = \begin{cases}n, & n = 2k - 1, \\ \dfrac{1}{n^2}, & n = 2k\end{cases}, v_n = \begin{cases}\dfrac{1}{n^2}, & n = 2k - 1, \\ n, & n = 2k\end{cases}k \in \mathbb{N}^{*}$, 则此时 $\sum\limits_{n = 1}^{\infty}\min\{v_n, u_n\} = \sum\limits_{n = 1}^{\infty}\dfrac{1}{n^2}$ 收敛. 因此 $\sum\limits_{n = 1}^{\infty}\min\{v_n, u_n\}$ 既可能发散, 也可能收敛. + +## 第 7 题 + +若 $\sum\limits_{n = 1}^{\infty}u_n(u_n>0)$ 收敛, 则 $\lim\limits_{n \to \infty}\dfrac{u_{n + 1}}{u_n} = l < 1$ 正确吗? 请举例说明. + +**解** + +不正确. 考虑 $u_n = \dfrac{1}{n^2}$, 则 $\sum\limits_{n = 1}^{\infty}u_n$ 收敛, 但 $\lim\limits_{n \to \infty}\dfrac{u_{n + 1}}{u_n} = \lim\limits_{n \to \infty}\dfrac{\frac{1}{(n + 1)^2}}{\frac{1}{n^2}} = \lim\limits_{n \to \infty}\dfrac{n^2}{(n+1)^2} = 1$, 不小于 $1$. 矛盾. + +## 第 8 题 + +利用 Raabe 判别法, 讨论下列级数的敛散性. + +(1) $\sum\limits_{n = 1}^{\infty}\dfrac{\sqrt{n!}}{(1 + \sqrt{1})(1 + \sqrt{2})\cdots(1 + \sqrt{n})}$; + +(2) $\sum\limits_{n = 1}^{\infty}\dfrac{n!n^{-p}}{q(q + 1)(q + 2)\cdots(q + n)}, p, q > 0$. + +**解** + +(1) $n\left(\dfrac{u_n}{u_{n + 1}} - 1\right) = n\left(\dfrac{1 + \sqrt{n + 1}}{\sqrt{n + 1}} - 1\right) = \dfrac{n}{\sqrt{n + 1}}$. 取 $\rho = 2$, 则当 $n \ge 100$ 时有 $\dfrac{n}{\sqrt{n + 1}} \ge \rho = 2$. 由 Raabe 判别法知 $\sum\limits_{n = 1}^{\infty}\dfrac{\sqrt{n!}}{(1 + \sqrt{1})(1 + \sqrt{2})\cdots(1 + \sqrt{n})}$ 收敛. + +(2) + +$$ +\begin{aligned} + n\left(\dfrac{u_n}{u_{n + 1}} - 1\right) & = n\left(\dfrac{q + n + 1}{n + 1}\cdot \left(1 - \dfrac{1}{n + 1}\right)^{-p} - 1\right) \\ + & = n\left(\dfrac{q + n + 1}{n + 1}\cdot\left(1 + \dfrac{p}{n + 1} + O\left(\dfrac{1}{(n + 1)^2}\right)\right) - 1\right) \\ + & = \dfrac{n(p + q)}{n + 1} + O\left(\dfrac{1}{n}\right) +\end{aligned} +$$ + +因此, 由 Raabe 判别法知, 当 $p + q > 1$ 时该级数收敛, 当 $p + q \le 1$ 时该级数发散. + +## 第 10 题 + +设 $\sum\limits_{n = 1}^{\infty}u_n$ 为正项级数, 证明: $\sum\limits_{n = 1}^{\infty}u_n$ 与 $\sum\limits_{n = 1}^{\infty}\dfrac{u_n}{u_n + 1}$ 的敛散性相同. + +**证明** + +若 $\sum\limits_{n = 1}^{\infty}u_n$ 收敛, 则 $\lim\limits_{n \to \infty}u_n = 0$. 此时 $\lim\limits_{n \to \infty} \dfrac{u_n}{\frac{u_n}{u_n + 1}} = \lim\limits_{n \to \infty}(u_n + 1) = 1$, 由比值判别法知 $\sum\limits_{n = 1}^{\infty}\dfrac{u_n}{u_n + 1}$ 收敛. + +若 $\sum\limits_{n = 1}^{\infty}\dfrac{u_n}{u_n + 1}$ 收敛, 则 $\lim\limits_{n \to \infty}\dfrac{u_n}{u_n + 1} = 0$, 这说明 $\lim\limits_{n \to \infty}u_n = 0$. 此时 $\lim\limits_{n \to \infty} \dfrac{u_n}{\frac{u_n}{u_n + 1}} = \lim\limits_{n \to \infty}(u_n + 1) = 1$, 由比值判别法知 $\sum\limits_{n = 1}^{\infty}u_n$ 收敛. diff --git a/services/homework-ans/docs/calculus-2/chapter5/exercise5-3.md b/services/homework-ans/docs/calculus-2/chapter5/exercise5-3.md new file mode 100644 index 0000000..e07e82e --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter5/exercise5-3.md @@ -0,0 +1,168 @@ + +## 第 1 题 + +举出相应的例子. + +(1) $u_n > 0, \lim\limits_{n \to \infty}u_n = 0$, 但 $\sum\limits_{n = 1}^{\infty}(-1)^{n}u_n$ 发散; + +(2) $u_n > 0$, $\{u_n\}$ 单调递减, 但 $\sum\limits_{n = 1}^{\infty}(-1)^{n}u_n$ 发散. + +**解** + +(1) 构造 $u_n = \begin{cases}\dfrac{2}{k}, & n = 2k-1, \\ \dfrac{1}{k}, & n = 2k,\end{cases}$ 则 $\lim\limits_{n \to \infty}u_n = 0$. 但 $\sum\limits_{n = 1}^{\infty}(-1)^{n}u_n = \sum\limits_{k = 1}^{\infty}\dfrac{1}{k}$ 发散. + +(2) 构造 $u_n = 1 + \dfrac{1}{n}$, 则 $\sum\limits_{n = 1}^{\infty}(-1)^{n}u_n = \sum\limits_{n = 1}^{\infty}(-1)^n + \sum\limits_{n = 1}^{\infty}\dfrac{(-1)^n}{n}$. 由于前者发散, 后者收敛, 故两者之和发散. + +## 第 3 题 + +若级数 $\sum\limits_{n = 1}^{\infty}u_n$ 收敛, 且 $\lim\limits_{n \to \infty}\dfrac{u_n}{v_n} = 1$, 能否断定级数 $\sum\limits_{n = 1}^{\infty}v_n$ 收敛? + +**解** + +不可以. 构造 $u_n = \dfrac{(-1)^n}{\sqrt{n}}, v_n = \dfrac{(-1)^n}{\sqrt{n}} + \dfrac{1}{n}$, 则满足 + +$$ +\begin{aligned} + \lim\limits_{n \to \infty}\dfrac{u_n}{v_n} & = \lim\limits_{n \to \infty}\dfrac{\frac{(-1)^n}{\sqrt{n}}}{\frac{(-1)^n}{\sqrt{n}} + \frac{1}{n}} \\ + & = \lim\limits_{n \to \infty} \dfrac{\sqrt{n}}{\sqrt{n} + (-1)^n} \\ + & = 1 +\end{aligned} +$$ + +但显然 $\sum\limits_{n = 1}^{\infty}v_n$ 不收敛. + +## 第 4 题 + +判断下列级数绝对收敛、条件收敛还是发散. + +(1) $\sum\limits_{n = 1}^{\infty}\dfrac{(-1)^n}{\sqrt{n + 1}}$; + +(3) $\sum\limits_{n = 1}^{\infty}(-1)^{n}\dfrac{n}{n + 1}$; + +(5) $\sum\limits_{n = 1}^{\infty}\dfrac{1}{2^n}\sin\dfrac{n\pi}{4}$; + +(7) $\sum\limits_{n = 1}^{\infty}(-1)^{n}\dfrac{2^{n^2}}{n!}$; + +(9) $\sum\limits_{n = 1}^{\infty}(-1)^n(\sqrt{n + 1} - \sqrt{n})$; + +(11) $\sum\limits_{n = 2}^{\infty}\dfrac{(-1)^n}{\sqrt{n + (-1)^n}}$; + +(13) $\dfrac{1}{\sqrt{2} - 1} + \dfrac{1}{\sqrt{2} + 1} + \dfrac{1}{\sqrt{3} - 1} + \dfrac{1}{\sqrt{3} + 1} + \cdots + \dfrac{1}{\sqrt{n} - 1} + \dfrac{1}{\sqrt{n} + 1} + \cdots$; + +(14) $1 - \ln 2 + \dfrac{1}{2} - \dfrac{3}{2} + \dfrac{1}{n} - \ln\dfrac{n + 1}{n} + \cdots$. + +**解** + +(1) 由于 $\sum\limits_{n = 1}^{\infty}\dfrac{(-1)^n}{\sqrt{n + 1}}$ 为 Leibniz 级数, 故该级数收敛. 而 + +$$ +\sum\limits_{n = 1}^{\infty}\left|(-1)^{n}\dfrac{1}{\sqrt{n + 1}}\right| = \sum\limits_{n = 1}^{\infty}\dfrac{1}{\sqrt{n + 1}} +$$ + +发散. 故原级数条件收敛. + +(3) 由于 $\sum\limits_{n = 1}^{\infty}(-1)^{n}\dfrac{n}{n + 1} = \sum\limits_{n = 1}^{\infty}(-1)^n + \sum\limits_{n = 1}^{\infty}\dfrac{(-1)^{n - 1}}{n + 1}$, 且前者发散, 后者收敛, 故原级数发散. + +(5) 由于 $\left|\dfrac{1}{2^n}\sin\dfrac{n\pi}{4}\right|\le \dfrac{1}{2^n}$ 且 $\sum\limits_{n = 1}^{\infty}\dfrac{1}{2^n}$ 收敛, 故原级数绝对收敛. + +(7) 由于 + +$$ +\begin{aligned} + \sum\limits_{n = 1}^{\infty}(-1)^{n}\dfrac{2^{n^2}}{n!} & = \sum\limits_{k = 1}^{\infty}\left(-\dfrac{2^{(2k-1)^2}}{(2k - 1)!} + \dfrac{2^{(2k)^2}}{(2k)!}\right) \\ + & = \sum\limits_{k = 1}^{\infty}\dfrac{2^{(2k - 1)^2}}{(2k)!}\cdot(2^{4k - 1} - 2k) +\end{aligned} +$$ + +显然 $\lim\limits_{k \to \infty}\dfrac{2^{(2k - 1)^2}}{(2k)!}\cdot(2^{4k - 1} - 2k) \neq 0$. 故该级数发散. + +(9) 由于 $\sum\limits_{n = 1}^{\infty}(-1)^n(\sqrt{n + 1} - \sqrt{n})$ 为 Leibniz 级数, 故该级数收敛. 而 + +$$ +\begin{aligned} + \sum\limits_{n = 1}^{\infty}\left|(-1)^n(\sqrt{n + 1} - \sqrt{n})\right| & = \sum\limits_{n = 1}^{\infty}\left(\sqrt{n + 1} - \sqrt{n}\right) \\ + & = \lim\limits_{n \to \infty}\sqrt{n + 1} - 1 +\end{aligned} +$$ + +故该级数的通项加上绝对值后发散. 综上所述, 该级数条件收敛. + +(11) 由于 + +$$ +\begin{aligned} + \sum\limits_{n = 2}^{\infty}\dfrac{(-1)^n}{\sqrt{n + (-1)^n}} & = \sum\limits_{k = 1}^{\infty}\left(\dfrac{(-1)^{2k}}{\sqrt{2k + (-1)^{2k}}} + \dfrac{(-1)^{2k + 1}}{\sqrt{2k + 1 + (-1)^{2k + 1}}}\right) \\ + & = \sum\limits_{k = 1}^{\infty}\left(\dfrac{1}{\sqrt{2k + 1}} - \dfrac{1}{\sqrt{2k}}\right) \\ + & = \sum\limits_{n = 2}^{\infty}\dfrac{(-1)^{n - 1}}{\sqrt{n}} +\end{aligned} +$$ + +为 Leibniz 级数, 因此该级数收敛. 而 + +$$ +\begin{aligned} + \sum\limits_{n = 2}^{\infty}\left|\dfrac{(-1)^n}{\sqrt{n + (-1)^n}}\right| & = \sum\limits_{n = 1}^{\infty}\dfrac{1}{\sqrt{n + (-1)^{n}}} \\ + & \ge \sum\limits_{n = 1}^{\infty}\dfrac{1}{\sqrt{n + 1}} \\ +\end{aligned} +$$ + +故该级数的通项加上绝对值后发散. 综上所述, 该级数条件收敛. + +(13) + +$$ +\begin{aligned} + & \quad \dfrac{1}{\sqrt{2} - 1} + \dfrac{1}{\sqrt{2} + 1} + \dfrac{1}{\sqrt{3} - 1} + \dfrac{1}{\sqrt{3} + 1} + \cdots + \dfrac{1}{\sqrt{n} - 1} + \dfrac{1}{\sqrt{n} + 1} + \cdots \\ + & = \sum\limits_{n = 2}^{\infty}\left(\dfrac{1}{\sqrt{n} - 1} + \dfrac{1}{\sqrt{n} + 1}\right) \\ + & = \sum\limits_{n = 2}^{\infty}\dfrac{2\sqrt{n}}{n - 1} \\ + & \ge \sum\limits_{n = 2}^{\infty}\dfrac{2}{n - 1} +\end{aligned} +$$ + +故原级数发散. + +(14) + +$$ +\begin{aligned} + & \quad 1 - \ln 2 + \dfrac{1}{2} - \dfrac{3}{2} + \dfrac{1}{n} - \ln\dfrac{n + 1}{n} + \cdots \\ + & = \sum\limits_{n = 1}^{\infty}\left(\dfrac{1}{n} - \ln\dfrac{n + 1}{n}\right) \\ + & = \lim\limits_{n \to \infty}\left(\sum\limits_{k = 1}^{n}\dfrac{1}{k} - \ln(n + 1)\right) \\ + & = \lim\limits_{n \to \infty}\left(\ln n + \gamma + \epsilon_n - \ln(n + 1)\right) \\ + & = \gamma +\end{aligned} +$$ + +其中 $\lim\limits_{n \to \infty}\epsilon_n = 0, \gamma = 0.577216\cdots$. 故原级数绝对收敛. + +## 第 6 题 + +级数 $\sum\limits_{n = 1}^{\infty}a_n^2, \sum\limits_{n = 1}^{\infty}b_n^2$ 收敛, 证明: $\sum\limits_{n = 1}^{\infty}(a_n + b_n)^2$ 收敛, $\sum\limits_{n = 1}^{\infty}\dfrac{a_n}{n}$ 绝对收敛. + +**证明** + +由于 $(a_n + b_n)^2 \le 2(a_n^2 + b_n^2)$, 且 $\sum\limits_{n = 1}^{\infty}2(a_n^2 + b_n^2)$ 收敛, 故由比较判别法知 $\sum\limits_{n = 1}^{\infty}(a_n + b_n)^2$ 收敛. + +不妨设 $a_n > 0$. 由于 $\dfrac{a_n}{n} \le a_n^2 + \dfrac{1}{4n^2}$, 且 $\sum\limits_{n = 1}^{\infty}\left(a_n^2 + \dfrac{1}{4n^2}\right) = \sum\limits_{n = 1}^{\infty}a_n^2 + \sum\limits_{n = 1}^{\infty}\dfrac{1}{4n^2}$ 收敛, 故由比较判别法知 $\sum\limits_{n = 1}^{\infty}\dfrac{a_n}{n}$ 绝对收敛. + +## 第 7 题 + +若级数 $\sum\limits_{n = 1}^{\infty}a_n, \sum\limits_{n = 1}^{\infty}b_n$ 均收敛, 且 $a_n \le c_n \le b_n$, 证明: $\sum\limits_{n = 1}^{\infty}c_n$ 收敛. + +**证明** + +由于 $0 \le c_n - a_n \le b_n - a_n$, 且 $\sum\limits_{n = 1}^{\infty}(b_n - a_n)$ 收敛, 故由比较判别法知 $\sum\limits_{n = 1}^{\infty}(c_n - a_n)$ 收敛. 又因为 $\sum\limits_{n = 1}^{\infty}a_n$ 收敛, 故 $\sum\limits_{n = 1}^{\infty}c_n$ 收敛. + +## 第 9 题 + +设正项数列 $\{u_n\}$ 单调减少, 且级数 $\sum\limits_{n = 1}^{\infty}(-1)^nu_n$ 发散, 证明: 级数 $\sum\limits_{n = 1}^{\infty}\left(\dfrac{1}{1 + u_n}\right)^n$ 收敛. + +**证明** + +由于正项数列 $\{u_n\}$ 单调减少, 故 $\lim\limits_{n \to \infty}u_n \ge 0$. 假设 $\lim\limits_{n \to \infty}u_n = 0$, 则级数 $\sum\limits_{n = 1}^{\infty}(-1)^nu_n$ 收敛, 矛盾. 故 $\lim\limits_{n \to \infty}u_n > 0$, 不妨设为 $c$. 由于 + +$$ +\lim\limits_{n \to \infty}\sqrt[n]{\left(\dfrac{1}{1 + u_n}\right)^n} = \lim\limits_{n \to \infty}\dfrac{1}{1 + u_n} = \dfrac{1}{1 + c} < 1 +$$ + +由根值判别法知级数 $\sum\limits_{n = 1}^{\infty}\left(\dfrac{1}{1 + u_n}\right)^n$ 收敛. diff --git a/services/homework-ans/docs/calculus-2/chapter5/exercise5-4.md b/services/homework-ans/docs/calculus-2/chapter5/exercise5-4.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter5/exercise5-4.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-2/chapter5/exercise5-rev.md b/services/homework-ans/docs/calculus-2/chapter5/exercise5-rev.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter5/exercise5-rev.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/services/homework-ans/docs/calculus-2/chapter6/exercise6-1.md b/services/homework-ans/docs/calculus-2/chapter6/exercise6-1.md new file mode 100644 index 0000000..436bf8d --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter6/exercise6-1.md @@ -0,0 +1,72 @@ + +## 第 2 题 + +求下列函数项级数的收敛域, 并指出使级数绝对收敛、条件收敛的 $x$ 的范围. + +(1) $\sum\limits_{n = 1}^{\infty}ne^{-nx}$; + +(2) $\sum\limits_{n = 1}^{\infty}\left(\dfrac{\ln x}{3}\right)^n$; + +(3) $\sum\limits_{n = 1}^{\infty}\left(\dfrac{n + 1}{x}\right)^n$; + +(4) $\sum\limits_{n = 1}^{\infty}x^n\sin\dfrac{x}{2^n}$; + +(5) $\sum\limits_{n = 1}^{\infty} \dfrac{1}{1 + x^n}$; + +**解** + +(1) 该级数每一项都为正数, 故绝对收敛域等于收敛域. 由于 $\lim\limits_{n \to \infty}\sqrt[n]{ne^{-nx}} = e^{-x}$, 故当 $x < 0$ 时 $\lim\limits_{n \to \infty}\sqrt[n]{u_n} > 1$, $\sum\limits_{n = 1}^{\infty}u_n$ 发散; 当 $x > 0$ 时 $\lim\limits_{n \to \infty}\sqrt[n]{u_n} < 1$, $\sum\limits_{n = 1}^{\infty}$ 收敛. 又因为当 $x = 0$ 时 $\sum\limits_{n = 1}^{\infty}u_n = \sum\limits_{n = 1}^{\infty}n$ 发散, 故该级数的绝对收敛域为 $(0, +\infty)$. + +(2) $\sum\limits_{n = 1}^{\infty}\left(\dfrac{\ln x}{3}\right)^n = \dfrac{\ln x}{3 - \ln x}\lim\limits_{n \to \infty}\left(1 - \left(\dfrac{\ln x}{3}\right)^n\right)$. 因此当 $\left|\dfrac{\ln x}{3}\right|< 1$, 即 $x \in (e^{-3}, e^3)$ 时级数收敛. 当 $x = e^{-3}$ 时 $\sum\limits_{n = 1}^{\infty}u_n = \sum\limits_{n = 1}^{\infty}(-1)^n$ 发散. 当 $x = e^3$ 时 $\sum\limits_{n = 1}^{\infty}u_n = \sum\limits_{n = 1}^{\infty}1$ 发散. 故该级数的收敛域为 $(e^{-3}, e^3)$. + +再考虑绝对收敛域. 由于当 $\left|\dfrac{\ln x}{3}\right|< 1$, 即 $x \in (e^{-3}, e^3)$ 时 $\lim\limits_{n \to \infty}\left|\dfrac{\ln x}{3}\right|^n = 0$, 故该级数的绝对收敛域也为 $(e^{-3}, e^3)$. + +(3) 由于对任意 $x \in \mathbb{R}$, 都有 $\lim\limits_{n \to \infty}\sqrt[n]{u_n} = \lim\limits_{n \to \infty}\dfrac{n + 1}{x}$ 不存在, 因此收敛域为 $\varnothing$. + +(4) 该级数每一项都为正数, 故绝对收敛域等于收敛域. 由于 $\lim\limits_{n \to \infty}\dfrac{u_{n + 1}}{u_n} = \lim\limits_{n \to \infty}\dfrac{x^{n + 1}\sin\frac{x}{2^{n + 1}}}{x^n\sin\frac{x}{2^n}} = \lim\limits_{n\to \infty}\dfrac{x}{2\cos\frac{x}{2^{n + 1}}} = \dfrac{x}{2}$, 因此当 $x \in (-2, 2)$ 时该级数收敛. 当 $x = \pm2$ 时, $\lim\limits_{n \to \infty}u_n = \lim\limits_{n \to \infty}x^n\cdot\dfrac{x}{2^n} = \lim\limits_{n \to \infty}\dfrac{(\pm 2)^{n + 1}}{2^n} \neq 0$, 此时该级数发散. 故该级数的绝对收敛域为 $(-2, 2)$. + +(5) 当 $x \in (-1, 1)$ 时, 由于 $\lim\limits_{n \to \infty}u_n = \lim\limits_{n \to \infty}\dfrac{1}{1 + x^n} = 1 \neq 0$, 故此时该级数发散. 当 $x = -1$ 时该级数不存在. 当 $x = 1$ 时, 该级数等于 $\sum\limits_{n = 1}^{\infty}\dfrac{1}{2}$ 发散. + +考虑 $\dfrac{u_{n + 1}}{u_n} = \dfrac{1 + x^n}{1 + x^{n + 1}}$. 当 $\left|x\right| > 1$ 时, $\lim\limits_{n \to \infty}\left|\dfrac{u_{n + 1}}{u_n}\right| = \lim\limits_{n \to \infty}\left|\dfrac{1 + x^n}{1 + x^{n + 1}}\right| = \lim\limits_{n \to \infty}\left|\dfrac{\frac{1}{x^n} + 1}{\frac{1}{x^n} + x}\right| = \dfrac{1}{\left|x\right|} < 1$, 该级数绝对收敛. 综上所述, 该级数在 $\{x | \left|x\right| > 1\}$ 上收敛, 且绝对收敛. + +## 第 3 题 + +下列函数项级数在收敛域上是否一致收敛? + +(1) $\sum\limits_{n = 1}^{\infty}\dfrac{1 - \cos nx}{n^2}$; + +(3) $\sum\limits_{n = 1}^{\infty}x^3e^{-nx^2}$; + +(5) $\sum\limits_{n = 1}^{\infty}\dfrac{\cos nx + \sin n^x}{n^{1.001}}$; + +**解** + +(1) 由于 $\left|\dfrac{1 - \cos nx}{n^2}\right| \le \dfrac{2}{n^2}$ 且 $\sum\limits_{n = 1}^{\infty}\dfrac{2}{n^2}$ 收敛, 因此由 Weierstrass 判别法知 $\sum\limits_{n = 1}^{\infty}\dfrac{1 - \cos nx}{n^2}$ 在收敛域上一致收敛. + +(3) 由于 $e^{nx^2} \ge 1 + (nx^2) + \dfrac{1}{2}(nx^2)^2$, 故 + +$$ +\left|\dfrac{x^3}{e^{nx^2}}\right| \le \dfrac{\left|x^3\right|}{1 + (nx^2) + \dfrac{1}{2}(nx^2)^2} \le \dfrac{\left|x^3\right|}{(nx^2) + \dfrac{1}{2}(nx^2)^2} \le \dfrac{\left|x^3\right|}{2\sqrt{(nx^2)}\cdot\dfrac{1}{2}(nx^2)^2} = \dfrac{\left|x^3\right|}{\sqrt{2n^3}\left|x^3\right|} = \dfrac{1}{\sqrt{2n^3}}. +$$ + +而 $\sum\limits_{n = 1}^{\infty}\dfrac{1}{\sqrt{2n^3}}$ 收敛, 因此由 Weierstrass 判别法知 $\sum\limits_{n = 1}^{\infty}x^3e^{-nx^2}$ 在收敛域上一致收敛. + +(5) 由于 $\left|\dfrac{\cos nx + \sin n^x}{n^{1.001}}\right| \le \dfrac{2}{n^{1.001}}$, 且 $\sum\limits_{n = 1}^{\infty}\dfrac{2}{n^{1.001}}$ 收敛, 因此由 Weierstrass 判别法知 $\sum\limits_{n = 1}^{\infty}\dfrac{\cos nx + \sin n^x}{n^{1.001}}$ 在收敛域上一致收敛. + +## 第 4 题 + +考察级数 $\sum\limits_{n = 1}^{\infty}\dfrac{(-1)^n}{x + 2^n}$ 在 $[0, +\infty)$ 上是否一致收敛? + +**解** + +一致收敛. 记 $u_n(x) = (-1)^n$. 由于 $\left|\sum\limits_{k = 1}^{n}u_k(x)\right| \le 1$ 部分和有界, 且 $v_n(x) = \dfrac{1}{x + 2^n}$ 对于任意的 $x \in [0, +\infty)$ 都单调且一致趋于 $0$, 故由 Dirichlet 判别法知 $\sum\limits_{n = 1}^{\infty}\dfrac{(-1)^n}{x + 2^n} = \sum\limits_{n = 1}^{\infty}u_n(x)v_n(x)$ 一致收敛. + +## 第 5 题 + +证明级数 $\sum\limits_{n = 1}^{\infty}\dfrac{(-1)^n}{x^2 + n}$ 在 $x \in (-\infty, +\infty)$ 上一致收敛, 但不绝对收敛. + +**证明** + +记 $u_n(x) = (-1)^n$. 由于 $\left|\sum\limits_{k = 1}^{n}u_k(x)\right| \le 1$ 部分和有界, 且 $v_n(x) = \dfrac{1}{x^2 + n}$ 对于任意的 $x \in (-\infty, +\infty)$ 都单调且一致趋于 $0$, 故由 Dirichlet 判别法知 $\sum\limits_{n = 1}^{\infty}\dfrac{(-1)^n}{x^2 + n} = \sum\limits_{n = 1}^{\infty}u_n(x)v_n(x)$ 一致收敛. + +当 $x = 1$ 时 $\sum\limits_{n = 1}^{\infty}\left|u_n\right| = \sum\limits_{n = 1}^{\infty}\dfrac{1}{1 + n}$ 发散, 因此该级数不绝对收敛. diff --git a/services/homework-ans/docs/calculus-2/chapter6/exercise6-2.md b/services/homework-ans/docs/calculus-2/chapter6/exercise6-2.md new file mode 100644 index 0000000..d1702e4 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter6/exercise6-2.md @@ -0,0 +1,94 @@ + +## 第 2 题 + +设 $S(x) = \sum\limits_{n = 1}^{\infty}\dfrac{1}{2^n}\tan\dfrac{x}{2^n}$, 计算 $\int_{\frac{\pi}{6}}^{\frac{\pi}{3}}S(x)\text{d}{x}$. + +**解** + +记 $u_n(x) = \dfrac{1}{2^n}, v_n(x) = \tan\dfrac{x}{2^n}, I = \left(\dfrac{\pi}{6}, \dfrac{\pi}{3}\right)$. 由于 $v_n(x)$ 对任意固定的 $x\in I$ 均单调递减, 且 $\left|v_n(x)\right| \le \dfrac{\sqrt{3}}{3}$ 在 $I$ 上一致有界, 且 $\sum\limits_{n = 1}^{\infty}u_n(x)$ 与 $x$ 无关, 在 $I$ 上一致收敛, 故由 Abel 判别法知 $S(x)$ 在 $I$ 上一致收敛. 故可以将积分与求和符号交换次序: + +$$ +\begin{aligned} + \int_{\frac{\pi}{6}}^{\frac{\pi}{3}}S(x)\text{d}{x} & = \int_{\frac{\pi}{6}}^{\frac{\pi}{3}}\sum\limits_{n = 1}^{\infty}\dfrac{1}{2^n}\tan\dfrac{x}{2^n}\text{d}{x} \\ + & = \sum\limits_{n = 1}^{\infty}\int_{\frac{\pi}{6}}^{\frac{\pi}{3}}\dfrac{1}{2^n}\tan\dfrac{x}{2^n}\text{d}{x} \\ + & = \sum\limits_{n = 1}^{\infty}\left(-\ln\cos\dfrac{x}{2^n}\right)\bigg\vert_{x=\frac{\pi}{6}}^{x=\frac{\pi}{3}} \\ + & = \sum\limits_{n = 1}^{\infty}\ln\dfrac{\cos\frac{\pi}{3\cdot2^{n+1}}}{\cos\frac{\pi}{3\cdot2^n}} \\ + & = \lim\limits_{n \to \infty}\ln\dfrac{\cos\frac{\pi}{3\cdot2^{n+1}}}{\cos\frac{\pi}{6}} \\ + & = \ln 2 - \dfrac{\ln 3}{2} +\end{aligned} +$$ + +## 第 3 题 + +证明: + +$$ +\int_{0}^{1}x^x\text{d}{x} = 1 - \dfrac{1}{2^2} + \dfrac{1}{3^3} - \dfrac{1}{4^4} + \cdots + (-1)^n\dfrac{1}{(n + 1)^{n + 1}} + \cdots. +$$ + +**证明** + +由于 $x^x = e^{x\ln x} = 1 + (x\ln x) + \dfrac{1}{2}(x\ln x)^2 + \cdots = \sum\limits_{n = 0}^{\infty}\dfrac{(x \ln x)^n}{n!}$, 且 $\left|x \ln x\right| \in (0, 1), \forall x \in (0, 1)$, 故 $\sum\limits_{n = 0}^{\infty}\dfrac{(x \ln x)^n}{n!} < \sum\limits_{n = 0}^{\infty}\dfrac{1}{n!}$. 而 $\sum\limits_{n = 0}^{\infty}\dfrac{1}{n!}$ 收敛, 故由 Weierstrass 判别法知 $\sum\limits_{n = 0}^{\infty}\dfrac{(x \ln x)^n}{n!}$ 在 $(0, 1)$ 上一致收敛. 因此可以交换积分与求和的次序: + +$$ +\begin{aligned} + \int_0^1x^x\text{d}{x} & = \int_{0}^{1}\sum\limits_{n = 0}^{\infty}\dfrac{(x \ln x)^n}{n!}\text{d}{x} \\ + & = \sum\limits_{n = 0}^{\infty}\int_{0}^{1}\dfrac{(x \ln x)^n}{n!}\text{d}{x} \\ + & = \sum\limits_{n = 0}^{\infty}\dfrac{1}{n!}\int_{0}^{1}(x\ln x)^n\text{d}{x} \\ + & = \sum\limits_{n = 0}^{\infty}\dfrac{1}{n!}\int_{0}^{1}\dfrac{\ln^n x}{n + 1}\text{d}{(x^{n + 1})} \\ + & = \sum\limits_{n = 0}^{\infty}\left(\dfrac{x^{n + 1}\ln^n x}{n + 1}\bigg\vert_{0}^{1} - \int_{0}^{1}\dfrac{n x^n \ln^{n-1} x}{n + 1}\text{d}{x}\right) \\ + & = -\sum\limits_{n = 0}^{\infty}\int_{0}^{1}\dfrac{n x^n \ln^{n-1} x}{n + 1}\text{d}{x} \\ + & = \sum\limits_{n = 0}^{\infty}\int_{0}^{1}\dfrac{n(n-1) x^n \ln^{n-2} x}{(n + 1)^2}\text{d}{x} \\ + & = \cdots \\ + & = \sum\limits_{n = 0}^{\infty}(-1)^{n}\int_{0}^{1}\dfrac{n! x^n}{(n + 1)^n}\text{d}{x} \\ + & = \sum\limits_{n = 0}^{\infty}\dfrac{(-1)^n n!}{(n + 1)^{n + 1}} \\ + & = 1 - \dfrac{1}{2^2} + \dfrac{1}{3^3} - \dfrac{1}{4^4} + \cdots + (-1)^n\dfrac{1}{(n + 1)^{n + 1}} + \cdots +\end{aligned} +$$ + +命题得证. + +## 第 4 题 + +证明: 函数 $f(x) = \sum\limits_{n = 1}^{\infty}\dfrac{n}{x^n}$ 是 $(1, +\infty)$ 上的连续函数. + +**证明** + +要证明函数 $f(x) = \sum\limits_{n = 1}^{\infty}\dfrac{n}{x^n}$ 是 $(1, +\infty)$ 上的连续函数, 只需证 $f(x)$ 在任意 $x = x_0 > 1$ 处连续即可. $\forall x_0 > 1$, 取 $r \in (1, r_0)$, 则 $f(x) = \sum\limits_{n = 1}^{\infty}\dfrac{n}{x^n} \le \sum\limits_{n = 1}^{\infty}\dfrac{n}{r^n}$, 而 $\sum\limits_{n = 1}^{\infty}\dfrac{n}{r^n}$ 收敛. 故由 Weierstrass 判别法知级数在 $[r, +\infty)$ 上一致收敛. 因此 $f(x)$ 在任意 $x = x_0 > 1$ 处连续. 命题得证. + +## 第 5 题 + +证明: 级数 $\sum\limits_{n = 1}^{\infty}\dfrac{x^2}{(1 + x^2)^n}$ 对任意的 $x$ 绝对收敛, 但在 $(-\infty, +\infty)$ 上非一致收敛. + +**证明** + +由于 $\sum\limits_{n = 1}^{\infty}\dfrac{x^2}{(1 + x^2)^n} < \sum\limits_{n = 1}^{\infty}\dfrac{1 + x^2}{(1 + x^2)^n} = \sum\limits_{n = 1}^{\infty}\dfrac{1}{(1 + x^2)^{n - 1}}$, 且 $\sum\limits_{n = 1}^{\infty}\dfrac{1}{(1 + x^2)^{n - 1}}$ 绝对收敛, 因此 级数 $\sum\limits_{n = 1}^{\infty}\dfrac{x^2}{(1 + x^2)^n}$ 对任意的 $x$ 绝对收敛. 接下来考虑 $\sum\limits_{k = n + 1}^{n + p}u_k(x)$. + +$$ +\begin{aligned} + \sum\limits_{k = n + 1}^{n + p}u_k(x) & = \sum\limits_{k = n + 1}^{n + p}\dfrac{x^2}{(1 + x^2)^{k}} \\ + & = \dfrac{x^2}{(1 + x^2)^{n + 1}}\times\dfrac{1 - \left(\frac{1}{1 + x^2}\right)^p}{1 - \frac{1}{1 + x^2}} \\ + & = \dfrac{1 - \left(\frac{1}{1 + x^2}\right)^p}{(1 + x^2)^n} +\end{aligned} +$$ + +取 $n = p = N + 1, x = \sqrt{\sqrt[N + 1]{2} - 1}, \epsilon = \dfrac{1}{4}$, 则 + +$$ +\begin{aligned} + \sum\limits_{k = n + 1}^{n + p}u_k(x) & = \dfrac{1 - \left(\frac{1}{1 + x^2}\right)^p}{(1 + x^2)^n} \\ + & = \dfrac{1 - \left(\frac{1}{1 + \sqrt[N+1]{2} - 1}\right)^{N+1}}{(1 + \sqrt[N+1]{2} - 1)^{N+1}} \\ + & = \dfrac{1 - \frac{1}{2}}{2} \\ + & = \dfrac{1}{4} = \epsilon +\end{aligned} +$$ + +因此, 级数 $\sum\limits_{n = 1}^{\infty}\dfrac{x^2}{(1 + x^2)^n}$ 在 $(-\infty, +\infty)$ 上非一致收敛. + +## 第 6 题 + +证明: 函数 $f(x) = \sum\limits_{n = 1}^{\infty}ne^{-nx}$ 在 $(0, +\infty)$ 上连续, 进一步证明在 $(0, +\infty)$ 上可微. + +**证明** + +首先, $u_n(x) = ne^{-nx}$ 在 $x \in (0, +\infty)$ 上连续可导, $u'_n(x) = -n^2e^{-nx}$. 其次, $\forall \delta > 0$, $-\sum\limits_{n = 1}^{\infty}u'_n = \sum\limits_{n = 1}^{\infty}n^2e^{-nx} < \sum\limits_{n = 1}^{\infty}n^2e^{-n\delta}$, 而 $\sum\limits_{n = 1}^{\infty}n^2e^{-n\delta}$ 收敛. 所以由 Weierstrass 判别法知 $\sum\limits_{n=1}^{\infty}u'_n(x)$ 在 $(\delta, +\infty)$ 上一致收敛. 由于 $\delta$ 可以任意小, 故 $\sum\limits_{n=1}^{\infty}u'_n(x)$ 在 $x \in (0, +\infty)$ 上一致收敛. 最后, $\exists x = x_0 = 1$ 时 $f(1) = \sum\limits_{n = 1}^{\infty}\dfrac{n}{e^n}$ 收敛. 因此, 函数 $f(x)$ 在 $(0, +\infty)$ 上连续, $f(x) = \sum\limits_{n = 1}^{\infty}ne^{-nx}$ 在 $(0, +\infty)$ 在 $(0, +\infty)$ 上可微. diff --git a/services/homework-ans/docs/calculus-2/chapter6/exercise6-3.md b/services/homework-ans/docs/calculus-2/chapter6/exercise6-3.md new file mode 100644 index 0000000..ac3d7d4 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter6/exercise6-3.md @@ -0,0 +1,200 @@ + +## 第 1 题 + +求下列幂级数的收敛半径与收敛域. + +(1) $\sum\limits_{n = 1}^{\infty}\dfrac{x^n}{n^n}$; + +(3) $\sum\limits_{n = 1}^{\infty}\dfrac{x^{3n + 1}}{(2n - 1)2^n}$; + +(5) $\sum\limits_{n = 1}^{\infty}\dfrac{\ln n}{n}x^n$; + +(7) $\sum\limits_{n = 1}^{\infty}\dfrac{1}{n^p}(x - 1)^n(p>0)$; + +(9) $\sum\limits_{n = 1}^{\infty}2^n(x+a)^{2n}$; + +**解** + +(1) 由于 $q = \lim\limits_{n \to \infty}\sqrt[n]{\dfrac{1}{n^n}} = \lim\limits_{n \to \infty} \dfrac{1}{n} = 0$, 故 $R = \dfrac{1}{q} = +\infty$. 收敛域为 $\mathbb{R}$. + +(3) 由于 $q = \lim\limits_{n \to \infty}\dfrac{u_{n + 1}}{u_n} = \lim\limits_{n \to \infty}\dfrac{x^3(2n - 1)}{2(2n + 1)} = \dfrac{x^3}{2}$, 当 $x \in (-\sqrt[3]{2}, \sqrt[3]{2})$ 时级数收敛. 故 $R = \sqrt[3]{2}$. 当 $x = -\sqrt[3]{2}$ 时为 Leibniz 级数, 收敛; 当 $x = \sqrt[3]{2}$ 时可化为 $\sum\limits_{n = 1}^{\infty}\dfrac{\sqrt[3]{2}}{2n - 1}$, 发散. 故收敛域为 $[-\sqrt[3]{2}, \sqrt[3]{2})$. + +(5) 由于 $q = \lim\limits_{n \to \infty}\dfrac{u_{n + 1}}{u_n} = \lim\limits_{n \to \infty}\dfrac{n\ln(n+1)}{(n+1)\ln n} = 1$, 故 $R = \dfrac{1}{q} = 1$. 当 $x = -1$ 时为 Leibniz 级数, 收敛; 当 $x = 1$ 时可化为 $\sum\limits_{n = 1}^{\infty}\dfrac{\ln n}{n} \ge -1 + \sum\limits_{n = 1}^{\infty}\dfrac{1}{n}$, 发散. 故收敛域为 $[-1, 1)$. + +(7) 由于 $q = \lim\limits_{n \to \infty}\sqrt[n]{\dfrac{1}{n^p}} = 1$, 故 $R = \dfrac{1}{q} = 1$. 当 $x = 0$ 时为该级数为 Leibniz 级数, 收敛. 当 $x = 2$ 时, $\sum\limits_{n = 1}^{\infty}\dfrac{1}{n^p}(x - 1)^{n} = \sum\limits_{n = 1}^{\infty}\dfrac{1}{n^p}$. 若 $p > 1$, 则级数收敛; 若 $0 < p \le 1$, 则级数发散. + +综上所述, 当 $p > 1$ 时, 收敛域为 $[0, 2]$; 当 $0 < p \le 1$ 时, 收敛域为 $[0, 2)$. + +(9) 由于 $q = \lim\limits_{n \to \infty}\dfrac{u_{n + 1}}{u_n} = \lim\limits_{n \to \infty}2(x+a)^2 = 2(x+a)^2$, 当 $x \in \left(-a - \dfrac{\sqrt{2}}{2}, -a + \dfrac{\sqrt{2}}{2}\right)$ 时级数收敛. 故 $R = \dfrac{\sqrt{2}}{2}$. 当 $x = -a \pm \dfrac{\sqrt{2}}{2}$ 时级数均发散. 故收敛域为 $\left(-a - \dfrac{\sqrt{2}}{2}, -a + \dfrac{\sqrt{2}}{2}\right)$. + +## 第 2 题 + +求下列幂级数的收敛域与和函数. + +(1) $\sum\limits_{n = 2}^{\infty}\dfrac{x^n}{n(n-1)}$; + +(3) $\sum\limits_{n = 1}^{\infty}(2n+1)x^{2n+1}$; + +(5) $\sum\limits_{n = 1}^{\infty}\dfrac{n(n+1)}{2}x^{n-1}$; + +**解** + +(1) 由于 $q = \lim\limits_{n \to \infty}\sqrt[n]{\dfrac{1}{n(n - 1)}} = 1$, 故 $R = \dfrac{1}{q} = 1$. 当 $x = \pm1$ 时级数均收敛, 故收敛域为 $[-1, 1]$. 设和函数为 $S(x)$, 则当 $x \neq 1$ 时 $S''(x) = \sum\limits_{n = 0}^{\infty}x^n = \dfrac{1}{1 - x}$. 积分可得 $S(x) = x + (1 - x)\ln(1 - x)$. 当 $x = 1$ 时 $S(x) = 1$. 因此 + +$$ +S(x) = \begin{cases} + 1, & x = 1, \\ + x + (1 - x)\ln(1 - x), & x \in [-1, 1). +\end{cases} +$$ + +(3) 由于 $q = \varlimsup\limits_{n \to \infty}a_n = \lim\limits_{n \to \infty}\sqrt[n]{2n+1} = 1$, 故 $R = \dfrac{1}{q} = 1$. 当 $x = \pm1$ 时级数均发散, 故收敛域为 $(-1, 1)$. 设和函数为 $S(x)$. 因此 + +$$ +\begin{aligned} + S(x) & = \dfrac{\text{d}{}}{\text{d}{x}}\left(\sum\limits_{n = 1}^{\infty}x^{2n + 2}\right)-\left(\sum\limits_{n = 1}^{\infty}x^{2n + 1}\right) \\ + & = \dfrac{\text{d}{}}{\text{d}{x}}\dfrac{x^4}{1 - x^2} - \dfrac{x^3}{1 - x^2} \\ + & = \dfrac{4x^3 - 2x^5}{(1 - x^2)^2} - \dfrac{x^3}{1 - x^2} \\ + & = \dfrac{3x^3 - x^5}{(1 - x^2)^2} \quad x \in (-1, 1) +\end{aligned} +$$ + +(5) 由于 $q = \lim\limits_{n \to \infty}\sqrt[n]{\dfrac{n(n + 1)}{2}} = 1$, 故 $R = \dfrac{1}{q} = 1$. 当 $x = \pm1$ 时级数均发散, 故收敛域为 $(-1, 1)$. 设和函数为 $S(x)$. 因此 + +$$ +\begin{aligned} + S(x) & = \dfrac{1}{2}\dfrac{\text{d}{}}{\text{d}{x^2}}\left(\sum\limits_{n = 1}^{\infty}x^{n+1}\right) \\ + & = \dfrac{1}{2}\dfrac{\text{d}{}}{\text{d}{x^2}}\left(\dfrac{1}{1 - x} - 1 - x\right) \\ + & = \dfrac{1}{2}\dfrac{\text{d}{}}{\text{d}{x}}\left(\dfrac{1}{(1 - x)^2} - 1\right) \\ + & = \dfrac{1}{(1 - x)^3} \quad x \in (-1, 1) +\end{aligned} +$$ + +## 第 3 题 + +将下列函数在 $x_0$ 点展成幂级数, 并求收敛域. + +(1) $\cos x, x_0 = \dfrac{\pi}{4}$; + +(3) $\ln(1 + x), x_0 = 2$; + +(5) $\sin x^2, x_0 = 0$; + +(7) $\dfrac{1}{x - 1}, x_0 = -1$; + +(9) $\dfrac{x}{(x - 1)(x + 3)}, x_0 = 0$; + +(11) $\ln(x + \sqrt{x^2 + 1}), x_0 = 0$; + +**解** + +(1) $f(x) = \cos x, f^{(n)}(x) = \cos\left(x + \dfrac{n\pi}{2}\right)$. 因此 + +$$ +f(x) = \sum\limits_{n = 0}^{\infty}\dfrac{\cos\left(\frac{\pi}{4} + \frac{n\pi}{2}\right)}{n!}\left(x - \dfrac{\pi}{4}\right)^n +$$ + +收敛域为 $\mathbb{R}$. + +(3) $f(x) = \ln(1 + x), f^{(n)}(x) = \begin{cases}\ln(1 + x), & n = 0, \\ \dfrac{(-1)^{n-1}(n-1)!}{(1 + x)^n}, & n \ge 1.\end{cases}$ 因此 + +$$ +f(x) = \ln 3 + \sum\limits_{n = 1}^{\infty}\dfrac{(-1)^{n-1}}{n\cdot 3^n}(x - 2)^n +$$ + +由 $\left|x - 2\right| < 3$ 解得 $x \in (-1, 5)$. 因为当 $x = -1$ 时级数发散, 当 $x = 5$ 时级数收敛, 故收敛域为 $(-1, 5]$. + +(5) $f(x) = \sin x^2$. 由于 $\sin x = \sum\limits_{k = 0}^{\infty}\dfrac{(-1)^kx^{2k+1}}{(2k+1)!}$, 因此 + +$$ +f(x) = \sum\limits_{k = 0}^{\infty}\dfrac{(-1)^kx^{4k+2}}{(2k+1)!} +$$ + +收敛域为 $\mathbb{R}$. + +(7) $f(x) = \dfrac{1}{x - 1}, f^{(n)}(x) = \dfrac{(-1)^nn!}{(x - 1)^{n + 1}}$. 因此 + +$$ +f(x) = -\sum\limits_{n = 0}^{\infty}\dfrac{1}{2^{n+1}}(x + 1)^n +$$ + +由 $\left|x + 1\right| < 2$ 解得 $x \in (-3, 1)$. 因为当 $x = -3$ 时级数收敛, 当 $x = 1$ 时级数发散, 故收敛域为 $[-3, 1)$. + +(9) $f(x) = \dfrac{x}{(x - 1)(x - 3)} = \dfrac{3}{2(x - 3)} + \dfrac{1}{2(x - 1)}, f^{(n)}(x) = \dfrac{3}{2}\cdot\dfrac{(-1)^nn!}{(x - 3)^{n + 1}} - \dfrac{1}{2}\cdot\dfrac{(-1)^nn!}{(x - 1)^{n + 1}}$. 因此 + +$$ +f(x) = \sum\limits_{n = 0}^{\infty}\left(\dfrac{1}{2} - \dfrac{1}{2\cdot3^n}\right)x^n +$$ + +由 $\left|x\right| < 1$ 解得 $x \in (-1, 1)$. 因为当 $x = \pm1$ 时级数均发散, 故收敛域为 $(-1, 1)$. + +(11) $f(x) = \ln(x + \sqrt{x^2 + 1}), f'(x) = (1 + x^2)^{-\frac{1}{2}}$. 由于 + +$$ +(1 + x^2)^{\frac{1}{2}} = 1 + \sum\limits_{n = 1}^{\infty}(-1)^n\dfrac{(2n-1)!!}{(2n)!!}x^{2n} \quad x \in [-1, 1] +$$ + +因此 + +$$ +\begin{aligned} + \ln(x + \sqrt{x^2 + 1}) & = \int_{0}^{x}(1 + t^2)^{-\frac{1}{2}}\text{d}{t} \\ + & = \int_{0}^{x}\left[1 + \sum\limits_{n = 1}^{\infty}(-1)^n\dfrac{(2n-1)!!}{(2n)!!}t^{2n}\right]\text{d}{t} \\ + & = x + \sum\limits_{n = 1}^{\infty}(-1)^n\dfrac{(2n-1)!!}{(2n)!!(2n + 1)}x^{2n + 1} \quad x \in [-1, 1] +\end{aligned} +$$ + +收敛域为 $[-1, 1]$. + +## 第 4 题 + +将下列函数在 $x_0 = 0$ 点展到指定的项. + +(1) $e^{\sin x}$, 展到 $x^3$ 项; + +(3) $\cos^3 x$, 展到 $x^4$ 项; + +**解** + +(1) 由 $e^x = 1 + x + \dfrac{1}{2}x^2 + \dfrac{1}{6}x^3 + o(x^3)$ 以及 $\sin x = x - \dfrac{1}{6}x^3 + o(x^3)$ 得 + +$$ +\begin{aligned} + e^{\sin x} & = 1 + \sin x + \dfrac{1}{2}\sin^2x + \dfrac{1}{6}\sin^3x + o(\sin^3 x) \\ + & = 1 + \left(x - \dfrac{1}{6}x^3 + o(x^3)\right) + \dfrac{1}{2}\left(x - \dfrac{1}{6}x^3 + o(x^3)\right)^2 + \dfrac{1}{6}\left(x - \dfrac{1}{6}x^3 + o(x^3)\right)^3 + o(x^3) \\ + & = 1 + x - \dfrac{1}{6}x^3 + \dfrac{1}{2}x^2 + \dfrac{1}{6}x^3 + o(x^3) \\ + & = 1 + x + \dfrac{1}{2}x^2 + o(x^3) +\end{aligned} +$$ + +(3) 由 $\cos x = 1 - \dfrac{1}{2}x^2 + o(x^2)$ 得 + +$$ +\begin{aligned} + \cos^3 x & = \left(1 - \dfrac{1}{2}x^2 + \dfrac{1}{24}x^4 + o(x^4)\right)^3 \\ + & = 1 - \dfrac{3}{2}x^2 + \dfrac{3}{4}x^4 + \dfrac{1}{8}x^4 + o(x^4) \\ + & = 1 - \dfrac{3}{2}x^2 + \dfrac{7}{8}x^4 + o(x^4) +\end{aligned} +$$ + +## 第 7 题 + +幂级数 $\sum\limits_{n = 1}^{\infty}a_nx^n$ 在 $x = 3$ 处条件收敛, 求 $\sum\limits_{n = 1}^{\infty}na_n(x - 1)^{n + 1}$ 的收敛区间. + +**解** + +由题知 $\sum\limits_{n = 1}^{\infty}a_nx^n$ 的收敛半径为 $R_1 = 3$. 因此 $q_1 = \varlimsup\limits_{n \to \infty}\sqrt[n]{a_n} = \dfrac{1}{R} = \dfrac{1}{3}$. 所以 $q_2 = \varlimsup\limits_{n \to \infty}\sqrt[n]{na_n} = \dfrac{1}{3}$. 故 $\sum\limits_{n = 1}^{\infty}na_n(x - 1)^{n + 1}$ 的收敛半径 $R_2 = \dfrac{1}{q_2} = 3$, 即收敛区间为 $(-2, 4)$. + +## 第 9 题 + +幂级数 $\sum\limits_{n = 0}^{\infty}a_nx^n$ 与 $\sum\limits_{n = 0}^{\infty}b_nx^n$ 的收敛半径分别为 $R_1, R_2$, 证明: + +(1) $\sum\limits_{n = 0}^{\infty}(a_n+b_n)x^n$ 的收敛半径 $R \ge \min\{R_1, R_2\}$. + +(2) $\sum\limits_{n = 0}^{\infty}a_nb_nx^n$ 的收敛半径 $R \ge R_1 R_2$. + +**证明** + +(1) 由题知 $\sum\limits_{n = 0}^{\infty}a_nx^n$ 与 $\sum\limits_{n = 0}^{\infty}b_nx^n$ 在 $\left|x\right|\le \min\{R_1, R_2\}$ 时同时收敛. 因此, 当 $\left|x\right|\le \min\{R_1, R_2\}$ 时一定有 $\sum\limits_{n = 0}^{\infty}(a_n+b_n)x^n$ 收敛. 故其收敛半径 $R \ge \min\{R_1, R_2\}$. + +(2) 由题知 $q_1 = \varlimsup\limits_{n \to \infty}\sqrt[n]{\left|a_n\right|}, q_2 = \varlimsup\limits_{n \to \infty}\sqrt[n]{\left|b_n\right|}, q = \varlimsup\limits_{n \to \infty}\sqrt[n]{\left|a_nb_n\right|}$. 而 $\varlimsup\limits_{n \to \infty}\sqrt[n]{\left|a_nb_n\right|} \le \varlimsup\limits_{n \to \infty}\sqrt[n]{\left|a_n\right|}\cdot\varlimsup\limits_{n \to \infty}\sqrt[n]{\left|b_n\right|}$. 故 $q \le q_1q_2$. 由于 $q_1 = \dfrac{1}{R_1}, q_2 = \dfrac{1}{R_2}, q = \dfrac{1}{R}$, 所以 $R \ge R_1R_2$. diff --git a/services/homework-ans/docs/calculus-2/chapter6/exercise6-rev.md b/services/homework-ans/docs/calculus-2/chapter6/exercise6-rev.md new file mode 100644 index 0000000..5dfff20 --- /dev/null +++ b/services/homework-ans/docs/calculus-2/chapter6/exercise6-rev.md @@ -0,0 +1,50 @@ + +## 第 4 题 + +设 $u_n(x) (n = 1, 2, \cdots)$ 是 $[a, b]$ 上的连续函数, 若 $\sum\limits_{n = 1}^{\infty}u_n(a), \sum\limits_{n = 1}^{\infty}u_n(b)$ 有一个发散, 证明: $\sum\limits_{n = 1}^{\infty}u_n(x)$ 在 $(a, b)$ 上非一致收敛. + +**证明** + +使用反证法. 假设 $\sum\limits_{n = 1}^{\infty}u_n(x)$ 在 $(a, b)$ 上一致收敛. 不妨设 $\sum\limits_{n = 1}^{\infty}u_n(a)$ 发散. 由于 $\sum\limits_{n = 1}^{\infty}u_n(x)$ 在 $(a, b)$ 上一致收敛, 则 + +$$ +\forall \epsilon > 0, \exists N(\epsilon) > 0, \text{s.t.}\, \forall n > N, p \in \mathbb{N}^*, \left|\sum\limits_{k = n + 1}^{n + p}u_k(x)\right| < \epsilon, \forall x \in (a, b). +$$ + +由于 $u_n(x) (n = 1, 2, \cdots)$ 是 $[a, b]$ 上的连续函数, 故不等式两端同时取极限 $x \to a$, 得 + +$$ +\left|\sum\limits_{k = n + 1}^{n + p}u_k(a)\right| \le \epsilon +$$ + +这说明 $\sum\limits_{n = 1}^{\infty}u_n(a)$ 收敛, 与题目矛盾, 因此假设不成立. 故 $\sum\limits_{n = 1}^{\infty}u_n(x)$ 在 $(a, b)$ 上非一致收敛. + +## 第 8 题 + +考查下列函数项级数在指定区间的一致收敛性. + +(1) $\sum\limits_{n = 2}^{\infty}\ln\left(1 + \dfrac{x}{n\ln^2n}\right), x \in (0, +\infty)$; + +(2) $\sum\limits_{n = 2}^{\infty}\ln\left(1 + \dfrac{x}{n\ln^2n}\right), x \in (-1, 1)$; + +(3) $\sum\limits_{n = 1}^{\infty}\dfrac{n^2}{\sqrt{n!}}(x^n + x^{-n}), \dfrac{1}{3} \le \left|x\right| \le 3$; + +**解** + +(1) 假设 $\sum\limits_{n = 2}^{\infty}\ln\left(1 + \dfrac{x}{n\ln^2n}\right)$ 在 $(0, +\infty)$ 上一致收敛, 则其一般项一致趋于 $0$. 但取 $\epsilon = \ln 2$, $\forall N \in \mathbb{N}^*$, 取 $n = N + 1, x = (N+1)\ln^2(N+1)$, 则 + +$$ +\left|\ln\left(1 + \dfrac{x}{n\ln^2n}\right)\right| = \ln(1 + 1) = \ln2 = \epsilon. +$$ + +这说明其一般项并非一致趋于 $0$., 矛盾. 故 $\sum\limits_{n = 2}^{\infty}\ln\left(1 + \dfrac{x}{n\ln^2n}\right)$ 在 $(0, +\infty)$ 上非一致收敛. + +(2) 由于 $\left|\ln\left(1 + \dfrac{x}{n\ln^2n}\right)\right| \le \left|\dfrac{x}{n\ln^2n}\right| \le \dfrac{1}{n\ln^2n} \quad (-1 { + MathJax.startup.output.clearCache() + MathJax.typesetClear() + MathJax.texReset() + MathJax.typesetPromise() + }) \ No newline at end of file diff --git a/services/homework-ans/mkdocs.yml b/services/homework-ans/mkdocs.yml new file mode 100644 index 0000000..fc2cf23 --- /dev/null +++ b/services/homework-ans/mkdocs.yml @@ -0,0 +1,125 @@ +site_name: 清华大学微积分 A 教材课后习题答案 +theme: + name: material + features: + - content.action.edit + - navigation.tabs + - navigation.instant + - admonition + - pymdownx.details + - pymdownx.superfences +markdown_extensions: + - pymdownx.arithmatex: + generic: true + - pymdownx.critic + - pymdownx.caret + - pymdownx.keys + - pymdownx.mark + - pymdownx.tilde +extra_javascript: + - javascripts/mathjax.js + - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js + +nav: + - '首页': index.md + - '微积分 A(1)': + - '总览': calculus-1/index.md + - '第1章': + - '习题1.1': calculus-1/chapter1/exercise1-1.md + - '习题1.2': calculus-1/chapter1/exercise1-2.md + - '习题1.3': calculus-1/chapter1/exercise1-3.md + - '习题1.4': calculus-1/chapter1/exercise1-4.md + - '习题1.5': calculus-1/chapter1/exercise1-5.md + - '第1章总复习题': calculus-1/chapter1/exercise1-rev.md + - '第2章': + - '习题2.1': calculus-1/chapter2/exercise2-1.md + - '习题2.2': calculus-1/chapter2/exercise2-2.md + - '习题2.3': calculus-1/chapter2/exercise2-3.md + - '习题2.4': calculus-1/chapter2/exercise2-4.md + - '习题2.5': calculus-1/chapter2/exercise2-5.md + - '习题2.6': calculus-1/chapter2/exercise2-6.md + - '第2章总复习题': calculus-1/chapter2/exercise2-rev.md + - '第3章': + - '习题3.1': calculus-1/chapter3/exercise3-1.md + - '习题3.2': calculus-1/chapter3/exercise3-2.md + - '习题3.3': calculus-1/chapter3/exercise3-3.md + - '第3章总复习题': calculus-1/chapter3/exercise3-rev.md + - '第4章': + - '习题4.1': calculus-1/chapter4/exercise4-1.md + - '习题4.2': calculus-1/chapter4/exercise4-2.md + - '习题4.3': calculus-1/chapter4/exercise4-3.md + - '习题4.4': calculus-1/chapter4/exercise4-4.md + - '习题4.5': calculus-1/chapter4/exercise4-5.md + - '习题4.6': calculus-1/chapter4/exercise4-6.md + - '第4章总复习题': calculus-1/chapter4/exercise4-rev.md + - '第5章': + - '习题5.1': calculus-1/chapter5/exercise5-1.md + - '习题5.2': calculus-1/chapter5/exercise5-2.md + - '习题5.3': calculus-1/chapter5/exercise5-3.md + - '习题5.4': calculus-1/chapter5/exercise5-4.md + - '习题5.5': calculus-1/chapter5/exercise5-5.md + - '习题5.6': calculus-1/chapter5/exercise5-6.md + - '习题5.7': calculus-1/chapter5/exercise5-7.md + - '第5章总复习题': calculus-1/chapter5/exercise5-rev.md + - '第6章': + - '习题6.1': calculus-1/chapter6/exercise6-1.md + - '习题6.2': calculus-1/chapter6/exercise6-2.md + - '第6章总复习题': calculus-1/chapter6/exercise6-rev.md + - '第7章': + - '习题7.1': calculus-1/chapter7/exercise7-1.md + - '习题7.2': calculus-1/chapter7/exercise7-2.md + - '习题7.3': calculus-1/chapter7/exercise7-3.md + - '习题7.4': calculus-1/chapter7/exercise7-4.md + - '习题7.5': calculus-1/chapter7/exercise7-5.md + - '习题7.6': calculus-1/chapter7/exercise7-6.md + - '第7章总复习题': calculus-1/chapter7/exercise7-rev.md + - '微积分 A(2)': + - '总览': calculus-2/index.md + - '第1章': + - '习题1.1': calculus-2/chapter1/exercise1-1.md + - '习题1.2': calculus-2/chapter1/exercise1-2.md + - '习题1.3': calculus-2/chapter1/exercise1-3.md + - '习题1.4': calculus-2/chapter1/exercise1-4.md + - '习题1.5': calculus-2/chapter1/exercise1-5.md + - '习题1.6': calculus-2/chapter1/exercise1-6.md + - '习题1.7': calculus-2/chapter1/exercise1-7.md + - '习题1.8': calculus-2/chapter1/exercise1-8.md + - '习题1.9': calculus-2/chapter1/exercise1-9.md + - '第1章总复习题': calculus-2/chapter1/exercise1-rev.md + - '第2章': + - '习题2.1': calculus-2/chapter2/exercise2-1.md + - '习题2.2': calculus-2/chapter2/exercise2-2.md + - '习题2.3': calculus-2/chapter2/exercise2-3.md + - '第2章总复习题': calculus-2/chapter2/exercise2-rev.md + - '第3章': + - '习题3.1': calculus-2/chapter3/exercise3-1.md + - '习题3.2': calculus-2/chapter3/exercise3-2.md + - '习题3.3': calculus-2/chapter3/exercise3-3.md + - '习题3.4': calculus-2/chapter3/exercise3-4.md + - '习题3.5': calculus-2/chapter3/exercise3-5.md + - '第3章总复习题': calculus-2/chapter3/exercise3-rev.md + - '第4章': + - '习题4.1': calculus-2/chapter4/exercise4-1.md + - '习题4.2': calculus-2/chapter4/exercise4-2.md + - '习题4.3': calculus-2/chapter4/exercise4-3.md + - '习题4.4': calculus-2/chapter4/exercise4-4.md + - '习题4.5': calculus-2/chapter4/exercise4-5.md + - '习题4.6': calculus-2/chapter4/exercise4-6.md + - '习题4.7': calculus-2/chapter4/exercise4-7.md + - '第4章总复习题': calculus-2/chapter4/exercise4-rev.md + - '第5章': + - '习题5.1': calculus-2/chapter5/exercise5-1.md + - '习题5.2': calculus-2/chapter5/exercise5-2.md + - '习题5.3': calculus-2/chapter5/exercise5-3.md + - '习题5.4': calculus-2/chapter5/exercise5-4.md + - '第5章总复习题': calculus-2/chapter5/exercise5-rev.md + - '第6章': + - '习题6.1': calculus-2/chapter6/exercise6-1.md + - '习题6.2': calculus-2/chapter6/exercise6-2.md + - '习题6.3': calculus-2/chapter6/exercise6-3.md + - '第6章总复习题': calculus-2/chapter6/exercise6-rev.md + - '第7章': + - '习题7.1': calculus-2/chapter7/exercise7-1.md + - '习题7.2': calculus-2/chapter7/exercise7-2.md + - '第7章总复习题': calculus-2/chapter7/exercise7-rev.md + - '关于': about.md \ No newline at end of file diff --git a/source/CNAME b/source/CNAME new file mode 100644 index 0000000..18bac5a --- /dev/null +++ b/source/CNAME @@ -0,0 +1 @@ +leverimmy.top \ No newline at end of file diff --git a/source/_data/head.swig b/source/_data/head.swig new file mode 100644 index 0000000..d6aa94b --- /dev/null +++ b/source/_data/head.swig @@ -0,0 +1 @@ + diff --git "a/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221Haskell-\344\273\216\345\205\245\351\227\250\345\210\260\345\205\245\345\234\237.md" "b/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221Haskell-\344\273\216\345\205\245\351\227\250\345\210\260\345\205\245\345\234\237.md" new file mode 100644 index 0000000..71cabbd --- /dev/null +++ "b/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221Haskell-\344\273\216\345\205\245\351\227\250\345\210\260\345\205\245\345\234\237.md" @@ -0,0 +1,26 @@ +--- +title: 【学习笔记】Haskell 从入门到入土 +tags: + - Haskell + - Lambda 演算 +categories: + - 笔记 +mathjax: true +toc: true +date: 2024-05-20 20:14:22 +password: +id: Introduction-to-Haskell +--- + +Haskell 从入门到入土。 + + + +## Lambda 演算 + + + +## 基础 + +### 变量类型与运算 + diff --git "a/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\346\225\260\345\255\227\351\200\273\350\276\221\344\270\216\346\225\260\345\255\227\351\233\206\346\210\220\347\224\265\350\267\257.md" "b/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\346\225\260\345\255\227\351\200\273\350\276\221\344\270\216\346\225\260\345\255\227\351\233\206\346\210\220\347\224\265\350\267\257.md" new file mode 100644 index 0000000..fee4c53 --- /dev/null +++ "b/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\346\225\260\345\255\227\351\200\273\350\276\221\344\270\216\346\225\260\345\255\227\351\233\206\346\210\220\347\224\265\350\267\257.md" @@ -0,0 +1,2264 @@ +--- +title: 【学习笔记】数字逻辑与数字集成电路 +tags: + - 数字逻辑电路 +categories: + - 笔记 +mathjax: true +toc: true +date: 2024-02-26 20:14:22 +password: +id: Shuziluoji-Yu-Shuzijichengdianlu +--- + +这是《数字逻辑与数字集成电路(第2版)》的学习笔记。 + +> 你知道全加器的四种画法吗? + +> 2023 年春季学期考过一次全加器,2024 年春应该不会再考一次了吧? + + + +## 第 1 章 数制和编码 + +### 十进制数的二进制编码 + +#### 8421 码(BCD 码) + +8421 码是一种有权码,由于从高到低位权分别为 $8, 4, 2, 1$ 而得名。二进制数 $1010 \sim 1111$ 在 8421 码中没有意义。 + +#### 5421 码 + +5421 码是一种有权码,由于从高到低位权分别为 $5, 4, 2, 1$ 而得名。由于部分十进制数字(例如 $5$ 到底是 $1000$ 还是 $0101$?)的表示可能**会有歧义**,故在实际运用中需要指定码表。 + +#### 2421 码 + +2421 码是一种有权码,由于从高到低位权分别为 $2, 4, 2, 1$ 而得名。歧义性同 5421 码。 + +#### 余三码 + +余三码是一种无权码,由 8421 码加 $(0011)_2$ 而命名。两个余三码 $a, b$ 相加的规则是 + +- 如果 $a + b \le 9$,即没有产生进位,则和为 $a + b - 0011$。 +- 如果 $a + b \ge 10$,则产生进位,所以和为 $10000 + (a + b - 0011) - 1010 = a + b + 0011$。 + - 注意,这里的 $10000 = 1010$,前者的 $1$ 代表着第二个“四位一组”的最低位,由于余三码本质是逢 $10$ 进 $1$,故 $10000 = (10)_{10} = 1010$。 + + +> 规则可以简记为:如果两个余三码相加没有进位,则和数要减 $3$;否则和数要加 $3$。 + +### 格雷码 + +格雷码是一种无权码,特点是**任何两个相邻的十进制数的格雷码仅有一位不同**(Hamming distance 为 $1$)。使用它可以减少代码变换中电路瞬间产生的错误,可靠性较好。 + +![十进制数的 4 种格雷码表](https://img.picgo.net/2024/03/08/1-gray-code840c4a784d6cef9c.png) + +#### 格雷码 1 + +是一种**反射码**,因为 $x$ 和 $10 - x$ 恰好仅有最高位相反。 + +#### 典型格雷码 + +假设待编码数 $x = \sum_{i = 0}^{n - 1}b_i\cdot2^i$,则典型格雷码 $y = \sum_{i = 0}^{n - 1} = g_i\cdot 2^i$ 满足 $g_i = b_{i +1}\oplus b_i$。 + +#### 修改格雷码 + +修改格雷码等于典型格雷码加 $(0011)_2$。 + +### ASCII 码 + +![美国信息交换代码 ASCII CODE](https://img.picgo.net/2024/03/08/1-ascii-code8f157ad715e57c9d.png) + +- 数字:高三位 $011$。 +- 大写字母:高三位 $100$。 +- 小写字母:高三位 $110$。 + +~~说明人们在设计 ASCII 的时候还是动了脑子的。~~ + +## 第 2 章 逻辑代数及逻辑函数的化简 + +### 逻辑代数的基本原理 + +#### 基本公式 + +个人认为最重要的公式只有一个: +$$ +(\text{consensus})\; +\begin{cases} +AB + \overline{A}C + BC = AB + \overline{A}C \\ +(A+B)(\overline{A}+C)(B+C) = (A+B)(\overline{A}+C) +\end{cases} +$$ +与运算的吸收律是 $B = \text{T}$ 的特例: +$$ +\text{(absorption)}\; A + \overline{A}C = A + C +$$ + +> 使用公式法化简,最终很容易忘记使用吸收律。例如,得到答案 +> $$ +> AD+ BC + \overline{A} +> $$ +> 是不对的,应为 $D + BC + \overline{A}$。 + +#### 反演规则和对偶规则 + +**反演规则**本质上是 De Morgan 律的使用。$\overline{F}$ 是 $F$ 经过以下操作: + +- 将所有“与”替换为“或”,“或”替换为“与” +- 将所有变量替换为反变量,反变量替换为原变量 +- 将所有 $0$ 替换为 $1$,$1$ 替换为 $0$ + +之后得到的结果。反演规则可以帮助我们方便地求出一个函数的反函数。 + +**对偶规则**是指,对偶式 $F'$ 是 $F$ 经过以下操作: + +- 将所有“与”替换为“或”,“或”替换为“与” +- 将所有 $0$ 替换为 $1$,$1$ 替换为 $0$ + +之后得到的结果。关于对偶规则有一个显然的结论:如果 $F = G$,则 $F' = G'$。 + +显然,$(F')' = F$。 + +#### 附加公式(不考) + +**附加公式**本质上是一种通过枚举函数 $f$ 中的某一变量 $x$ 的真假来化简函数的方法。 + +附加公式一: +$$ +\begin{align*} +x \cdot f(x, \overline{x}, y, \cdots, z) & = x \cdot f(1, 0, y, \cdots, z) \\ +\overline{x} \cdot f(x, \overline{x}, y, \cdots, z) & = \overline{x} \cdot f(0, 1, y, \cdots, z) \\ +x + f(x, \overline{x}, y, \cdots, z) & = x + f(0, 1, y, \cdots, z) \\ +\overline{x} + f(x, \overline{x}, y, \cdots, z) & = \overline{x} + f(1, 0, y, \cdots, z) +\end{align*} +$$ +附加公式二: +$$ +\begin{align*} +f(x, \overline{x}, y, \cdots, z) & = x\cdot f(x, \overline{x}, y, \cdots, z) + \overline{x} \cdot f(x, \overline{x}, y, \cdots, z) \\ +& = x\cdot f(1, 0, y, \cdots, z) + \overline{x} \cdot f(0, 1, y, \cdots, z) \\ +f(x, \overline{x}, y, \cdots, z) & = [x + f(x, \overline{x}, y, \cdots, z)]\cdot[\overline{x} + f(x, \overline{x}, y, \cdots, z)] \\ +& = [x + f(0, 1, y, \cdots, z)]\cdot[\overline{x} + f(1, 0, y, \cdots, z)] +\end{align*} +$$ + +### 逻辑函数的化简 + +化简的要求: + +1. “与”项(即乘积项)的个数最少; +2. 在满足上述条件的情况下,每个乘积项的变量数最少。 + +#### 公式法 + +个人认为最常见的是这个循环对称式: +$$ +A\overline{B} + B\overline{C} + \overline{A}C +$$ +事实上,它可能还会以其他形式出现: +$$ +\begin{align*} +A\overline{B} + B\overline{C} + \overline{A}C & = A\overline{B} + B\overline{C} + \overline{A}C + (\overline{A}B + \overline{B}C + A\overline{C}) \\ +& = A\overline{B} + B\overline{C} + \overline{A}C + \overline{A}B \\ +& = \cdots +\end{align*} +$$ +也就是说,这个循环对称式可以加上“所有变量取反后得到的另一个循环不变式”中的**任意子集**。 + +有时也会出现 +$$ +\overline{A}\;\overline{B} + A\overline{C} + BC, +$$ +只需要看出它是 $B \gets{\overline{B}}$ 的一个代入即可。 + +#### Karnaugh 图法 + +![Karnaugh 图](https://img.picgo.net/2024/03/08/2-karnaugh-18f7ba5a5a8e8f79b.jpeg) + +**Karnaugh 图的构造**:二至五变量的表格横纵坐标分别为 $B\backslash A, C\backslash BA, DC\backslash BA, ED\backslash CBA$,可以看出个数是增加到行/增加到列交替进行的。横纵编号,相邻两个的变化也是有规律的:从最右侧的一位开始,考虑该位被翻转后得到的数字是否已经出现过,如果出现过则按从右到左的顺序考虑下一位;否则写下这个数字。 + +例如五变量 Karnaugh 图的横坐标:首先是 $000$,然后发现最右侧一位翻转得到的 $001$ 并未出现过,所以写下 $001$。$001$ 的最右侧一位翻转得到的 $000$ 出现过,所以考虑右数第二位翻转,即 $011$。此时最右侧一位翻转得到的 $010$ 并未出现过,写下 $010$。以此类推,得到 +$$ +000,001,011,010,110,111,101,100. +$$ +**Karnaugh 图的化简**:包含一个最小项的小方块被称为 $0$ 维块,包含 $2$ 个 $n$ 维块的块被称为 $n+1$ 维块。Karnaugh 图化简的目的在于 + +最终覆盖所有值为 $1$ 的最小项,且所用覆盖尽可能用高维块。 + +- 左右边界是“循环”的,所以也相邻; +- 同理可以推出,四个角的方块也相邻; +- 五变量卡诺图注意“相重”,即左右对称。 + +![五变量 Karnaugh 图的化简](https://img.picgo.net/2024/03/08/2-karnaugh-285392fed8a4999cb.jpeg) + +似乎题干有误,最后一项应为 $A\overline{B}CD\overline{E}$。上述例子中重点之一在于利用“相重”写出 $ABE$ 这一项。 + +> 需要注意的一点是,如果一个**高维块被几个必需的低维块所覆盖**,则**不应包含**该高维块。 +> +> 每次 Karnaugh 图化简完后,一定要检查是否有冗余的块! + +求某一函数 $F$ 的反函数的化简也可以使用卡诺图:考虑覆盖为 $0$ 的块即可。 + +#### Quine-McCluskey 化简法(不考) + +~~这玩意儿是真复杂,要是手算真不如 Karnaugh 图。~~ + +~~不考。亏我还看书看了那么长时间。~~ + +Quine-McCluskey 化简法遵循两个步骤: + +1. 求出全部的质蕴含项; +2. 从质蕴含项中选出必要质蕴涵项。 + +**求出全部的质蕴含项**: + +- 对于函数内出现过的最小项按照二进制数取值中 $1$ 的个数由少至多分组,每组内最小项按照从小到大排列。 +- 相邻组看是否能合并,例如: + - $0001$ 和 $0011$ 合并为 $00-1$; + - $00-1$ 和 $10-1$ 合并为 $-0-1$。 + - 如果能合并,就在两原项后打 $\checkmark$。 +- 直到无法合并为止。此时没有 $\checkmark$ 的项即为质蕴含项,记为 $P_1, P_2, \cdots$。 + +考虑求 $F = f(A, B, C, D) = \sum m^4(0, 4, 6, 8, 10, 11, 13, 14, 15)$ 的全部质蕴含项过程如下: + +![求全部质蕴含项](https://img.picgo.net/2024/03/08/2-prime-implicants-1013965303e7ccccb.jpeg) + +**选出必要质蕴含项**: + +- 对于两**行**来说,如果 $a$ 行是 $b$ 行的**子集**,那么将 $a$ 行删去; +- 对于两**列**来说,如果 $a$ 行是 $b$ 行的**超集**,那么将 $a$ 行删去。 + +最终剩下的质蕴含项即为必要质蕴涵项。值得注意的是,行、列消去中先进行哪个消去并不影响简化结果。 + +仍使用上例,过程如下: + +![选出必要质蕴含项](https://img.picgo.net/2024/03/08/2-prime-implicants-2fa49df4d4df455be.jpeg) + +最终必要质蕴含项为 $P_1, P_2, P_3, P_4, P_5$。化简后的答案为 +$$ +F = P_1 + P_2 + P_3 + P_4 + P_5 = \overline{A}\;\overline{B}CD + \overline{B}\;\overline{C}\;\overline{D} + BC\overline{D} + A\overline{C} + AB. +$$ + +#### 多输出逻辑函数的 Quine-McCluskey 化简法(不考) + +尽管每个函数不是最简,但是只要找到函数的公共“与”项,就能达到最佳的总体效果。 + +**求出各个函数的公共质蕴含项**: + +在表上分别写 $F_1, F_2, \cdots$ 列,用 $\triangle$ 来表示某个最小项属于哪些函数。假设包含 $m_i$ 的函数集合为 $\mathscr{F}$,包含 $m_j$ 的函数集合为 $\mathscr{G}$,则 $m_i$ 和 $m_j$ 可以合并,当且仅当 $m_i$ 和 $m_j$ 相邻,且 $\mathscr{F} \cap \mathscr{G} \neq \varnothing$。 + +只有当 $\mathscr{F} \subset \mathscr{G}$ 的时候,才能在 $\mathscr{F}$ 的后面打 $\checkmark$。 + +**选出必要质蕴含项**: + +区别在于,列消去只能在在 $F_1, F_2, \cdots$ 每组内使用,而不能跨组使用。行消去和之前的做法相同。最终得到必要质蕴含项表。 + +**确定每个函数的必要质蕴含项**: + +属于多个函数的必要质蕴涵项中只有部分与单一函数有关,所以还需要进一步计算,从中选出每个函数的必要质蕴涵项。对于函数 $F_i$ 而言,把必要质蕴涵表中与 $F_i$ 相关的项单独列出来并进行消去,最终得到 $F_i$ 的必要质蕴涵项。 + +#### 包含任意项的逻辑函数的化简 + +**使用 Karnaugh 图**:将任意项的小方块中填入 $\phi$,它可以等于 $1$ 也可以等于 $0$,以最方便的为准(但是一旦确定了之后就必须固定下来)。比如此例中的任意项 $12$,它作为 $0$ 来考虑;而任意项 $3,9,15$ 均作为 $1$ 来考虑。 + +![包含任意项的逻辑函数化简](https://img.picgo.net/2024/03/08/2-any02a0a8b7d82997f6.jpeg) + +**使用 Quine-McCluskey 化简法**:将任意项当做最小项之一参与相邻项的合并,但在最后的结果中并不把任意项当做质蕴含项列出,也不参与必要质蕴涵项的筛选。 + +#### 不同形式逻辑函数的变换及化简(不考) + +**“与或”变为“与非-与非”**:两次求反。例如 $F = AB+AC+AD$, +$$ +F = \overline{\overline{F}} = \overline{\overline{AB+AC+AD}} = \overline{\overline{AB} \cdot \overline{AC} \cdot \overline{AD}} +$$ +**“与或”变为“或非-或非”**:将对偶式求最简与非-与非表达式后再对 回来。例如 $F = AB+A\overline{C}+\overline{A}C$, +$$ +\begin{align*} +F' & = (A+B)(A+\overline{C})(\overline{A}+C) \\ +& = \overline{A}B\overline{C}+AC+ABC \\ +F' & = \overline{\overline{F'}} \\ +& = \overline{\overline{\overline{A}B\overline{C}+AC+ABC}} \\ +& = \overline{\overline{\overline{A}B\overline{C}} \cdot \overline{AC} \cdot \overline{ABC}} \\ +F & = (F')' \\ +& = \overline{\overline{\overline{A} + B +\overline{C}} + \overline{A + C} + \overline{A + B + C}} +\end{align*} +$$ +**“与或”变为“或与非”**:(用 Karnaugh 图等方式)求出 $\overline{F}$ 的与或表达式 $G$,再求 $\overline{G}$。例如 $F = AB+\overline{B}\;\overline{C}+ AB\overline{C}+\overline{A}B\overline{C}+\overline{A}\;\overline{B}\;\overline{C}$。 + +用 Karnaugh 图求得 $\overline{F} = \overline{A}C+\overline{B}C$,则 +$$ +\begin{align*} +F & = \overline{\overline{F}} \\ +& = \overline{\overline{A}C+\overline{B}C} +\end{align*} +$$ +**“与或”变为“或与”**:同“或与非”,只是最后还需要再化简一次,例如上例中 $F = \overline{\overline{A}C+\overline{B}C}$。 +$$ +\begin{align*} +F & = \overline{\overline{A}C+\overline{B}C} \\ +& = (A+\overline{C})(B+\overline{C}) +\end{align*} +$$ +**“或与”变为“或非-或非”**:对偶-化简-对偶-两次求反。例如 $F = (\overline{A}+\overline{B})(\overline{A}+\overline{C}+\overline{D})(A+C)(B+\overline{C})$。 +$$ +\begin{align*} +F' & = \overline{A}\;\overline{B} + \overline{A}\;\overline{C}\;\overline{D}+AC+B\overline{C} \\ +& = \overline{A}\;\overline{B} + AC + B\overline{C} \\ +F & = (F')' \\ +& = (\overline{A}+\overline{B})(A+C)(B+\overline{C}) \\ +F & = \overline{\overline{F}} \\ +& = \overline{\overline{(\overline{A}+\overline{B})(A+C)(B+\overline{C})}} \\ +& = \overline{\overline{\overline{A}+\overline{B}} + \overline{A+C} + \overline{B+\overline{C}}} +\end{align*} +$$ + +## 第 3 章 集成门电路与触发器 + +### 组合逻辑电路引言 + +#### 组合逻辑电路的特点 + +电路的输出仅与输入的当前状态有关,和过去的状态无关;区别于与过去的状态有关的**时序逻辑电路**。 + +#### 集成逻辑电路的分类 + +- 按**功能**分类: + - 模拟电路 + - 数字电路 +- 按**半导体制造工艺**分类: + - TTL + - MOS +- 按**封装(外形)**分类: + - 双列直插 + - 表面封装 + - BGA(Ball Grid Array) + - PLCC +- 按**集成规模**分类:小、中、大、超大(Very Large)、甚大(Ultra Large)规模集成电路 + +#### 两大类半导体制造工艺技术的特点 + +| 工艺技术 | 速度 | 功耗 | 集成度 | +| :------: | :--: | :--: | :----: | +| TTL | 快 | 大 | 低 | +| MOS | 慢 | 小 | 高 | + +目前常用器件使用 CMOS(互补金属氧化物半导体)工艺。 + +### TTL 门电路 + +#### 正逻辑与负逻辑 + +**正逻辑**:高电平为 $1$,低电平为 $0$,即 $\text{H} = 1, \text{L} = 0$; + +**负逻辑**:高电平为 $0$,低电平为 $1$,即 $\text{H} = 0, \text{L} = 1$。 + +在不同逻辑下,同一个逻辑门电路实现的功能不同,例如 + +| $A$ | $B$ | $F$ | +| :--------: | :--: | :--: | +| $\text{L}$ | $\text{L}$ | $\text{H}$ | +| $\text{H}$ | $\text{L}$ | $\text{H}$ | +| $\text{L}$ | $\text{H}$ | $\text{H}$ | +| $\text{H}$ | $\text{H}$ | $\text{L}$ | + +在正逻辑下表示与非门 $F = \overline{AB}$,但在负逻辑下表示或非门 $F = \overline{A+B}$。 + +> **注意**:本博客遵循教材和 PPT 的习惯,采用**正逻辑**。 + +#### 典型的 TTL 门电路(不考) + +~~学不会;幸亏不考。~~ + +#### TTL 与非门电路的外部特性与级联 + +**技术参数**: + +- 扇入:一个门的可用**输入**数目 +- 扇出:一个门的输出可以**驱动**的标准门个数 +- 功耗:逻辑门消耗的能量,以热的形式散发 +- …… + +**传输延迟**:从输入传输到输出所需要的时间。电路的处理速度与电路门的最大传输延迟成反比例关系。 + +- 最大值和最小值的 $50\%$ 点作为时间参考点 +- 高到低($t_{\text{PHL}}$)或低到高($t_{\text{PLH}}$)的输出信号改变可能有不同的传输延迟: + $$ + t_{\text{Pd}} = \dfrac{1}{2}(t_{\text{PHL}} + t_{\text{PLH}}). + $$ +- 高到低或低到高跃迁是根据**输出关系**定义的,而不是输入关系。 + - 如果是非门,则输出和输入跃迁相反 + - 如果是同相门,则输出和输入跃迁相同 + + 也就是说,看的是**输出信号**是从低到高还是从高到低跃迁。 +- 测量传输延迟 + $$ + t_{\text{Pd}} = \frac{1}{\text{number of gates}} \cdot \frac{t_{\text{Pd}_1} + t_{\text{Pd}_2}}{2}. + $$ +- 传输延迟的一个应用是**自激震荡** + + 最后一个门输出的信号与最先一个门输入的信号相反,则会产生自激震荡。 + + > **注意**:自激振荡的周期是 $2t_{\text{Pd}} \cdot \text{number of gates}$,原因是一个门会有上升沿和下降沿两次延迟。 + +**转移特性**:门电路中输出电压随输入电压的变化特性。 + +![V_IN-V_OUT关系曲线](https://img.picgo.net/2024/03/18/3-v-in-v-out24c859ec1da02932.jpeg) + +在曲线上 $V_{\text{OUT}}$ 急剧下降时的 $V_{\text{IN}}$ 称为阈值电压 $V_{\text{T}}$,也称门槛电压。 + +**直流参数**: + +| 输入端 | 输入电流 | 输出电流 | 输出电压 | +| :----: | :------------------------------------: | :----------------------------------: | :-----------------------------------------------: | +| $0$ | $I_{\text{IL}} \le 1.6\;\mathrm{mA}$ | $I_{\text{OH}} \le 0.4\;\mathrm{mA}$ | $V_{\text{OH}} \ge 3\;\mathrm{V}$(10 个负载) | +| $1$ | $I_{\text{IH}} \le 40\;\mathrm{\mu A}$ | $I_{\text{OL}} \le 16\;\mathrm{mA}$ | $V_{\text{OL}} \le 0.35\;\mathrm{V}$(10 个负载) | + +**噪音容限**:在前一级输出为最坏的情况下,为保证后一级正常工作,所允许的最大噪声幅度。噪音容限时叠加到正常输入值的最大的外部噪音电压,它不会在电路的输出产生不可预料的变化。 + +![与非门的电压传输特性曲线](https://img.picgo.net/2024/03/18/3-noise-marginc73a962d698ef511.jpeg) + +图中假设 $V_{\text{O}} = f(V_{\text{I}})$,则在确定 $V_{\text{ON}}$ 和 $V_{\text{OFF}}$ 后,有 +$$ +\begin{align*} +V_{\text{NL}} = V_{\text{OFF}} - f(V_{\text{ON}}), \\ +V_{\text{NH}} = f(V_{\text{OFF}}) - V_{\text{ON}}. +\end{align*} +$$ +$V_{\text{NL}}$ 的意义是,可将低电平输入信号 $\text{L}$ 破坏的最小噪声,$V_{\text{NH}}$ 的意义是,可将高电平输入信号 $\text{H}$ 破坏的最小噪声。 + +#### TTL 与非门电路的级联 + +**级联**:前一个器件的输出就是后一个器件的输入,后一个是前一个的负载,两者要相互影响。 + +**负载计算**: +$$ +\begin{align*} +I_{\text{OH}} = N \cdot I_{\text{IH}}, \\ +I_{\text{OL}} = N \cdot I_{\text{IL}}. +\end{align*} +$$ +当负载数量超过理论值时,门电路进入非正常工作状态。负载大于与非门承受能力时,**低电平变高,高电平变低**。 + +#### 集电极开路(OC)与非门 + +**线与逻辑**:两个输出端(包括两个以上)直接互连就可以实现逻辑与的逻辑功能。 + +**普通与非门线与的问题** + +普通与非门不能直接线与在一起,因为 Totem 输出结构的电路,是不能把它们的输出线与在一起的。 + +否则,当一门电路的输出为 $H$,另一门输出为 $L$ 时,有大电流从 $H$ 端流向 $L$ 端,电流太大,会烧坏与非门。 + +**集电极开路输出(OC)与非门** + +![OC 与非门](https://img.picgo.net/2024/03/18/3-oc-gatefa97785d51166f90.jpeg) + +缺点:由于 OC 门输出不是 Totem 结构,电路的上升延迟很大。 + +- T5 退饱和很慢。 +- 对输出负载的充电电流只能通过外接的 $R_{\text{L}}$ 来提供。因此,输出波形的上升沿时间很大。 +- 采用 OC 门只适合速度较慢的电路,对于速度要求较快(例如 CPU 的数据总线),就不能使用 OC 门。 + +> **注意**:OC 门**不可以**和普通与非门实现线与。 + +#### 三态门 + +**特点**: + +- 三态门电路既保留了 Totem 输出结构,又具有 OC 门输出可以“线与”的特点 +- 完成“线与”逻辑的**速度较快** + +![三态门](https://img.picgo.net/2024/03/18/3-tri-state-gate771633b5c45583f9.jpeg) + +**功能表**: + +> **注意**:这里的 $\overline{G}$ 是一个记号,是一个整体,而不是 $G$ 的补。 + +| $A$ | $B$ | $\overline{G}$ | $F$ | +| :--: | :--: | :------------: | :------------------: | +| - | - | $0$ | $\text{Z}$(高阻态) | +| $0$ | $0$ | $1$ | $1$(正常态) | +| $1$ | $0$ | $1$ | $1$(正常态) | +| $0$ | $1$ | $1$ | $1$(正常态) | +| $1$ | $1$ | $1$ | $0$(正常态) | + +值得注意的是,三态门有不止一种画法,不同的三态门的功能表并不相同;但它们的共同点是,从侧面**输入**的信号如果为 $0$,则为高阻态;否则为正常态。 + +例如下面的第一种三态门,$\overline{G} = 1$,经过非门导致三态门的侧面输入实际为 $0$,因此为高阻态。 + +![两种基本的三态与非门](https://img.picgo.net/2024/03/18/3-two-fundamentala301cd3517d70b27.jpeg) + +**应用**: + +- 两个三态门和总线(BUS)通过线与相连 + ![三态总线的状态转换](https://img.picgo.net/2024/03/18/3-buseeaca06f46896f0c.jpeg) + + - 同时只能有一个三态门处于正常态,否则门 1、2 输出间有很大的浪涌电流从而影响 BUS 正常工作 + - 因此,三态电路由正常态转到高阻态的延迟,应小于由高阻态转到正常态的延迟 + - 状态转换时应**先将正常态的一方转为高阻态**,**再将高阻态的一方转为正常态** + +- 1 位双向总线驱动器(Transceiver,收发器) + ![1 位双向总线驱动器](https://img.picgo.net/2024/03/18/3-1-transceiver9bf4aae136b441a7.jpeg) + + 图中箭头方向即为数据传输方向,也是电流传输方向。 + +- 4 位双向总线驱动器 + ![4 位双向总线驱动器](https://img.picgo.net/2024/03/18/3-4-transceiver078437a08bd2b312.jpeg) + + > **注意**:此例中 $E = 0$ 为读操作,$E = 1$ 为写操作;与上一例子相反。 + + ![举例](https://img.picgo.net/2024/03/18/3-example0dff2902afdec130.jpeg) + + 整体的规律是: + + - 首先判断哪个三态门是输入的工作端(正常态) + - 然后判断总线是高电平还是低电平 + - 如果是高电平($1$ 态),则其余(包括高阻态)电流都朝外 + - 如果是低电平($0$ 态),则其余(包括高阻态)电流都朝里 + - 最后标注电流符号 + - 输入端 + - 如果是正常态的三态门,则为 $I_{\text{OH}}$ 或 $I_{\text{OL}}$ + - 如果是高阻态的三态门,则为 $I_{\text{OZ}}$ + - 输出端 + - 如果是正常态的三态门,则为 $I_{\text{IH}}$ 或 $I_{\text{IL}}$ + - 如果是高阻态的三态门,则为 $I_{\text{IZ}}$ + - 这里输入端为 $I_{\text{O}}$,输出端为 $I_{\text{I}}$ 的原因是,电流符号是相对于**三态门**的。输入端与 BUS 相连的导线恰为三态门的输出,故为 $I_{\text{O}}$。 + +> **注意**:三态门在保证控制信号符合三态门要求的情况下可以线与,其他情况均不可以线与。 + +### 触发器 + +触发器是一种存储 1 位二进制数的记忆元件,英文缩写为 FF(Flip-flop)。 + +触发器可以按照触发(时钟控制)方式分类,也可以按照功能分类。 + +**按时钟控制分类**: + +- 电位触发(Level Trigger)方式 FF +- 边沿触发(Edge Trigger)方式 FF +- 主-从触发(Master-slave,或称为 Pulse Trigger)方式 FF + +**按功能分类**: + +- D 触发器(Delay) +- R-S 触发器(Reset-set) +- J-K 触发器 +- T 触发器(Toggle) + +#### 基本 R-S 触发器 + +**基本组成** + +R-S 触发器有两个输入端 $R, S$ 和两个输出端 $Q, \overline{Q}$。当触发器正常工作时,$Q$ 和 $\overline{Q}$ 两个输出端为互补关系。 + +一般规定用 $Q$ 的状态代表触发器的状态: + +- 若 $Q = 0, \overline{Q} = 1$,则称触发器处于“0”状态,也称**置位**状态。 +- 若 $Q = 1, \overline{Q} = 0$,则称触发器处于“1”状态,也称**复位**状态。 + +一般称 $S$ 为置“1”端,也称置位端;称 $R$ 为置“0”端,也称复位端。 + +- 实质上,与非门构成的触发器的状态变化,是由在输入端引入“0”引起的。 +- 若 $S = R = 1$,则 $Q = \overline{Q} = 1$,破坏了触发器所规定的 $Q$ 和 $\overline{Q}$ 的互补关系,此时触发器**既不表示“1”状态,也不表示“0”状态**。 + + > **注意**:此时当 $S, R$ 同时由“0”跳变成“1”时,触发器究竟变成“0”还是“1”状态是随机的,触发器状态将是不确定的。 +- 正常工作条件:$\overline{R}\;\overline{S} = 0$。 + +**逻辑图** + +![基本 R-S 触发器](https://img.picgo.net/2024/04/15/3-L-R-Sa0a4a74540b64f22.jpeg) + +**功能表** + +| $R$ | $S$ | $Q$ | $\overline{Q}$ | +| :--: | :--: | :---: | :--------------: | +| $1$ | $0$ | $0$ | $1$ | +| $0$ | $1$ | $1$ | $0$ | +| $1$ | $1$ | $Q_0$ | $\overline{Q_0}$ | +| $0$ | $0$ | $1^*$ | $1^*$ | + +> **注意**:R-S 触发器也有不同的画法,例如将上例中的与非门改为或非门(或是,改为与或非门)。此时,功能表也会有相应的变化。可以通过观察 $R = S = 1$ 和 $R = S = 0$ 判断出哪一种输入描述的是非法工作状态,以及此时 $Q = \overline{Q} = 0$ 还是 $Q = \overline{Q} = 1$。 + +#### 电位触发方式的触发器 + +当触发器的同步控制信号 $E$ 为约定的状态时,触发器接收数据,输入数据的任何变化都会在输出端得到反映。 + +当 $E$ 为非约定状态时,触发器的状态保持不变。 + +**某种电位触发器** + +此例中,$E = 0$ 为约定状态。 + +![某种电位触发器](https://img.picgo.net/2024/04/15/3-Latch-109b37e9d3e25b82b.jpeg) + +功能表: + +| $E$ | $R$ | $S$ | $Q$ | $\overline{Q}$ | +| :--: | :--: | :--: | :---: | :--------------: | +| $1$ | - | - | $Q_0$ | $\overline{Q_0}$ | +| $0$ | $1$ | $1$ | $Q_0$ | $\overline{Q_0}$ | +| $0$ | $0$ | $1$ | $1$ | $0$ | +| $0$ | $1$ | $0$ | $0$ | $1$ | +| $0$ | $0$ | $0$ | $1^*$ | $1^*$ | + +**R-S 型电位触发器** + +为了保证结构的一致性,增加控制端后构成的 R-S 触发器也**全用与非门**。$E = 1$ 为约定状态。 + +![R-S 型电位触发器](https://img.picgo.net/2024/04/15/3-Latch-2634174493da29257.jpeg) + +> **注意**:此时 $S$ 和 $R$ 在输入后经过了一级与非门,所以输出端 $Q$ 和 $\overline{Q}$ 的位置与之前有所不同。 + +功能表: + +| $E$ | $R$ | $S$ | $Q$ | $\overline{Q}$ | +| :--: | :--: | :--: | :---: | :--------------: | +| $0$ | - | - | $Q_0$ | $\overline{Q_0}$ | +| $1$ | $0$ | $0$ | $Q_0$ | $\overline{Q_0}$ | +| $1$ | $0$ | $1$ | $1$ | $0$ | +| $1$ | $1$ | $0$ | $0$ | $1$ | +| $1$ | $1$ | $1$ | $1^*$ | $1^*$ | + +- 特点:当 $E = 0$ 时能保持触发器状态不被破坏。 +- 问题:当 $ERS = 1$ 时,同样存在不定状态。 + +**电位型 D 触发器** + +> 如何解决 R-S 型电位触发器 $ERS = 1$ 时仍存在不定状态的问题呢? +> +> **分析**: +> +> - 控制端可以保证状态保持; +> - 当 $\overline{R}\;\overline{S} = 1$ 时,状态保持,其功能与控制端重复; +> - 当 $R \oplus S = 1$ 时,为正常工作状态。 +> +> **解决办法**: +> +> - 控制端控制状态保持; +> - 输入端保证 $R \oplus S = 1$。 +> +> **设计**: +> +> - R-S 型电位触发器的输入由 $R, S$ 双端输入改为单端输入,则不会出现不定状态。 + +![修改后的 R-S 型电位触发器](https://img.picgo.net/2024/04/15/3-Latch-37561d9dc0efdd218.jpeg) + +> **存在的问题**:从 $D$ 输入到 $Q$ 和 $\overline{Q}$ 稳定需要**四级门延迟**。尽可能减小延迟可以提高触发器的工作速度。 + +![电位型 D 触发器](https://img.picgo.net/2024/04/15/3-L-De70dfacb22c01dba.jpeg) + +- $E = 1$,$D$ 以互补形式进入,进行 store 操作。 +- $E = 0$,$D$ 被封锁,进行 hold 操作。 + +> **注意**:此时 $D$ 作为原来的 set 端(即 $S$),没有经过一级与非门,所以输出端 $Q$ 和 $\overline{Q}$ 的位置恢复从前。 + +功能表: + +| $E$ | $D$ | $Q$ | $\overline{Q}$ | +| :--: | :--: | :---: | :--------------: | +| $1$ | $D$ | $D$ | $\overline{D}$ | +| $0$ | - | $Q_0$ | $\overline{Q_0}$ | + +- 特点: + - 电位型 D 触发器在控制电位 $E$ 的控制下接收数据,消除了不定状态。 + - $E = 1$ 电位一到,触发器就接收数据,所以叫“电位触发器”,也叫“锁存器”。 +- 问题: + - 抗干扰能力差,容易发生空翻现象。 + - 如何解决? + - 考虑使用边沿触发方式的触发器:接收使能(时钟)脉冲某一跳变来到时,输出才变化为输入的值。 + + +#### 边沿触发方式的触发器 + +- 触发器只有在时钟输入 $\text{CP}$ 的某一约定跳变(正跳变 $\uparrow$ 或负跳变 $\downarrow$)到来时,才接收输入数据。 +- 当 $\text{CP}$ 没有跳变期间($\text{CP} = 0$ 或 $\text{CP} = 1$),输入数据的变化不会引起触发器输出状态的变化。 +- 当 $\text{CP}$ 的非约定跳变到来时,触发器也不会接收输入数据。 + +**正边沿触发的 D 型触发器** + +逻辑图: + +![正边沿触发的 D 型触发器](https://img.picgo.net/2024/04/15/3-E-D-positivebcb3d08d0a4c72d4.jpeg) + +- 最左侧线被称为**维持“0”阻塞“1”线**,这是因为若正边沿跳变时有 $D = 0$,则门 3 输出由 $1$ 变为 $0$,这导致门 5 的输出自此恒为 $1$,无论 $D$ 如何改变。顶部的 R-S 触发器维持着 $Q = 0$。 +- 最右侧线被称为**维持“1”阻塞“0”线**,这是因为若正边沿跳变时有 $D = 1$,则门 4 输出由 $1$ 变为 $0$,这导致门 6 的输出自此恒为 $1$,无论 $D$ 如何改变。顶部的 R-S 触发器维持着 $Q = 1$。 + +总而言之,时钟正边沿跳变后,在 $\text{CP} = 1$ 时,$Q$ 只由那一时刻 $D$ 的状态决定;输出的状态不再受 $D$ 变化的影响。 + +功能表: + +| $\text{CP}$ | $D$ | $Q$ | $\overline{Q}$ | +| :------------------------: | :--: | :---: | :--------------: | +| $\uparrow$ | $D$ | $D$ | $\overline{D}$ | +| $0$ 或 $1$ 或 $\downarrow$ | - | $Q_0$ | $\overline{Q_0}$ | + +**带有异步置位端的正边沿 D 型触发器** + +![带有异步置位端的正边沿 D 型触发器](https://img.picgo.net/2024/04/15/3-E-D-positive-R-S338d1e951fa7a711.jpeg) + +功能表: + +| $\overline{R_D}$ | $\overline{S_D}$ | $\text{CP}$ | $D$ | $Q$ | $\overline{Q}$ | +| :--------------: | :--------------: | :------------------------: | :--: | :---: | :--------------: | +| $0$ | $1$ | - | - | $0$ | $1$ | +| $1$ | $0$ | - | - | $1$ | $0$ | +| $1$ | $1$ | $\uparrow$ | $0$ | $0$ | $1$ | +| $1$ | $1$ | $\uparrow$ | $1$ | $1$ | $0$ | +| $1$ | $1$ | $0$ 或 $1$ 或 $\downarrow$ | - | $Q_0$ | $\overline{Q_0}$ | + +只要 $\overline{R_D} = 0$,触发器就有 $Q = 0, \overline{Q} = 1$;只要 $\overline{S_D} = 0$,触发器就有 $Q = 1, \overline{Q}= 0$。 + +> **疑问**:如果 $\overline{R_D}$ 和 $\overline{S_D}$ 同时为 $0$ 呢? +> +> **解答**:一般它们在工业设计上会控制它们互锁。 + +**负边沿触发的 J-K 触发器** + +负边沿 J-K 触发器是利用触发器**内部门电路的延迟时间不同**来实现负沿触发的。 + +![负边沿触发的 J-K 触发器](https://img.picgo.net/2024/04/25/4-J-K100e8eb3c609b726.jpeg) + +要求:$t_{\text{Pd, nand gate}} > 2\times t_{\text{Pd, and-or-not gate}}$。这是因为当负边沿触发时,置 $0$ 或置 $1$ 操作时,$K$ 或 $J$ 所连接的与非门接收到了 $\text{CP}$ 的信号,但是输出端需要在新的 $Q$ 或 $\overline{Q}$ 信号传递到与非门时再更新;而该过程需要经过两个与或非门。 + +功能表: + +| $\overline{R_D}$ | $\overline{S_D}$ | $\text{CP}$ | $J$ | $K$ | $Q$ | $\overline{Q}$ | 功能 | +| :--------------: | :--------------: | :----------------------: | :--: | :--: | :--------------: | :--------------: | :--------- | +| $0$ | $1$ | - | - | - | $0$ | $1$ | 异步清 $0$ | +| $1$ | $0$ | - | - | - | $1$ | $0$ | 异步置 $1$ | +| $1$ | $1$ | $\downarrow$ | $0$ | $1$ | $0$ | $1$ | 置 $0$ | +| $1$ | $1$ | $\downarrow$ | $1$ | $0$ | $1$ | $0$ | 置 $1$ | +| $1$ | $1$ | $\downarrow$ | $0$ | $0$ | $Q_0$ | $\overline{Q_0}$ | 保持 | +| $1$ | $1$ | $\downarrow$ | $1$ | $1$ | $\overline{Q_0}$ | $Q_0$ | 翻转 | +| $1$ | $1$ | $0$ 或 $1$ 或 $\uparrow$ | - | - | $Q_0$ | $\overline{Q_0}$ | 保持 | + +#### 电位触发器和边沿触发器间的比较 + +1. 输入数据 + - 对于**电位触发器**,只要 $E$ 为约定的接收数据电平,数据来到后就立即被接受;但是,如果电位触发器的输入数据在 $E$ 的约定电平期间撤除,那么,触发器的状态也将随之改变。 + - 因此,若要保持电位触发器状态不变,则输入数据就不应在 $E$ 的约定电平期间撤除,而应使其延迟直到 $E$ 的约定电平消失后再撤除数据信号。 + - 对于**边沿触发器**,为了使数据可靠地被接收,其输入数据必须比使触发器接收数据的约定时钟跳变提前到达数据输入端。 + - 与电位触发器不同,边沿触发器待时钟约定跳变把输入数据送入触发器后,输入数据即可撤除。 +2. 数据端的干扰 + - 对于**电位触发器**,在 $E$ 的约定电平期间出现在数据端的干扰很容易被触发器接收。 + - 对于**边沿触发器**,在 $\text{CP} = 0$ 或 $\text{CP} = 1$ 期间,出现在触发器数据输入端的正向及负向干扰均不会被接收。因此,它具有很强的抗干扰能力。 +3. “空翻现象” + - **空翻现象**指的是在时钟脉冲的高电平作用下,触发器的状态发生两次或更多次的翻转。这通常发生在电平触发的情况下,即在时钟脉冲为高电平期间,如果数据输入端连续发生变化,触发器也会随之连续变化,直到时钟脉冲变为低电平才会停止。 + - 由于边沿触发器在约定时钟跳变来到后的电平期间,数据的变化是不会被接收的,因此,用边沿触发器组成计数器或移位寄存器时不存在“空翻现象”。 +4. 应用场景 + - 对于**电位触发器**,由于“空翻现象”,故只能用来组成寄存器,而不能用作计数器和移位寄存器。 + - 对于**边沿触发器**,不存在“空翻现象”,故除了可用来组成寄存器外,还可用来组成计数器和移位寄存器。 + +#### 主-从触发方式的触发器(不考) + +主-从触发方式的触发器由两级**电位触发器**(主触发器和从触发器)串联而成。 + +- 当 $\text{CP} = 1$ 期间,主触发器接收**输入数据**,从触发器封锁; +- 当 $\text{CP} = 0$ 期间,从触发器接收**主触发器的输出数据**,主触发器封锁。 + +> 注意,当 $\text{CP} = 0$ 时,从触发器接收的不是此时的**输入数据**。 + +**主-从 R-S 触发器** + +![主-从 R-S 触发器](https://img.picgo.net/2024/04/25/4-M-S-R-Sed43bd133266e709.jpeg) + +功能表: + +| $R_D$ | $S_D$ | $\text{CP}$ | $R$ | $S$ | $Q$ | $\overline{Q}$ | +| :---: | :---: | :----------------------------------------------------------: | :--: | :--: | :---: | :--------------: | +| $0$ | $1$ | - | - | - | $0$ | $1$ | +| $1$ | $0$ | - | - | - | $1$ | $0$ | +| $1$ | $1$ | $\underset{\rightarrow}{}\uparrow\overset{\rightarrow}{}\downarrow\underset{\rightarrow}{}$ | $1$ | $0$ | $0$ | $1$ | +| $1$ | $1$ | $\underset{\rightarrow}{}\uparrow\overset{\rightarrow}{}\downarrow\underset{\rightarrow}{}$ | $0$ | $1$ | $1$ | $0$ | +| $1$ | $1$ | $\underset{\rightarrow}{}\uparrow\overset{\rightarrow}{}\downarrow\underset{\rightarrow}{}$ | $0$ | $0$ | $Q_0$ | $\overline{Q_0}$ | +| $1$ | $1$ | $\underset{\rightarrow}{}\uparrow\overset{\rightarrow}{}\downarrow\underset{\rightarrow}{}$ | $1$ | $1$ | $1^*$ | $1^*$ | + +**主-从 J-K 触发器** + +逻辑图: + +![主-从 J-K 触发器](https://img.picgo.net/2024/04/25/4-M-S-J-K6765f40772060ed6.jpeg) + +考虑怎么从主-从 R-S 触发器构造出主-从 J-K 触发器。 + +功能表: + +| $R_D$ | $S_D$ | $\text{CP}$ | $R$ | $S$ | $Q$ | $\overline{Q}$ | +| :---: | :---: | :----------------------------------------------------------: | :--: | :--: | :--------------: | :--------------: | +| $0$ | $1$ | - | - | - | $0$ | $1$ | +| $1$ | $0$ | - | - | - | $1$ | $0$ | +| $1$ | $1$ | $\underset{\rightarrow}{}\uparrow\overset{\rightarrow}{}\downarrow\underset{\rightarrow}{}$ | $0$ | $1$ | $0$ | $1$ | +| $1$ | $1$ | $\underset{\rightarrow}{}\uparrow\overset{\rightarrow}{}\downarrow\underset{\rightarrow}{}$ | $1$ | $0$ | $1$ | $0$ | +| $1$ | $1$ | $\underset{\rightarrow}{}\uparrow\overset{\rightarrow}{}\downarrow\underset{\rightarrow}{}$ | $0$ | $0$ | $Q_0$ | $\overline{Q_0}$ | +| $1$ | $1$ | $\underset{\rightarrow}{}\uparrow\overset{\rightarrow}{}\downarrow\underset{\rightarrow}{}$ | $1$ | $1$ | $\overline{Q_0}$ | $Q_0$ | + +> **注意**: +> +> - 主-从 J-K 触发器的功能表的前提是,在 $\text{CP} = 1$ 的情况下,$J, K$ 均未发生变化。 +> - 如果 $J, K$ 在 $\text{CP} = 1$ 期间变化的话,触发器的状态就可能不满足功能表。 +> - 主-从 J-K 触发器抗干扰能力差。 + +```mermaid +graph TD + +style Q fill:none,stroke-width:0px +style QQ fill:none,stroke-width:0px +style N1 fill:none,stroke-width:0px +style N2 fill:none,stroke-width:0px + +subgraph "J-K 触发器" + +Q($Q$) --- A("R-S 触发器") +QQ("$\overline{Q}$") --- A +A ---|$R$| B(某组合) +A ---|$S$| B +B --- N1($J$) +B --- N2($K$) + +end +``` + +画出 J-K 触发器的 Karnaugh 图如下: + +| $Q_0\backslash JK$ | $00$ | $01$ | $11$ | $10$ | +| :----------------: | :--: | :--: | :--: | :--: | +| $0$ | $0$ | $0$ | $1$ | $1$ | +| $1$ | $1$ | $0$ | $0$ | $1$ | + +因此 R-S 触发器需要满足(单元格内为对应 $RS$ 取值): + +| $Q_0\backslash JK$ | $00$ | $01$ | $11$ | $10$ | +| :----------------: | :--: | :--: | :--: | :--: | +| $0$ | $X0$ | $X0$ | $01$ | $01$ | +| $1$ | $0X$ | $10$ | $10$ | $0X$ | + +可以发现: +$$ +\begin{cases} +R & = KQ, \\ +S & = J\;\overline{Q}. +\end{cases} +$$ + + +![用 R-S 触发器构造的 J-K 触发器](https://img.picgo.net/2024/04/25/4-M-S-J-K-by-R-Sf54f9ccbdaefa784.jpeg) + +> 主-从 J-K 触发器和负边沿 J-K 触发器的区别: +> +> - 主-从 J-K 触发器,主触发器在 $\text{CP} = 1$ 期间接收数据,但当 $\text{CP} = 0$ 时从触发器才会接收主触发器的状态,这似乎意味着主-从 J-K 触发器的状态在 $\text{CP}$ 负跳变到来时才会发生变化,似乎就等价于一个负边沿 J-K 触发器; +> - 但实际上,负边沿 J-K 触发器在约定时钟跳变(负跳变)到来时,输出反映的是触发器的**输入数据**作为输入得到的结果,但主-从 J-K 触发器反映的是**主触发器的输出数据**作为从触发器输入得到的结果,并不一定与此时的输入 $J, K$ 有关。 + +主-从 J-K 触发器的时钟配合方式: + +- 触发器功能特点决定了时钟配合方式 +- 使用窄脉宽的CP信号,高电平时间缩短,可以保证 J-K 触发器正常工作 + +#### T 触发器 + +- 不设数据输入端,只要来一个时钟脉冲,触发器就翻转一次。 +- T 触发器可由 D 触发器或 J-K 触发器等构成。 +- T 触发器一般都是**边沿触发器**。这是因为如果用电位触发器,当 $T = 1$ 时会有“空翻现象”。 + +![T 触发器](https://img.picgo.net/2024/04/25/4-T85da77fb69692c53.jpeg) + +图中 (c) 为可控 T 触发器,当控制端 $C = 1$ 时,T 触发器工作;当 $C = 0$ 时,T 触发器保持。 + +### 触发器的开关特性 + +> **注意**:以下以**正沿 D 触发器**为例进行说明。负边沿触发器的各个开关特性位于的电平时间与其**相反**。 + +![正边沿触发的 D 型触发器](https://img.picgo.net/2024/04/15/3-E-D-positivebcb3d08d0a4c72d4.jpeg) + +#### $\text{CP}$ 到输出的传输延迟 $t_{\text{Pd}_{\text{CP}\to Q}}$ + +$\text{CP}$ 到输出的传输延迟 $t_{\text{Pd}_{\text{CP}\to Q}}$ 是指从边沿触发器的约定时钟跳变开始,到 $Q$ 发生变化为止所需的平均延迟时间。 + +$t_{\text{Pd}_{\text{CP}\to Q}}$ 必须在时钟的**高电平**期间。 + +#### 数据建立(setup)时间 $t_{\text{su}}$ + +在 $\text{CP}$ 正跳变期间,门 3 和门 4 需要接收数据,而最慢的一个数据是从 D 输入到门 5,再经过门 6 输出至门 4 的,因此必须有 +$$ +t_{\text{su}} \ge t_{\text{Pd}_5} + t_{\text{Pd}_6}. +$$ + +$t_{\text{su}}$ 必须在时钟的**低电平**期间。 + +#### 数据保持(hold)时间 $t_{\text{h}}$ + +在 $\text{CP}$ 正边沿到来后, + +- 若 $D = 0$,则需要等待门 3 需要封锁住门 5 后才能撤除 $D$; +- 若 $D = 1$,则需要等待门 4 需要封锁住门 3 和门 6 后才能撤除 $D$。 + +因此必须有: +$$ +t_{\text{h}} \ge \max\{t_{\text{Pd}_3}, t_{\text{Pd}_4}\}. +$$ + +$t_{\text{h}}$​ 必须在时钟的**高电平**期间。 + +![数据建立时间和数据保持时间](https://img.picgo.net/2024/06/18/3-D-t_su-t_hb5e64bba91f45c61.jpeg) + +#### 最高时钟工作频率 $f_{\max_{\text{CP}}}$ + +触发器的最短时钟正周期 $T_{\min_\text{CP}}^{+}$ 和最短时钟负周期 $T_{\min_\text{CP}}^{-}$ 如下: +$$ +\begin{align*} +T_{\min_\text{CP}}^{+} & = \max\{t_{\text{h}}, t_{\text{Pd}_{\text{CP}\to Q}}\}, \\ +T_{\min_\text{CP}}^{-} & = t_{\text{su}}. +\end{align*} +$$ +此时最高时钟工作频率 $f_{\max_{\text{CP}}}$ 为 +$$ +f_{\max_{\text{CP}}} = \dfrac{1}{T_{\min_\text{CP}}} = \dfrac{1}{T_{\min_\text{CP}^+} + T_{\min_\text{CP}}^-} = \dfrac{1}{\max\{t_{\text{h}}, t_{\text{Pd}_{\text{CP}\to Q}}\} + t_{\text{su}}}. +$$ +需要注意的是,$f_{\max_{\text{CP}}}$ 是**触发器的**最高时钟频率,而不是**系统的**最高工作频率。 + +如果在两个触发器间加入控制门,引入信号传输延迟 $t_{\text{Pd}_G}$,则 $t_{\text{Pd}_G}$ 可以**跨高电平或低电平**。此时最短时钟正周期为 +$$ +T_{\min_{CP}}^+ = \max\{t_{\text{h}}, t_{\text{Pd}_{\text{CP}\to Q}} + t_{\text{Pd}_G}\}. +$$ +因此可得到**系统的**最高工作频率: +$$ +f_{\max_{\text{CP}}} = \dfrac{1}{T_{\min_\text{CP}}} = \dfrac{1}{T_{\min_\text{CP}^+} + T_{\min_\text{CP}}^-} = \dfrac{1}{\max\{t_{\text{h}}, t_{\text{Pd}_{\text{CP}\to Q}} + t_{\text{Pd}_G}\} + t_{\text{su}}}. +$$ +![引入信号传输延迟](https://img.picgo.net/2024/06/18/3-D-t_Pd_G9ab0476d04327d2f.jpeg) + +## 第 4 章 组合逻辑电路 + +### 译码器 + +#### 功能分类 + +- 变量译码器:用来表示变量状态的全部组合 + - $N$ 位输入,$2^N$ 位输出。常见的集成化译码器有 2-4、3-8、4-16 译码器等。 +- 码制译码器:如 8421 码变换为循环码 +- 显示译码器:控制数码管显示 + +#### 2-4 变量译码器 + +**变量译码器的原理** + +假设 $A, B$ 是变量输入端,其中 $A$ 为地位,$B$ 为高位;$Y_0 \sim Y_3$ 为译码器的输出。则可以写出表达式: +$$ +\begin{align*} +Y_0 & = \overline{\overline{A}\;\overline{B}}, \\ +Y_1 & = \overline{A\;\overline{B}}, \\ +Y_2 & = \overline{\overline{A}\;B}, \\ +Y_3 & = \overline{AB}. +\end{align*} +$$ +输出端有 $Y_i = 0, Y_j = 1(j \neq i)$,当且仅当输入端有 $(BA)_2 = i$。 + +![输入的负载过多](https://img.picgo.net/2024/03/28/4-overloadf43203f46d17db5b.jpeg) + +为了减轻前一级电路驱动 $A, B$ 端的负担,设置了 $A, B$ 输入缓冲反相门,以形成译码器所需要的 $A$ 和 $\overline{A}$、$B$ 和 $\overline{B}$ 的互补输入。 + +![添加输入缓冲部分](https://img.picgo.net/2024/03/28/4-buffer90c4ccca010465a8.jpeg) + +**使能端** + +可以添加一个“使能”端 $\overline{E}$ 作为控制端,当 $\overline{E} = 1$ 时,译码器的四个输出均为 $1$,译码器的工作被禁止;只有当 $\overline{E} = 0$ 的时候,译码器才处于正常的工作状态。 + +> **注意**:与 $\overline{G}$ 类似,这里的 $\overline{E}$ 是一个记号,是一个整体,而不是 $E$ 的补。 + +![有使能端的 2-4 译码器](https://img.picgo.net/2024/03/28/4-2-4-Eb615a345ddfed079.jpeg) + +- 用于多片扩展 + - 搭建 3-8 译码器需要 2 片 2-4 译码器 + - ![用两片带使能端的 2-4 译码器组成 3-8 译码器](https://img.picgo.net/2024/03/28/4-2-4-3-859064124c2274d5c.jpeg) + - 搭建 4-16 译码器需要 5 片 2-4 译码器 + - ![用五片带使能端的 2-4 译码器组成 4-16 译码器](https://img.picgo.net/2024/03/28/4-2-4-4-1644bc666a1990c851.jpeg) + - 其中有一片的使能端 $\overline{E}$​ 作为 4-16 译码器的使能端。 + - 本质上是进行在 $4$ 个 2-4 译码器里进行四选一。 + - 如何搭建 32-2^{32} 译码器? + - ~~问得好,我也不会~~ +- 用作选通:解决门电路的传输延迟造成的竞争、冒险问题 + - **尖峰**: + - 由于缓冲与非门有延迟导致 $\overline{A}$ 的改变滞后于 $A$。例如 $A(1 \to 0)$ 时,$A\;\overline{A}$ 在某一时段,$\overline{A}$ 还没反应过来,仍为 $1$,导致 $A\;\overline{A} = 1$。分为负向尖峰和正向尖峰。 + - **零重叠**: + - 两次缓冲导致的与非门 $A' = \overline{\overline{A}}$ 相对于 $A$ 有传输延迟。这会导致 $\overline{A'B'}$ 和 $\overline{\overline{A}\;\overline{B}}$ 在某个时间段内会同时为 $0$。 + - ![尖峰与零重叠](https://img.picgo.net/2024/03/28/4-spike-overlapc793ec5873df91cd.jpeg) + - 如果两输入信号 $A, B$ 间相对还有传输延迟,则尖峰会加宽。 + - 因此,需要使能端 $\overline{E}$ 强加一个能覆盖输入变化的正脉冲 $\overline{E} = 1$,使得在 $A, B$ 变化期间 $Y_0 \sim Y_3$ 恒为 $1$,即可消除干扰。抑制尖峰和零重叠的使能正信号应先于(或同时)译码器的变量输入变化前到来,正信号撤除应滞后于变量输入的变化(至少滞后 $1$ 级缓冲的延迟)。但也不能太宽,否则速度会慢。 +- 用作数据分配器 + - $\overline{E}$ 的值决定了 $C_1$ 和 $C_2$ 共同控制的输出中的那一位到底是 $0$ 还是 $1$。 + - ![译码器用作数据分配器](https://img.picgo.net/2024/03/28/4-demultiplexer6ad31530bf0ab837.jpeg) + +#### 3-8 变量译码器 + +![无使能端的 3-8 译码器](https://img.picgo.net/2024/03/28/4-3-8d0a524c32b9a87d2.jpeg) + +- 用无使能端的 3-8 译码器扩展成 4-16 译码器 + - ![用无使能端的 3-8 译码器扩展成 4-16 译码器](https://img.picgo.net/2024/03/28/4-3-8-4-164dad71e165078c00.jpeg) +- 具有多个使能端的 3-8 译码器扩展成 4-16 译码器 + - 多使能端 $E_1, \overline{E}_{2A}, \overline{E}_{2B}$: + - 当 $E_1 = 1$ 且 $\overline{E}_{2A} = \overline{E}_{2B} = 0$ 时,译码器处于工作状态 + - 当 $E_1 = 0$ 或 $\overline{E}_{2A} = 1$ 或 $\overline{E}_{2B} = 1$ 时,译码器处于禁止状态 + - ![具有多个使能端的 3-8 译码器扩展成 4-16 译码器](https://img.picgo.net/2024/03/28/4-3-8-4-16-Ecadbe5d680e1a5d2.jpeg) + - 上图中,本质上是通过 $D$ 进行译码器的选择,分别接入 $\overline{E}_{2A}$ 和 $E_1$。至于左块的 $E_1$ 和右块的 $\overline{E}_{2A}$,其实没有用。 + +#### 4-16 变量译码器 + +多使能端 $\overline{E}_1, \overline{E}_2$: + +- 当 $\overline{E}_1 = \overline{E}_2 = 0$ 时,译码器处于工作状态 +- 当 $\overline{E}_1 = 1$ 或 $\overline{E}_2 = 1$ 时,译码器处于禁止状态 + +![具有多个使能端的 4-16 译码器](https://img.picgo.net/2024/03/28/4-4-16-E882071fa711ac29a.png) + +**存在的问题**: + +- 缓冲门的负载较大: + - 第一级缓冲门(反变量)负载 $9$ 个负载,第二级缓冲门(原变量)负载 $8$ 个负载 +- 使能端与门的负载有 $16$ 个,必须在制造芯片时增大驱动能力 + > 当译码器的输入变量数 $N$ 增大时,用单级译码器不能实现。 + > + > - 译码部分与非门的输入端数会增多 + > - 每个与非门的输入端数均为 $N+1$ 个(包含使能端) + > - 二级缓冲的每个输出负载加重 + > - 负载:第一级为 $2^{N-1}+1$,第二级为 $2^{N-1}$,使能端为 $2^{N}$。例如,当 $N = 11$ 时,这么多负载,这是不可实现的。 + > - 原变量和反变量应该各占 $2^{N}$ 的一半;但是,第一级为 $2^{N-1}+1$,原因是第一级还有到第二级的一根负载。 + > + > 采用多级译码技术可以减少负载:用在大容量存储器片内的译码结构。 + +#### 多级译码 + +采用“中间变量”的方式来减少负载。 + +![多级译码-1](https://img.picgo.net/2024/03/28/4-multilevel-19bf52241853191ae.jpeg) + +![多级译码-2](https://img.picgo.net/2024/03/28/4-multilevel-24e8d1cd6b9636b13.jpeg) + +![多级译码-3](https://img.picgo.net/2024/03/28/4-multilevel-38f2125a8e8c4e534.jpeg) + +![多级译码-4](https://img.picgo.net/2024/03/28/4-multilevel-450bfbc6af4116564.jpeg) + +#### 码制译码器 + +码制译码器是一种将一种编码变换为另外一种编码的逻辑电路。 + +**不完全译码的 BCD 译码器** + +当输入 $ABCD$ 出现 $0101 \sim 1111$(左为最低位)时,译码器输出 $Y_0 \sim Y_9$ 均为任意值。 + +画包含任意项的 Karnaugh 图可以得到: +$$ +\begin{align*} +Y_0 & = \overline{\overline{A}\;\overline{B}\;\overline{C}\;\overline{D}}, \\ +Y_1 & = \overline{A\;\overline{B}\;\overline{C}\;\overline{D}}, \\ +Y_2 & = \overline{\overline{A}\;B\;\overline{C}}, \\ +Y_3 & = \overline{A\;B\;\overline{C}}, \\ +Y_4 & = \overline{\overline{A}\;\overline{B}\;C}, \\ +Y_5 & = \overline{A\;\overline{B}\;C}, \\ +Y_6 & = \overline{\overline{A}\;B\;C}, \\ +Y_7 & = \overline{A\;B\;C}, \\ +Y_8 & = \overline{\overline{A}\;\overline{D}}, \\ +Y_9 & = \overline{A\;D}. +\end{align*} +$$ +逻辑图: + +![不完全译码的 BCD 译码器](https://img.picgo.net/2024/03/28/4-incomplete-BCD0f0c58f637bd8ceb.jpeg) + +**完全译码的 BCD 译码器** + +当输入 $ABCD$ 出现 $0101 \sim 1111$ 时,译码器输出 $Y_0 \sim Y_9$ 均为 $1$。 + +画 Karnaugh 图可以得到: +$$ +\begin{align*} +Y_0 & = \overline{\overline{A}\;\overline{B}\;\overline{C}\;\overline{D}}, \\ +Y_1 & = \overline{A\;\overline{B}\;\overline{C}\;\overline{D}}, \\ +Y_2 & = \overline{\overline{A}\;B\;\overline{C}\;\overline{D}}, \\ +Y_3 & = \overline{A\;B\;\overline{C}\;\overline{D}}, \\ +Y_4 & = \overline{\overline{A}\;\overline{B}\;C\;\overline{D}}, \\ +Y_5 & = \overline{A\;\overline{B}\;C\;\overline{D}}, \\ +Y_6 & = \overline{\overline{A}\;B\;C\;\overline{D}}, \\ +Y_7 & = \overline{A\;B\;C\;\overline{D}}, \\ +Y_8 & = \overline{\overline{A}\;\overline{B}\;\overline{C}\;D}, \\ +Y_9 & = \overline{A\;\overline{B}\;\overline{C}\;D}. +\end{align*} +$$ +逻辑图: + +![完全译码的 BCD 译码器](https://img.picgo.net/2024/03/28/4-complete-BCD3684c144a660328d.jpeg) + +#### 显示译码器 + +**七段数码管** + +一个七段数码管有 $7$ 个控制端输入 $a\sim g$,分别对应与数码管的 $7$ 段。有些数码管是 $8$ 个输入,在右下方有一个小数点。七段数码管分为两类: + +- 共阳极显示:低电平($0$)亮,高电平($1$)灭 +- 共阴极显示:高电平亮,低电平灭 + +**注意**:本博客遵循教材和 PPT 的习惯,采用**共阳极显示数码管**。 + +**显示译码器** + +显示译码器本质上是一个 BCD 码到一个特殊的七进制数码管编码的码制译码器。 + +![显示译码器](https://img.picgo.net/2024/03/28/4-display3c9975996085d549.jpeg) + +各个变量的逻辑表达式: +$$ +\begin{align*} +a & = BD + \overline{A}C + A\overline{B}\;\overline{C}\;\overline{D}, \\ +b & = BD + A \overline{B}C, \\ +c & = \overline{A}B\overline{C} + CD, \\ +d & = A \overline{B}\;\overline{C} + \overline{A}\;\overline{B}C + ABC, \\ +e & = A + \overline{B}C, \\ +f & = A\overline{C}\;\overline{D} + AB + B\overline{C}, \\ +g & = \overline{B}\;\overline{C}\;\overline{D} + ABC. +\end{align*} +$$ +LT、RBI、BI/BRO 是显示译码器控制功能的输入,主要用于对数码管进行测试。 + +### 数据选择器 + +在选择控制的信号作用下,能从多个输入数据中选择一个或多个作为输出。 + +- 多输入单输出数据选择器 +- 多输入多输出数据选择器 + +#### 4 选 1 数据选择器 + +$$ +Y = \overline{S}_0\;\overline{S}_1D_0 + S_0\overline{S}_1D_1 + \overline{S}_0S_1D_2 + S_0S_1D_3. +$$ + +通过控制 $S_0$ 和 $S_1$ 来选择 $D_0 \sim D_3$ 中的数据。 + +![无使能端的 4 选 1 数据选择器](https://img.picgo.net/2024/03/28/4-4-1f62b653721fb6b40.jpeg) + +![有使能端的 4 选 1 数据选择器](https://img.picgo.net/2024/03/28/4-4-1-Ecf7a925b972f96cf.jpeg) + +![有使能端的双通道 4 选 1 数据选择器](https://img.picgo.net/2024/03/28/4-2-4-1-E1ad7f565f3993b37.jpeg) + +左右两侧的数据选择器一模一样;输出的结构中,既有正信号 $Y$ 也有反信号 $W$。 + +**数据选择器的扩展** + +例:用双通道 4 选 1 数据选择器扩展成 16 选 1 数据选择器 + +有两种不同的扩展方案:可以先选择低两位,也可以先选择高两位。 + +![用双通道 4 选 1 数据选择器(无使能端)扩展成 16 选 1 数据选择器](https://img.picgo.net/2024/03/28/4-4-1-16-13c9bcff807e89303.jpeg) + +![用双通道 4 选 1 数据选择器(有使能端)扩展成 16 选 1 数据选择器](https://img.picgo.net/2024/03/28/4-4-1-16-1-Ee3602fee69ae41d2.jpeg) + +#### 译码器与数据选择器实现逻辑函数 + +**译码器** + +译码器可以看成是 $N$ 个输入变量组成的 $2^N$ 个最小项。如果再加一级与非门,可组成“与非-与非”逻辑,也可表达“与-或”逻辑。即可用译码器实现“与-或”逻辑函数。 + +![利用译码器实现逻辑函数](https://img.picgo.net/2024/03/28/4-decoder-selector753425a60866b7e9.jpeg) + +**数据选择器** + +数据选择器本身的逻辑结构就是“与-或”表达式。数据选择器可以看成是 $N$ 个控制端的 $2^N$ 个最小项和 $2^N$ 个输入组成的“与-或”表达式。选择某些输入为 $1$,就是选中这些最小项组成逻辑函数。 + +“1”端取的是 Karnaugh 图中的“1”块,“0”端取的是 Karnaugh 图中的“0”块。 + +![用 8 选 1 数据选择器实现 3 变量函数](https://img.picgo.net/2024/03/28/4-selector-function1f9b858db80af2a2c.jpeg) + +> **注意**:8 选 1 数据选择器也可以实现 4 变量函数。 +> +> 4 个变量,其中 3 个用在选择端;第 4 个变量放在**数据输入端**。 +> +> ![用 8 选 1 数据选择器实现 4 变量函数](https://img.picgo.net/2024/03/28/4-selector-function235eab0c72b23ec74.jpeg) + +### 编码器 + +**功能**:将译码器反过来,对应输入的每一个状态,输出一个编码。 + +**常用编码器**: + +- 4-2 编码,将输入的 4 个状态,编成 2 位二进制数码 +- 8-3 编码,将输入的 8 个状态,编成 3 位二进制数码 +- BCD 编码(8421 码),将输入的 10 个状态,编成 4 位 BCD 码 + +#### 4-2 编码器 + +**功能表** + +| $I_0$ | $I_1$ | $I_2$ | $I_3$ | $A_0$ | $A_1$ | +| :---: | :---: | :---: | :---: | :---: | :---: | +| $0$ | $1$ | $1$ | $1$ | $0$ | $0$ | +| $1$ | $0$ | $1$ | $1$ | $1$ | $0$ | +| $1$ | $1$ | $0$ | $1$ | $0$ | $1$ | +| $1$ | $1$ | $1$ | $0$ | $1$ | $1$ | + +输出的逻辑表达式: +$$ +\begin{align*} +A_0 & = I_0\overline{I_1}I_2I_3 + I_0I_1I_2\overline{I_3} = \overline{\overline{I_0}I_1I_2I_3 + I_0I_1\overline{I_2}I_3}, \\ +A_1 & = I_0I_1\overline{I_2}I_3 + I_0I_1I_2\overline{I_3} = \overline{\overline{I_0}I_1I_2I_3 + I_0\overline{I_1}I_2I_3}. +\end{align*} +$$ +![4-2 编码器](https://img.picgo.net/2024/04/07/4-4-2-encoder6834d3a69f2b7ad2.jpeg) + +#### 8421 码编码器 + +**功能表** + +| $X_9$ | $X_8$ | $X_7$ | $X_6$ | $X_5$ | $X_4$ | $X_3$ | $X_2$ | $X_1$ | $X_0$ | $Y_3$ | $Y_2$ | $Y_1$ | $Y_0$ | +| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | +| $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $1$ | $0$ | $0$ | $0$ | $0$ | +| $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $1$ | $0$ | $0$ | $0$ | $0$ | $1$ | +| $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $1$ | $0$ | $0$ | $0$ | $0$ | $1$ | $0$ | +| $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $1$ | $0$ | $0$ | $0$ | $0$ | $0$ | $1$ | $1$ | +| $0$ | $0$ | $0$ | $0$ | $0$ | $1$ | $0$ | $0$ | $0$ | $0$ | $0$ | $1$ | $0$ | $0$ | +| $0$ | $0$ | $0$ | $0$ | $1$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $1$ | $0$ | $1$ | +| $0$ | $0$ | $0$ | $1$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $1$ | $1$ | $0$ | +| $0$ | $0$ | $1$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $1$ | $1$ | $1$ | +| $0$ | $1$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $1$ | $0$ | $0$ | $0$ | +| $1$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $1$ | + +输出的逻辑表达式: +$$ +\begin{align*} +Y_0 & = X_1 + X_3 + X_5 + X_7 + X_9, \\ +Y_1 & = X_2 + X_3 + X_6 + X_7, \\ +Y_2 & = X_4 + X_5 + X_6 + X_7, \\ +Y_3 & = X_8 + X_9. +\end{align*} +$$ +逻辑图: + +![8421 码编码器](https://img.picgo.net/2024/04/07/4-8421-encoderb4ea07984360f462.jpeg) + +#### 8-3 优先编码器 + +> **问题**:以 4-2 编码器为例,当 $I_0 = I_1 = 0$ 时,仍能得到 $A_0 = A_1 = 1$。 +> +> **原因**:2-4 译码器的输出并没有包含所有四输入的可能组合。只有**互斥**输入时,才能使用这种编码器。在任意时刻所有输入线中最多**只允许有一个**为 $0$(4-2 编码器)或 $1$(8421 码编码器),否则编码器会发生混乱。 +> +> **解决办法**:使用优先编码器。 + +**优先编码器**:当两条或两条以上的输入线为 $0$ 时,**优先按照输入编号最大的信号进行编码**,称为优先编码器。 + +**8-3 优先编码器**: + +- **输出为反码**,即用 $000$ 来表示 $7$,用 $111$ 来表示 $0$​。 + + > **注意**:8-3 优先编码器输出为**反码**。一定要牢记在心。 + +- 输入使能端 $\overline{E}_1$:当 $\overline{E}_1 = 0$ 时,允许电路编码;当 $\overline{E}_1 = 1$ 时,禁止电路编码(输出全 $1$,包括 $E_0$ 和 $G_s$)。 + +- 输出的编码是否有效 $G_s$:当 $G_s = 0$ 时,表示当前编码有效;当 $G_s = 1$ 时,表示当前编码无效。 + +- 输出使能端 $E_0$:只有当输入数据($0 \sim 7$)中出现 $0$ 时,或是“禁止电路编码”时,才为 $1$;其余情况(即,允许电路编码,且输入中无 $0$ 时)为 $0$。 + +输出的逻辑表达式: +$$ +\begin{align*} +A_0 & = \overline{\overline{\overline{E}_1} \cdot \overline{7} + \overline{\overline{E}_1} \cdot 6 \cdot\overline{5} + \overline{\overline{E}_1} \cdot 6 \cdot 4 \cdot \overline{3} + \overline{\overline{E}_1} \cdot 6 \cdot 4 \cdot 2 \cdot \overline{1}}, \\ +A_1 & = \overline{\overline{\overline{E}_1} \cdot \overline{7} + \overline{\overline{E}_1} \cdot \overline{6} + \overline{\overline{E}_1} \cdot 5 \cdot 4 \cdot \overline{3} + \overline{\overline{E}_1} \cdot 5 \cdot 4 \cdot \overline{2}}, \\ +A_2 & = \overline{\overline{\overline{E}_1} \cdot \overline{7} + \overline{\overline{E}_1} \cdot \overline{6} + \overline{\overline{E}_1} \cdot \overline{5} + \overline{\overline{E}_1} \cdot \overline{4}}, \\ +E_0 & = \overline{\overline{\overline{E}_1} \cdot 7 \cdot 6\cdot 5 \cdot 4 \cdot 3 \cdot 2 \cdot 1 \cdot 0}, \\ +G_s & = \overline{\overline{\overline{E}_1}\cdot E_0}. +\end{align*} +$$ +**将 8-3 优先编码器扩展成 16-4 优先编码器** + +![8-3 优先编码器扩展成 16-4 优先编码器](https://img.picgo.net/2024/04/07/4-8-3-16-4d64527c07a3bffc6.jpeg) + +为什么把高位片和低位片的 $A_i$ 与起来作为最终输出呢?因为 + +- 当高位片无 $0$ 的时候,高位片有 $A_0 =A_1 = A_2= A_3 = 1$,输出取决于低位片的 $A_0 \sim A_3$。 +- 当高位片有 $0$ 的时候,高位片有 $E_0 = 1$,将高位片的 $E_0$ 作为低位片的 $\overline{E}_1$ 以**禁止低位片**。输出取决于高位片的 $A_0 \sim A_3$。 + +**优先编码器的应用**: + +- 设备按照优先等级编码,用于中断响应 +- 键盘输入的读取 + +### 数据比较器 + +数据比较器是数字系统中能够完成**数据比较功能**的部件。 + +#### 比较条件 + +假设给定两数码 $A, B \in \{0, 1\}$,则 + +- $A < B$ 的条件:$A = 0, B = 1$,即 $\overline{A}B = 1$,等价地,$W = B\overline{AB} = 1$。 +- $A = B$ 的条件:$A \oplus B = 0$,等价地,$Y = \overline{A\overline{AB} + B\overline{AB}} = 1$。 +- $A > B$ 的条件:$A = 1, B = 0$,即 $A\overline{B} = 1$,等价地,$Z = A\overline{AB} = 1$。 + +逻辑图如下: + +![比较条件的逻辑图](https://img.picgo.net/2024/04/07/4-comparede165c242b2b9f1f.jpeg) + +按照从高到低每位决定大小,则可以写出 4 位比较器的输出表达式: +$$ +\begin{align*} +[A < B] & = \overline{Z_3 + Y_3Z_2 + Y_3Y_2Z_1 + Y_3Y_2Y_1Z_0 + Y_3Y_2Y_1Y_0}, \\ +[A = B] & = Y_3Y_2Y_1Y_0, \\ +[A > B] & = \overline{W_3 + Y_3W_2 + Y_3Y_2W_1 + Y_3Y_2Y_1W_0 + Y_3Y_2Y_1Y_0}. +\end{align*} +$$ + +> **注意**:$[AB]$ 枚举的实际上是 $A \le B$ 的条件。 + +根据输出表达式画出 4 位比较器的原理图如下: + +![4 位并行比较器原理图](https://img.picgo.net/2024/04/07/4-4-comparec13566005f1b00cd.jpeg) + +#### 分段比较 + +分段比较是多片比较器构成更长位数的方法。比较器不仅输出比较结果,**还要能接受其它片输出的结果**。 + +![用两片 4 位数字比较器构成一个 8 位的数字比较器](https://img.picgo.net/2024/04/07/4-4-compare-8-compare0f068da153e20d5e.jpeg) + +### 奇偶校验器 + +奇偶校验器通过检测数据中包含奇数个 $1$ 还是偶数个 $1$,来检查数据传输后和数码记录中是否有错误的一种电路。但是它只能发现“一位错”,而且不能纠错。要想产生更强的检错和纠错能力,需要增加校验位数。 + +#### 异或电路 + +- 异或电路能“成对地”消去 $1$,因此可用来检测两位数码的奇偶性质。 +- 异或电路塔状连接能对多位数据进行奇偶检测。 + +#### 用“异或非”门作基本检测元件的奇偶检测电路 + +![9 位奇偶检测电路之一](https://img.picgo.net/2024/04/07/4-9-digit-even-odd9163788f39d1f611.png) + +- 采用“异或非”门而不是“异或”门,是为了简化线路和提高速度。 +- 输入端 $I_0 \sim I_9$ 均设置了**隔离反相门**,但这一措施不会影响奇偶校验的本质,因为 $i\oplus j \equiv \overline{i}\oplus \overline{j}$。 +- 该电路的缺点是**传输延迟较长**,输入信号需要经过 4 级“异或非”门、1 级反相门和 1 级“或非”门才能达到 $0$ 输出。 + +#### 奇偶检测电路的应用和扩展 + +![奇偶检测系统](https://img.picgo.net/2024/04/07/4-2-9-digit-8-digit-even-odd1fadd736e1486718.jpeg) + +左片的 $I_{81}$ 被称为“奇偶码”,假设奇偶码被设为 $I_{81} = 1$: + +- 左片的输出为奇偶检测码 $O_1$,与输入数据 $I_{01}\sim I_{71}$ 的异或和 $I_1 = \oplus_{i = 0}^{i=7}I_{i1}$ 相反。 +- $O_1$ 作为右片的 $I_{82}$ 作为输入,则右片的输出 $O_2 = O_1 \oplus I_2 = O_1 \oplus(\oplus_{i=0}^{i=7}I_{i2}) = \overline{\oplus_{i=0}^{i=7}(I_{i1}\oplus I_{i2})}$。 +- 若 $O_2 = 1$,则输出正确;若 $O_2 = 0$​,则输出错误。 + +可以看出,运输过程中信息正确,当且仅当 $O_2 = I_{81}$。 + +### 算术逻辑运算单元 + +#### 1 位半加器 + +不考虑低位进位输入和向高位的进位输出,两数码 $X_n, Y_n$ 相加,称**半加**。 + +表达式如下: +$$ +H_n = X_n\overline{Y_n} + \overline{X_n}Y_n = X_n \oplus Y_n. +$$ + +#### 1 位全加器 + +将输入 $X_n, Y_n$ 以及低位进位 $C_{n-1}$ 相加,并将进位输出 $C_n$,称**全加**。 + +功能表如下: + +| $X_n$ | $Y_n$ | $C_{n-1}$ | $F_n$ | $C_n$ | +| :---: | :---: | :-------: | :---: | :---: | +| $0$ | $0$ | $0$ | $0$ | $0$ | +| $1$ | $0$ | $0$ | $1$ | $0$ | +| $0$ | $1$ | $0$ | $1$ | $0$ | +| $1$ | $1$ | $0$ | $0$ | $1$ | +| $0$ | $0$ | $1$ | $1$ | $0$ | +| $1$ | $0$ | $1$ | $0$ | $1$ | +| $0$ | $1$ | $1$ | $0$ | $1$ | +| $1$ | $1$ | $1$ | $1$ | $1$ | + +**全加器的四种形式** + +![全加器的四种形式](https://img.picgo.net/2024/06/18/4-full-adder429832df55e3aad7.jpeg) + +(a):不化简,全部用最小项实现,$C_n$ 和 $F_n$ 均需要 **3 级门延迟**。 +$$ +\begin{align*} +F_n & = X_n\overline{Y_n}\;\overline{C_{n-1}} + \overline{X_n}Y_n\overline{C_{n-1}} + \overline{X_n}\;\overline{Y_n}C_{n-1} + X_nY_nC_{n-1}, \\ +C_n & = X_nY_n\overline{C_{n-1}} + X_n\overline{Y_n}C_{n-1} + \overline{X_n}Y_nC_{n-1} + X_nY_nC_{n-1}. +\end{align*} +$$ + +(b):变换后,$C_n$ 和 $F_n$ 均需要 **2 级门延迟**。 +$$ +\begin{align*} +F_n & = \overline{X_nY_n\overline{C_{n-1}} + X_n\overline{Y_n}C_{n-1} + \overline{X_n}Y_nC_{n-1} + \overline{X_n}\;\overline{Y_n}\;\overline{C_{n-1}}} , \\ +C_n & = \overline{\overline{X_n}\;\overline{Y_n} + \overline{X_n}\;\overline{C_{n-1}} + \overline{Y_n}\;\overline{C_{n-1}}}. +\end{align*} +$$ + +> 分析全加器中 $F_n$ 和 $C_n$ 间的关系,可以发现 $F_n$ 在两种情况下可以为 $1$: +> +> 1. $X_n = Y_n = C_{n-1} = 1$; +> 2. $X_n$、$Y_n$ 和 $C_{n-1}$ 中至少有一个为 $1$,且 $C_n = 0$。 +> +> 因此,可以用 $C_n$ 表示 $F_n$,**先组合出 $C_n$,再表示出 $F_n$**。 + +(c):$C_n$ 需要 **2 级门延迟**,$F_n$ 需要 **3 级门延迟**。 +$$ +\begin{align*} +F_n & = X_nY_nC_{n-1} + X_n\overline{C_n} + Y_n\overline{C_n} + C_{n-1}\overline{C_n}, \\ +C_n & = X_nY_n + X_nC_{n-1} + Y_nC_{n-1}. +\end{align*} +$$ + +(d):$C_n$ 需要 **2 级门延迟**,$F_n$ 需要 **3 级门延迟**。 +$$ +\begin{align*} +F_n & = \overline{\overline{X_n}\;\overline{Y_n}\;\overline{C_{n-1}} + \overline{X_n}C_n + \overline{Y_n}C_n + \overline{C_{n-1}}C_n}, \\ +C_n & = \overline{\overline{X_n}\;\overline{Y_n} + \overline{X_n}\;\overline{C_{n-1}} + \overline{Y_n}\;\overline{C_{n-1}}}. +\end{align*} +$$ + +> **注意**:由原理可知,$F_n$ 需要的级数等于 $C_n$ 需要的级数 + 1 级。 + +#### 4 位串行进位加法器 + +将四个 1 位全加器串联起来,前一级输出的 $C_{n-1}$ 作为后一级输入的 $C_{n-1}$,即可得到 4 位串行进位加法器。 + +![4 位串行进位加法器](https://img.picgo.net/2024/04/13/4-4-adderaf082a41d994aaa2.jpeg) + +1. 若仅使用 (b),计算 $F_n$ 需要 2 级,$C_n$ 需要 2 级,设 $C_{i-1}, X_i, Y_i$ 同时到达。 + - $F_1$ 需要 2 级,$C_1$ 需要 2 级。 + - $F_2$ 需要 4 级,$C_2$ 需要 4 级。 + - $F_3$ 需要 6 级,$C_3$ 需要 6 级。 + - **$F_4$ 需要 8 级,$C_4$ 需要 8 级**。 +2. 若仅使用 (c) 或 (d),计算 $F_n$ 需要 3 级,$C_n$ 需要 2 级,设 $C_{i-1}, X_i, Y_i$ 同时到达。 + - $F_1$ 需要 3 级,$C_1$ 需要 2 级。 + - $F_2$ 需要 5 级,$C_2$ 需要 4 级。 + - $F_3$ 需要 7 级,$C_3$ 需要 6 级。 + - **$F_4$ 需要 9 级,$C_4$ 需要 8 级**。 +3. 使用 (c) (d) **交叉串联**可以更快。 + - 由于 (c) 输出的进位是以**反码**形式出现的,故接下来接 (d) 可以省去输入 $C_{1}$ 时额外的与非门。这样输出 $C_2$ 总共只经过 2 级门延迟。以此类推。 + - ![(c) (d) 交叉串联](https://img.picgo.net/2024/04/13/4-4-addercde92d67e84512b1f5.png) + - $F_1$ 需要 3 级,$C_1$ 需要 2 级。 + - $F_2$ 需要 3 级,$C_2$ 需要 2 级(原本的串联 2 + 2,再减去省下的 2,故为 2)。 + - $F_3$ 需要 5 级,$C_3$ 需要 4 级。 + - **$F_4$ 需要 5 级,$C_4$​ 需要 4 级**。 + + > **注意**:类似于 (c) (d) 的原理,$F_n$ 需要的级数等于 $C_n$ 需要的级数 + 1 级。 + +**问题**: + +- 由于前一个加法完成并提供进位后,下一个加法器才能开始运算。 +- 延迟长,速度慢。 +- 位数越多,加法完成的时间越长。 + +#### 4 位并行加法器 + +> 是否可以用**专用的进位电路**提高速度? + +并行加法器(超前进位加法器)各位的进位不是由前一级全加器的进位输出来提供的,而是由**专门的进位门**来提供的。 + +![4 位并行加法器原理图](https://img.picgo.net/2024/04/13/4-4-adder-parallel-thumbnail5c3ab055549df164.jpeg) + +写出各位进位如下: +$$ +\begin{align*} +C_1 & = \overline{\overline{X_1 + Y_1} + \overline{X_1Y_1}\;\overline{C_{0}}}, \\ +C_2 & = \overline{\overline{X_2 + Y_2} + \overline{X_2Y_2}\;\overline{X_1 + Y_1} + \overline{X_2Y_2}\;\overline{X_1Y_1}\;\overline{C_0}}, \\ +C_3 & = \overline{\overline{X_3 + Y_3} + \overline{X_3Y_3}\;\overline{X_2 + Y_2} + \overline{X_3Y_3}\;\overline{X_2Y_2}\;\overline{X_1 + Y_1} + \overline{X_3Y_3}\;\overline{X_2Y_2}\;\overline{X_1Y_1}\;\overline{C_0}}, \\ +C_4 & = \overline{\overline{X_4 + Y_4} + \overline{X_4Y_4}\;\overline{X_3 + Y_3} + \overline{X_4Y_4}\;\overline{X_3Y_3}\;\overline{X_2 + Y_2} + \overline{X_4Y_4}\;\overline{X_3Y_3}\;\overline{X_2Y_2}\;\overline{X_1 + Y_1} + \overline{X_4Y_4}\;\overline{X_3Y_3}\;\overline{X_2Y_2}\;\overline{X_1Y_1}\;\overline{C_0}}. +\end{align*} +$$ +引入进位传递函数 $P_i$ 和进位产生函数 $G_i$ 如下: +$$ +\begin{cases} +P_i = X_i + Y_i, \\ +G_i = X_iY_i. +\end{cases} +$$ +则各位进位可以被表示为: +$$ +\begin{align*} +C_1 & = \overline{\overline{P_1} + \overline{G_1}\;\overline{C_0}}, \\ +C_2 & = \overline{\overline{P_2} + \overline{G_2}\;\overline{P_1} + \overline{G_2}\;\overline{G_1}\;\overline{C_0}}, \\ +C_3 & = \overline{\overline{P_3} + \overline{G_3}\;\overline{P_2} + \overline{G_3}\;\overline{G_2}\;\overline{P_1} + \overline{G_3}\;\overline{G_2}\;\overline{G_1}\;\overline{C_0}}, \\ +C_4 & = \overline{\overline{P_4} + \overline{G_4}\;\overline{P_3} + \overline{G_4}\;\overline{G_3}\;\overline{P_2} + \overline{G_4}\;\overline{G_3}\;\overline{G_2}\;\overline{P_1} + \overline{G_4}\;\overline{G_3}\;\overline{G_2}\;\overline{G_1}\;\overline{C_0}}. +\end{align*} +$$ + +> **注意**:$G_i \oplus P_i = X_i \oplus Y_i$。 + +$P_i$ 表示的是两个加数中是否已经有 $1$;$G_i$ 表示的是此位是否已经产生进位。因此,没有产生进位的条件是: + +- 当前加数没有 $1$,即 $\overline{P_i}$;或 +- 当前位没有进位且上一位加数中没有 $1$,即 $\overline{G_i}\;\overline{P_{i-1}}$;或 +- 当前位没有进位且上一位没有进位,且上上一位加数中没有 $1$,即 $\overline{G_i}\;\overline{G_{i-1}}\;\overline{P_{i-2}}$;或 +- …… + +![4 位并行加法器](https://img.picgo.net/2024/04/13/4-4-adder-parallel1535352f0e5ac046.png) + +$C_i$ 延迟级数与位数无关,都是 2 级;$F_i$ 延迟级数基本为 3 级($F_1$ 为特例,只需 2 级)。 + +> 如果写出各位进位如下: +> $$ +> \begin{align*} +> C_1 & = X_1Y_1 + (X_1 + Y_1)C_0, \\ +> C_2 & = X_2Y_2 + (X_2 + Y_2)X_1Y_1 + (X_2 + Y_2)(X_1 + Y_1)C_0, \\ +> C_3 & = X_3Y_3 + (X_3 + Y_3)X_2Y_2 + (X_3 + Y_3)(X_2 + Y_2)X_1Y_1 \\ +> & \quad + (X_3 + Y_3)(X_2 + Y_2)(X_1 + Y_1)C_0, \\ +> C_4 & = X_4Y_4 + (X_4 + Y_4)X_3Y_3 + (X_4 + Y_4)(X_3 + Y_3)X_2Y_2 \\ +> & \quad + (X_4 + Y_4)(X_3 + Y_3)(X_2 + Y_2)X_1Y_1 \\ +> & \quad + (X_4 + Y_4)(X_3 + Y_3)(X_2 + Y_2)(X_1 + Y_1)C_0, +> \end{align*} +> $$ +> 则各位进位可以被表示为: +> $$ +> \begin{align*} +> C_1 & = G_1 + P_1C_0, \\ +> C_2 & = G_2 + P_2G_1 + P_2P_1C_0, \\ +> C_3 & = G_3 + P_3G_2 + P_3P_2G_1 + P_3P_2P_1C_0, \\ +> C_4 & = G_4 + P_4G_3 + P_4P_3G_2 + P_4P_3P_2G_1 + P_4P_3P_2P_1C_0. +> \end{align*} +> $$ +> 将 $P_i$ 和 $G_i$的定义代入上述式子中,可能会更容易理解。产生进位的条件是: +> +> - 当前位已经进位,即 $G_i$;或 +> - 上一位已经进位,且这一位加数中有 $1$,即 $P_iG_{i-1}$;或 +> - 上上一位已经进位,且上一位和这一位加数中都有 $1$,即 $P_iP_{i-1}G_{i-2}$;或 +> - …… + +#### 16 位加法器 + +> 如果将四块 4 位加法器串联组成 16 位加法器,虽然各片内的进位是采用超前进位的,但是**片间进位仍是逐片传递的**,所以仍然有延迟长、速度慢的问题。 +> +> 因此,可以考虑类似超前进位加法器的原理形成各组间进位 $C_4, C_8, C_{12}, C_{16}$,从而形成各片间的快速进位。 + +记 +$$ +\begin{align*} +G_{m_i} & = G_i + P_iG_{i-1} + P_iP_{i-1}G_{i-2} + P_iP_{i-1}P_{i-2}G_{i-3}, \\ +P_{m_i} & = P_iP_{i-1}P_{i-2}P_{i-3}, +\end{align*} +$$ +则 $C_4, C_8, C_{12}, C_{16}$ 可被表示为 +$$ +\begin{align*} +C_4 & = G_{m_1} + P_{m_1}C_0, \\ +C_8 & = G_{m_2} + P_{m_2}G_{m_1} + P_{m_2}P_{m_1}C_0, \\ +C_{12} & = G_{m_3} + P_{m_3}G_{m_2} + P_{m_3}P_{m_2}G_{m_1} + P_{m_3}P_{m_2}P_{m_1}C_0, \\ +C_{16} & = G_{m_4} + P_{m_4}G_{m_3} + P_{m_4}P_{m_3}G_{m_2} + P_{m_4}P_{m_3}P_{m_2}G_{m_1} + P_{m_4}P_{m_3}P_{m_2}P_{m_1}C_0. +\end{align*} +$$ +实际上,只要把 $C_1\sim C_4$ 表达式中的 $P_i, G_i$ 替换为 $P_{m_i}, G_{m_i}$,就可变为 $C_4, C_8, C_{12}, C_{16}$ 的表达式。 + +![超前进位扩展器逻辑图](https://img.picgo.net/2024/04/13/4-16-adder-parallel790ba09b58b92c37.png) + +四位并行加法器的输出提供 $P_{m_i}, G_{m_i}$ 需 2 级延迟。 + +- 产生 $C_4, C_8, C_{12}, C_{16}$ 需 3 级延迟。 +- 产生 $F_1 \sim F_4$ 需要 3 级延迟,产生 $F_5 \sim F_{16}$ 需要 6 级延迟。 + +#### 算术逻辑运算单元(ALU) + +ALU 是 CPU 的核心,不仅能完成算术运算(加法、减法等),而且能完成逻辑运算(比较、与、或、非、移位等)。 + +**4 位算术逻辑运算单元** + +4 位 ALU 的核心是 4 位并行加法器,通过控制加法器的一些逻辑门或改变进位逻辑门能够获得多种功能。 + +运算能力的两种获得方法: + +- 方法一:封锁 4 位加法器中的一些逻辑门 + - 比较简单 + - 只能得到种类较少的运算 +- 方法二:改变加法器的进位产生函数 $G_i$ 及进位传递函数 $P_i$ + - 可以获得种类较多的运算 + - 运算单元结构复杂 + +方法一:在控制信号 $C_{\text{INH}}, E_{\text{INH}}$ 的作用下,可以完成 4 位数的加、比较和逻辑乘(与)运算。 + +![4 位算术逻辑运算单元(方法一)](https://img.picgo.net/2024/04/13/4-4-ALU-149fbaa93f9bbb8c6.jpeg) + +方法二:$M$ 为状态控制端。当 $M = \text{H}$ 时,电路执行逻辑运算;当 $M = \text{L}$ 时,电路执行算术运算。 + +![4 位算术逻辑运算单元(方法二)(1)](https://img.picgo.net/2024/04/13/4-4-ALU-21802e8086eab86501.jpeg) + +![4 位算术逻辑运算单元(方法二)(2)](https://img.picgo.net/2024/04/13/4-4-ALU-223a9c1b2bc1dd9eb4.jpeg) + +## 第 5 章 同步时序电路 + +### 时序逻辑电路和组合逻辑电路的区别 + +- 组合逻辑电路某一时刻的输出只取决于此时刻的输入。 +- 时序逻辑电路某一时刻的稳定输出不仅取决于当时的输入,还取决于过去的输入(历史状态)。 + - **记忆元件**(Memory Device)是时序逻辑电路的基本元件。 + - 计算机中的实现记忆存储功能的元件有多种:磁存储、光存储、半导体存储(电存储)。 + - 时序逻辑电路中的记忆元件一定要是可修改、可控制的。这种元件被称为“触发器”。 + +### 同步时序电路的结构 + +![时序电路的一般结构](https://img.picgo.net/2024/04/29/5-sslc894980929506e921.jpeg) + +#### 概念 + +- 激励函数:**次态和中间变量**关于**现态、中间变量和其他输入**的函数。 +- 激励表:功能表经行列重排后的表格,以**现态**和**次态**为**自变量**,**输入**为**因变量**。 +- 状态表:以输入和现态为自变量,次态为因变量的表格。 +- 状态图:将状态表转化为类似 DFA 形式的图形。 + +#### 触发器的状态方程 + +牢记三种触发器的状态方程,可以辅助我们快速写出时序电路的激励函数。 + +- D 触发器的状态方程为 $Q_{n+1} = D$。 +- J-K 触发器的状态方程为 $Q_{n+1} = J\overline{Q_n}+\overline{K}Q_n$。 +- T 触发器的状态方程为 $Q_{n+1} = T \oplus Q_n$。 + +#### 特点 + +- 各触发器使用同一个 CP。 +- 只有约定时钟到来,电路状态才能改变。 +- 一个脉冲只能改变一次状态。 + +### 同步时序电路的分析 + +#### 分析步骤 + +1. 根据电路图列出触发器激励函数表达式和电路输出函数(分析由于触发器输入的变化而引起次态的变化以及输出的变化,所以必须要明确触发器的输入变化); +1. 根据电路输入和触发器激励函数建立次态表达式和状态表(分析触发器状态的变化规律); +1. 画出状态图和时序图(能够更直观分析状态的变化规律); +1. 分析输出序列和输入序列的关系,说明时序电路的逻辑功能。 + +#### 例题 + +> 作出以下同步时序电路的状态表和状态图,$X$ 的输入序列为 $0110110$ 时的时序图,所用触发器为主-从型 J-K 触发器。 +> +> ![某同步时序电路的逻辑图](https://img.picgo.net/2024/04/29/5-analysis-example-logic-graph59274606119b2eb5.jpeg) + +写出电路的输出函数和触发器的激励函数如下: +$$ +\begin{cases} +Z & = \overline{Q_1 J_1}, \\ +J_0 & = X, \\ +K_0 & = \overline{Q_1 X}, \\ +J_1 & = Q_0 X + \overline{Q_1}X, \\ +K_1 & = \overline{X} + \overline{Q_0}Q_1. +\end{cases} +$$ +又有 J-K 触发器的状态方程如下: +$$ +\begin{cases} +Q_{1, n+1} & = J_1\overline{Q_{1, n}} + \overline{K_1}Q_{1, n}, \\ +Q_{0, n+1} & = J_0\overline{Q_{0, n}} + \overline{K_0}Q_{0, n}. +\end{cases} +$$ +整理得: +$$ +\begin{cases} +Q_{1, n+1} & = \overline{Q_{1, n}}X + Q_{1, n}Q_{0, n}X, \\ +Q_{0, n+1} & = \overline{Q_{0, n}}X + Q_{1, n}Q_{0, n}X, \\ +Z & = \overline{Q_{1, n}Q_{0, n}X} +\end{cases} +$$ +因此,写出状态表如下(表中状态为 $Q_{0, n+1}Q_{1, n+1}/Z$): + +| $Q_{0, n}Q_{1, n}\backslash X$ | $0$ | $1$ | +| :----------------------------: | :----: | :----: | +| $00$ | $00/1$ | $11/1$ | +| $01$ | $00/1$ | $10/1$ | +| $11$ | $00/1$ | $11/0$ | +| $10$ | $00/1$ | $01/1$ | + +状态图如下(转移边为 $X/Z$): + +```mermaid +graph LR + +A((00)) -->|1/1| D((11)) +A -->|0/1| A +B((01)) -->|0/1| A +B -->|1/1| C +C((10)) -->|0/1| A +C -->|1/1| B +D -->|0/1| A +D -->|1/0| D +``` + +由于使用的是**主-从 J-K 触发器**,因此输入 $X$ 的变化在 $\text{CP} = 0$ 时进行,输出波形的变化发生在 $\text{CP}$ 负跳变到来的时候。时序图如下($X$ 的输入序列为 $0110110$): + +![某同步时序电路的时序图](https://img.picgo.net/2024/04/29/5-analysis-example-time-diagrama8b5bea64c27871b.jpeg) + +### 同步时序电路的设计 + +#### 设计步骤 + +1. **确定输入变量和输出变量** +2. **作原始状态表**:根据给定的电路设计条件构成原始状态表。 +3. **状态化简**:原始状态表通常不是最小化状态表,它一般包含多余的状态,因此要对原始状态表进行化简。 + - 使用类似 DFA 最小化的方法进行化简 + - 定义**对应输出不同**的状态是*可区分的* + - 然后检测后继是否为可区分的,来判断当前状态对是否是可区分的 + - 见[【学习笔记】自动机理论、语言和计算导论 | Clever_Jimmy 的博客](https://leverimmy.top/2023/09/17/IATLC/#自动机的等价性和最小化) +4. **状态分配**:给简化后的状态用一个二进制数来编码。 +5. **求出激励函数和输出函数**:根据选用的触发器激励表和电路的状态表,综合出电路中各个触发器的激励函数和电路的输出函数。 +6. **画逻辑图** + +#### 例题 + +> 用与非门和 D 触发器设计一个同步时序逻辑电路,以检测输入信号序列是否为连续的 $110$。 + +**第一步:确定输入变量和输出变量** + +由题知: + +- 只有一个输入变量,记为 $X$,$X$ 是一个二进制序列。 +- 只有一个输出变量,记为 $Z$。$Z = 0$ 表示没有连续的 $110$ 序列;$Z = 1$ 表示有连续的 $110$ 序列。 + +**第二步:作原始状态表** + +状态图(本质为一个 DFA)如下: + +```mermaid +graph LR + +style Start fill:none,stroke-width:0px + +Start --> a((a)) +a -->|0/0| b((b)) +a -->|1/0| c((c)) +b -->|0/0| d((d)) +b -->|1/0| e((e)) +c -->|0/0| f((f)) +c -->|1/0| g((g)) +d -->|0/0| d +d -->|1/0| e +e -->|0/0| f +e -->|1/0| g +f -->|0/0| d +f -->|1/0| e +g -->|0/1| f +g -->|1/0| g +``` + +假设初始状态为 `a`。 + +> 状态图也有另外一种方式来表示: +> +> ![状态图的另一种方式](https://img.picgo.net/2024/05/06/5-state-diagram91a7df5af458dc94.jpeg) + +原始状态表如下(表中元素为 $(Q_{N+1}, Z)$: + +| $Q_N\backslash X$ | $0$ | $1$ | +| :---------------: | :------: | :------: | +| $a$ | $(b, 0)$ | $(c, 0)$ | +| $b$ | $(d, 0)$ | $(e, 0)$ | +| $c$ | $(f, 0)$ | $(g, 0)$ | +| $d$ | $(d, 0)$ | $(e, 0)$ | +| $e$ | $(f, 0)$ | $(g, 0)$ | +| $f$ | $(d, 0)$ | $(e, 0)$ | +| $g$ | $(f, 1)$ | $(g, 0)$ | + +**第三步:状态化简** + +注意到 $\{b, d, f\}$ 三行完全相同,$\{c, e\}$ 两行完全相同,故将它们分别作为整体;之后发现 $a$ 和 $p_0 = \{b, d, f\}$ 两行完全相同,故组合为 +$$ +\begin{align*} +p & = \{a, b, d, f\}, \\ +q & = \{c, e\}, \\ +r & = \{g\}. +\end{align*} +$$ +化简后的状态表为(表中元素为 $(Q_{N+1}, Z)$: + +| $Q_N\backslash X$ | $0$ | $1$ | +| :---------------: | :------: | :------: | +| $p$ | $(p, 0)$ | $(q, 0)$ | +| $q$ | $(p, 0)$ | $(r, 0)$ | +| $r$ | $(p, 1)$ | $(r, 0)$ | + +状态图如下: + +```mermaid +graph LR + +p((p)) -->|0/0| p +p -->|1/0| q((q)) +q -->|0/0| p +q -->|1/0| r((r)) +r -->|1/0| r +r -->|0/1| p +``` + +**第四步:状态分配** + +一共有 $p, q, r$ 三种状态,故需要 $\left\lceil\log_2(3)\right\rceil = 2$ 个触发器。假设用 $p = 00, q = 10, r = 11$ 来编码,则可以画出 $110$ 序列检测器的组成框图如下: + +![110 序列检测器的组成框图](https://img.picgo.net/2024/05/06/5-example-110-combinationa8fd435664e518b9.jpeg) + +**第五步:求出激励函数和输出函数** + +- 输入为 $X, Q_1, \overline{Q_1}, Q_2, \overline{Q_2}$ +- 输出为 $Z, D_1, D_2$ + +写出激励函数和输出函数表格如下: + +| $X$ | $Q_{2N}$ | $Q_{1N}$ | $Q_{2, N+1}$ | $Q_{1, N+1}$ | $D_2$ | $D_1$ | $Z$ | +| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | +| $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | +| $0$ | $1$ | $0$ | $0$ | $0$ | $0$ | $0$ | $0$ | +| $0$ | $1$ | $1$ | $0$ | $0$ | $0$ | $0$ | $1$ | +| $1$ | $0$ | $0$ | $1$ | $0$ | $1$ | $0$ | $0$ | +| $1$ | $1$ | $0$ | $1$ | $1$ | $1$ | $1$ | $0$ | +| $1$ | $1$ | $1$ | $1$ | $1$ | $1$ | $1$ | $0$ | +| - | $0$ | $1$ | - | - | - | - | - | + +得到 $D_2 = X, D_1 = XQ_{2N}, Z = \overline{X}Q_{1N}$。 + +**第六步:画逻辑图** + +![110 序列检测器的逻辑图](https://img.picgo.net/2024/05/06/5-example-final-diagramaa1dad166f653a32.jpeg) + +### 计数器 + +#### D 触发器实现的 4 位二进制计数器 + +**状态方程** +$$ +\begin{align*} +D_0 & = Q_{0, N+1} = \overline{Q_{0, N}}, \\ +D_1 & = Q_{1, N+1} = Q_{1, N} \oplus Q_{0, N}, \\ +D_2 & = Q_{2, N+1} = Q_{2, N} \oplus Q_{1, N}Q_{0, N}, \\ +D_3 & = Q_{3, N+1} = Q_{3, N} \oplus Q_{2, N}Q_{1, N}Q_{0, N}. +\end{align*} +$$ + +#### J-K 触发器实现的 4 位二进制计数器 + +**状态方程** +$$ +\begin{align*} +J_0 & = K_0 = 1, \\ +J_1 & = K_1 = Q_0, \\ +J_2 & = K_2 = Q_1Q_0, \\ +J_3 & = K_3 = Q_2Q_1Q_0. +\end{align*} +$$ + +#### 可逆计数器 + +基本结构为 $Q_{1} = XF^{-} + \overline{X}\;F^{+}$,当 $X$ 为 $0$ 时正向计数;当 $X = 1$ 时反向计数。 + +#### 集成化的 4 位二进制计数器 + +**集成化的计数器具有的基本功能** + +- 异步/同步清零:初始化 + - 异步清零有两种方式:(1) 用触发器提供的异步清零 (2) 在输出时用组合逻辑限定 $\overline{R_D}\cdot Q$ + - 方法 (2) 在使用时需要慎重,因为这只是从输出上(外表上)清零了,计数器仍然在工作,可能会出现 $0000$ 后直接出现 $0011$ 这类的情况。 +- 同步置数:开始计数的初值 + - 有的时候不希望只能从 $0$ 开始计数。 +- 计数:正常工作 +- 保持:计数到某个特定的计数值保持 + - 假设低位片进位到了高位片,低位片清零。此时低位片继续开始计数,高位片需要保持。 +- 扩展性:相同的计数器级联更多位数的计数器 +- 进位传递:扩展时进位传递到高位片 + +![集成化的 4 位二进制计数器逻辑图](https://img.picgo.net/2024/05/19/5-counter-integrated-p78bd566c700e14cf.jpeg) + +**用负边沿 D 触发器构成的 4 位二进制计数器** + +| $\overline{R_D}$ | $\text{CLR}$ | $L$ | $T$ | $P$ | $\text{CP}$ | 功能 | +| :--------------: | :----------: | :--: | :--: | :--: | :----------: | ----------------------------- | +| $0$ | - | - | - | $X$ | - | 清零(异步) | +| $1$ | $0$ | - | - | - | $\downarrow$ | 清零(同步) | +| $1$ | $1$ | $0$ | - | - | $\downarrow$ | Load(并行数据输入) | +| $1$ | $1$ | $1$ | $1$ | $1$ | $\downarrow$ | Count(计数) | +| $1$ | $1$ | $1$ | $0$ | - | - | Hold(保持),$\text{RC} = 0$ | +| $1$ | $1$ | $1$ | $1$ | $0$ | - | Hold(保持) | + +- $\text{CLR}$ + - 只要 $\text{CLR} = 0$,在下一个时钟跳变的时候输出均应该为 $0$。 + $$ + \begin{align*} + D_A & = \text{CLR} \cdot \overline{Q_A}, \\ + D_B & = \text{CLR} \cdot (Q_B \oplus Q_A), \\ + D_C & = \text{CLR} \cdot (Q_C \oplus Q_BQ_A), \\ + D_D & = \text{CLR} \cdot (Q_D \oplus Q_CQ_BQ_A). + \end{align*} + $$ +- $L$ + - 本质上 $L$ 控制的是“接受新的数据输入”和“原激励不变”之间进行数据二选一。 + $$ + \begin{align*} + D_A & = \text{CLR} \cdot (\overline{L}\; A + L\;\overline{Q_A}), \\ + D_B & = \text{CLR} \cdot (\overline{L}\; B + L\;(Q_B \oplus Q_A)), \\ + D_C & = \text{CLR} \cdot (\overline{L}\; C + L\;(Q_C \oplus Q_BQ_A)), \\ + D_D & = \text{CLR} \cdot (\overline{L}\; D + L\;(Q_D \oplus Q_CQ_BQ_A)). + \end{align*} + $$ +- $T$ + - 设计 $\text{RC}$ 表示进位标志: + - 四位二进制计数器 $\text{RC} = Q_DQ_CQ_BQ_A$; + - 十进制计数器 $\text{RC} = Q_D\overline{Q_C}\overline{Q_B}Q_A$。 + - 当 $T = 0$ 时,触发器保持;当 $T = 1$ 时才允许计数,这也是一个数据二选一。 + $$ + \begin{align*} + D_A & = \text{CLR} \cdot (\overline{L}\; A + L\;(\overline{T}\; Q_A + T\;\overline{Q_A}), \\ + D_B & = \text{CLR} \cdot (\overline{L}\; B + L\;(\overline{T}\; Q_B + T\;(Q_B \oplus Q_A))), \\ + D_C & = \text{CLR} \cdot (\overline{L}\; C + L\;(\overline{T}\; Q_C + T\;(Q_C \oplus Q_BQ_A))), \\ + D_D & = \text{CLR} \cdot (\overline{L}\; D + L\;(\overline{T}\; Q_D + T\;(Q_D \oplus Q_CQ_BQ_A))), \\ + \text{RC} & = Q_DQ_CQ_BQ_AT. + \end{align*} + $$ + - 此时的问题是片间进位信号是通过 $\text{RC}$ 串行逐片传递的,这会导致计数频率不能很高。 + + ![串行扩展,RC 逐片传递](https://img.picgo.net/2024/05/19/5-counter-integrated-tcf2c063195eab7d1.jpeg) + +- $P$ + - 为了提高计数频率,再引入输入 $P$。当 $TP = 1$ 时触发器才开始计数。这样,$P = 0$ 能够限制多片进位时间,使得它们能够同时进位。 + $$ + \begin{align*} + D_A & = \text{CLR} \cdot (\overline{L}\; A + L\;(\overline{TP}\; Q_A + TP\;\overline{Q_A}), \\ + D_B & = \text{CLR} \cdot (\overline{L}\; B + L\;(\overline{TP}\; Q_B + TP\;(Q_B \oplus Q_A))), \\ + D_C & = \text{CLR} \cdot (\overline{L}\; C + L\;(\overline{TP}\; Q_C + TP\;(Q_C \oplus Q_BQ_A))), \\ + D_D & = \text{CLR} \cdot (\overline{L}\; D + L\;(\overline{TP}\; Q_D + TP\;(Q_D \oplus Q_CQ_BQ_A))). + \end{align*} + $$ + - 此时的问题是最高位的 RC 为高电平并不表示整体进位!此时各个位的 RC 全部与起来,如果为高电平,才表示整体进位。 + + ![快速扩展](https://img.picgo.net/2024/05/19/5-counter-integrated-p78bd566c700e14cf.jpeg) + +> **注意**:在应用 74163(或 74161)集成化 4 位二进制计数器的时候,记得将 $\text{CP}$ 连上时钟信号,同时令 $\text{CLR} = T = P = 1$。 + +### 寄存器 + +#### 基本寄存器 + +寄存器的基本功能是存储。 + +![4D 寄存器逻辑图](https://img.picgo.net/2024/06/19/5-4D-registerc58966f9a89e429a.jpeg) + +> **注意**:对 $\overline{R_d}$ 和 $\text{CP}$ 多接两次与非门是为了**减少对外的负载**。 + +输入数据为 $D$,通过 $\overline{E}$ 来控制保持还是置数,通过输入输出使能端 $\overline{OE}$ 来实现有控制的输入输出。 + +**功能表** + +| $\overline{R_d}$ | $\overline{E}$ | $\text{CP}$ | $D$ | $\overline{OE}$ | $Q_{n+1}$ | 功能 | +| :--------------: | :------------: | :---------: | :--: | :-------------: | :-----------: | :----------- | +| $0$ | - | - | - | - | $0$ | 异步置零 | +| $1$ | $1$ | $\uparrow$ | - | $0$ | $Q_n$ | 保持 | +| $1$ | $0$ | $\uparrow$ | $D$ | $0$ | $D$ | 置数 | +| $1$ | - | - | - | $1$ | $Z$(高阻态) | 拒绝输入输出 | + +**逻辑图** + +![带使能端的 4D 寄存器逻辑图](https://img.picgo.net/2024/06/19/5-4D-register-enable2e65b89c2a0c302a.jpeg) + +#### 移位寄存器 + +在计算机中使用的寄存器需要支持**移位功能**,例如在乘法运算中,需要将部分积移位,在除法运算中,需要将余数移位;移位寄存器应运而生。 + +**移位寄存器**指的是,每来一个时钟脉冲(移位命令),寄存器中的数据就按照顺序左(右)移动一位。因此,必须采用**边沿触发器**或**主从触发器**。 + +**串入-并出移位寄存器** + +逻辑图: + +![串入-并出移位寄存器逻辑图](https://img.picgo.net/2024/06/19/5-shift-register-sequence-in-parallel-outb2d85946427f2042.jpeg) + +**并入-并出移位寄存器** + +功能表: + +| $\overline{R_D}$ | $S_0$ | $S_1$ | $D_i$ | $\text{CP}$ | $Q_{n+1}$ | 功能 | +| :--------------: | :---: | :---: | :---: | :---------: | :--------: | :------- | +| $0$ | - | - | - | - | $0$ | 异步置零 | +| $1$ | $0$ | $0$ | - | $\uparrow$ | $Q_n$ | 保持 | +| $1$ | $1$ | $0$ | - | $\uparrow$ | $Q_{L, n}$ | 右移 | +| $1$ | $0$ | $1$ | - | $\uparrow$ | $Q_{R, n}$ | 左移 | +| $1$ | $1$ | $1$ | $D$ | $\uparrow$ | $D$ | 置数 | + +状态方程: +$$ +Q_{n+1} = \overline{S_0}\;\overline{S_1}Q_n + S_0\overline{S_1}Q_{L,n} + \overline{S_0}S_1Q_{R, n}+ S_0S_1D +$$ +逻辑图: + +![并入-并出移位寄存器逻辑图](https://img.picgo.net/2024/06/19/5-shift-register-parallel-in-parallel-outd5ee12084873bd5f.jpeg) + +**应用举例:用移位寄存器设计信号发生器** + +- 信号发生器的用途 + - 通讯设备的同步系统中,需要产生一些顺序码,用于设备间的同步 + - 复杂的控制系统,需要有特定的信号序列 +- 设计方法 + - 能确定与 $D$ 相连的组合逻辑函数 + - **无堵塞**:能自行进入工作循环 + +假设需要产生信号长度为 $m = 6$ 的信号序列 $101000$,则寄存器的位数 $n$ 必须满足 $2^n \ge m$。 + +取 $n = 3$,则发现 $010$ 的下一态不确定是 $100$ 还是 $101$,故考虑 $n = 4$。 + +| $Q_0$ | $Q_1$ | $Q_2$ | $Q_3$ | +| :---: | :---: | :---: | :---: | +| $1$ | $0$ | $0$ | $0$ | +| $0$ | $1$ | $0$ | $0$ | +| $1$ | $0$ | $1$ | $0$ | +| $0$ | $1$ | $0$ | $1$ | +| $0$ | $0$ | $1$ | $0$ | +| $0$ | $0$ | $0$ | $1$ | + +$D_i$ 影响的是 $Q_0$,因此写出每一行对下一行 $Q_0$ 的影响的卡诺图。 + +| $Q_3Q_2\backslash Q_1Q_0$ | $00$ | $01$ | $11$ | $10$ | +| :-----------------------: | :--: | :--: | :--: | :--: | +| $00$ | - | $0$ | - | 1 | +| $01$ | $0$ | $0$ | - | - | +| $11$ | - | - | - | - | +| $10$ | $1$ | - | - | 0 | + +化简后,可以得到 +$$ +D_i = Q_1\overline{Q_3} + \overline{Q_1}Q_3 = Q_1 \oplus Q_3. +$$ +可惜的是,这样的信号发生器并不能自启动。 + +```mermaid +graph TD +subgraph 非工作循环 +subgraph a +0 +end +subgraph b +3 --> 7 +7 --> 15 +15 --> 14 +14 --> 12 +12 --> 9 +9 --> 3 +end +subgraph c +6 --> 13 +13 --> 11 +11 --> 6 +end +end +subgraph 工作循环 +1 --> 2 +2 --> 5 +5 --> 10 +10 --> 4 +4 --> 8 +8 --> 1 +end +``` + +> **注意**:如果信号发生器启动时进入非工作循环状态,则必须经过若干个时钟周期以后能进入工作循环。 +> +> **改动思路**:对于所有的非工作循环,取其中一个或多个非工作循环状态,令其的次态为工作循环。 + +这本质上是在限制 Karnaugh 图中的任意项为具体的值。 + +例如,将 $0000$ 纳入工作循环,可以得到卡诺图: + +| $Q_3Q_2\backslash Q_1Q_0$ | $00$ | $01$ | $11$ | $10$ | +| :-----------------------: | :--: | :--: | :--: | :--: | +| $00$ | $1$ | $0$ | - | $1$ | +| $01$ | $0$ | $0$ | - | - | +| $11$ | - | - | - | - | +| $10$ | $1$ | - | - | $0$ | + +类似这样的步骤,将所有非工作循环纳入工作循环中,可以得到 +$$ +D_i = Q_1\overline{Q_3} + \overline{Q_0}\;\overline{Q_1}\;\overline{Q_2}. +$$ +修改后的工作循环为 + +```mermaid +graph LR +0 --> 1 +1 --> 2 +2 --> 5 +5 --> 10 +10 --> 4 +4 --> 8 +8 --> 1 +15 --> 14 +14 --> 12 +12 --> 8 +7 --> 14 +13 --> 11 +11 --> 6 +9 --> 3 +3 --> 6 +6 --> 12 +``` + +## 第 7 章 可编程逻辑电路 + +“软件固化”和“以存代算”的理念催生了“用软件设计硬件”的新思路,进而诞生了多种硬件设计语言(Hardware Design Language,HDL)。随着硬件设计技术的进步,我们获得了显著的优势:用户可编程性使得设计修改变得便捷,设计本身也变得更加灵活,更易于转化为现实产品。 + +可编程逻辑器件(Programmable Logic Device,PLD)是一大类集成电路的总成,包括: + +- ROM(Read-only Memory):只读存储器 +- PLA(Programmable Logic Array):可编程逻辑阵列 +- PAL(Programmable Array Logic):可编程阵列逻辑 +- GAL(General Array Logic):通用阵列逻辑 +- …… + +### 只读存储器(ROM) + +#### 存储器的性质 + +- 只读存储器(ROM) + - 一旦信息写入,在运行机器上只读 + - 存放固定信息,例如程序,常数,指令等 + - 信息“非易失”(nonvolatile) + - 结构简单,规律性强,容量大 +- 随机存储器(RAM) + - 在运行机器上可读可写 + +#### ROM 的类别 + +- 掩模型 ROM(Mask ROM)(工厂编程) + - 用户提交码点,在工厂编程 + - 与阵列、或阵列均固定 +- 可编程 ROM(PROM)(用户一次编程) + - 出厂保留全部熔丝,用户可编程但不可改写 + - 与阵列固定,或阵列可编程 +- 可改写 ROM(EPROM)(用户多次编程) + - 光可改写(UV EPROM) + - 电可改写(EEPROM) + +![ROM 分类](https://img.picgo.net/2024/04/08/7-ROM-classificationf42a7f74e4f978de.jpeg) + +![ROM](https://img.picgo.net/2024/04/08/7-ROMf09e38a954f07c8c.jpeg) + +上例中的与阵列表示: +$$ +\begin{align*} +W_0 & = \overline{A_0}\;\overline{A_1}, \\ +W_1 & = A_0\overline{A_1}, \\ +W_2 & = \overline{A_0}A_1, \\ +W_3 & = A_0A_1, +\end{align*} +$$ +或阵列表示: +$$ +\begin{align*} +B_0 & = W_0 + W_2, \\ +B_1 & = W_1 + W_3, \\ +B_2 & = W_0 + W_3, \\ +B_3 & = W_2. +\end{align*} +$$ +![PROM](https://img.picgo.net/2024/04/08/7-PROM71b96c1712bd3052.jpeg) + +上例 PROM 中的与阵列表示: +$$ +\begin{align*} +W_0 & = \overline{A_0}\;\overline{A_1}, \\ +W_1 & = A_0\overline{A_1}, \\ +W_2 & = \overline{A_0}A_1, \\ +W_3 & = A_0A_1. +\end{align*} +$$ +或阵列可以通过包含不同的与阵列项,来得到不同的输出结果。 + +> **注意**:推荐 ROM 中与阵列的画法: +> +> - 一二行,一下一上一下一上; +> - 三四行,两下两上两下两上; +> - 五六行,四下四上四下四上; +> - 七八行,八下八上八下八上; +> - …… + +### 可编程逻辑阵列(PLA) + +> ROM 的特点为**输入地址和存储信息一一对应**,这导致与阵列表示的译码器包括了**全部最小项**,信息表完全。 +> +> 为了提高芯片的利用率,与阵列不一定产生所有的最小项,只需产生逻辑函数所需的乘积项即可。 +> +> PLA 针对这一点,进行**逻辑压缩**。 + +#### 用 PLA 实现 8421 码到格雷码的转换 + +8421 码表示为 $B_3B_2B_1B_0$,格雷码表示为 $G_3G_2G_1G_0$。 + +![PLA 实现 8421 码到格雷码的转换](https://img.picgo.net/2024/04/08/7-PLA1329d8ce7c084d3b.jpeg) + +#### PLA 的性质 + +- 与阵列可编程,形成 $P$ 项(不一定是最小项,但是一定为“与项”) +- 或阵列可编程 +- PLA 的读出方式:一组地址可以选中多个 $P$ 项 +- PLA 和 ROM 的区别: + - ROM 的信息表原封不动,全译码 + - PLA 做了逻辑压缩,信息表改动很大,但**逻辑上等价** +- PLA 的容量表示:(输入数 $2N$)$\times$($P$ 项数)$\times$(输出数 $M$​) + - $2N$ 是上半部分行数 + - $P$ 是列数 + - $M$ 是下半部分行数 + +### PROM、PLA、PAL 对比 + +- PROM + - **与阵列固定,或阵列可编程**,实现组合逻辑 + - 实现时序逻辑电路需要外加触发器 +- PLA + - **与或阵列均可编程**,实现组合逻辑 + - 实现时序逻辑电路需要外加触发器 +- PAL + - **与阵列可编程,或阵列固定** + - 不同的芯片可实现不同的逻辑,有些 PAL 只能实现组合逻辑电路,有些只能实现时序逻辑电路 + - 一次性编程 + + +> PROM、PLA、PAL 共同存在的问题:不存在只用一种芯片,既可以实现组合逻辑电路,又可以实现时序逻辑电路。 +> +> GAL(General Array Logic,通用阵列逻辑)是为解决这一问题而产生的芯片。 +> +> **注意**:GAL 的基本逻辑结构与 PAL 相同,**与阵列可编程,或阵列固定**。 + + +### 可编程器件工艺演化过程 + +- PROM $\to$ PLA + - 从只有或阵列可编程变为与、或阵列都可编程 + - 更加灵活,能节省码点 +- PLA $\to$ PAL + - 工艺:简化工艺,降低成本(熔丝工艺,一次编程) + - 结构:输入/输出共用 + - PAL 是专用词,MMI 公司的产品 +- PAL $\to$ GAL + - 工艺:电可擦除,多次编程 + - 结构:输出宏单元,更通用 + - GAL 是 Lattice 公司 1985 年专利 + +## 补充 + +### 设计中的实用化技术 + +#### 负载问题 + +1. 输入缓冲:减少外部负载 +2. 内部负载分配 +3. 输出的扇出最大化(用 $\overline{Q}$ 反馈到内部) + +#### 可靠性问题 + +1. 设计的电路结构规则:如设计电路中有时用“异或”而不用“与或” + + 传输延迟可预测,可读性好,布线方便 + +2. 添加冗余电路:消除竞争与冒险 + +#### 扩展问题 + +设计所有的集成电路都要考虑扩展,没有可扩展性的设计是没有生命力的。 + +#### 线与问题 + +1. 总线的接口电路采用三态结构 +2. 集开极电路的“线与”问题 + +#### 自启动问题 + +自启动问题是所有时序电路都必须解决的问题,否则设计出来的产品是废品。 + diff --git "a/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\346\225\260\347\220\206\351\200\273\350\276\221\344\270\216\351\233\206\345\220\210\350\256\272.md" "b/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\346\225\260\347\220\206\351\200\273\350\276\221\344\270\216\351\233\206\345\220\210\350\256\272.md" new file mode 100644 index 0000000..209e267 --- /dev/null +++ "b/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\346\225\260\347\220\206\351\200\273\350\276\221\344\270\216\351\233\206\345\220\210\350\256\272.md" @@ -0,0 +1,2086 @@ +--- +title: 【学习笔记】数理逻辑与集合论 +tags: + - 离散数学 + - 数理逻辑 + - 集合论 +categories: + - 笔记 +mathjax: true +toc: true +date: 2023-09-02 10:14:22 +password: +id: Shuliluoji-Yu-Jihelun +--- + +这是《数理逻辑与集合论(第2版)》的学习笔记。 + + + +## 第 1 章 命题逻辑的基本概念 + +### 代入规则 + +{% note warning %} + +#### 注意:代入规则 + +1. 公式中被代换的只能是 **命题变元**,而不能是复合命题。 + 例如,可以用 $(R\land S)$ 来代替某公式中的 $P$,记作 $\frac{P}{(R\land S)}$,但不能反过来将公式中的 $(R\land S)$ 以 $P$ 代之。 + +2. 对公式中某命题变项施以代入,必须对该公式中出现的所有同一命题变项代换同一公式。 + 其实就是说,要代换就所有都代换完。对于重言式 $(P\lor\lnot P)$,仅仅代换前一部分的 $P \gets \lnot Q$,那么就变成了 $(\lnot Q \lor \lnot P)$,这并非重言式。 + +{% endnote %} + +### 波兰式与逆波兰式 + +简而言之,如果将一个合式公式用二叉树来表示,那么 + +- 波兰式就是前缀表达式,即先序遍历,先输出自己,再依次遍历左、右子树。 + +- 逆波兰式就是后缀表达式,即后序遍历,先依次遍历左、右子树,再输出自己。 + +{% note warning %} + +#### 注意:波兰式与逆波兰式 + +越 **先运算** 的式子的深度应该越 **深**。 + +> 例1.1 将下列公式写成波兰式。 +> $\lnot\lnot P \lor(W\land R)\lor \lnot Q$ + +这题的正确答案应该是 $\lor\lor\lnot\lnot P \land W R \lnot Q$。(而不是 $\lor\lnot\lnot P\lor\land W R \lnot Q$!) + +{% endnote %} + +## 第 2 章 命题逻辑的等值和推理演算 + +### 等值公式 + +{% note info %} + +#### 公式:等值公式 + +1. $(P \to Q) \to R \neq P \to (Q \to R)$ + +2. $P \leftrightarrow (Q \leftrightarrow R) \neq (P \leftrightarrow Q) \leftrightarrow (P \leftrightarrow Q)$ + +3. $P \to \lnot P = \lnot P, \lnot P \to P = P$ + +4. $P \leftrightarrow Q = (P \land Q) \lor (\lnot P \land \lnot Q)$ + +5. $P \leftrightarrow Q = (P \lor \lnot Q) \land (\lnot P \lor Q)$ + +6. $P \to (Q \to R) = (P \land Q) \to R$ + +7. $(P \to R) \land (Q \to R) = (P \lor Q) \to R$ + +{% endnote %} + +~~妈的,与和或之间没有交换律。~~ + +**定理 1**:不知道逻辑上这两者不等的原因是什么,但显然左式是 $P \land \lnot Q \lor R$,但右式是 $\lnot P \lor \lnot Q \lor R$,二者不等。 + +**定理 2**:当 $P = Q = R = \mathrm{F}$ 时,左式为假,右式为真。 + +**定理 3**:十分合理,拆开发现是俩相同东西的或。 + +**定理 4**:这可解释为 $P \leftrightarrow Q$ 为真,有两种可能的情形,即 $(P \land Q)$ 为真,或 $(\lnot P \land \lnot Q)$ 为真。其实就是 $P$ 和 $Q$ 二者同真同假。 + +**定理 5**:这可解释为 $P \leftrightarrow Q$ 为假,有两种可能的情形,即 $(P \lor \lnot Q)$ 为假,或 $(\lnot P \lor Q)$ 为假。其实就是 $P$ 和 $Q$ 二者真假不同。 + +**定理 6**:$P$ 是 $(Q \to R)$ 的前提,$Q$ 是 $R$ 的前提,于是可将两个前提的合取 $(P \land Q)$ 作为总的前提。 + +**定理 7**:左端说明由 $P$ 而且由 $Q$ 都有 $R$ 成立,从而可以说明由 $P$ 或由 $Q$ 就有 $R$ 成立,即右端。 + +### 对偶式 + +{% note primary %} + +#### 定义:对偶式 + +假定命题公式 $A$ 中仅出现 $\lnot, \lor, \land$ 三个联结词。将 $A$ 中出现的 $\lor, \land, \text{T}, \text{F}$ 分别以 $\land, \lor, \text{F}, \text{T}$ 代换,得到公式 $A^*$,则称 $A^*$ 是 $A$ 的 **对偶式**,或说 $A$ 和 $A^*$ 互为对偶式。 + +{% endnote %} + +{% note info %} + +#### 性质:对偶式 + +为方便,若 $A = A(P_1, P_2, \cdots, P_n)$,令 $A^- = A(\lnot P_1, \lnot P_2, \cdots, \lnot P_n)$。 + +1. $\lnot(A^*) = (\lnot A)^*, \lnot(A^-) = (\lnot A)^-$ +2. $(A^*)^* = A, (A^-)^- = A$ +3. $\lnot A = A^{*-}$ + +{% endnote %} + +证明的思路是对 $A$ 中出现的联结词个数进行归纳证明。 + +### 范式 + +{% note info %} + +#### 性质:极小项与极大项 + +**极小项**: + +1. 对一个含有 $n$ 个变项的公式来说,所有可能的极小项个数和该公式的解释个数一样多,都是 $2^n$。 + +2. 每个极小项只在一个解释下为真。 + +3. 极小项两两不等值,而且 $m_i \land m_j = \text{F}(i \neq j)$。 + +4. 恰由 $2^n$ 个极小项的析取构成的公式,必为重言式。即 + $$ + \bigvee_{i = 0}^{2^n-1}m_i = \text{T} + $$ + +**极大项**: + +1. 对一个含有 $n$ 个变项的公式来说,所有可能的极大项个数和该公式的解释个数一样多,都是 $2^n$。 + +2. 每个极大项只在一个解释下为假。 + +3. 极大项两两不等值,而且 $M_i \lor M_j = \text{T}(i \neq j)$。 + +4. 恰由 $2^n$ 个极大项的合取构成的公式,必为矛盾式。即 + $$ + \bigwedge_{i = 0}^{2^n-1}M_i = \text{F} + $$ + +{% endnote %} + +可以理解为极小项(极大项)构成了含 $n$ 个命题变项的命题组成的空间的一组基底,极小项(极大项)两两不等值且与(或)得到的结果为 $\text{F}$($\text{T}$)类似于基底中基向量的正交性。 + +#### 填满变量的简便方法 + +例如 $\lnot P \lor Q$,可以将 $\lnot P$ 看做 $m^{0x}$,$Q$ 看做 $m^{x1}$。其中 $x$ 表示任意值。 + +因此 $\lnot P \lor Q = m^{00} \lor m^{01} \lor m^{01} \lor m^{11} = m_0 \lor m_1\lor m_3$。 + +#### 主合取范式与主析取范式之间的转换 + +若已知 $A$ 的主析取范式,如 +$$ +\begin{aligned} +A & = \lor_{0, 1, 4, 5, 7} \\ +& = \land_{(\{0, 1, \cdots, 7\} - \{0, 1, 4, 5, 7\})_\text{ 补}} \\ +& = \land_{\{2, 3, 6\}_{\text{ 补}}} \\ +& = \land_{5, 4, 1} +\end{aligned} +$$ +若已知 $A$ 的主合取范式,如 +$$ +\begin{aligned} +A & = \land_{1, 4, 5} \\ +& = \lor_{(\{0, 1, \cdots, 7\} - \{1, 4, 5\})_\text{ 补}} \\ +& = \lor_{\{0, 2, 3, 6, 7\}_\text{ 补}} \\ +& = \lor_{7, 5, 4, 1, 0} +\end{aligned} +$$ + +取补是为了求出命题变项的否定。在此例中,$2^n-1 = 7$,所以取补就是用 $7$ 减去其他的值。 + +{% note warning %} + +#### 注意:空公式 + +永真式的主合取范式为空公式。 + +矛盾式的主析取范式为空公式。 + +{% endnote %} + +### 推理演算 + +{% note warning %} + +#### 注意:推理形式 + +前提真,结论必真的推理形式为正确的推理形式。 + +$A \implies B$ 表示一种 $A$ 和 $B$ 之间的真值关系,$\implies$ 不是逻辑联结词,$A \implies B$ 也不是合式公式。 + +$A \implies B$ 说明推理形式 $A \to B$ 是正确的。 + +{% endnote %} + +{% note info %} + +#### 公式:基本的推理公式 + +1. $P \land Q \implies P$ +2. $\lnot(P \to Q) \implies P$ +3. $\lnot(P \to Q) \implies \lnot Q$ +4. $P \implies P \lor Q$ +5. $\lnot P \implies P \to Q$ +6. $Q \implies P \to Q$ +7. $\lnot P \land (P \lor Q) \implies Q$ +8. $P \land (P \to Q)\implies Q$ +9. $\lnot Q \land (P \to Q) \implies \lnot P$ +10. $(P \to Q) \land (Q \to R) \implies P \to R$ +11. $(P \leftrightarrow Q) \land (Q \leftrightarrow R) \implies P \leftrightarrow R$ +12. $(P \to R) \land (Q \to R) \land (P \lor Q) \implies R$ +13. $(P \to Q) \land (R \to S) \land (P \lor R) \implies Q \lor S$ +14. $(P \to Q) \land (R \to S) \land (\lnot Q \lor \lnot S) \implies \lnot P \lor \lnot R$ +15. $(Q \to R) \implies ((P \lor Q) \to (P \lor R))$ +16. $(Q \to R) \implies ((P \to Q) \to (P \to R))$ + +{% endnote %} + +公式 8 常称作假言推理,或称作分离规则,是最常使用的推理公式。 + +公式 10 常称作三段论。 + +公式 15 和 公式 16 值得玩味。 + +#### 证明推理公式的方法 + +{% note default %} + +#### 定理:$A \implies B$ 的充要条件 + +1. $A \implies B$ 等价于 $A \to B$ 是重言式。 +2. $A \implies B$ 等价于 $A \land \lnot B$ 是矛盾式。 + +{% endnote %} + +{% note default %} + +#### 规则:推理规则 + +1. 前提引入规则 + + 在推理过程中,可以随时引入前提。 + +2. 结论引用规则 + + 在推理过程中所得到的中间结论,可作为后续推理的前提。 + +3. 代入规则 + + 在推理过程中,对重言式中的命题变项可使用代入规则。 + +4. 置换规则 + + 在推理过程中,命题公式中的任何部分公式都可以用与之等值的命题公式来置换。 + +5. 分离规则(假言推理) + + 如果已知命题公式 $A \to B$ 和 $A$,则有命题公式 $B$。 + +6. 条件证明规则 + + $A_1 \land A_2 \implies B$ 与 $A_1 \implies A_2 \to B$ 是等价的。 + +{% endnote %} + +规则 6 将 $A_1 \implies A_2 \to B$ 的证明化为 $A_1 \land A_2 \implies B$ 的证明。意思是说,可以将要证明的结论 $A_2 \to B$ 中的 $A_2$ 作为条件来使用,从而简化了证明。 + +{% note warning %} + +#### 注意:推理规则 + +在证明过程中,将 $P \lor Q$ 写成 $\lnot P \to Q$ 更便于推理。 + +{% endnote %} + +### 归结推理法 + +{% note primary %} + +#### 定义:归结式 + +设 $C_1 = L \lor C_1', C_2 = \lnot L \lor C_2'$ 为两个子句,有互补对 $L$ 和 $\lnot L$。则新子句 +$$ +R(C_1, C_2) = C_1' \lor C_2' +$$ +称作 $C_1, C_2$ 的 **归结式**。 + +{% endnote %} + +{% note default %} + +#### 定理:归结证明 + +设 $C_1 = L \lor C_1', C_2 = \lnot L \lor C_2'$ 为两个子句,有互补对 $L$ 和 $\lnot L$。则 +$$ +C_1 \land C_2 \implies R(C_1, C_2) +$$ +这说明归结式 $R(C_1, C_2)$ 是子句 $C_1$ 和 $C_2$ 的逻辑推论,从而归结是正确推理规则。 + +{% endnote %} + +设在任意解释下 $C_1$ 和 $C_2$ 均为真,则若 $L$ 为真,则 $\lnot L$ 为假,$C_2'$ 必为真,$R(C_1, C_2)$ 为真。反之则 $L$ 为假,$C_1'$ 必为真,$R(C_1, C_2)$ 仍为真。 + +#### 归结证明过程 + +1. 为证明 $A \to B$ 是重言式,这等价于证明 $A \land \lnot B$ 是矛盾式。使用归结证明法,就是从 $A \land \lnot B$ 出发。 + +2. 建立子句集 $S$ + + 将 $A \land \lnot B$ 化成合取范式,如 + $$ + P \land (P \lor R) \land (\lnot P \lor \lnot Q) \land (\lnot P \lor R) + $$ + 进而将所有子句(析取式)构成子句集 + $$ + S = \{P, (P \lor R), (\lnot P \lor \lnot Q), (\lnot P \lor R)\} + $$ + 以集合来描述合取范式,这种表示法对归结过程的阐明是方便的。 + +3. 对 $S$ 作归结 + + 进而对 $S$ 的子句作归结(消互补对),如子句 $P \lor R$ 与 $\lnot P \lor \lnot Q$ 作归结,得归结式 $R \lor \lnot Q$,并将这归结式仍放入 $S$ 中。重复此过程。 + +4. 直至归结出矛盾式 $\square$。 + +{% note warning %} + +#### 注意:归结推理法 + +一般情况下推理规则和归结不能混用。因为它俩本质上是同一回事。 + +{% endnote %} + +## 第 3 章 命题逻辑的公理化 + +### 罗素公理系统 + +{% note default %} + +#### 公理:罗素公理系统 + +1. $\vdash((P \lor P) \to P)$ +2. $\vdash (P \to (P \lor Q))$ +3. $\vdash((P \lor Q)\to(Q \lor P))$ +4. $\vdash((Q \to R)\to((P \lor Q)\to(P \lor R))$ + +{% endnote %} + +{% note default %} + +#### 规则:罗素公理系统 + +1. 代入规则 + + 将合式公式 $A$ 中出现的某一符号 $\pi$ 到处都代以某一合式公式 $B$,得到合式公式 $A \dfrac{\pi}{B}$ 叫代入。代入规则说,如果 $\vdash A$,那么 $\vdash A \dfrac{\pi}{B}$。 + +2. 分离规则 + + 如果 $\vdash A, \vdash A \to B$,那么 $\vdash B$。 + +3. 置换规则 + + 定义的左右两方可以互相替换。设公式 $A$,替换后为 $B$。置换规则说,如果 $\vdash A$,那么 $\vdash B$。 + +{% endnote %} + +{% note default %} + +#### 定理:罗素公理系统 + +1. $\vdash (Q \to R)\to((P \to Q) \to (P \to R))$ +2. $\vdash P \to P$ +3. $\vdash \lnot P \lor P$ +4. $\vdash P \lor \lnot P$ +5. $\vdash P \to \lnot\lnot P$ +6. $\vdash \lnot\lnot P \to P$ +7. $\vdash (P \to Q)\to(\lnot Q \to \lnot P)$ + +{% endnote %} + +~~懒得推。~~ + +一般形如 $\vdash\square_1 \to \square_2$ 的定理,先会化简 $\square_1$,中间都会有一步 $\vdash(P \lor Q)\to(Q \lor P)$, 然后化简 $\square_2$ 发现能凑出逻辑链。 + +### 公理系统的完备性 + +设 $A$ 是任意一个重言式,需要说明它在公理系统中是可证明的。先将 $A$ 写成与之等值的合取范式 $A_1 \land A_2 \land \cdots \land A_n$。其中 $A_i(i = 1, 2, \cdots, n)$ 必为 $\pi \lor \lnot \pi \lor B$ 的形式,$\pi$ 是命题变项。依公理系统 $\vdash P \lor \lnot P, \vdash P \lor \lnot P \lor Q$ 都成立,从而有 $\vdash A_i$。 + +又因为 $\vdash P \to (Q \to P \land Q)$,使用分离规则可得 $\vdash A_1\land A_2 \land \cdots \land A_n$。故 $A$ 是可证明的。 + +### 王浩算法 + +{% note primary %} + +#### 定义:初始符号 + +1. $A, B, \cdots, X, Y, Z$ 表示命题 +2. $\lnot, \land, \lor, \to, \leftrightarrow$ 表示联结词 +3. $(, ), ,$ 圆括号和逗点 +4. $\alpha, \beta, \gamma, \cdots$ 表示公式串 + +{% endnote %} + +{% note primary %} + +#### 定义:相继式 + +1. 如果 $\alpha$ 和 $\beta$ 都是公式串,则称 + $$ + \alpha \overset{s}{\to} \beta + $$ + 是 **相继式**,$\alpha$ 为前件,$\beta$ 为后件。 + +2. 规定 $\overset{s}{\to}$ 前件中的”$,$“以 $\land$ 表示,后件中的”$,$“以 $\lor$ 表示,便可将 $\alpha \overset{s}{\to} \beta$ 化为 $\gamma \to \delta$。 + +3. 相继式 $\alpha \overset{s}{\to} \beta$ 为真,便以 $\alpha \overset{s}{\implies} \beta$ 表示。 + +{% endnote %} + +{% note default %} + +#### 规则:变形规则 + +**前件规则**: + +1. $\lnot\implies$ + + 如果 $\alpha, \beta \overset{s}{\implies}X, \gamma$,那么 $\alpha, \lnot X, \beta \overset{s}{\implies}\gamma$。 + +2. $\land\implies$ + + 如果 $X, Y, \alpha, \beta \overset{s}{\implies}\gamma$,那么 $\alpha, X\land Y, \beta \overset{s}{\implies}\gamma$。 + +3. $\lor\implies$ + + 如果 $X, \alpha, \beta \overset{s}{\implies}\gamma$ 而且 $Y, \alpha, \beta \overset{s}{\implies}\gamma$,那么 $\alpha, X \lor Y, \beta \overset{s}{\implies}\gamma$。 + +4. $\to\implies$ + + 如果 $Y, \alpha, \beta \overset{s}{\implies}\gamma$ 而且 $\alpha, \beta \overset{s}{\implies}X, \gamma$,那么 $\alpha, X \to Y, \beta \overset{s}{\implies}\gamma$。 + +5. $\leftrightarrow\implies$ + + 如果 $X, Y, \alpha, \beta \overset{s}{\implies}\gamma$ 而且 $\alpha, \beta \overset{s}{\implies}X, Y, \gamma$,那么 $\alpha, X \leftrightarrow Y, \beta \overset{s}{\implies}\gamma$。 + +**后件规则**: + +1. $\implies\lnot$ + + 如果 $X, \alpha\overset{s}{\implies}\beta, \gamma$,那么 $\alpha\overset{s}{\implies}\beta, \lnot X, \gamma$。 + +2. $\implies\land$ + + 如果 $\alpha \overset{s}{\implies} X, \beta, \gamma$ 而且 $\alpha \overset{s}{\implies} Y, \beta, \gamma$,那么 $\alpha \overset{s}{\implies}\beta, X\land Y, \gamma$。 + +3. $\implies\lor$ + + 如果 $\alpha \overset{s}{\implies} X, Y, \beta, \gamma$,那么 $\alpha \overset{s}{\implies} \beta, X\lor Y, \gamma$。 + +4. $\implies\to$ + + 如果 $X, \alpha\overset{s}{\implies}Y, \beta, \gamma$,那么 $\alpha\overset{s}{\implies}\beta, X \to Y, \gamma$。 + +5. $\implies\leftrightarrow$ + + 如果 $X, \alpha\overset{s}{\implies}Y, \beta, \gamma$ 而且 $Y, \alpha\overset{s}{\implies}X, \beta, \gamma$,那么 $\alpha \overset{s}{\implies} \beta, X \leftrightarrow Y, \gamma$。 + +{% endnote %} + +在符号 $\overset{s}{\implies}$ 两边移动符号 $X$ 会导致其取反,这是因为 +$$ +\begin{aligned} +\alpha \land \beta \implies& X \lor \gamma \\ +\alpha \land \beta \implies& \lnot X \to \gamma \\ +\alpha \land \beta \land \lnot X \implies& \gamma \\ +\alpha, \beta, \lnot X \overset{s}{\implies}& \gamma +\end{aligned} +$$ + +### 命题逻辑的自然演绎系统 + +{% note primary %} + +#### 定义:初始符号 + +$$ +\Gamma = \{A_1, A_2, \cdots, A_n\} = A_1, A_2, \cdots, A_n +$$ + +表示有限个命题公式的集合。 +$$ +\Gamma \vdash A +$$ +表示 $\Gamma, A$ 间有形式推理关系,$\Gamma$ 为形式前提,$A$ 为形式结论,或说使用推理规则可由 $\Gamma$ 得 $A$。 + +{% endnote %} + +{% note default %} + +#### 规则:变形规则 + +1. $A_1, A_2, \cdots, A_n \vdash A_i(i = 1, 2, \cdots, n)$。肯定前提律。 + + 推理过程中前提总是被肯定的,前提中任何命题都可作为结论。 + +2. 如果 $\Gamma \vdash A, A \vdash B$,则 $\Gamma \vdash B$。传递律。 + +3. 如果 $\Gamma, \lnot A \vdash B$,且 $\Gamma, \lnot A \vdash \lnot B$,则 $\Gamma \vdash A$。反证律。 + + 在前提 $\Gamma$ 下,再假设 $A$ 是假的,若可推出矛盾命题,则可由前提 $\Gamma$ 推出 $A$。 + +4. $A \to B, A \vdash B$。蕴涵词消去律(分离规则)。 + +5. 如果 $\Gamma, A \vdash B$,则 $\Gamma \vdash A \to B$。蕴涵词引入律。 + + 在前提 $\Gamma$ 下,又知 $A$ 为真,可得 $B$。那么在原前提 $\Gamma$ 下可推得如果 $A$ 那么 $B$。 + +{% endnote %} + +## 第 4 章 谓词逻辑的基本概念 + +### 合式公式 + +{% note warning %} + +#### 注意:合式公式 + +1. 如果 $A, B$ 是合式公式,而无变元 $x$ 在 $A, B$ 的一个中是约束的而在另一个中是自由的,则 $A \land B, A \lor B, A \to B, A \leftrightarrow B$ 也算是合式公式。 +2. 如果 $A$ 是合式公式,而 $x$ 在 $A$ 中是自由变元,则 $(\forall x)A, (\exists x)A$ 也是合式公式。 + +{% endnote %} + +第 1 点说明 $(\forall x)P(x) \lor Q(x)$ 不是合式公式。一个恰当的写法是 $(\forall x)P(x) \lor Q(y)$。 + +第 2 点说明 $(\exists x)((\forall x)F(x))$ 不是合式公式,因为内层 $x$ 并不是自由变元。 + +### 自然语句的形式化 + +#### “所有的有理数都是实数”的形式化 + +以 $P(x)$ 表示 $x$ 是有理数,$Q(x)$ 表示 $x$ 是实数。则“所有的有理数都是实数”可以被形式化地描述为 +$$ +(\forall x)(P(x) \to Q(x)) +$$ +注意,这句话并不能表示为 $(\forall x)(P(x) \land Q(x))$。当论域包含不是有理数的东西的时候,$(\forall x)(P(x) \land Q(x))$ 恒为假,这不是我们希望看到的。 + +#### ”有的实数是有理数“的形式化 + +以 $P(x)$ 表示 $x$ 是有理数,$Q(x)$ 表示 $x$ 是实数。则“有的实数是有理数”可以被形式化地描述为 +$$ +(\exists x)(Q(x) \land P(x)) +$$ +注意,这句话并不能表示为 $(\exists x)(Q(x) \to P(x))$。当论域包含不是实数的东西的时候,$x$ 取这些事物时恒有 $Q(x)$ 为假,那么 $(\exists x)(Q(x) \to P(x))$ 恒为真,这也不是我们希望看到的。 + +#### “没有无理数是有理数”的形式化 + +以 $A(x)$ 表示 $x$ 是无理数,$B(x)$ 表示 $x$ 是有理数。则“没有无理数是有理数”可以被形式化地描述为 +$$ +\lnot (\exists x)(A(x) \land B(x)) +$$ + +#### “有的实数不是有理数”的形式化 + +以 $A(x)$ 表示 $x$ 是实数,$B(x)$ 表示 $x$ 是有理数。则“有的实数不是有理数”可以被形式化地描述为 +$$ +(\exists x)(A(x) \land \lnot B(x)) +$$ + +#### 自然数集的形式描述 + +自然数集的定义: + +1. 对每个数,有且仅有一个相继后元。 +2. 没有这样的数,$0$ 是其相继后元。 +3. 对除 $0$ 以外的数,有且仅有一个相继前元。 + +一个比较常用的描述唯一性的方法是,“如果有两个则它们必相等”。即若对每个 $x$ 都存在 $y$,使得 $y$ 是 $x$ 的相继后元,且对任意 $z$,如果 $z$ 也是 $x$ 的相继后元,则 $z = y$。 + +引入谓词 $\mathsf{E}(x, y)$ 表示 $x = y$。函数 $f(x)$ 表示个体 $x$ 的相继后元,即 $f(x) = x + 1$。函数 $g(x)$ 表示个体 $x$ 的相继前元,即 $g(x) = x - 1$。 + +1. $(\forall x)(\exists y)(\mathsf{E}(y, f(x))\land (\forall z)(\mathsf{E}(z, f(x)) \to \mathsf{E}(y, z)))$ +2. $\lnot (\exists x)\mathsf{E}(0, f(x))$ +3. $(\forall x)(\lnot\mathsf{E}(x, 0) \to (\exists y)(\mathsf{E}(y, g(x)) \land (\forall z)(\mathsf{E}(z, g(x)) \to \mathsf{E}(y, z))))$ + +{% note warning %} + +#### 注意:对谓词变元多次量化的分析 + +1. $(\forall x)(\forall y)P(x, y) = (\forall y)(\forall x)P(x, y)$ +2. $(\exists x)(\exists y)P(x, y) = (\exists y)(\exists x)P(x, y)$ +3. $(\forall x)(\exists y)P(x, y) \neq (\exists y)(\forall x)P(x, y)$ + +{% endnote %} + +注意第 3 点左式表明 $y$ 是 $x$ 的函数 $y(x)$,也就是 $x_1$ 可以对应存在 $y_1$,$x_2$ 对应存在 $y_2$……但右式要求一个固定的 $y$ 对所有的 $x$ 都成立。 + +事实上,$(\exists y)(\forall x)P(x, y) \implies (\forall x)(\exists y)P(x, y)$。 + +### 公式的普遍有效性和判定问题 + +{% note primary %} + +#### 定义:普遍有效性 + +对一个谓词公式: + +1. 如果在它的任一解释 $I$ 下真值都为真,便称它是 **普遍有效的**。 +2. 如果在它的某个解释 $I$ 下真值为真,便称它是 **可满足的**。 +3. 如果在它的任一解释 $I$ 下真值都为假,便称它是 **不可满足的**。 + +{% endnote %} + +有限域上一个公式的可满足性和普遍有效性仅依赖于个体域个体的数目。即在某个含 $k$ 个元素的 $k$ 个体域上普遍有效(可满足),则在任一 $k$ 个体域上也普遍有效(可满足)。 + +如果某公式在 $k$ 个体域上普遍有效,则在 $k - 1$ 个体域上也普遍有效。 + +如果某公式在 $k$ 个体域上可满足,则在 $k + 1$ 个体域上也可满足。 + +#### 判定问题 + +1. 谓词逻辑是不可判定的。 + + 对任一谓词公式而言,没有可行方法能判明它是否是普遍有效的。但这并不排除谓词公式有子类是可判定的。判定问题的困难在于个体域是个无穷集以及对谓词设定的任意性。 + +2. 只含有一元谓词变项的公式是可判定的。 + +3. $$ + (\forall x_1)(\forall x_2)\cdots(\forall x_n)P(x_1, x_2, \cdots, x_n) + $$ + + 和 + $$ + (\exists x_1)(\exists x_2)\cdots(\exists x_n)P(x_1, x_2, \cdots x_n) + $$ + 型公式,若 $P$ 中无量词和其他自由变项时是可判定的。 + +## 第 5 章 谓词逻辑的等值和推理演算 + +### 量词分配等值式 + +{% note info %} + +#### 公式:量词对 $\to$ 的分配律 + +1. $(\forall x)(P(x) \to q) = (\exists x)P(x) \to q$ +2. $(\exists x)(P(x) \to q) = (\forall x)P(x) \to q$ +3. $(\forall x)(p \to Q(x)) = p \to (\forall x)Q(x)$ +4. $(\exists x)(p \to Q(x)) = p \to (\exists x)Q(x)$ + +其中 $p, q$ 为命题变项,与个体变元 $x$ 无关。 + +{% endnote %} + +~~这应该如何感性地理解?~~ + +### 范式 + +{% note primary %} + +#### 定义:前束范式 + +说公式 $A$ 是一个 **前束范式**,如果 $A$ 中一切量词都位于该公式的最左边(不含否定词)且这些量词的辖域都延伸到公式的末端。 + +前束范式 $A$ 的一般形式为 +$$ +(Q_1 x_1)(Q_2 x_2)\cdots(Q_n x_n)M(x_1, x_2, \cdots, x_n) +$$ +其中 $Q_i(i = 1, 2, \cdots, n)$ 为量词 $\forall$ 或 $\exists$,$M$ 称为公式 $A$ 的母式,$M$ 中不再有量词。 + +{% endnote %} + +#### 求前束范式的步骤 + +例如求 $\lnot((\forall x)(\exists y)P(a, x, y) \to (\exists x)(\lnot(\forall y)Q(y, b) \to R(x)))$ 的前束范式。 + +1. 消去联结词 $\to, \leftrightarrow$。 + $$ + \lnot(\lnot(\forall x)(\exists y)P(a, x, y) \lor (\exists x)(\lnot\lnot(\forall y)Q(y, b) \lor R(x))) + $$ + +2. $\lnot$ 内移(反复使用摩根律)。 + $$ + (\forall x)(\exists y)P(a, x, y) \land (\forall x)((\exists y)\lnot Q(y, b) \land \lnot R(x))) + $$ + +3. 量词左移(使用分配等值式)。 + $$ + (\forall x)((\exists y)P(a, x, y) \land (\exists y)\lnot Q(y, b) \land \lnot R(x)) + $$ + +4. 变元易名(使用变元易名分配等值式)。 + $$ + \begin{aligned} + &(\forall x)((\exists y)P(a, x, y) \land (\exists y)\lnot Q(y, b) \land \lnot R(x)) \\ + = & (\forall x)((\exists y)P(a, x, y) \land (\exists z)\lnot Q(z, b) \land \lnot R(x)) \\ + = & (\forall x)(\exists y)(\exists z)(P(a, x, y) \land \lnot Q(z, b) \land \lnot R(x)) \\ + = & (\forall x)(\exists y)(\exists z)S(a, b, x, y, z) + \end{aligned} + $$ + +{% note primary %} + +#### 定义:$\exists$ 前束范式 + +一个公式的 **$\exists$ 前束范式** 为 +$$ +(\exists x_1)(\exists x_2)\cdots(\exists x_i)(\forall x_{i+1})\cdots(\forall x_n)M(x_1, x_2, \cdots, x_n) +$$ +即存在量词都在全称量词的左边,且可保持至少有一个存在量词($i \ge 1$),其中 $M(x_1, x_2, \cdots, x_n)$ 中不再含有量词也无自由个体变项。 + +{% endnote %} + +{% note info %} + +#### 性质:$\exists$ 前束范式 + +谓词逻辑的任一公式 $A$,都可化成相应的 $\exists$ 前束范式,并且 $A$ 是普遍有效的当且仅当其 $\exists$ 前束范式是普遍有效的。 + +{% endnote %} + +#### 求 $\exists$ 前束范式的步骤 + +例如求 $(\exists x)(\forall y)(\exists u)P(x, y, u)$ 的 $\exists$ 前束范式。 + +将一公式化为 $\exists$ 前束范式,必须先求出前束范式,再做 $\exists$ 前束范式。 + +首先将全称量词 $(\forall y)$ 改写为存在量词 $(\exists y)$,其次引入谓词 $S$ 和一个变元 $z$ 得 $S(x, z)$,建立公式 +$$ +(\exists x)((\exists y)(\exists u)(P(x, y, u) \land \lnot S(x, y)) \lor (\forall z)S(x, z)) +$$ +进而将 $(\forall z)$ 左移,便得 $\exists$ 前束范式 +$$ +(\exists x)(\exists y)(\exists u)(\forall z)((P(x, y, u) \land \lnot S(x, y)) \lor S(x, z)) +$$ +{% note primary %} + +#### 定义:Skolem 标准型 + +**Skolem 标准型** 是仅保留全称量词的前束范式。 + +{% endnote %} + +{% note info %} + +#### 性质:Skolem 标准型 + +谓词逻辑的任一公式 $A$,都可化成相应的 Skolem 标准型,并且 $A$ 是不可满足的当且仅当其 Skolem 标准型是不可满足的。 + +{% endnote %} + +#### 求 Skolem 标准型的步骤 + +例如求 $(\exists x)(\forall y)(\forall z)(\exists u)(\forall v)(\exists w)P(x, y, z, u, v, w)$ 的 Skolem 标准型。 + +将一个公式化成 Skolem 标准型,首先也得化成前束范式。 + +首先将最左侧的 $(\exists x)$ 消去,而将谓词 $P$ 中出现的所有变元 $x$ 均以论域中的某个常项 $a$(未在 $P$ 中出现过)代入。进而消去从左数第二个存在量词 $(\exists u)$,因 $(\exists u)$ 左侧有两个全称量词 $(\forall y)(\forall z)$,所以需要将谓词 $P$ 中出现的所有变元 $u$ 均以 $y, z$ 的某个二元函数 $f(y, z)$(未在 $P$ 中出现过)代入。最后按照同样的方法消去存在量词 $(\exists w)$,因 $(\exists w)$ 得左边有全称量词 $(\forall y)(\forall z)$ 和 $(\forall v)$,所以需要将谓词 $P$ 中出现的所有变元 $w$ 均以 $y, z, w$ 的某个三元函数 $g(y, z, w)$(未在 $P$ 中出现过也不同于 $f$)代入。这样便会得到 Skolem 标准型 +$$ +(\forall y)(\forall z)(\forall v)P(a, y, z, f(y, z) v, g(y, z, v)) +$$ +{% note warning %} + +#### 注意:Skolem 标准型 + +虽然 Skolem 标准型和原式 **不等值**,但在不可满足的意义下两者是一致的。 + +{% endnote %} + +### 推理演算 + +{% note info %} + +#### 公式:基本的推理公式 + +1. $(\forall x)P(x) \lor (\forall x)Q(x) \implies (\forall x)(P(x)\lor Q(x))$ +2. $(\exists x)(P(x) \land Q(x)) \implies (\exists x) P(x) \land (\exists x) Q(x)$ +3. $(\forall x)(P(x) \to Q(x)) \implies (\forall x) P(x) \to (\forall x) Q(x)$ +4. $(\forall x)(P(x) \to Q(x)) \implies (\exists x) P(x) \to (\exists x) Q(x)$ +5. $(\forall x)(P(x) \leftrightarrow Q(x)) \implies (\forall x)P(x) \leftrightarrow (\forall x)Q(x)$ +6. $(\forall x)(P(x) \leftrightarrow Q(x)) \implies (\exists x)P(x) \leftrightarrow (\exists x)Q(x)$ +7. $(\forall x)(P(x) \to Q(x)) \land (\forall x)(Q(x) \to R(x)) \implies (\forall x)(P(x) \to R(x))$ +8. $(\forall x)(P(x) \to Q(x)) \land P(a) \implies Q(a)$ +9. $(\forall x)(\forall y)P(x, y) \implies (\exists x)(\forall y)P(x, y)$ +10. $(\exists x)(\forall y)P(x, y) \implies (\forall y)(\exists x)P(x, y)$ + +{% endnote %} + +这些推理公式的逆都是不成立的,因为它们都减弱了推理的强度。 + +{% note default %} + +#### 规则:推理规则 + +1. 全称量词消去规则 + $$ + (\forall x)P(x) \implies P(y) + $$ + 其中 $y$ 是论域中任一个体,且 $y$ 不在 $P(x)$ 中被约束。 + +2. 全称量词引入规则 + $$ + P(y) \implies (\forall x)P(x) + $$ + 其中 $y$ 是论域中任一个体,且 $x$ 不在 $P(y)$ 中被约束。 + +3. 存在量词消去规则 + $$ + (\exists x)P(x) \implies P(c) + $$ + 其中 $c$ 是论域中一个个体常项,且 $(\exists x)P(x)$ 中没有自由个体,且 $P(x)$ 中不含有 $c$。 + +4. 存在量词引入规则 + $$ + P(c) \implies (\exists x)P(x) + $$ + 其中 $c$ 是论域中一个个体常项,且 $x$ 不出现在 $P(c)$ 中。 + +{% endnote %} + +这四条规则的共性是,引入或消去量词时,被约束的变量不能和已有变量相关导致产生更多隐性约束。 + +### 谓词逻辑的归结推理法 + +#### 归结证明过程 + +1. 为证明 $A \to B$ 是重言式,这等价于证明 $G = A \land \lnot B$ 是矛盾式。使用归结证明法,就是从 $A \land \lnot B$ 出发。注意此时的 $A, B$ 都是谓词公式。 + +2. 建立子句集 $S$ + + 如何消去 $G$ 中量词(尤其是存在量词),是建立子句集 $S$ 的关键。 + + 解决办法是首先将 $G$ 化成等值的前束范式,进而将前束范式化成 Skolem 标准型,得到 **仅含全称量词** 的公式 $G^*$。由于 $G$ 和 $G^*$ 在不可满足的意义下是一致的,从而对 $G$ 的不可满足性,可以由 $G^*$ 的不可满足性来求得。 + + 再将 $G^*$ 中的全称量词省略,并把 $\land$ 替换为“$,$”,便得到了 $G^*$ 的子句集 $S$。 + + 实际操作时常常直接求出 $A$ 和 $\lnot B$ 的子句集之后取并。 + +3. 对 $S$ 作归结 + +4. 直至归结出 $\square$。 + +## 第 9 章 集合 + +### 集合间的关系 + +{% note primary %} + +#### 定义:子集关系 + +定义 **子集关系** $\subseteq$ 如下: +$$ +A \subseteq B \iff (\forall x)(x \in A \to x \in B) +$$ + +{% endnote %} + +由此我们可以推出 + +$$ +\begin{aligned} +A = B & \iff (\forall x)(x \in A \leftrightarrow x \in B) \\ +A \neq B & \iff (\exists x)\lnot(x \in A \leftrightarrow x \in B) \\ +\end{aligned} +$$ + +{% note warning %} + +#### 注意:子集关系 + +在子集关系中,如果 $A = \varnothing$,则前件 $x \in A$ 恒为假,所以对任意集合 $B$ 都有 $\varnothing \subseteq B$。 + +{% endnote %} + +{% note info %} + +#### 性质:子集关系 + +1. $A \subseteq B \implies (A \cup C) \subseteq (B \cup C)$ +2. $A \subseteq B \implies (A \cap C) \subseteq (B \cap C)$ +3. $A \subseteq B \land C \subseteq D \implies (A \cup C) \subseteq (B \cup D)$ +4. $A \subseteq B \land C \subseteq D \implies (A \cap C) \subseteq (B \cap D)$ +5. $A \subseteq B \land C \subseteq D \implies (A - D) \subseteq (B - C)$ +6. $C \subseteq D \implies (A - D) \subseteq (A - C)$ + +{% endnote %} + +上述的 6 个性质中,我们可以发现 $\subseteq$ 与 $\le$ 类似。 + +{% note info %} + +#### 性质:幂集合 + +1. $A \subseteq B \iff P(A) \subseteq P(B)$ +2. $P(A) \in P(B) \implies A \in B$ +3. $P(A) \cap P(B) = P(A \cap B)$ +4. $P(A) \cup P(B) = P(A \cup B)$ +5. $P(A - B) \subseteq (P(A) - P(B)) \cup \{\varnothing\}$ + +{% endnote %} + +性质 1 的推论是 $A = B \iff P(A) = P(B)$。 + +**性质 2**: +$$ +\begin{aligned} +P(A) \in P(B) & \iff P(A) \subseteq B \\ +& \iff (P(A) \subseteq B) \land (A \in P(A)) \\ +& \implies A \in B +\end{aligned} +$$ + + +性质 2 的逆定理不成立。 + +性质 4 的左式缺少的是同时含 $A$ 和 $B$ 中元素的集合。 + +性质 5 的右式要并上 $\{\varnothing\}$,是因为左式的差运算把 $\{\varnothing\}$ 消去了。左式缺少的是同时含 $A - B$ 和 $A \cap B$ 中元素的集合。 + +{% note primary %} + +#### 定义:传递集合 + +若集合的集合 $A$ 的任意元素都是 $A$ 的元素,则称 $A$ 为 **传递集合**。形式化地表述,$A$ 是传递集合等价于 +$$ +(\forall x)(\forall y)((x \in y \land y \in A) \to x \in A) +$$ +{% endnote %} + +由定义可知,$A$ 的任意元素都是 $A$ 的子集。 + +{% note info %} + +#### 性质:传递集合 + +1. $A$ 是传递集合等价于 $A \subseteq P(A)$。 +2. $A$ 是传递集合等价于 $P(A)$ 是传递集合。 + +{% endnote %} + +**性质 1**: + +必要性:显然。 + +充分性:已知 $A \subseteq P(A)$。 +$$ +\begin{aligned} +x \in y \land y \in A & \implies x \in y \land y \in P(A) \\ +& \iff x \in y \land y \subseteq A \\ +& \implies x \in A +\end{aligned} +$$ +**性质 2**: + +必要性:已知 $A$ 是传递集合。 +$$ +\begin{aligned} +x \in y \land y \in P(A) & \iff x \in y \land y \subseteq A \\ +& \implies x \in A \\ +& \iff x \subseteq P(A) \\ +& \iff x \in P(A) +\end{aligned} +$$ +充分性:已知 $P(A)$ 是传递集合。 +$$ +\begin{aligned} +x \in y \land y \in A & \iff x \in y \land \{y\} \subseteq A \\ +& \iff x \in y \land y \in \{y\} \land \{y\} \in P(A) \\ +& \implies x \in y \land y \in P(A) \\ +& \iff x \in y \land y \subseteq A \\ +& \implies x \in A +\end{aligned} +$$ + +### 集合的运算 + +{% note info %} + +#### 性质:差运算 + +1. $A - B = A - (A \cap B)$ +2. $A - B = A \cap -B$ +3. $A \cup (B - A) = A \cup B$ +4. $A \cap (B - C) = (A \cap B) - C$ + +{% endnote %} + +用 $A - B = A \cap -B$ 的代换可以在推导过程中消去差运算。 + +{% note primary %} + +#### 定义:广义交和广义并 + +1. 定义集合 $A$ 的 **广义交** 为 $\cup A = \{x | (\exists z)(z \in A \land x \in z)\}$。 + +2. 定义集合 $A$ 的 **广义并** 为 $\cap A = \{x | (\forall z)(z \in A \to x \in z)\}$。 + +{% endnote %} + +广义交是所有元素的公共元素组成的集合,广义并是所有元素的元素组成的集合。 + +{% note warning %} + +#### 注意:广义交和广义并 + +规定 $\cup\varnothing = \varnothing$,$\cap\varnothing$ 无意义。 + +{% endnote %} + +{% note info %} + +#### 性质:广义交和广义并 + +1. $A \subseteq B \implies \cup A \subseteq \cup B$ +2. $A \subseteq B \implies \cap B \subseteq \cap A$ +3. $\cup(A \cup B) = (\cup A)\cup(\cup B)$ +4. $\cap(A \cup B) = (\cap A)\cup(\cap B)$ +5. $\cup(P(A)) = A$ + +6. $A$ 是传递集合可以推出 $\cup A, \cap A$ 均为传递集合。 +7. $A$ 的元素都是传递集合能推出 $\cup A, \cap A$ 均为传递集合。 + +{% endnote %} + +性质 5 说明广义并是幂集的左逆运算,**但它并不是幂集的右逆运算**。 + +性质 6 和性质 7 说明广义并、广义交对于传递集合有封闭性。 + +{% note primary %} + +#### 定义:有序数对 + +使用归纳法定义 **有序数对** 如下: + +- 基础:$\left = \{\{x_1\}, \{x_1, x_2\}\}$。 + +- 归纳:$\left = \left<\left, x_n\right>$。 + +{% endnote %} + +{% note primary %} + +#### 定义:笛卡尔积 + +对集合 $A, B$,定义它们的 **笛卡尔积** 为 $A \times B = \{\left | x \in A \land y \in B\}$。 + +{% endnote %} + +{% note warning %} + +#### 注意:笛卡尔积 + +在笛卡尔积相关证明中,常常需要考虑 $x = y$ 的情况。此时 $\left = \{\{x\}, \{x, y\}\}$ 退化为 $\{\{x\}\}$ 为单元素集合。 + +{% endnote %} + +{% note info %} + +#### 性质:笛卡尔积 + +1. $A \times \varnothing = \varnothing \times A = \varnothing$ +2. 若 $A$ 是集合,$x, y \in A$,则 $\left \in PP(A)$。 + +{% endnote %} + +性质 1 的解释是自然的,因为你无法从 $\varnothing$ 中选出元素来和 $A$ 中的元素进行组合,也就表明了这个笛卡尔积是空集。 + +**性质 2**: +$$ +\begin{aligned} +x \in A \land y \in A & \iff \{x\}, \{x, y\} \subseteq A \\ +& \iff \{x\}, \{x, y\} \in P(A) \\ +& \iff \{\{x\}, \{x, y\}\} \subseteq P(A) \\ +& \iff \left \subseteq P(A) \\ +& \iff \left \in PP(A) +\end{aligned} +$$ + +#### 运算符优先级 + +符号优先级从上到下。 + +| 类型 | 符号 | +| :--------: | :-----------------------------------------------: | +| 一元运算符 | $-A, P(A), \cap A, \cup A$ | +| 二元运算符 | $A-B, A \cap B, A \cup B, A \oplus B, A \times B$ | +| 集合关系符 | $=, \subseteq, \subset, \in$ | +| 一元联结词 | $\lnot$ | +| 二元联结词 | $\land, \lor, \to, \leftrightarrow$ | +| 逻辑关系符 | $\iff, \implies$ | + +### 集合论公理系统 + +{% note default %} + +#### 公理:子集公理模式 + +$$ +(\forall x)(\exists y)(\forall z)(z \in y \leftrightarrow(z \in x \land p(z))) +$$ + +{% endnote %} + +子集公理模式是说,对任意的集合 $x$,存在 $x$ 的子集 $y$,$y$ 的元素 $z$ 都能使 $p(z)$ 成立。它能用于以下情况:已知若干满足条件 $p(z)$ 的元素 $z$,但不知道这些元素能否组成一个集合。此时找到一个集合 $A$,使得这些满足 $p(z)$ 的 $z$ 都有 $z \in A$,这样就可由 $A$ 和 $p(x)$ 用子集公理得到满足条件的集合 +$$ +\{x | x \in A \land p(x)\} +$$ + +{% note primary %} + +#### 定义:极小元 + +对任意集合 $A$ 和 $B$,当有 $A \in B$ 且 $A \cap B = \varnothing$,就称 $A$ 为 $B$ 的一个 **极小元**。 + +{% endnote %} + +{% note default %} + +#### 公理:正则公理 + +$$ +(\forall x)(x \neq \varnothing \to (\exists y)(y \in x \land x \cap y = \varnothing)) +$$ + +{% endnote %} + +正则公理是说,任意非空集合都有极小元。 + +{% note info %} + +#### 推论:正则公理 + +1. 对任意的集合 $A$,$A \notin A$。 +2. 对任何非空的传递集合 $A$,有 $\varnothing \in A$。 + +{% endnote %} + +**推论 1**: + +假设存在集合 $A$,使得 $A \in A$,则构造 $\{A\}$。由正则公理知 $\{A\}$ 一定有极小元,而 $\{A\}$ 是一个单元素集合,所以极小元只可能为 $A$。但是 $A \in A$ 所以 $A \cap \{A\} = A$ 不满足极小元的定义,产生矛盾。故 $A \notin A$。 + +**推论 2**: + +假设存在一个非空传递集合 $A$ 满足 $\varnothing \notin A$。由正则公理知 $A$ 中一定存在极小元 $y$,满足 $y \in A \land y \cap A = \varnothing$。因为 $\varnothing \notin A$,故 $y \neq \varnothing$。由正则公理知 $y$ 中一定存在极小元 $z$,满足 $z \in y \land z \cap y = \varnothing$。由于 $A$ 是传递集合,且 $z \in y \land y \in A$,所以 $z \in A$。又因为 $z \in y$,因此 $y \cap A$ 至少包含 $z$,则 $y \cap A \neq \varnothing$,不满足极小元的定义,产生矛盾。故 $\varnothing \in A$。 + +{% note primary %} + +#### 定义:奇异集合 + +如果集合 $A$ 中有集合的序列 $A_0 \in A, A_1 \in A, \cdots, A_n \in A$,使得 +$$ +\cdots \in A_{n + 1} \in A_n \in A_{n - 1} \in \cdots \in A_2 \in A_1 \in A_0 +$$ +则称 $A$ 为 **奇异集合**。 + +{% endnote %} + +{% note info %} + +#### 性质:奇异集合 + +1. 奇异集合不满足正则公理。 +2. 若非空集合 $A$ 不是奇异集合,则 $A$ 满足正则公理。 + +{% endnote %} + +**性质 1**: + +设 $A$ 为奇异集合,取序列 $A_0 \in A, A_1 \in A, \cdots, A_n \in A$,使得 +$$ +\cdots \in A_{n + 1} \in A_n \in A_{n - 1} \in \cdots \in A_2 \in A_1 \in A_0 +$$ +构造 $A$ 的非空子集 $B = \{A_0, A_1, \cdots, A_n, \cdots\}$。假设 $B$ 中有极小元 $A_i(i \ge 0)$,则 $A_i \cap B \neq \varnothing$,然而由于 $A_{i + 1} \in A_{i}$ 且 $A_{i + 1} \in B$,所以 $A_i \cap B$ 至少包含 $A_{i + 1}$,这说明 $A_i \cap B \neq \varnothing$,矛盾。故 $B$ 没有极小元,不满足正则公理。所以 $A$ 为奇异集合,不满足正则公理。 + +**性质 2**: + +假设 $A$ 中没有极小元,则 $\forall A_0 \in A$,都应该存在 $A_1 \in A_0$ 满足 $A_1 \in A$。但 $A_1$ 也不是 $A$ 的极小元,故存在 $A_2 \in A_1$ 满足 $A_2 \in A$。以此类推得 $A$ 中应有元素 $A_0, A_1, \cdots, A_n, \cdots$ 满足 +$$ +\cdots \in A_{n + 1} \in A_n \in A_{n - 1} \in \cdots \in A_2 \in A_1 \in A_0 +$$ +这说明 $A$ 是奇异集合,与已知矛盾。故 $A$ 一定满足正则公理。 + +## 第 10 章 关系 + +### 关系运算 + +{% note primary %} + +#### 定义:限制和象 + +- $R$ 在 $A$ 上的限制 $R \upharpoonright A = \{\left | \left \in R \land x \in A\}$。 +- $A$ 在 $R$ 下的象 $R[A] = \{y | (\exists x)(x \in A \land \left \in R)\}$。 + +{% endnote %} + +{% note info %} + +#### 性质:关系运算 + +1. $R_1 \circ (R_2 \cup R_3) = R_1 \circ R_2 \cup R_1 \circ R_3$ +1. $R_1 \circ (R_2 \cap R_3) \subseteq R_1 \circ R_2 \cap R_1 \circ R_3$ +1. $(R_1 \cup R_2) \circ R_3 = R_1 \circ R_3 \cup R_2 \circ R_3$ +1. $(R_1 \cap R_2) \circ R_3 \subseteq R_1 \circ R_3 \cup R_2 \circ R_3$ + +{% endnote %} + +**性质 2**: + +左式缺少下图的 $\left$,因为 $\left$ 和 $\left$ 在 $R_2 \cap R_3$ 的过程中被除去了;但右式含有 $\left$。 + +```mermaid +graph LR +subgraph $A$ +A +end +subgraph $B$ +D +end +A(($x$)) --> |$R_1$| B(($y_1$)) +A --> |$R_1$| C(($y_2$)) +B --> |$R_2$| D(($z$)) +C --> |$R_3$| D +``` + +**性质 4**: + +左式缺少下图的 $\left$,因为 $\left$ 和 $\left$ 在 $R_1 \cap R_2$ 的过程中被除去了;但右式含有 $\left$。 + +```mermaid +graph LR +subgraph $A$ +A +end +subgraph $B$ +D +end +A(($x$)) --> |$R_1$| B(($y_1$)) +A --> |$R_2$| C(($y_2$)) +B --> |$R_3$| D(($z$)) +C --> |$R_3$| D +``` + +{% note info %} + +#### 性质:象 + +1. $R[A \cup B] = R[A] \cup R[B]$ +2. $R[\cup A] = \cup\{R[B] | B \in A\}$ +3. $R[A \cap B] \subseteq R[A] \cap R[B]$ +4. $R[\cap A] \subseteq \cap\{R[B] | B \in A\}$ +5. $R[A] - R[B] \subseteq R[A - B]$ + +{% endnote %} + +**性质 3**: + +左式缺少下图的 $z$,因为 $x$ 和 $y$ 在 $A \cap B$ 的过程中被除去了;但右式含有 $z$。 + +```mermaid +graph LR +subgraph $A$ +A +end +subgraph $B$ +B +end +subgraph $C$ +C +end +A(($x$)) --> C(($z$)) +B(($y$)) --> C +``` + +**性质 5**: + +左式缺少下图的 $z$,因为 $z$ 在 $R[A] - R[B]$ 的过程中因为重复而被除去了;但 $A - B$ 仍含有 $x$,故右式含有 $z$。 + +```mermaid +graph LR +subgraph $A$ +A +end +subgraph $B$ +B +end +subgraph $C$ +C +end +A(($x$)) --> C(($z$)) +B(($y$)) --> C +``` + +### 关系的性质 + +{% note primary %} + +#### 定义:自反性、对称性和传递性 + +对 $A$ 上的关系 $R$: + +- 自反性 + + - 若 $(\forall x)(x \in A \to x R x)$,则称 $R$ 是 **自反的**。 + - 若 $(\forall x)(x \in A \to x \not R x)$,则称 $R$ 是 **非自反的**。 + +- 对称性 + + - 若 $(\forall x)(\forall y)((x \in A \land y \in A \land xRy) \to yRx)$,则称 $R$ 是 **对称的**。 + - 若 $(\forall x)(\forall y)((x \in A \land y \in A \land xRy \land yRx) \to x = y)$,则称 $R$ 是 **反对称的**。 + +- 传递性 + + 若 $(\forall x)(\forall y)(\forall z)((x \in A \land y \in A \land z \in A \land xRy \land yRz) \to xRz)$,则称 $R$ 是 **传递的**。 + +{% endnote %} + +自反性的充要条件是 $I_A \subseteq R$,也就是每个顶点上都得有自环。需要注意的是,“自反的”和“非自反的”并不构成命题上的否定。 + +对于交、并、补等运算而言,需要注意的是 $R_1$ 和 $R_2$ 是传递的并不能推出 $R_1 \cup R_2$ 是传递的,因为可能 $R_1$ 中的 $\left$ 和 $R_2$ 中的 $\left$ 接上之后得出的 $\left \notin R_1 \cup R_2$。 $R_1$ 和 $R_2$ 是反对称的也不能推出 $R_1 \cup R_2$ 是反对称的。反对称等价于每个顶点上都不能有长度为 $2$ 的不经过自己的环,$R_1 \cup R_2$ 之后可能会有两个半环刚好拼起来变成一个整的环,导致 $R_1 \cup R_2$ 并非是反对称的。 + +{% note info %} + +#### 性质:自反性、对称性和传递性 + +1. $R$ 对称等价于 $R = R^{-1}$。 +2. $R$ 反对称等价于 $R \cap R^{-1} \subseteq I_A$。 + +{% endnote %} + +### 闭包 + +{% note primary %} + +#### 定义:闭包 + +对非空集合 $A$ 上的关系 $R$,若 $A$ 上有另一关系 $R'$ 满足: + +1. $R'$ 是自反的(对称的,传递的) +2. $R \subseteq R'$ +3. 对 $A$ 上任何自反的(对称的,传递的)关系 $R''$ 均有 $R\subseteq R'' \to R' \subseteq R''$ + +则称 $R'$ 为 $R$ 的**自反(对称,传递)闭包**,记作 $r(R)(s(R), t(R))$。 + +{% endnote %} + +闭包就是 $A$ 上满足该性质的 $R$ 的最小的超集合。 + +{% note info %} + +#### 性质:闭包 + +1. 若 $R_1 \subseteq R_2$,则 $r(R_1) \subseteq r(R_2)$。 +2. 若 $R_1 \subseteq R_2$,则 $s(R_1) \subseteq s(R_2)$。 +3. 若 $R_1 \subseteq R_2$,则 $t(R_1) \subseteq t(R_2)$。 +4. $r(R_1)\cup r(R_2) = r(R_1 \cup R_2)$ +5. $s(R_1)\cup s(R_2) = s(R_1 \cup R_2)$ +6. $t(R_1)\cup t(R_2) \subseteq t(R_1 \cup R_2)$ + +{% endnote %} + +性质 6 之所以是 $\subseteq$,是因为传递性并不能通过并集传递。 + +#### 闭包的构造方法 + +- $r(R) = R \cup R^{0}$ +- $s(R) = R \cup R^{-1}$ +- $t(R) = R \cup R^2 \cup \cdots \cup R^{n} \cup \cdots = R^{+}$ + +{% note info %} + +#### 性质:闭包的复合 + +1. 若 $R$ 是自反的,则 $s(R), t(R)$ 是自反的。 +2. 若 $R$ 是对称的,则 $r(R), t(R)$ 是对称的。 +3. 若 $R$ 是传递的,则 $r(R)$ 是传递的。 + +{% endnote %} + +因此 $rs(R) = sr(R), rt(R) = tr(R), st(R) \subseteq ts(R)$。 + +{% note warning %} + +#### 注意:复合闭包的顺序 + +由于 $R$ 传递并不能推出 $s(R)$ 传递,所以如果想求出 $R$ 的自反、对称且传递的闭包,则应求 $tsr(R)$。 + +{% endnote %} + +### 相容关系和覆盖 + +{% note primary %} + +#### 定义:相容关系 + +对非空集合 $A$ 上的关系 $R$,如果 $R$ 是自反的、对称的,则称 $R$ 为 $A$ 上的 **相容关系**。 + +{% endnote %} + +{% note primary %} + +#### 定义:相容类 + +- 对非空集合 $A$ 上的相容关系 $R$,若 $C \subseteq A$ 且 $C$ 中任意两个元素 $x, y$ 都有 $xRy$,则称 $C$ 是由相容关系 $R$ 产生的 **相容类**。 +- 一个相容类若不是任何相容类的真子集,就称为 **最大相容类**,记为 $C_R$。 + +{% endnote %} + +在相容关系的简化图中,如果一个子图是完全图,那么这些顶点的集合是一个最大相容类;如果两个点的连线并不是完全图的边,那么这两个点的集合也是最大相容类。 + +{% note default %} + +#### 定理:最大相容类的存在性 + +对非空集合 $A$ 上的相容关系 $R$,若 $C$ 是一个相容类,则存在一个最大相容类 $C_R$,使 $C \subseteq C_R$。 + +{% endnote %} + +设 $A = \{a_1, a_2, \cdots, a_n\}$,构造相容类的序列 $C_0 \subset C_1 \subset C_2 \subset \cdots$ 使得 $C_0 = C, C_{i + 1} = C_i \cup \{a_j\}$,其中 $j$ 是满足 $a_j \notin C_i$ 且 $a_j$ 与 $C_i$ 中各元素都有关系 $R$ 的最小下标。 + +由于 $|A| = n$,所以至多进行 $n - |C|$ 步,过程就结束,而且序列中最后一个相容类是 $C_R$。 + +{% note primary %} + +#### 定义:覆盖 + +对非空集合 $A$,若存在集合 $\Omega$ 满足下列条件: + +1. $(\forall x)(x \in \Omega \to x \subseteq A)$ +2. $\varnothing \notin \Omega$ +3. $\cup\Omega = A$ + +则称 $\Omega$ 是 $A$ 的一个 **覆盖**,称 $\Omega$ 中的元素为 $\Omega$ 的 **覆盖块**。 + +{% endnote %} + +对任意的 $a \in A$,有相容类 $\{a\}$。它必定包含在某个 $C_R$ 中。所以,$C_R$ 的集合覆盖住 $A$。 + +{% note default %} + +#### 定理:完全覆盖的唯一性 + +对非空集合 $A$ 上的相容关系 $R$,最大相容类的集合是 $A$ 的一个覆盖,称为 $A$ 的完全覆盖,记作 $C_R(A)$,$C_R(A)$ 唯一。 + +{% endnote %} + +### 偏序关系 + +{% note primary %} + +#### 定义:偏序关系 + +对非空集合 $A$ 上的关系 $R$,如果 $R$ 是自反的、反对称的和传递的,则称 $R$ 为 $A$ 上的 **偏序关系**。 + +{% endnote %} + +{% note primary %} + +#### 定义:拟序关系 + +对非空集合 $A$ 上的关系 $R$,如果 $R$ 是非自反的和传递的,则称 $R$ 为 $A$ 上的 **拟序关系**。 + +{% endnote %} + +{% note info %} + +#### 性质:拟序关系 + +对非空集合 $A$ 上的拟序关系 $R$,$R$ 是反对称的。 + +{% endnote %} + +假设 $R$ 不是反对称的,则存在 $x, y \in A$ 满足 $x \neq y$,使得 $\left \in R$ 且 $\left \in R$。由传递性可得 $\left \in R$,这与非自反性矛盾。 + +{% note primary %} + +#### 定义:盖住关系 + +对偏序集 $\left$,如果 $x, y \in A, x \le y, x \neq y$,且不存在元素 $z \in A$ 使得 $x \le z$ 且 $z \le y$,则称 $y$ 盖住 $x$。$A$ 上的 **盖住关系** 定义为: +$$ +\text{cov}A = \{\left | x \in A \land y \in A \land y \text{ 盖住 }x\} +$$ +{% endnote %} + +#### 哈斯图 + +对偏序集 $\left$,$A$ 上的盖住关系 $\text{cov}A$ 是唯一的。可以用盖住关系画偏序集的哈斯图: + +1. 每个顶点代表 $A$ 的一个元素。 +2. 若 $x \le y$ 且 $x \neq y$,则顶点 $y$ 在顶点 $x$ 上方。 +3. 若 $\left \in \text{cov}A$,则 $x, y$ 间连无向边。 + +对 $A = \{a, b, c\}$,$\left$ 是偏序集,它的哈斯图如下: + + + +![哈斯图样例](https://img.picgo.net/2023/10/02/hasse830e2fbe2978fd5d.png) + +{% note primary %} + +#### 定义:最大元、最小元、极大元、极小元 + +对偏序集 $\left$,且 $B \subseteq A$,定义: + +- 若 $(\exists y)(y \in B \land (\forall x)(x \in B \to y \le x))$,则称 $y$ 为 $B$ 的 **最小元**。 +- 若 $(\exists y)(y \in B \land (\forall x)(x \in B \to x \le y))$,则称 $y$ 为 $B$ 的 **最大元**。 +- 若 $(\exists y)(y \in B \land (\forall x)((x \in B \land x \le y) \to x = y))$,则称 $y$ 为 $B$ 的 **极小元**。 +- 若 $(\exists y)(y \in B \land (\forall x)((x \in B \land y \le x) \to x = y))$,则称 $y$ 为 $B$ 的 **极大元**。 + +{% endnote %} + +如下图所示,令 $B_1 = \{2, 4, 6, 12\}$,则 $B_1$ 的最大元和极大元是 $12$,最小元和极小元是 $2$。令 $B_2 = \{2, 3, 4, 6\}$,则 $B_2$ 的极大元是 $4$ 和 $6$,没有最大元和最小元。 + +![例子1](https://img.picgo.net/2023/10/02/example1e9c19128870ed187.png) + +{% note warning %} + +#### 注意:最大元、最小元、极大元、极小元 + +要区分最小元和极小元。$B$ 的最小元应 **小于等于** $B$ 中其他各元,$B$ 的极小元应 **不大于** $B$ 中其他各元(可以与 $B$ 中的一部分元素不可比,例如上述例子中的 $B_2$)。最小元不一定存在,若存在必唯一。在非空有限集合 $B$ 中,极小元必存在,不一定唯一。 + +最大元和极大元是类似的。 + +{% endnote %} + +{% note primary %} + +#### 定义:上界、下界、上确界、下确界 + +对偏序集 $\left$,且 $B \subseteq A$,定义: + +- 若 $(\exists y)(y \in A \land (\forall x)(x \in B \to x \le y))$,则称 $y$ 为 $B$ 的 **上界**。 +- 若 $(\exists y)(y \in A \land (\forall x)(x \in B \to y \le x))$,则称 $y$ 为 $B$ 的 **下界**。 +- 若集合 $C = \{y | y \text{ 是 } B \text{ 的上界}\}$,则 $C$ 的最小元称为 $B$ 的 **上确界**。 +- 若集合 $C = \{y | y \text{ 是 } B \text{ 的下界}\}$,则 $C$ 的最大元称为 $B$ 的 **下确界**。 + +{% endnote %} + +如下图所示,$B_1 = \{2, 4\}$ 的上界是 $4$ 和 $12$,上确界是 $4$,下界和下确界是 $2$。$B_2 = \{4, 6, 9\}$ 没有上下界,没有上下确界。$B_3 = \{2, 3\}$ 的上界是 $6, 12, 18$,上确界是 $6$,没有下界和下确界。 + +![例子2](https://img.picgo.net/2023/10/02/example2e685afddf9646d51.png) + +{% note warning %} + +#### 注意:上界、下界、上确界、下确界 + +$B$ 的上下界和上下确界可能在 $B$ 中,可能不在 $B$ 中,但一定在 $A$ 中。上下界不一定存在,不一定唯一。上下确界不一定存在,若存在必唯一。 + +感性地看,上确界就是 LCA,下确界就是 LCD(我创造的词,Least Common Descendant,最近公共后代)。上下界即为 CA 和 CD。 + +{% endnote %} + +### 全序关系 + +{% note primary %} + +#### 定义:可比性 + +对偏序集 $\left$,如果对任意的 $x, y \in A$,都有 $x \le y$ 或者 $y \le x$,则称 $x$ 和 $y$ 是 **可比的**。 + +{% endnote %} + +{% note primary %} + +#### 定义:全序关系 + +对偏序集 $\left$,如果对任意的 $x, y \in A$,$x$ 和 $y$ 都可比,则称 $\le$ 为 $A$ 上的 **全序关系**,并称 $\left$ 为 **全序集**。 + +{% endnote %} + +{% note primary %} + +#### 定义:链和反链 + +对偏序集 $\left$,且 $B \subseteq A$,定义: + +- 如果对任意的 $x, y \in B$ 都有 $x$ 和 $y$ 是可比的,则称 $B$ 为 $A$ 上的 **链**,$B$ 中元素个数称为 **链的长度**。 +- 如果对任意的 $x, y \in B$ 都有 $x$ 和 $y$ 不可比,则称 $B$ 为 $A$ 上的 **反链**,$B$ 中元素个数称为 **反链的长度**。 + +{% endnote %} + +$A$ 上的反链实际上就是有向图的点独立集。 + +{% note default %} + +#### 定理:Dilworth 定理 + +对偏序集 $\left$,设 $A$ 中最长链的长度为 $n$,则将 $A$ 中元素分成不相交的反链,反链个数至少是 $n$。 + +{% endnote %} + +**基础**:当 $n = 1$ 时,$A$ 本身就是一条反链,定理成立。 + +**归纳**:假设对于 $n = k$,结论成立。考虑 $n = k + 1$ 的情况。当 $A$ 中最长链的长度为 $k + 1$ 时,令 $M$ 为 $A$ 中极大元的集合,显然 $M$ 是一条反链,而且 $A - M$ 中最长链的长度为 $k$。由归纳假设,可以把 $A - M$ 分成至少 $k$ 个不相交的反链;再加上反链 $M$,则 $A$ 可分成至少 $k +1$ 条反链。定理得证。 + +### 良序关系 + +{% note primary %} + +#### 定义:良序关系 + +对偏序集 $\left$,如果 $A$ 的任何非空子集都有最小元,则称 $\le$ 为 $A$ 上的 **良序关系**,并称 $\left$ 为 **良序集**。 + +{% endnote %} + +## 第 11 章 函数 + +### 函数的定义与性质 + +{% note primary %} + +#### 定义:函数 + +对集合 $A$ 到集合 $B$ 的关系 $f$,若满足以下条件: + +1. $(\forall x)(\forall y_1)(\forall y_2)((xfy_1 \land xfy_2) \to y_1 = y_2)$ +2. $(\forall x)(x \in A \to (\exists y)(y \in B \land xfy))$ + +则称 $f$ 为从 $A$ 到 $B$ 的 **函数**。 + +{% endnote %} + +第一个条件是为了保证 $f$ 的单值性,第二个条件是为了保证 $f$ 的定义域内的所有 $x$ 都能有象。 + +{% note primary %} + +#### 定义:所有函数的集合 + +对集合 $A$ 到集合 $B$,从 $A$ 到 $B$ 的 **所有函数的集合** 记为 $A_B$。形式化地, +$$ +A_B = \{f|f:A\to B\} +$$ +{% endnote %} + +若 $A$ 和 $B$ 都是有限集合,且 $|A| = m, |B| = n$,则 $|A_B| = n^m$。因此,$\varnothing_\varnothing = \varnothing_B = \{\varnothing\}$;当 $A \neq \varnothing$ 时 $A_\varnothing = \varnothing$。 + +{% note info %} + +#### 性质:函数 + +1. 若 $f \circ g$ 为满射,则 $f$ 为满射。 +2. 若 $f \circ g$ 为单射,则 $g$ 为单射。 +3. 若 $f \circ g$ 为双射,则 $f$ 为满射,$g$ 为单射。 + +{% endnote %} + +“单看里,满看外。”性质 3 是 性质 1 和性质 2 的直接推论。 + +### 选择公理 + +{% note default %} + +#### 公理:选择公理 + +对任意的关系 $R$,存在函数 $f$,使得 $f \subseteq R$ 且 $\text{dom}(f) = \text{dom}(R)$。 + +{% endnote %} + +一般的关系 $R$ 不一定有单值性,所以不一定是函数;但对每个原象,我们只选取 $R$ 中对应的一个象,将这个映射组合放到 $f$ 中。这样构造出的函数 $f$,满足 $f \subseteq R$ 且 $\text{dom}(f) = \text{dom}(R)$。 + +### 函数的相容性 + +{% note primary %} + +#### 定义:函数的相容性 + +- 设 $f:A\to B, g:C \to D$,如果对任意的 $x \in A \cap C$ 都有 $f(x) = g(x)$,则称 $f$ 和 $g$ 是 **相容的**。 +- 若函数的集合 $C$ 满足其中任意两个函数都是相容的,则称 $C$ 是相容的。 + +{% endnote %} + +{% note default %} + +#### 定理:函数的相容性的等价条件 + +设 $f:A\to B, g:C \to D$,则 $f$ 和 $g$ 是相容的当且仅当 $f \cup g$ 是函数。 + +{% endnote %} + +这两个说法都在叙述同样的一件事:两函数定义域相交的部分是单值的。 + +### 函数与等价关系的相容性 + +{% note primary %} + +#### 定义:函数与等价关系的相容性 + +设 $R$ 是 $A$ 上的等价关系,且 $f:A \to A$,如果对任意的 $x , y \in A$ 都有 $\left \in R \implies \left \in R$,则称关系 $R$ 与函数 $f$ 是相容的。 + +{% endnote %} + +这个相容的等价关系诱导出一个 $A/R$ 上的自映射 $F = \{\left<[x]_R, [f(x)]_R\right> | x \in A\}$。感性地理解,就是等价关系将 $A$ 分成了很多个连通块,而函数 $f$ 也能被抽象成连通块间的函数(而不导致矛盾)。 + +### 特征函数与模糊子集 + +{% note primary %} + +#### 定义:特征函数 + +设 $E$ 是全集,对 $A \subseteq E$,定义 $A$ 的 **特征函数** 为 +$$ +\chi_A:E \to \{0, 1\}, \chi_A(a) = \begin{cases}1, a \in A, \\ 0, a\notin A. \end{cases} +$$ +{% endnote %} + +{% note primary %} + +#### 定义:模糊子集 + +设 $E$ 是论域,$E$ 上的一个**模糊子集** $\underset{\sim}{A}$ 是指:存在一个函数 $\mu_{\underset{\sim}{A}}:E \to [0, 1]$,并称 $\mu_{\underset{\sim}{A}}$ 为 $\underset{\sim}{A}$ 的 **隶属函数**。 + +{% endnote %} + +这个定义说明,$\mu_{\underset{\sim}{A}}(x)$ 表示 $x$ 属于 $\underset{\sim}{A}$ 的程度。$\mu_{\underset{\sim}{A}}(x) = 1$ 表示 $x \in \underset{\sim}{A}$,$\mu_{\underset{\sim}{A}} = 0$ 表示 $x \notin \underset{\sim}{A}$。$0 < \mu_{\underset{\sim}{A}}(x) < 1$ 表示 $x$ 在一定程度上属于 $\underset{\sim}{A}$,此时 $x \in \underset{\sim}{A}$ 和 $x \notin \underset{\sim}{A}$ 都不成立。 + +{% note info %} + +#### 性质:模糊子集 + +设 $E$ 是全集,$F(E)$ 表示 $E$ 上全体模糊子集组成的集合,$\underset{\sim}{A}, \underset{\sim}{B} \in F(E)$,则 $\underset{\sim}{A} \cup \underset{\sim}{B}, \underset{\sim}{A} \cap \underset{\sim}{B}, -\underset{\sim}{A}$ 具有下列隶属函数: + +1. $\mu_{\underset{\sim}{A} \cup \underset{\sim}{B}}(x) = \max\{\mu_{\underset{\sim}{A}}(x), \mu_{\underset{\sim}{B}}(x)\}$ +2. $\mu_{\underset{\sim}{A} \cap \underset{\sim}{B}}(x) = \min\{\mu_{\underset{\sim}{A}}(x), \mu_{\underset{\sim}{B}}(x)\}$ +3. $\mu_{-\underset{\sim}{A}}(x) = 1 - \mu_{\underset{\sim}{A}}(x)$ + +{% endnote %} + +### 截集和分解定理 + +{% note primary %} + +#### 定义:截集 + +设 $E$ 是全集,$\underset{\sim}{A} \in F(E)$,对 $\lambda \in [0, 1]$,集合 +$$ +(\underset{\sim}{A})_\lambda = \{x|\mu_{\underset{\sim}{A}}(x) \ge \lambda\} +$$ +称为 $\underset{\sim}{A}$ 的 **截集**,$(\underset{\sim}{A})_\lambda$ 可以写作 $A_\lambda$。 + +{% endnote %} + +{% note info %} + +#### 性质:截集 + +设 $E$ 是全集,$\underset{\sim}{A}, \underset{\sim}{B} \in F(E)$,对 $\lambda \in [0, 1]$,则 + +1. $(\underset{\sim}{A} \cup \underset{\sim}{B})_{\lambda} = (\underset{\sim}{A})_{\lambda} \cup (\underset{\sim}{B})_{\lambda}$ +2. $(\underset{\sim}{A} \cap \underset{\sim}{B})_{\lambda} = (\underset{\sim}{A})_{\lambda} \cap (\underset{\sim}{B})_{\lambda}$ + +{% endnote %} + +{% note default %} + +#### 定理:分解定理 + +设 $E$ 是全集,$\underset{\sim}{A} \in F(E), \lambda \in [0, 1]$,$\chi_{A_\lambda}$ 是 $A_\lambda$ 的特征函数,则 +$$ +\mu_{\underset{\sim}{A}}(u) = \sup_{\lambda \in [0, 1]}\{\inf\{\lambda, \chi_{A_\lambda}(u)\}\} +$$ +{% endnote %} +$$ +\begin{aligned} +\sup_{\lambda \in [0, 1]}\{\inf\{\lambda, \chi_{A_\lambda}\}\} = \max\{& \sup_{\lambda \in [0, \mu_{\underset{\sim}{A}}(u)]}\{\inf\{\lambda, \chi_{A_\lambda}(u)\}\}, \\ +& \sup_{\lambda \in [\mu_{\underset{\sim}{A}}(u), 1]}\{\inf\{\lambda, \chi_{A_\lambda}(u)\}\} & \} +\end{aligned} +$$ +当 $\mu_{\underset{\sim}{A}}(u) < \lambda \le 1$ 时,$u \notin A_{\lambda}$,则 $\chi_{A_\lambda}(u) = 0, \inf\{\lambda, \chi_{A_\lambda}(u)\} = 0$。所以 +$$ +\begin{aligned} +\sup_{\lambda \in [0, 1]}\{\inf\{\lambda, \chi_{A_\lambda}(u)\}\} & = \sup_{\lambda \in [0, \mu_{\underset{\sim}{A}}(u)]}\{\inf\{\lambda, \chi_{A_\lambda}(u)\}\} \\ +& = \sup_{\lambda \in [0, \mu_{\underset{\sim}{A}}(u)]}\{\inf\{\lambda, 1\}\} \\ +& = \sup_{\lambda \in [0, \mu_{\underset{\sim}{A}}(u)]}\lambda \\ +& = \mu_{\underset{\sim}{A}}(u) +\end{aligned} +$$ +{% note primary %} + +#### 定义:支集、核和边界 + +设 $E$ 是全集,$\underset{\sim}{A} \in F(E)$,则 +$$ +\text{supp}\underset{\sim}{A} = \{u|\mu_{\underset{\sim}{A}}(u) > 0\} +$$ +称为 $\underset{\sim}{A}$ 的 **支集**,截集 $A_1$ 称为 $\underset{\sim}{A}$ 的 **核**,$(\text{supp}\underset{\sim}{A}) - A_1$ 称为 $\underset{\sim}{A}$ 的 **边界**。 + +若核 $A_1$ 的元素完全隶属于 $\underset{\sim}{A}$,若 $A_1 \neq \varnothing$,就称 $\underset{\sim}{A}$ 为 **正规模糊集**;若 $A_1 = \varnothing$,就称 $\underset{\sim}{A}$ 为 **非正规模糊集**。 + +{% endnote %} + +截集、支集、核、和边界如图所示: + +![截集、支集、核、和边界](https://img.picgo.net/2023/10/02/cut-kernel-boundary-supportb993f8de8581d98b.png) + +## 第 12 章 实数集合与集合的基数 + +### 整数集合 $\mathbb{Z}$ + +{% note primary %} + +#### 定义:整数集合 $\mathbb{Z}$ + +已知自然数集合 $\mathbb{N}$,定义: + +- $\mathbb{Z}_{+} = \mathbb{N} - \{0\}$ +- $\mathbb{Z}_{-} = \{\left<0, n\right> | n \in \mathbb{Z}_{+}\}$ +- $\mathbb{Z} = \mathbb{Z}_{-} \cup \{0\} \cup \mathbb{Z}_{+}$ + +称 $\mathbb{Z}_{+}$ 的元素为 **正整数**,$\mathbb{Z}_{-}$ 的元素为 **负整数**,$\mathbb{Z}$ 的元素为 **整数**。 + +{% endnote %} + +{% note primary %} + +#### 定义:整数的相反数 + +一个整数 $n$ 的 **相反数** 分别是 + +- $-n = \left<0, n\right>$,当 $n \in \mathbb{Z}_{+}$ 时。 +- $-n = 0$,当 $n = 0$ 时。 +- $-\left<0, n\right> = n$,当 $n \in \mathbb{Z}_{+}$ 时。 + +{% endnote %} + +{% note primary %} + +#### 定义:$\mathbb{Z}$ 上的偏序关系 + +- 在集合 $\mathbb{Z}$ 上定义小于等于关系 $\le_{\mathbb{Z}}$ 为: + + 对任意的 $x, y \in \mathbb{Z}$,$x \le_{\mathbb{Z}} y$ 当且仅当 + $$ + \begin{aligned} + & (x \in \mathbb{N} \land y \in \mathbb{N} \land x \le_{\mathbb{N}} y) \\ + \lor & (x \in \mathbb{Z}_{-} \land y \in \mathbb{N}) \\ + \lor & (x \in \mathbb{Z}_{-} \land y \in \mathbb{Z}_{-} \land -y \le_{\mathbb{N}} -x) + \end{aligned} + $$ + +- 在集合 $\mathbb{Z}$ 上定义小于关系 $<_{\mathbb{Z}}$ 为: + + 对任意的 $x, y \in \mathbb{Z}$,$x <_{\mathbb{Z}} y$ 当且仅当 $(x \le_{\mathbb{Z}} y) \land (x \neq y)$。 + + +{% endnote %} + +### 有理数集合 $\mathbb{Q}$ + +{% note primary %} + +#### 定义:$\mathbb{Z}$ 上的因式的集合 $Q_1$ + +对整数集合 $\mathbb{Z}$,令 +$$ +Q_1 = \mathbb{Z} \times(\mathbb{Z} - \{0\}) = \{\left | a \in \mathbb{Z} \land b \in \mathbb{Z} \land b \neq 0\} +$$ +并称 $Q_1$ 是 **$\mathbb{Z}$ 上的因式的集合**。 + +记 $\left = a/b$。在 $Q_1$ 上定义等价关系 $\simeq$ 为对任意的 $a/b, c/d \in Q_1$,有: +$$ +a/b \simeq c/d \iff a\cdot d = b \cdot c +$$ +其中 $\cdot$ 是在 $\mathbb{Z}$ 上定义的乘法,$=$ 是 $\mathbb{Z}$ 上的相等关系。 + +{% endnote %} + +{% note primary %} + +#### 定义:有理数集合 $\mathbb{Q}$ + +令 $\mathbb{Q} = Q_1 / \simeq$,即 $\mathbb{Q}$ 是集合 $Q_1$ 对等价关系 $\simeq$ 的商集,则称 $\mathbb{Q}$ 的元素为 **有理数**,称 $\mathbb{Q}$ 为 **有理数集合**。 + +一般用 $a/b$ 表示 $\mathbb{Q}$ 中的元素 $[\left]_{\simeq}$。习惯上取 $a, b$ 为互素的整数,且 $b > 0$。 + +{% endnote %} + +{% note primary %} + +#### 定义:$\mathbb{Q}$ 上的偏序关系 + +- 在集合 $\mathbb{Q}$ 上定义小于等于关系 $\le_{\mathbb{Q}}$ 为: + + 对任意的 $a/b, c/d \in \mathbb{Q}$,$a/b \le_{\mathbb{Q}} c/d$ 当且仅当 $a \cdot d \le_{\mathbb{Z}} b \cdot c$。 + +- 在集合 $\mathbb{Q}$ 上定义小于关系 $<_{\mathbb{Q}}$ 为: + + 对任意的 $a/b, c/d \in \mathbb{Q}$,$a/b <_{\mathbb{Q}} c/d$ 当且仅当 $(a/b \le_{\mathbb{Q}} c/d) \land (a/b \neq c/d)$。 + + +{% endnote %} + +### 实数集合 $\mathbb{R}$ + +{% note primary %} + +#### 定义:基本函数 + +如果 $f:\mathbb{N} \to \mathbb{Q}$ 满足条件: + +1. $(\exists x)(x \in \mathbb{Q} \land (\forall n)(n \in \mathbb{N} \to \left|f(n)\right| < x))$ +2. $(\exists n)(n \in \mathbb{N} \land (\forall m)(\forall i)((m \in \mathbb{N} \land i \in \mathbb{N} \land n \le m \land n \le i \land m \le i) \to (f(m) \le f(i))))$ + +则称 $f$ 是一个 **基本函数**,或 **有界非递减函数**。记 $B$ 为由所有基本函数组成的集合。 + +在 $B$ 上定义等价关系 $\simeq$ 为对任意的 $f, g \in B$,有: +$$ +f \simeq g \iff (\forall \varepsilon)((\varepsilon \in \mathbb{Q} \land \varepsilon > 0) \to (\exists n)(n \in \mathbb{N} \land (\forall m)((m \in \mathbb{N} \land n \le m) \to \left|f(m) - f(n)\right| < \varepsilon))) +$$ +{% endnote %} + +直观上说,$f \simeq g$ 等价于 $f$ 和 $g$ 的极限相同。 + +{% note primary %} + +#### 定义:实数集合 $\mathbb{R}$ + +令 $\mathbb{R} = B / \simeq$,即 $\mathbb{R}$ 是集合 $B$ 对等价关系 $\simeq$ 的商集,则称 $\mathbb{R}$ 的元素为 **实数**,称 $\mathbb{R}$ 为 **实数集合**。 + +{% endnote %} + +{% note primary %} + +#### 定义:$\mathbb{R}$ 上的偏序关系 + +- 在集合 $\mathbb{R}$ 上定义小于关系 $<_{\mathbb{R}}$ 为: + + 对任意的 $f, g \in B$,$f <_{\mathbb{R}} g$ 当且仅当 + $$ + (\exists \varepsilon)((\varepsilon \in \mathbb{Q} \land 0 < \varepsilon) \land (\exists n)(n \in \mathbb{N} \land (\forall m)((m \in \mathbb{N} \land n \le m) \to (g(m) - f(m) > \varepsilon)))) + $$ + +- 在集合 $\mathbb{R}$ 上定义小于等于关系 $\le_{\mathbb{R}}$ 为: + + 对任意的 $f, g \in B$,$f \le_{\mathbb{R}} g$ 当且仅当 ($f <_{\mathbb{R}} g) \lor (f \simeq g)$。 + + +{% endnote %} + +直观上说,$f \le_{\mathbb{R}}g$ 等价于 $f$ 的极限小于等于 $g$ 的极限。 + +### 集合的等势 + +{% note primary %} + +#### 定义:等势 + +对集合 $A, B$,如果存在从 $A$ 到 $B$ 的双射函数,则称 $A$ 和 $B$ 是 **等势的**,记作 $A \approx B$。如果不存在从 $A$ 到 $B$ 的双射函数,则称 $A$ 和 $B$ **不等势**,记作 $\lnot A \approx B$。 + +{% endnote %} + +$\mathbb{N} \approx \mathbb{Z}$,因为存在双射函数 +$$ +f: \mathbb{N} \to \mathbb{Z}, f(n) = \begin{cases}- \dfrac{1 + n}{2}, &n \text{ 是奇数}, \\ \dfrac{n}{2}, &n \text{ 是偶数}.\end{cases} +$$ +$\mathbb{R} \approx \mathbb{R}_{+}$,因为存在双射函数 +$$ +f: \mathbb{R} \to \mathbb{R}_{+}, f(x) = e^x +$$ + + +$\mathbb{N} \times \mathbb{N} \approx \mathbb{N}$,因为存在双射函数 +$$ +f: \mathbb{N} \times \mathbb{N} \to \mathbb{N}, f(\left) = \dfrac{(m + n)(m + n + 1)}{2} + m +$$ +$(0, 1) \approx \mathbb{R}$,因为存在双射函数 +$$ +f: (0, 1) \to \mathbb{R}, f(x) = \tan\dfrac{\pi(2x - 1)}{2} +$$ +$[0, 1] \approx (0, 1)$,因为存在双射函数 +$$ +f:[0, 1] \to (0, 1), f(x) = \begin{cases}\dfrac{1}{4}, & x = 0, \\ \dfrac{1}{2}, & x = 1, \\ \dfrac{x}{4}, & x = 2^{-n}, n = 1, 2, 3, \cdots, \\ x, & x \text{ 取其他值}.\end{cases} +$$ +{% note default %} + +#### 定理:幂集与 $A_2$ 等势 + +对任意的集合 $A$,有 +$$ +P(A) \approx A_2 +$$ +{% endnote %} + +因为 $2 = \{0, 1\}$,所以 $A_2$ 是所有函数 $f:A \to \{0, 1\}$ 组成的集合。构造双射函数 $H:P(A) \to A_2, H(B) = \chi_B(x)$。其中 $\chi_B(x)$ 是以 $A$ 为全集时 $B$ 的特征函数。对任意的 $B \in P(A)$,则 $g: A \to \{0, 1\}$,存在集合 $B$ 为 +$$ +B = \{x | x \in A \land g(x) = 1\} +$$ +则 $g(x) = \chi_B(x) = H(B)$,且这样的 $B$ 是唯一的,所以 $H$ 是双射。 + +{% note default %} + +#### 定理:Cantor 定理 + +1. $\lnot \mathbb{N} \approx \mathbb{R}$ +2. 对任意的集合 $A$,$\lnot A \approx P(A)$ + +{% endnote %} + +**定理 1**: + +只需要证明 $\lnot \mathbb{N} \approx [0, 1]$ 即可。为此需要证明对任意函数 $f:\mathbb{N} \to [0, 1]$,都存在 $x \in [0, 1]$ 使 $x \notin \text{ran}(f)$,即任何函数 $f:\mathbb{N} \to [0, 1]$ 都不是双射的。 + +对任意一个 $f: \mathbb{N} \to [0, 1]$,顺序列出 $f$ 的值: +$$ +\begin{cases} +f(0) & = x_1 = 0.a_{11}a_{21}\cdots a_{n1}\cdots \\ +f(1) & = x_2 = 0.a_{21}a_{22}\cdots a_{n2}\cdots \\ +\cdots \\ +f(n - 1) & = x_n = 0.a_{n1}a_{n2}\cdots a_{nn}\cdots \\ +\cdots +\end{cases} +$$ +其中 $a_{ij} \in \{0, 1, \cdots, 9\}$,对 $i, j = 1, 2, 3, \cdots$。为了使表示法唯一,约定像 $0.4999\cdots$ 这样的数写成 $0.5000\cdots$。这样,对 $i = 1, 2, 3, \cdots$,取 $b_i = \{0, 1, 2, \cdots, 8\}$,使 $b_i \neq a_{ii}$,则有 +$$ +x = 0.b_1b_2\cdots b_n\cdots +$$ +显然 $x \in [0, 1]$,但是 $x$ 和任意 $x_n$ 比较,因 $b_n \neq a_{nn}$,故都有 $x \neq x_n$,于是 $x \notin \text{ran}(f)$。所以,$f$ 不可能是满射的,即不存在双射函数 $f: \mathbb{N} \to [0, 1]$。 + +**定理 2**: + +对任意的函数 $g: A \to P(A)$,构造集合 $B = \{x | x \in A \land x \notin g(x)\}$。显然,$B \subseteq A, B \in P(A)$。对任意的 $x \in A$,有 $x \in B \iff x \notin g(x)$,则 $B \neq g(x)$。所以 $B \notin \text{ran}(g)$,但 $B \in P(A)$,这说明 $g$ 不是满射的。所以不存在双射函数 $g:A \to P(A)$。 + +### 集合的基数 + +$\text{card}(\mathbb{N}) = \aleph_0$,同时 $\text{card}(\mathbb{Z}) = \text{card}(\mathbb{Q}) = \text{card}(\mathbb{N}\times\mathbb{N}) = \aleph_0$。 + +$\text{card}(\mathbb{R}) = \aleph_1$,同时 $\text{card}([0, 1]) = \text{card}((0, 1)) = \text{card}(\mathbb{R}_{+}) = \aleph_1$。 + +{% note info %} + +#### 性质:$\aleph_0$ 相关运算 + +对任意的 $n \in \mathbb{N}$, + +1. $n +\aleph_0 = \aleph_0$ +2. $n \cdot \aleph_0 = \aleph_0$ +3. $\aleph_0 + \aleph_0 = \aleph_0$ +4. $\aleph_0 \cdot \aleph_0 = \aleph_0$ + +{% endnote %} + +### 可数集合与连续统假设 + +{% note primary %} + +#### 定义:可数集合 + +对集合 $K$,如果 $\text{card}(K) \le \aleph_0$,则称 $K$ 是 **可数集合**。 + +{% endnote %} + +{% note info %} + +#### 性质:可数集合 + +1. 可数集的任何子集是可数集。 +2. 两个可数集的并集和笛卡尔积是可数集。 +3. 若 $K$ 是无限集合,则 $P(K)$ 是不可数的。 +4. 可数个可数集的并集是可数集。 + +{% endnote %} + +{% note default %} + +#### 假设:连续统假设 + +已知的基数按从小到大的次序排列就是 +$$ +0, 1, \cdots, n, \cdots, \aleph_0, \aleph_1, 2^{\aleph_1}, \cdots +$$ +**连续统假设** 是指,不存在基数 $k$,使 +$$ +\aleph_0 < k < 2^{\aleph_0} +$$ +{% endnote %} \ No newline at end of file diff --git "a/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\346\267\261\345\205\245\347\220\206\350\247\243\350\256\241\347\256\227\346\234\272\347\263\273\347\273\237.md" "b/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\346\267\261\345\205\245\347\220\206\350\247\243\350\256\241\347\256\227\346\234\272\347\263\273\347\273\237.md" new file mode 100644 index 0000000..3b5019b --- /dev/null +++ "b/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\346\267\261\345\205\245\347\220\206\350\247\243\350\256\241\347\256\227\346\234\272\347\263\273\347\273\237.md" @@ -0,0 +1,1139 @@ +--- +title: 【学习笔记】深入理解计算机系统 +tags: + - 计算机系统 + - 整数 + - 浮点数 + - 汇编语言 + - 链接 + - 虚拟内存 + - 进程 + - 异常控制流 + - 线程 + - 死锁 +categories: + - 笔记 +mathjax: true +toc: true +date: 2024-01-05 20:40:01 +password: +id: CSAPP +--- + +这是清华大学计算机系秋季课程《计算机系统概论》期末考试复习笔记,教材为《深入理解计算机系统(原书第3版)》。 + + + +## 整数 + +### 字数据大小 + +$1 \,\mathrm{Byte} = 8 \,\mathrm{bits}$,字节是最小的可寻址的内存单位。 + +字长为 $w$ 的机器,虚拟地址的范围为 $[0, 2^{w} - 1]$。 + +大多数 $64$ 位机器也可以运行 $32$ 位机器编译的程序,向后兼容。 + +$32$ 位程序和 $64$ 位程序的区别是该程序是 **如何编译**的,而不是 **如何运行** 的。 + +`char` 并没有规定是有符号还是无符号。 + +[Is char signed or unsigned by default?](https://stackoverflow.com/questions/2054939/is-char-signed-or-unsigned-by-default) + +[Why don't the C or C++ standards explicitly define char as signed or unsigned?](https://stackoverflow.com/questions/15533115/why-dont-the-c-or-c-standards-explicitly-define-char-as-signed-or-unsigned) + +| C 声明 | C 声明 | 字节数 | 字节数 | +| :-------------: | :--------------: | :-----: | :-----: | +| 有符号 | 无符号 | $32$ 位 | $64$ 位 | +| `[signed] char` | `unsigned char` | $1$ | $1$ | +| `short` | `unsigned short` | $2$ | $2$ | +| `int` | `unsigned` | $4$ | $4$ | +| `long` | `unsigned long` | $4$ | $8$ | +| `int32_t` | `uint32_t` | $4$ | $4$ | +| `int64_t` | `uint64_t` | $8$ | $8$ | +| `char*` | | $4$ | $8$ | +| `float` | | $4$ | $4$ | +| `double` | | $8$ | $8$ | + +### 字节顺序 + +小端法还是大端法。地址从低到高,是权重小的数在前(小端)还是权重大的在前。 + +在 C 语言中,`sizeof(T)` 返回变量 `T` 的字节数。如果 `T` 是数组: + +- 此次调用在 `T` 的生命周期内,则返回数组的大小。 +- 否则,按照指针处理,返回 $8$($64$ 位机器)或 $4$($32$ 位机器)。 + +### 整数运算 + +逻辑右移与算术右移的区别:前者在最高位补 $0$,后者在最高位补符号位。 + +Two's Complement 和 Ones' Complement 的来源。 + +补码表示法里的加法逆元:`-x == (~x) + 1`。 + +整数除法总是 **舍入到 $0$**。当 $x < 0$ 时,需要用 `(x + (1 << k) - 1) >> k` 来计算 $\left\lfloor\dfrac{x}{2^k}\right\rfloor$。 + +### 类型转换 + +有符号数和无符号数的比较:强制转换为无符号数,然后运算,再强制转化回去。比如 `(-1 < 0u) == false`,`int x = -1 + 1u;` 则 `(x == 0) == true `。 + +为什么 `INT_MIN` 被定义为 `(-INT_MAX - 1)`? + +- [参考资料 1](https://csapp.cs.cmu.edu/public/waside/waside-tmin.pdf) +- [参考资料 2](https://www.cnblogs.com/jack47/archive/2013/01/06/tmin32-in-c.html) +- 用一句话来解释 C 语言中 $TMin_{32}$ 的古怪写法的原因:虽然 $-2147483648$ 这个数值能够用 `int` 类型来表示,但在 C 语言中却没法写出对应这个数值的 `int` 类型常量。 + +`short` 转为 `unsigned` 的时候,**先改变大小**,**再完成从有符号到无符号的转换**。也就是说, + +```cpp +short x; +//... using (unsigned)x +``` + +等价于 `(unsigned)(int)x`,而不是 `(unsigned)(unsigned short)x`。 + +### 溢出 + +无符号加法溢出:$s = x + y$,溢出则 $s < x$ 或等价地,$s < y$。 + +有符号加法溢出:$s = x + y$,溢出当且仅当:$x, y > 0$ 且 $s \le 0$;或 $x, y < 0$ 且 $s \ge 0$。 + +## 浮点数 + +### 表示方法 + +IEEE 754 表示浮点数:$V = (-1)^s \times M \times 2^E$。按以下形式存储:存储:`s | exp | frac`。 + +| 类型 | 表示 | +| :--------: | :--------------------------- | +| 规格化的 | `s | 非全 0, 非全 1 | frac` | +| 非规格化的 | `s | 0000 ... 0000 | frac` | +| 无穷大 | `s | 1111 ... 1111 | 全 0` | +| `NaN` | `s | 1111 ... 1111 | 非全 0` | + +- 规格化的:认为 `exp` 从 `0111...1111` 开始编码 $0$。认为 `frac` 是 `1.[frac]`。 +- 非规格化的:认为 `exp` 为 $2 - 2^{|E| - 1}$。认为 `frac` 是 `0.[frac]`。$0$ 是非规格化数。 + +最小的正非规格化数:`0 | 0000 | 001` 即 +$$ +2^{2 - 2^{|E| - 1}} \cdot 2^{-|F|} +$$ +最大的正非规格化数:`0 | 0000 | 111` 即 +$$ +2^{2 - 2^{|E|-1}} \cdot (1 - 2^{-|F|}) +$$ +最小的正规格化数:`0 | 0001 | 000` 即 +$$ +2^{2 - 2^{|E|-1}} +$$ +最大的正规格化数:`0 | 1110 | 111` 即 +$$ +2^{2^{|E| - 1} - 1}\cdot(2 - 2^{-|F|}) +$$ + +### 运算与类型转换 + +向偶数舍入:四舍六入五成双。 + +浮点加法不具有结合性,但有单调性。$\forall x \neq \mathrm{NaN}, a \ge b \implies a + x \ge b +x$。 + +| 原始类型 | 转化为 | 溢出 | 舍入 | +| :-------------: | :------: | :----: | :------: | +| `int` | `float` | 否 | 有可能 | +| `int` / `float` | `double` | 否 | 否 | +| `double` | `float` | 是 | 是 | +| `float/double` | `int` | 有可能 | 向零舍入 | + +`float` / `double` 转为 `int` 的时候,如果溢出,则没有规定的结果。一个典型的固定值是 `INT_MIN`。 + +## 汇编 + +### 数据格式 + +`%rip`:PC,程序计数器,给出将要执行的 **下一条指令** 在内存中的地址。 + +`nop` 对程序没有影响,只是为了使函数代码按照 $16$ 字节对齐。 + +按照 `%rdi` `%rsi` `%rdx` `%rcx` `%r8` `%r9` 的顺序接收参数,剩下的全部放栈里。 + +$16$ 位数据类型称为“字(word)”,$32$ 位数为“双字(double words)”,$64$ 位数为“四字(quad words)”。 + +| C 声明 | Intel 数据类型 | 汇编代码后缀 | 大小(x86-64,字节) | +| :------: | :------------: | :----------: | :------------------: | +| `char` | 字节 | `b` | $1$ | +| `short` | 字 | `w` | $2$ | +| `int` | 双字 | `l` | $4$ | +| `long` | 四字 | `q` | $8$ | +| `char*` | 四字 | `q` | $8$ | +| `float` | 单精度 | `s` | $4$ | +| `double` | 双精度 | `l` | $8$ | + +注意,`int` 和 `double` 的汇编代码后缀都是 `l`,但这不会有歧义,因为浮点数使用的是一组完全不同的指令和寄存器。 + +![03-02 整数寄存器](https://img.picgo.net/2024/01/08/03-027142551b80cfbca1.png) + +被调用者保存寄存器(callee-saved):`%rbx`,`%rbp`,`%r12`~`%r15` + +调用者保存寄存器(caller-saved):所有其他的寄存器,除了 `%rsp`。 + +复制和生成 **小于 $8$ 字节** 结果的指令: + +- 生成 $1$ 字节和 $2$ 字节的指令会 **保持剩下的字节不变** +- 生成 $4$ 字节的指令会 **把高位 $4$ 个字节置为 $0$** + +### 算术指令 + +寻址模式:`Imm(rb, ri, s) == Mem[Imm + Reg[rb] + Reg[ri] * s]`,`s` 只能取 $1, 2, 4, 8$。 + +`mov a b` 的意思是 move a to b。两个操作数 **不能都指向内存**,所以要先将源内存中的值加载到寄存器,再复制到目标内存。寄存器大小必须和指令后缀(`b`, `w`, `l`, `q`)指定的大小匹配。`movl` 会把寄存器高位 $4$ 字节设置为 $0$。 + +```assembly +movabsq $0x0011223344556677, %rax # %rax = 0011223344556677 +movb $-1, %al # %rax = 00112233445566FF +movw $-1, %ax # %rax = 001122334455FFFF +movl $-1, %eax # %rax = 00000000FFFFFFFF +movq $-1, %rax # %rax = FFFFFFFFFFFFFFFF +``` + +压入栈是 `subq $8, %rsp`。**栈往低地址生长。** + +`sub S, D` 是 `D <- D - S`。 + +`leaq S, D` 是 `D <- &S`。注意这个取地址符,这直接导致 `leaq` 在算术运算中的潜力。**`D` 必须是一个寄存器。** + +移位操作 `sal, shl, sar, shr`,格式:`sal k, D`。其中 `k` 要么是个立即数,要么放在 `%cl` 里。移位量是由 `%c1` 寄存器的低 $m$ 位决定的,这里 $2^m=w$。高位会被忽略。所以,例如当寄存器 `%cl` 的十六进制值为 `0xFF` 时,指令 `salb` 会移 $7$ 位,`salw` 会移 $15$ 位,`sall` 会移 $31$ 位,而 `salq` 会移 $63$ 位。 + +$128$ 位整数算术操作: + +![03-12 特殊的算术操作](https://img.picgo.net/2024/01/08/03-1268941b79a702df48.png) + +目标寄存器的选择是固定的。注意这里固定使用 `%rdx` 和 `%rax` 作为 $128$ 位数的高 $64$ 位和低 $64$ 位。除法的时候商存在 `%rax` 里,余数存在 `%rdx` 里。 + +比较和测试指令 **不修改任何寄存器的值**,只设置关键码。注意比较指令的操作数顺序。**这两个指令的第二个操作数(即 $S_2$)不能为立即数。** + +| 指令 | 基于 | 描述 | +| ---------------------------- | :----------: | :------: | +| $\text{CMP} \quad S_1, S_2$ | $S_2 - S_1$ | 比较 | +| `cmpb` | | 比较字节 | +| `cmpw` | | 比较字 | +| `cmpl` | | 比较双字 | +| `cmpq` | | 比较四字 | +| $\text{TEST} \quad S_1, S_2$ | $S_1 \& S_2$ | 测试 | +| `testb` | | 测试字节 | +| `testw` | | 测试字 | +| `testl` | | 测试双字 | +| `testq` | | 测试四字 | + +![03-14 SET指令](https://img.picgo.net/2024/01/08/03-04889d3cb915147de6.png) + +`set` 的类型限制了操作数的类型,包括是有符号(`setg` 等)还是无符号类型(`seta` 等),还是指针(只能进行 `sete` 和 `setne`)。 + +注意 `jmp %rax`、`jmp *%rax` 和 `jmp *(%rax)` 的区别。 + +当执行 PC 相对寻址时,程序计数器的值是 **跳转指令后面的那条指令的地址**,而不是跳转指令本身的地址。 + +### 逻辑指令 + +#### 条件传送 + +- 使用 **控制** 的条件转移:更改程序的执行路径 + 有可能很低效 +- 使用 **数据** 的条件转移:将两个分支的结果都计算出来,再根据条件从中选取一个 + 不能用于错误条件(空指针访问)或副作用(修改全局变量)的情况。 + +#### 循环 + +- **跳转到中间策略**:执行一个无跳转跳到循环结尾处的测试。 + ``` + goto test; + loop: + body-statement + test: + t = test-expr; + if (t) + goto loop; + ``` +- **guarded-do 策略**:首先用条件分支判断首次是否执行,把代码变为 do-while。 + ``` + t = test-expr; + if (!t) + goto done; + loop: + body-statement + t = test-expr + if (t) + goto loop; + done: + ``` + +#### 多分支 + +开关情况数量比较多(例如 $4$ 个以上),并且 **值的范围跨度比较小** 时,就会使用跳转表。 + +注意,这里没有使用哈希,而是单纯地用数组第 $i$ 个来表示跳转到基址 $+i$,所以要求范围跨度比较小。 + +#### 控制转移 + +从 P 转移到 Q,直接将 PC 设置为 Q 的首地址。返回地址需要压入栈。 + +多余 $6$ 个的参数,从右往左压入栈。所有的数大小都向 $8$ 的倍数对齐。 + +什么时候会使用栈上的局部存储: + +- 寄存器不够放 +- 对一个局部变量使用了取地址符 `&` +- 某些局部变量是数组或结构 + +#### 数组 + +访问数组中元素的时候记得 **乘上类型大小**。 + +```cpp +int A[5][3]; +``` + +等价于 + +```cpp +typedef int row3_t[3]; +row3_t A[5]; +``` + +对于 `T D[R][C];` 的数组而言,`D[i][j]` 的内存地址为 +$$ +\& D[i][j] = x_D + \,\mathrm{sizeof}(T) \cdot (C\cdot i + j) +$$ +$C$ 为列大小,$x_D$ 是数组基址,即 `&D[0][0]`。 + +定长数组可以优化。变长数组也可以优化。本质上是识别出多维数组的元素的步长。 + +#### 结构与联合 + +用联合来获取位表示: + +```cpp +unsigned long double2bits(double d) { + union { + double d; + unsigned long u; + } temp; + temp.d = d; + return temp.u; +} +``` + +**数据对齐**: + +任何 $K$ 字节的基本对象的地址都必须是 $K$ 的倍数。 + +结构体的末尾会填充空格,使得结构体数组内的每个元素的每个字段都满足对齐要求。 + +例如: +```cpp +struct S2 { + int i; + int j; + char c; +}; +``` + +如果定义 `S2 d[4];` 那它的大小就不能为 $9$。因为 `d[1].i` 就不满足对齐要求。 + +大多数函数的栈帧的边界都必须是 $16$ 字节的倍数。 + +任何内存分配函数(`alloca`、`malloc`、`calloc` 或 `realloc`)生成的块的起始地址都必须是 $16$ 的倍数。 + +函数指针的值是该函数机器代码表示中第一条指令的地址。 + +### 缓冲区溢出攻击 + +对抗缓冲区溢出攻击: + +- **栈随机化** + 程序开始的时候先随机分配一段空间。 +- **栈破坏检测** + 设置金丝雀值。 +- **限制可执行代码区域** + +ROP 攻击能够绕开“限制可执行代码区域”这种保护方法,但绕不开“栈破坏检测”这种保护方法。 + +## 链接 + +链接器的两个任务:符号解析,以及重定位。 + +- 符号解析 + 符号是指:函数名称,全局变量名称,或者是静态变量名称。 +- 重定位代码和数据的节,重新修改符号的引用,让它们指向应该指向的位置。 + +链接器将块(有的包含程序代码,有的包含程序数据,其他则包含引导链接器和加载器的数据结构)连接起来,确定被连接块的运行时位置,并且修改代码和数据块中的各种位置。 + +**目标文件**: + +- 可重定位目标文件(编译器和汇编器生成) + - (普通的) + - (特殊的)共享目标文件 +- 可执行目标文件(链接器生成) + +### 可重定位目标文件 + +| 类型 | 条目 | 位置 | +| :--------------: | :---------: | :--: | +| 节 | ELF 头 | $0$ | +| 节 | `.text` | | +| 节 | `.rodata` | | +| 节 | `.data` | | +| 节 | `.bss` | | +| 节 | `.symtab` | | +| 节 | `.rel.text` | | +| 节 | `.rel.data` | | +| 节 | `.debug` | | +| 节 | `.line` | | +| 节 | `.strtab` | | +| 描述目标文件的节 | 节头部表 | | + +| 条目 | 内容 | +| :---------: | :----------------------------------------------------------- | +| `.text` | 已编译程序的机器代码 | +| `.rodata` | 只读数据,包括 `printf` 里的格式串和开关语句的跳转表 | +| `.data` | 已初始化的全局和静态 C 变量 | +| `.bss` | 未初始化的全局和静态 C 变量,以及所有被初始化为 $0$ 的全局或静态变量 | +| `.symtab` | 定义和引用的函数和全局变量的信息,**不包含局部变量** | +| `.rel.text` | `.text` 中,当链接器把当前目标文件和其他文件组合时,要修改的位置。包含任何调用外部函数或者引用全局变量的指令;调用本地函数的指令则不需要修改。 | +| `.rel.data` | 被模块引用或定义的所有全局变量的重定位信息。任何已初始化的全局变量,如果它的初始值是一个全局变量地址或者外部定义函数的地址,都需要被修改。 | +| `.debug` | 程序里的局部变量和类型定义(需要 `-Og` 生成) | + +### 符号和符号表 + +| 符号类型 | 定义 | +| :------: | :---------------------------------------------------: | +| 全局符号 | 由模块 $m$ 定义并能被其他模块引用 | +| 外部符号 | 由其他模块定义并被模块 $m$ 引用 | +| 局部符号 | 只被模块 $m$ 定义和引用(例如静态函数、静态全局变量) | + +任何带有 `static` 属性声明的全局变量或者函数都是模块私有的。 + +形参属于局部变量,链接器对局部变量一无所知。 + +**强符号和弱符号**: + +强符号:函数或已初始化的全局变量。 + +弱符号:未初始化的全局变量。 + +1. 不允许有多个同名强符号 +2. 如果有一个强符号和多个弱符号同名,那么选择强符号 +3. 如果有多个弱符号同名,那么从这些弱符号中任意选择一个 + +**静态库文件**: + +1. 将多个相关的重定位对象文件集成为一个单一的带索引的文件 (称为归档文件,archive file) +2. 增强链接器的功能使之能够在归档文件中解析外部符号 +3. 如果归档文件中的某个成员解析了外部符号,就将其链接入执行文件 + +**静态库文件的劣势**: + +1. 执行文件中会重复包含有所需的库文件函数或者数据 +2. 运行时内存中也会有重复部分 +3. 库文件的细微变动需要所有相关执行文件进行重链接 + +**更好的方案**: + +共享库文件,特殊类型的重定向对象文件,可以被装载入内存后进行动态链接;链接可以在装载时或者运行时完成 。即 Windows 系统下的 DLL 文件。 + +### 重定位 + +#### 重定位:节和符号定义 + +合并所有的 `.data` 节为一个节,等。这一步完成时,程序中的每条指令和全局变量都有唯一的运行时地址了。 + +#### 重定位:节中的符号引用 + +修改代码节和数据节中对每个符号的引用,使得它们指向正确的运行时地址。 + +#### 共享库中的全局变量寻址 + +代码段中的任意指令与数据段中的任意变量之间的“距离”在运行时是一个常量,与代码和数据加载的绝对内存位置无关。 + +全局偏移量表(GOT) + +## 虚存 + +在有限物理内存前提下设计出连续的、相互独立的虚拟内存。 + +**虚拟寻址**: + +![09-02 一个使用虚拟寻址的系统](https://img.picgo.net/2024/01/08/09-026168a9f67c0501e6.png) + +### 地址空间 + +虚拟地址空间:$[0, N - 1]$,其中 $N = 2^n$。 + +物理地址空间:$[0, M - 1]$,其中 $M = 2^m$。对应于系统中物理内存的 $M$ 个字节。 + +### 物理内存是虚拟内存的缓存 + +虚拟页:虚拟内存中大小固定的块。每个虚拟页的大小为 $P = 2^p$ 字节。 + +物理页(页帧):物理内存中大小固定的块。每个物理页的大小为 $P = 2^p$ 字节。 + +![09-03 一个VM系统是如何使用主存作为缓存的](https://img.picgo.net/2024/01/08/09-03af8a1fd6f3e0f1b0.png) + +| 虚拟页面状态 | 意思 | +| :----------: | :-----------------------------------------: | +| 未分配的 | VM 系统还未分配(创建)的页,不占用任何空间 | +| 缓存的 | 已缓存在物理内存中的已分配页 | +| 未缓存的 | 未缓存在物理内存中的已分配页 | + +### 页表 + +将虚拟页映射到物理页的页表项数组。 + +有效位:表示该虚拟页当前是否被缓存到在 DRAM 中。 + +![09-04 页表](https://img.picgo.net/2024/01/08/09-04b5ecc84ba581d6a2.png) + +**页缺失**: + +- 触发缺页异常 +- 页缺失处理程序选择要被替换的页面 + 由操作系统(通过异常处理代码)将所需数据从硬盘读入内存。若被替换页面是写入过的,则内存页面写入外部存储。 +- 触发页缺失的指令重新执行,这次可以确保命中(page hit) + +### 局部性 + +数据/指令的访问具有局部性 + +在任何时刻,运行的程序都倾向于访问一组“活跃”的虚拟页,活跃页面的集合称为工作集 + +具有较好的时间局部性的程序将具有较小的工作集 + +### 虚拟内存:内存管理 + +操作系统为每个进程都提供了一个单独的页表。多个虚拟页面可以映射到同一个共享物理页面上。 + +### 虚拟内存:内存保护 + +扩展页表项,增加使用权限位;违反许可条件则会触发 `SIGSEGV`(段错误) + +![09-10 用虚拟内存来提供页面级的内存保护](https://img.picgo.net/2024/01/08/09-10d323e3d660981a62.png) + +### 地址翻译 + +#### 基本参数 + +| 符号 | 描述 | +| :-------: | :----------------------: | +| $N = 2^n$ | 虚拟地址空间中的地址数量 | +| $M = 2^m$ | 物理地址空间中的地址数量 | +| $P = 2^p$ | 页的大小(字节) | + +#### 虚拟地址(VA)的组成部分 + +| 符号 | 描述 | +| :---------------: | :--------------------: | +| VPO($p$ 位) | 虚拟页面偏移量(字节) | +| VPN($n - p$ 位) | 虚拟页号 | +| TLBI | 快表(TLB)索引 | +| TLBT | 快表(TLB)标记 | + +#### 物理地址(PA)的组成部分 + +| 符号 | 描述 | +| :---------------: | :--------------------: | +| PPO($p$ 位) | 物理页面偏移量(字节) | +| PPN($m - p$ 位) | 物理页号 | + +#### 具体过程 + +![09-12 使用页表的地址翻译](https://img.picgo.net/2024/01/08/09-1220d645b6a9e7a550.webp) + +**页命中**: + +- **第 1 步:**处理器生成一个虚拟地址,并把它传送给 MMU。 +- **第 2 步:**MMU 生成 PTE 地址,并从高速缓存/主存请求得到它。 +- **第 3 步:**高速缓存/主存向 MMU 返回 PTE。 +- **第 4 步:**MMU 构造物理地址,并把它传送给高速缓存/主存。 +- **第 5 步:**高速缓存/主存返回所请求的数据字给处理器。 + +![09-13 页面命中和缺页的操作图](https://img.picgo.net/2024/01/08/09-1307e5496d6569c454.webp) + +**页缺失**: + +- **第 1 步到第 3 步:**和图 9-13a 中的第 1 步到第 3 步相同。 +- **第 4 步:**PTE 中的有效位是零,所以 MMU 触发了一次异常,传递 CPU 中的控制到操作系统内核中的缺页异常处理程序。 +- **第 5 步:**缺页处理程序确定出物理内存中的牺牲页,如果这个页面已经被修改了,则把它换出到磁盘。 +- **第 6 步:**缺页处理程序页面调入新的页面,并更新内存中的 PTE。 +- **第 7 步:**缺页处理程序返回到原来的进程,再次执行导致缺页的指令。CPU 将引起缺页的虚拟地址重新发送给 MMU。因为虚拟页面现在缓存在物理内存中,所以就会命中,在 MMU 执行了图 9-13b 中的步骤之后,主存就会将所请求字返回给处理器。 + +#### 快表(TLB) + +**快表项**: + +![09-15 虚拟地址中用以访问TLB的组成部分](https://img.picgo.net/2024/01/08/09-1530d38b7e6b4f2c3b.png) + +**快表命中**: + +TLB 命中消除了⼀次内存访问。 + +![09-16 TLB命中和不命中的操作图](https://img.picgo.net/2024/01/08/09-16824253c251678c98.webp) + +**快表不命中**: + +当 TLB 不命中时,MMU 必须从 L1 缓存中取出相应的 PTE。新取出的 PTE 存放在 TLB 中,可能会覆盖一个已经存在的条目。 + +### Linux 虚拟内存系统 + +#### Linux 虚拟内存区域 + +![09-26 一个linux进程的虚拟内存](https://img.picgo.net/2024/01/08/09-2688019634287e25d6.png) + +内核为系统中的每个进程维护一个单独的任务结构(源代码中的 `task_struct`)。 + +`task_struct` 里包含:PID、指向用户栈的指针、可执行目标文件的名字,以及程序计数器。 + +`mm_struct` 述了虚拟内存的当前状态:`pgd` 指向第一级页表(页全局目录)的基址,而 `mmap` 指向一个 `vm_area_structs`(区域结构)的链表。 + +`vm_area_struct` 中的每个结构都描述了当前虚拟地址空间的一个区域。 + +![09-27 linux是如何组织虚拟内存的](https://img.picgo.net/2024/01/08/09-270401219653ff0cf0.png) + +- `vm_start`:指向这个区域的起始处。 +- `vm_end`:指向这个区域的结束处。 +- `vm_prot`:描述这个区域内包含的所有页的读写许可权限。 +- `vm_flags`:描述这个区域内的页面是与其他进程共享的,还是这个进程私有的(还描述了其他一些信息)。 +- `vm_next`:指向链表中下—区域结构。 + +#### Linux 缺页异常处理 + +1. 虚拟地址 A 是合法的吗(是否存在)? +2. 试图进行的内存访问是否合法(有没有权限)? +3. 否则,这个访问是可以处理的缺页(只是没放缓存而已)。 + - 选择一个牺牲页面,如果这个牺牲页面被修改过,那么就将它交换出去,换入新的页面并更新页表。 + - 然后 CPU 重新启动引起缺页的指令,此时不会再缺页了。 + +![09-28 linux缺页处理](https://img.picgo.net/2024/01/08/09-282967758e7040f64f.png) + +### 内存映射 + +通过关联硬盘上存储的各类对象来初始化虚存的各个区域。 + +虚拟内存区域可以映射到: + +- Linux 文件系统中的普通文件 +- 匿名文件 + 由内核创建,全是 $0$。与进程虚存空间里的运行时 **栈**、**堆**、**未初始化的全局数据** 对应。 + +建立映射关系并不一定分配空间。只是修改了元数据。 + +共享对象的物理内存相同,但是两进程里对应的虚拟内存不一定相同。 + +#### 私有写时复制 + +![09-30 一个私有的写时复制对象](https://img.picgo.net/2024/01/08/09-307c6cdad0b7aff1af.webp) + +直到进程修改私有区域内的某个页面时,才会在物理内存中创建这个页面的一个新副本,更新页表条目指向这个新的副本,然后恢复这个页面的可写权限。尽可能地延迟复制。 + +## 内存分配基础 + +### 基本概念 + +`brk` 指向堆顶。 + +动态内存分配器将堆视作不同大小的内存块的集合——这些块要么是 **已分配的**,要么是 **空闲的**。 + +- 处理任意请求序列 +- 立即响应请求 +- 只使用堆 +- 对齐块(对齐要求) +- 不修改已分配的块 + +**吞吐率**:单位时间内完成的请求数。 + +**峰值利用率**: +$$ +U_k = \dfrac{\max\limits_{i \le k}P_i}{H_k} +$$ +$P_i$:第 $i$ 步时,当前已分配的块的有效载荷之和。$H_i$:第 $i$ 步时,堆的大小。 + +### 内部碎片与外部碎片 + +#### 内部碎片 + +- 维护堆结构的开销 +- 地址对齐用的数据填充 +- 与分配策略相关的额外开销 + 例如,返回一个大块来满足一个小请求 + +#### 外部碎片 + +当堆内有足够多的空闲内存总和,但没有一个单一的足够大的空闲块 + +### 隐式空闲链表 + +#### 结构 + +![09-35 一个简单的堆块的格式](https://img.picgo.net/2024/01/08/09-357b2b60d125f7457c.png) + +很多个这样的堆块连接起来的链表。 + +![09-36 用隐式空闲链表来组织堆](https://img.picgo.net/2024/01/08/09-36725a6285881efa0b.png) + +#### 分配:选择空闲块 + +- **First fit**:从头开始搜索 + - 会在链表的起始处附近引起碎片化 +- **Next fit**:从上一次搜索结束的地方开始搜索 + - 比 first fit 快 + - 但有研究表明,碎片化更糟糕 +- **Best fit**:选择最合适的空闲块,使得剩余字节最少 + - 会产生大量的难以利用的“小外部碎片” + - 比 first fit 要慢 + +#### 释放:合并块 + +双向合并。 + +![img](https://1087580735-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHt_spaxGgCbp2POnfq%2F-MIYeLALxK-y0CUwSgR8%2F-MIYekFIMUTfBv704Brm%2F09-40%20%E4%BD%BF%E7%94%A8%E8%BE%B9%E7%95%8C%E6%A0%87%E8%AE%B0%E7%9A%84%E5%90%88%E5%B9%B6.png?alt=media&token=53c975b1-b058-49a6-a678-39a06c2c6597) + +## 异常控制流 + +### 异常类型 + +**异步异常** 是由处理器外部的 I/O 设备中的时间产生的。 + +**同步异常** 是执行一条指令的直接产物。 + +| 类别 | 原因 | 异步/同步 | 返回行为 | +| :--: | ------------------- | :-------: | -------------------- | +| 中断 | 来自 I/O 设备的信号 | 异步 | 总是返回到下一条指令 | +| 陷阱 | 有意的异常 | 同步 | 总是返回到下一条指令 | +| 故障 | 潜在可恢复的错误 | 同步 | 可能返回到当前指令 | +| 终止 | 不可恢复的错误 | 同步 | 不会返回 | + +**陷阱** 是一条系统调用,它可以是故障,也可以是用户程序通过 `syscall` 向内核请求服务。 + +### 进程控制 + +| 函数 | 作用 | +| :----------------------------------------------------------- | ------------------------------------------------------------ | +| `pid_t getpid(void);` | 返回当前进程的 PID | +| `pid_t getppid(void);` | 返回父进程的 PID | +| `void exit(int status);` | 以 `status` 退出状态来终止进程 | +| `pid_t fork(void);` | 子进程返回 $0$,父进程返回子进程的 PID;如果出错,返回 $-1$ | +| `pid_t waitpid(pid_t pid, int *statusp, int options);` | 如果成功,返回子进程 PID;如果 WNOHANG,则为 $0$;如果其他错误,则为 $-1$ | +| `pid_wait(int *status sp);` | 等价于 `waitpid(-1, statusp, 0);` | +| `int execve(const char *filename, const char*argv[], const char *envp[])` | 在 **当前进程的上下文中** 加载并运行一个新程序 | + +**`fork` 函数**: + +1. 调用一次,返回两次。 +2. 并发执行:不能确定执行顺序。 +3. **相同但是独立**的地址空间:相同的用户栈、相同的本地变量值、相同的堆、相同的全局变量值、相同的代码,但是是独立的。 +4. 共享文件。 + +**`waitpid` 函数**:等待它的子进程终止或者停止。 + +1. `pid`:如果 `pid` 大于 $0$,则等待集合就是单独的子进程,它的 PID 是 `pid`;如果 `pid` 等于 $-1$,则等待集合由父进程的所有子进程组成的。 +2. `options`: + `WNOHANG`:如果等待集合中的任何子进程都还没有终止,那么就立即返回(返回值为 $0$)。默认的行为是挂起调用进程,直到有子进程终止。在等待子进程终止的同时,如果还想做些有用的工作,这个选项会有用。 + `WUNTRACED`:挂起调用进程的执行,直到等待集合中的一个进程变成已终止或者被停止,返回的 PID 为导致返回的已终止或被停止子进程的 PID。默认的行为是只返回已终止的子进程。当你想要检査已终止和被停止的子进程时,这个选项会有用。 + `WCONTINUED`:挂起调用进程的执行,直到等待集合中一个正在运行的进程终止或等待集合中一个被停止的进程收到 `SIGCONT` 信号重新开始执行。 + `WNOHANG | WUNTRACED`:立即返回,如果等待集合中的子进程都没有被停止或终止,则返回值为 $0$;如果有一个停止或终止,则返回值为该子进程的 PID。 +3. `statusp`:检查已回收子进程的退出状态,假设 `statusp = &status`。 + `WIFEXITED`:如果于进程通过调用 `exit` 或者 `return` 正常终止,就返回真。 + `WEXITSTATUS`:返回一令正常终止的子进程的退出状态。只有在 `WIFEXITED()` 返回为真时,才会定义这个状态。 + `WIFSIGNALED`:如果子进程是因为一个未被捕获的信号终止的,那么就返回真。 + `WTERMSIG`:返回导致子进程终止的信号的编号。只有在 `WIFSIGNALED()` 返回为真时,才定义这个状态。 + `WIFSTOPPED`:如果引起返回的子进程当前是停止的,那么就返回真。 + `WSTOPSIG`:返回引起子进程停止的信号的编号。只有在 `WIFSTOPPED()` 返回为真时,才定义这个状态。 + `WIFCONTINUED`:如果子进程收到 `SIGCONT` 信号重新启动,则返回真。 + +如果没有子进程,则返回 $-1$ 并设置 `errno` 为 `ECHILD`;如果 `waitpid` 函数被一个信号中断,则返回 $-1$ 并设置 `errno` 为 `EINTR`。 + +**`execve` 函数**: + +1. 保持进程号(PID)、打开的文件描述符和信号上下文不变 +2. 正常情况下 **不返回** + +## 信号处理 + +待处理信号(pending signal):在任何时刻,一种类型的信号 **至多只会有一个** 待处理信号。 + +### 发送信号 + +| 函数 | 作用 | +| ---------------------------------------- | -------------------------------------------------------- | +| `pid_t getpgrp(void);` | 返回调用进程的进程组 ID | +| `int setpgid(pid_t pid, pid_t pgid);` | 改变 `pid` 的进程组;成功返回 $0$,失败返回 $-1$ | +| `int kill(pid_t pid, int sig);` | 发送信号给 `pid` 的进程;成功返回 $0$,失败返回 $-1$ | +| `unsigned int alarm(unsigned int secs);` | 返回前一次闹钟剩余的秒数;如果以前没有设定过,则返回 $0$ | + +**`setpgid` 函数**: + +如果 `pid` 为 $0$,则用当前进程作为 PID;如果 `pgid` 为 $0$,则用 `pid` 指定的进程的进程组 ID 作为进程组 ID。 + +一般而言,进程组 ID 通常取自作业中父进程中的一个。 + +输入 Ctrl+C 会导致内核发送一个 `SIGINT` 信号到 **前台进程组的每个进程**。 + +输入 Ctrl+Z 会发送一个 `SIGTSTP` 信号到 **前台进程组的每个进程**。默认情况下,结果是停止(挂起)前台作业。 + +**`alarm` 函数**: + +内核在 `secs` 秒后发送一个 `SIGALRM` 信号给调用这个函数的进程。如果 `secs` 是 $0$,则啥事儿也不干。在任何情况下,`alarm` 都会取消之前所有待处理的闹钟,并且返回任何待处理的闹钟在被发送前还剩下的秒数。 + +### 接收信号 + +内核将 $p$ 从内核态切到用户态的时候,会检查 $p$ 的未被阻塞的待处理信号的集合。从小到大,强制 $p$ 接收某一信号 $k$。 + +**默认行为**: + +- 进程终止 +- 进程终止并转储内存 +- 进程停止(挂起)直到被 `SIGCONT` 信号重启 +- 进程忽略该信号 + +```cpp +typedef void (*sighandler_t)(int); +sighandler_t signal(int signum, sighandler_t handler); +``` + +**关于 `handler` 的值**: + +- 如果 `handler` 是 `SIG_IGN`,那么忽略类型为 `signum` 的信号 +- 如果 `handler` 是 `SIG_DFL`,那么类型为 `signum` 的信号行为恢复为默认行为 +- 否则,`handler` 就是用户定义的函数的地址,作为信号处理程序 + - 调用信号处理程序被称为 *捕获信号* + - 执行信号处理程序被称为 *处理信号* + +### 非本地跳转 + +```cpp +int setjmp(jmp_buf env); +int sigsetjmp(sigjmp_buf env, int savesigs); +``` + +`setjmp` 函数在 `env` 缓冲区保存当前环境,以供后面的 `longjmp` 使用,并返回 0。 + +调用一次,返回多次。 + +调用环境包括程序计数器、栈指针和通用目的寄存器。 + +**`setjmp` 函数的返回值不能作为右值。** + +```cpp +void longjmp(jmp_buf env, int retval); +void siglongjmp(sigjmp_buf, int retval); +``` + +`longjmp` 函数从 `env` 缓冲区恢复调用函数,然后出发一个从最近一次初始化 `env` 的 `setjmp` 调用的返回。然后 `setjmp` 返回,并带有非零的返回值 `retval`。 + +**调用一次,从不返回。** + +非本地跳转的一个重要应用就是允许从一个深层嵌套的函数调用中立即返回,通常是由检测到某个错误情况引起的。如果在一个深层嵌套的函数调用中发现了一个错误情况,我们可以使用非本地跳转 **直接返回** 到一个普通的本地化的错误处理程序,而不是费力地解开调用栈。 + +由于在信号处理期间自动屏蔽了正在被处理的信号,而使用 `setjmp`/`longjmp` 跳出信号处理程序时又不会自动将信号屏蔽码修改会原来的屏蔽码,从而引起该信号被永久屏蔽。 + +可以使用 `sigsetjmp`/`siglongjmp` 来解决这一问题。`sigsetjmp` 在 `savesigs` 非 $0$ 的时候会储存。 + +## IO 处理 + +- **普通文件** + - 文本文件:只含有 ASCII 或 Unicode 字符的文件 + - 二进制文件:其他文件 + 对于内核而言,二者并没有区别。 +- **目录**:包含一组 *链接* 的文件,每个链接将一个文件名映射到一个文件。 +- **套接字** + +### 打开和关闭文件 + +```cpp +// 成功返回新文件描述符,出错返回 -1 +int open(char *filename, int flags, mode_t mode); +// 成功返回 0,出错返回 -1 +int close(int fd); +``` + +`open` 函数将 `filename` 转换为一个 *文件描述符* (file descriptor),并且返回描述符数字。 + +关闭一个已关闭的描述符会出错。 + +| `flags` 参数 | 意义 | +| :----------: | :----------------------------------------------: | +| `O_RDONLY` | 只读 | +| `O_WRONLY` | 只写 | +| `O_RDWR` | 可读可写 | +| `O_CREAT` | 如果文件不存在,就创建一个空文件 | +| `O_TRUNC` | 如果文件已经存在,就截断它(重头开始写) | +| `O_APPEND` | 每次写操作前,设置文件位置到文件末尾(每次添加) | + +`mode` 参数是设置访问权限用的。 + +### 读和写文件 + +```cpp +// 若成功,返回读的字节数;出错返回 -1 +ssize_t read(int fd, void *buf, size_t n); +// 若成功,返回写的字节数;出错返回 -1 +ssize_t write(int fd, const void *buf, size_t n); +``` + +$n$ 是 **最多** 读取/写入的字节数。`read` 返回 0 表示 EOF。 + +`ssize_t` 是有符号的 `size_t`,因为出错要返回 $-1$。这也使 read/write 的返回值能够达到的返回缩小了一半。 + +可能返回值小于 $n$,此时返回值被称为 *不足值*: + +- 读时遇到 EOF +- 从终端读文本行 + 一次 `read` 将传送一个文本行,返回的不足值等于文本行的大小。 +- 读和写网络套接字 + +### 共享文件 + +- **描述符表** + + - 每个进程一张表 + - 特殊的 file descriptor + | 文件描述符(fd) | 默认打开 | + | :------------: | :------: | + | 0 | stdin | + | 1 | stdout | + | 2 | stderr | +- **打开文件表** + + - 由所有进程共享 + - refcnt 存指向该文件的描述符的个数 +- **v-node 表** + + - 由所有进程共享 + - **多个描述符可以通过不同的文件表项来引用同一个文件** + +`fork` 函数对于共享文件的影响:复制一份一模一样的描述符表。打开文件表的 `refcnt += 1`。 + +### IO 重定向 + +```cpp +int dup(int oldfd); +int dup2(int oldfd, int newfd); +``` + +**成功**:`dup` 函数返回当前系统可用的最小整数值,并让这个值代表的 `fd` 指向 `oldfd`。`dup2` 函数返回第一个不小于 `newfd` 的整数值。也就是分为两种情况: + +- 如果 `newfd` 已经打开,则先将其关闭,再复制文件描述符。 +- 如果 `newfd` 等于 `oldfd`,则 `dup2` 返回 `newfd`,而不关闭它。 + +**失败**:均返回 $-1$,并设置 `errno`。 + +本质上是修改了描述符表中表项指向的打开文件表的位置。`dup2` 以后,可能会导致某个文件被关闭,导致打开文件表和 v-node 表被删除。 + +### UNIX IO + +**优点**: + +- Unix IO 是最通用而且额外开销最小的 IO 形式 +- 所有其他 IO 包都是使用 UNIX IO 来实现的 +- Unix IO 提供了访问文件元数据的功能 + +**缺点**: + +- 对不足值的处理不够,容易出错 +- 有效读取文本行需要某种形式的缓冲,容易出错 +- 这些问题在标准 IO 和 RIO 包中都得到解决 + +### 标准 I/O + +标准 I/O 函数在实现过程中使用了缓存,在写入 `\n` 时或者显式调用 `fflush()` 时讲缓存内容刷入到输出文件。 + +**优点**: + +- 通过减小 `read` 和 `write` 调用的数目,缓冲增加了效率 +- 不足值可以自动处理 + +**缺点**: + +- 没有提供访问文件元数据的功能 +- 标准 IO 程序并非同步信号安全的,也不适合在信号处理程序中采用 +- 标准 IO 不适合于对网络 socket 的输入输出进行处理 + +### 选择 I/O 函数 + +**通用规则:使用能用的最高级别的 IO 函数。** + +- **什么时候使用标准 IO**: + - 当处理磁盘和终端文件的时候。 +- **什么时候使用裸 UNIX IO**: + - 信号处理程序,因为只有它是同步信号安全的 + - 在很少的情况下,当你需要高性能的时候 +- **什么时候用 RIO**: + - 读写网络套接字的时候 + - 避免对 socket 使用标准 IO + +## 线程与线程同步基础 + +线程是运行在一个单一进程上下文中的逻辑流,由内核进行调度。 + +每个线程都有它自己的线程上下文(thread context),包括以个唯一的整数线程 ID(Thread ID,TID)、栈、栈指针、程序计数器、通用目的寄存器和条件码。所有的运行在一个进程里的线程共享该进程的整个虚拟地址空间。 + +### 线程执行模型 + +线程之间是并列的关系,而不是像进程那样的父子关系。 + +主线程和其他线程的区别仅在于它总是进程中第一个运行的线程。对等线程池概念的主要影响是,一个线程可以杀死它的任何对等线程,或者等待它的任意对等线程终止。另外,每个对等线程都能读写相同的共享数据。 + +### 相关函数 + +#### 创建线程 + +```cpp +#include +typedef void *(func)(void *); + +int pthread_create(pthread_t *tid, pthread_attr_t *attr, func *f, void *arg); +pthread_t pthread_self(void); // 获取自身的线程 ID +``` + +创建一个新的线程,带着一个输入变量 `arg`,在新的线程上下文中运行线程例程 `f`。返回时: + +- `tid` 包含新创建线程的 TID +- 函数若成功执行,返回 $0$;出错,返回非零。 + +#### 终止线程 + +当顶层的线程例程返回时,线程会 *隐式地* 终止。 + +```cpp +void pthread_exit(void *thread_return); // 从不返回 +``` + +通过调用 `pthead_exit` 函数,线程会 *显式地* 终止。如果主线程调用 `pthread_exit` 函数,它会等待所有其他对等线程终止,然后再终止主线程和整个进程,返回值为 `thread_return`。 + +某个对等线程调用 Linux 的 `exit` 函数,该函数终止进程以及所有与该进程相关的线程。 + +```cpp +int pthread_cancel(pthread_t tid); +``` + +可以通过 `pthread_cancel` 来终止某个线程。函数若成功执行,返回 $0$;出错,返回非零。 + +#### 回收已终止线程的资源 + +```cpp +int pthread_join(pthread_t tid, void **thread_return); +``` + +阻塞直至 `tid` 终止,`thread_return` 里存的是终止的那个线程的返回值。函数若成功执行,返回 $0$;出错,返回非零。 + +### 共享变量 + +一个变量 x 被共享,当且仅当多个线程引用 x 的(至少)一个实例 。 + +#### 线程内存模型 + +- 独有的:线程号、栈、栈指针、PC、条件码,以及通用寄存器 + 寄存器值是严格隔离和受到保护的;但不同线程的栈互相间 **不设防**,也就是说,可以强行通过地址偏移来访问。 +- 共有的:代码、数据(内存)、堆、共享库、打开的文件,以及设置好的信号处理函数(handler) + +#### 将变量实例映射到内存 + +| 变量类型 | 定义 | 内存中的实例 | +| :----------: | :------------------------------: | :----------------------------------: | +| 全局变量 | 定义在所有函数外面 | 虚拟内存包含全局变量的唯一实例 | +| 本地自动变量 | 定义在函数内部,无 `static` 属性 | 每个线程栈包含每个局部变量的一个实例 | +| 本地静态变量 | 定义在函数内部,有 `static` 属性 | 虚拟内存包含局部静态变量的唯一实例 | + +### 临界区与不安全区 + +Head-(Load-Update-Store)-Tail + +![12-19 badcnt.c第一次循环迭代的进度图](https://img.picgo.net/2024/01/08/12-1951ba6b6799847e52.png) + +![12-20 一个轨迹线示例](https://img.picgo.net/2024/01/08/12-20e3c1841764feb2fa.png) + +每个线程的 L-U-S 段被称为 *临界区*,两个线程临界区的“笛卡尔积”围城的区域称为 *不安全区*。 + +#### 安全轨迹线与不安全轨迹线 + +![12-21 安全和不安全轨迹线](https://img.picgo.net/2024/01/08/12-21332b7723979205e8.png) + +需要保证两个线程对临界区的互斥访问。 + +### 信号量 + +```cpp +void P(T s) { + while (s == 0) + wait(); + s--; +} +``` + +```cpp +void V(T s) { + s++; +} +``` + +信号量不变性:当初始 $s$ 非负时,之后的过程中 $s \ge 0$ 恒成立。 + +#### 使用信号量来实现互斥 + +二元信号量:$0$ / $1$ + +**互斥锁(mutex)**:P “锁定”互斥锁,V “释放”互斥锁。 + +**定义**: + +```cpp +volatile long cnt = 0; /* Counter */ +sem_t mutex; /* 一个保护 Counter 的信号量 */ +``` + +**初始化**: + +```cpp +Sem_init(&mutex, 0, 1); /* mutex = 1 */ +``` + +**操作**: + +```cpp +for (int i = 0; i < niters; i++) { + P(&mutex); + // do something... + // 将临界区域用 P 和 V 操作包围 + V(&mutex); +} +``` + +#### 生产者-消费者问题 + +$n$ 个槽的有限缓冲区,生产者线程反复生成新的项目,消费者线程不断地从缓冲区取出这些项目。 + +- 如果缓冲区是满的,那么生产者必须等待直到有一个槽位变为可用; +- 如果缓冲区是空的,那么消费者必须等待直到有一个项目变为可用。 + +用一个循环队列作为缓冲区。除了需要一个互斥锁来管理 `buffer` 是否可用之外,还要有两个互斥锁管理可用槽位数量和可用项目数量:不仅要有 `slots`,还要有 `items`。`insert` 的时候要等 `slots` 开锁;`remove` 的时候要等 `items` 开锁。 + +### 竞争 + +程序的正确性依赖于部分线程的执行顺序。 + +**解决办法**:为每个 ID 分配独立的块。 + +### 死锁 + +一组线程被阻塞了,等待一个永远也不会为真的条件。 + +![12-44 一个会死锁的程序的进度图](https://img.picgo.net/2024/01/08/12-4421417387d17331ee.png) + +死锁状态禁止向上或向右的拓展,这导致这个程序无法继续进行。 + +**解决办法**: + +- 执行轨迹不要进入死锁区域 +- 不同进程以相同的顺序获得锁 +- 释放锁的顺序不重要 + +![12-45 一个无死锁程序的进度图](https://img.picgo.net/2024/01/08/12-45cdac8cc5c0ac64a5.png) diff --git "a/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\350\207\252\345\212\250\346\234\272\347\220\206\350\256\272\343\200\201\350\257\255\350\250\200\345\222\214\350\256\241\347\256\227\345\257\274\350\256\272.md" "b/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\350\207\252\345\212\250\346\234\272\347\220\206\350\256\272\343\200\201\350\257\255\350\250\200\345\222\214\350\256\241\347\256\227\345\257\274\350\256\272.md" new file mode 100644 index 0000000..4ed83e3 --- /dev/null +++ "b/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\350\207\252\345\212\250\346\234\272\347\220\206\350\256\272\343\200\201\350\257\255\350\250\200\345\222\214\350\256\241\347\256\227\345\257\274\350\256\272.md" @@ -0,0 +1,1599 @@ +--- +title: 【学习笔记】自动机理论、语言和计算导论 +tags: + - 自动机理论、语言和计算导论 + - 有穷自动机 + - 正则表达式 + - 上下文无关文法 + - 下推自动机 +categories: + - 笔记 +mathjax: true +toc: true +date: 2023-09-17 14:49:56 +password: +id: IATLC +--- + +这是《自动机理论、语言和计算导论》的学习笔记。 + + + +## 第一章 自动机:方法与体验 | 第二章 有穷自动机 + +### 字母表、串、语言和问题 + +#### 字母表 + +**字母表** 是符号的有穷非空集合,记为 $\Sigma$。 + +#### 串 + +**串(单词)** 是从某个字母表中选择的符号组成的有穷序列。 + +- 串的长度 + + 选择出来的符号个数被称为串的长度。 + +- 空串 $\varepsilon$ + + 它的长度为 $0$,是可以从任何字母表中选择的串。**但它不属于任何字母表**。$\varepsilon \not\in \Sigma$。 + +- 字母表的幂 + + 如果 $\Sigma$ 是一个字母表,则 $\Sigma^k$ 表示这个字母表长度为 $k$ 的所有串所组成的集合。 + +$$ +\begin{aligned} + \Sigma^0 &= \{\varepsilon\} \\ + \Sigma^{+} &= \Sigma^1\cup\Sigma^2\cup\Sigma^3\cdots \\ + \Sigma^{*} &= \Sigma^{+} \cup \{\varepsilon\} +\end{aligned} +$$ + +#### 语言 + +设 $\Sigma$ 为一个字母表,$L \subseteq \Sigma^{*}$ 被称为 $\Sigma$ 上的 **语言**。 + +- 空语言 $\varnothing$ 与只包含空串的语言 $\{\varepsilon\}$ + + $\varnothing$ 和 $\{\varepsilon\}$ 都是任意字母表上的语言,但 $\varnothing \neq \{\varepsilon\}$,前者没有串,后者有一个串。 + +- 若 $L$ 是 $\Sigma$ 上的语言,则 $L$ 是任何是 $\Sigma$ 的超集的字母表上的语言。 + +#### 问题 + +在自动机理论中,一个 **问题** 就是 “判定一个给定的串是否属于某个具体语言” 这一行为。 + +问题和语言是可以相互等价的。如果 $\Sigma$ 是字母表,$L$ 是 $\Sigma$ 上的语言,则问题 $L$ 就是“给定 $\Sigma^{*}$ 中的一个串 $w$,判断 $w$ 是否属于 $L$。这说明 $L$ 是一个语言,也可以被看成是一个问题。 + +### 有穷自动机的形式化定义 + +#### 确定性有穷自动机(DFA) + +通常使用一个五元组 $A = (Q, \Sigma, \delta, q_0, F)$ 来表示一个 DFA。其中 $A$ 是 DFA 的名称,$Q$ 是状态集合,$\Sigma$ 是输入符号,$\delta$ 是转移函数,$q_0$ 是初始状态,$F$ 是接受状态集合。 + +##### DFA 的表示方法 + +- 转移图 + + ```mermaid + graph LR + + style Start fill:none,stroke-width:0px + + Start --> A(($q_0$)) + A --> |$0$| C(($q_2$)) + A --> |$1$| A + C --> |$0$| C + C --> |$1$| B((($q_1$))) + B --> |$0, 1$| B + ``` + + 初始状态用 `Start` 指示,接受状态用双圆圈标记(例如 $q_1$)。 + +- 转移表 + + 我们也可以使用转移表来直观地表示一个 DFA,着重强调它的转移函数 $\delta$。 + + | | $0$ | $1$ | + |-:|:-:|:-:| + | $\to q_0$ | $q_2$ | $q_0$ | + | $*q_1$ | $q_1$ | $q_1$ | + | $q_2$ | $q_2$ | $q_1$ | + + 初始状态用箭头标记,接受状态用星号标记。 + +##### 转移函数 $\delta$ + +本质上就是转移图上的有向边,边权为字母表中的字符。 + +- 扩展转移函数 $\hat\delta$ + + 感性地说,就是 **让转移函数的自变量不再限于单个字符**,而是可以给定一个串,它能在自动机上从给定状态开始,沿着转移图的边走,一直走到它最终对应的状态。 + + 形式化的定义如下: + + > 基础:$\hat\delta(q, \varepsilon) = q$。 + > + > 归纳:$\hat\delta(q, w) = \delta(\hat\delta(q, x), a)$,其中 $w = xa$。 + +##### DFA 的语言 + +定义 DFA $A = (Q, \Sigma, \delta, q_0, F)$ 的语言 $L(A)$ 如下: + +$$ +L(A) = \{w | \hat\delta(q_0, w) \in F\} +$$ + +$L(A)$ 是 $A$ 的 **所有可接受的串** 所组成的集合。如果对于某个 DFA $A$ 来说 $L$ 是 $L(A)$,则我们称 $L$ 是一个 **正则语言**。 + +#### 非确定性有穷自动机(NFA) + +~~NFA 就是多线程 DFA(确信)~~ + +在读入每个串的时候,NFA 可以向多个方向同时转移,最后只取可接受状态组成的状态集合。 + +##### NFA 的表示方法 + +转移表既可以表示 NFA 的转移函数,也可以用来规定 DFA 的转移函数,区别在于,NFA 转移表中的 **每一项都是集合**,即使是单元素集合;如果在某个状态上不存在向其他状态的转移时,应该填入 $\varnothing$。 + +##### 转移函数 $\delta$ + +- 扩展转移函数 $\hat\delta(q, w)$ + + 形式化的表述如下: + + > 基础:$\hat\delta(q, \varepsilon) = \{q\}$。 + > + > 归纳:$\hat\delta(q, w) = \bigcup\limits_{p \in \hat\delta(q, x)}\delta(p, a)$,其中 $w = xa$。 + +##### NFA 的语言 + +相应地,由于 NFA 可以同时向多个方向转移,所以对于一个串来说,只要存在一个状态使得 NFA 能接受该串,那么这个串就属于这个 NFA 对应的语言。 + +$$ +L(A) = \{w | \hat\delta(q_0, w) \cap F \neq \varnothing\} +$$ + +#### DFA 和 NFA 的区别与联系 + +DFA 和 NFA 之间的唯一区别在于,$\delta$ 在 DFA 的情况下,返回的是 **单个状态**;而在 NFA 的情况下,返回的是一个 **状态集合**。 + +##### DFA 和 NFA 的等价性 + +显然一个 DFA 可以转化成一个 NFA,只需要把状态中的每个元素写成其对应的单元素集合即可。重点在于怎么通过一个 NFA $N = (Q_N, \Sigma, \delta_N, \{q_0\}, F_N)$ 开始,描述一个 DFA $D = (Q_D, \Sigma, \delta_D, q_0, F_D)$ 使得 $L(N) = L(D)$。可以采用 **子集构造** 的方式来解决此问题。 + +- $Q_D = P(Q_N)$,即 $Q_D$ 是 $Q_N$ 的幂集合。但值得注意的一点是,虽然它们是“集合”,但它们是单个状态,而不是状态的集合。换句话说,构造出来的 $D$ 中,每个状态本身都是集合。 +- $F_D = \{S \subseteq Q_N | S \cap F_N \neq \varnothing\}$。也就是说,$F_D$ 是所有至少含有一个 $N$ 的接受状态的 $N$ 的状态集合的集合。 +- 对于每个集合 $S \subseteq Q_N$ 以及 $a \in \Sigma$,构造转移函数如下: + $$ + \delta_D(S, a) = \bigcup_{p \in S}\delta_N(p, a) + $$ + 也就是说,对于 $S$ 中所有状态 $p$,在 $N$ 中从 $p$ 上通过输入 $a$ 进入的状态,这些状态的并集,就是 $\delta_D(S, a)$。 + +**定理**:如果 $D = (Q_D, \Sigma, \delta_D, \{q_0\}, F_D)$ 是用子集构造从 NFA $N = (Q_N, \Sigma, \delta_N, q_0, F_N)$ 构造出来的 DFA,那么 $L(D) = L(N)$。 + +**证明**:只需证明 $\hat\delta_D(\{q_0\}, w) = \hat\delta_N(q_0, w)$。 + +基础:设 $|w| = 0$,则 $w = \varepsilon$,显然有 $\hat\delta_D(\{q_0\}, \varepsilon) = \hat\delta_N(q_0, \varepsilon)$。 + +归纳:设 $|w| = n + 1$,且命题对 $|v| = n$ 的所有 $v$ 均成立。记 $w = xa$,假设 $\hat\delta_D(\{q_0\}, x) = \hat\delta_N(q_0, x) = \{p_1, p_2, \cdots, p_k\}$。 + +由 NFA 的 $\hat\delta$ 的定义的归纳部分说明 $\hat\delta(q_0, w) = \cup_{i = 1}^k\delta_N(p_i, a)$。另一方面,子集构造说明 $\delta_D(\{p_1, p_2, \cdots, p_k\}, a) = \cup_{i = 1}^k\delta_N(p_i, a)$。因此 + +$$ +\hat\delta_D(\{q_0\}, w) = \delta_D(\hat\delta_D(\{q_0\}, x), a) = \delta_D(\{p_1, p_2, \cdots, p_k\}, a) = \bigcup_{i = 1}^k\delta_N(p_i, a) = \hat\delta(q_0, w) +$$ + +所以对于某个串 $w$ 而言,它在 $D$ 和 $N$ 中的可达性是相同的。 + +因此 $\hat\delta_D(\{q_0\}, w)q_{n - 1} = \hat\delta_N(q_0, w) \iff L(D) = L(N)$。命题得证。 + +```mermaid +graph LR + +style Start fill:none,stroke-width:0px + +Start --> A(($q_0$)) +A --> |$0, 1$| A +A --> |$0$| B(($q_1$)) +B --> |$1$| C((($q_2$))) +``` + +这是一个接受所有以 `01` 结尾的 01 串的 NFA。它所对应的 DFA 为 + +```mermaid +graph LR + +style Start fill:none,stroke-width:0px + +Start --> A(("$\{q_0\}$")) +A --> |$1$| A +A --> |$0$| B(("$\{q_0, q_1\}$")) +B --> |$0$| B +B --> |$1$| C((("$\{q_0, q_2\}$"))) +C --> |$0$| B +C --> |$1$| A +``` + +转移表如下: + + | | $0$ | $1$ | + |-:|:-:|:-:| + | $\varnothing$ | $\varnothing$ | $\varnothing$ | + | $\to \{q_0\}$ | $\{q_0, q_1\}$ | $\{q_0\}$ | + | $\{q_1\}$ | $\varnothing$ | $\{q_2\}$ | + | $*\{q_2\}$ | $\varnothing$ | $\varnothing$ | + | $\{q_0, q_1\}$ | $\{q_0, q_1\}$ | $\{q_0, q_2\}$ | + | $*\{q_0, q_2\}$ | $\{q_0, q_1\}$ | $\{q_0\}$ | + | $*\{q_1, q_2\}$ | $\varnothing$ | $\{q_2\}$ | + | $*\{q_0, q_1, q_2\}$ | $\{q_0, q_1\}$ | $\{q_0, q_2\}$ | + +##### 子集构造的最劣情形 + +考虑 $L(N)$ 是所有使得倒数第 $n$ 位是 $1$ 的 01 串集合。 + +```mermaid +graph LR + +style Start fill:none,stroke-width:0px +style ... fill:none,stroke-width:0px + +Start --> A(($q_0$)) +A --> |$0, 1$| A +A --> |$1$| B(($q_1$)) +B --> |$0, 1$| C(($q_2$)) +C --> |$0, 1$| ... +... --> |$0, 1$| D(("$q_{n-1}$")) +D --> |$0, 1$| E((($q_n$))) +``` + +这个 NFA 没有少于 $2^n$ 个状态的等价 DFA。这很好理解,因为你最少要存下来每个 01 串的最后 $n - 1$ 位,所以会导致 DFA 的状态数指数型增长。 + +### $\varepsilon$ 转移 + +$\varepsilon$ 转移可以理解成边权为空串 $\varepsilon$ 的边。 + +#### $\varepsilon$ - NFA 的形式化定义 + +只有转移函数 $\delta$ 与 NFA 不同。在 $\varepsilon$ - NFA 中,$\delta$ 的定义域被拓展为 $Q \times \left(\Sigma \cup \{\varepsilon\}\right)$,它需要包含所有通过 $\varepsilon$ 边转移的信息。 + +#### $\varepsilon$ 闭包 + +这就有点类似于在有向图中缩点了。$\varepsilon$ 闭包就是能被缩成一个点的块儿,消除 $\varepsilon$ 转移就是缩点的过程。 + +递归地定义 $q$ 的 $\varepsilon$ 闭包如下: + +> 基础:$q \in \text{ECLOSE}(q)$ +> +> 归纳:若 $p \in \text{ECLOSE}(q)$,且存在 $p$ 到 $r$ 的 $\varepsilon$ 转移,则 $r \in \text{ECLOSE}(q)$。 + +- 扩展转移函数 $\hat\delta(q, w)$ + 形式化的定义如下: + > 基础:$\hat\delta(q, \varepsilon) = \text{ECLOSE}(q)$。 + > + > 归纳:$\hat\delta(q, w) = \bigcup\limits_{p \in \hat\delta(q, x)}\text{ECLOSE}(\delta(p, a))$,其中 $w = xa$。 + +用通俗的话说,通过 $\varepsilon$ 的边将状态 $q$ 和它周围的状态联系起来,它们本质上是“同一个状态”,“同一个状态”对应的就是 $\text{ECLOSE}(q)$。 + +#### 消除 $\varepsilon$ 转移 + +给定一个 $\varepsilon$ - NFA $E = (Q_E, \Sigma, \delta_E, q_0, F_E)$,求满足 $L(E) = L(D)$ 的 DFA $D = (Q_D, \Sigma, \delta_D, q_D, F_D)$。 + +- $Q_D = \{S \subseteq Q_E | S = \text{ECLOSE}(S)\}$ +- $q_D = \text{ECLOSE}(q_0)$ +- $F_D = \{S \subseteq Q_D | S \cap F_E \neq \varnothing\}$ +- $\delta_D$ 满足 + $$ + \delta_D(S, a) = \bigcup_{p \in S}\text{ECLOSE}(\delta(p, a)) + $$ + +对于 $E$ 和其对应的 $D$,也有 + +**定理**:$L$ 被 $\varepsilon$ - NFA $E$ 接受,当且仅当 $L$ 被 DFA $D$ 接受。 + +定理的证明与 NFA 和 DFA 的等价性处的证明类似。 + +### 练习题 + +**习题 1** + +![习题 1](https://img.picgo.net/2023/12/20/exercise11b1ec947067fc985.jpeg) + +注意,要按照 $bac$ 和 $acb$ 重叠部分的长度分成三类。 + +**习题 2** 给出接受下列在字母表 $\{0, 1\}$ 上的语言的 DFA:所有 *倒过来* 解释成二进制整数时是 $5$ 的倍数的串的集合。例如 $010011, 1001100$ 和 $0101$。 + +先画出接受正方向串的 DFA $D$。这是容易的,按照除以 $5$ 得到的余数分类设计 $5$ 个状态即可。接着,接受倒过来串的 DFA 就是将 $D$ 中所有边全部反向得到的 DFA。 + +**习题 3** 给出接受下列在字母表 $\{0, 1\}$ 上的语言的 DFA:所有倒数第 $10$ 个符号是 $1$ 的串的集合。 + +设计 $2^{10}$ 个状态,表示已输入的串除以 $2^{10}$ 得到的余数,余数 $ \in [2^{9}, 2^{10} - 1]$ 为接受状态。 + +## 第三章 正则表达式与正则语言 + +### 正则表达式的运算符 + +#### 并与连接 + +- 并 + $$ + L \cup M = \{w | w \in L \lor w \in M\} + $$ + +- 连接 + $$ + LM = \{w = uv | u \in L \land v \in M\} + $$ + +#### 闭包 + +语言 $L$ 的闭包记作 $L^*$。形式化的定义是: + +$$ +L^* = \bigcup_{i \ge 0}L^i +$$ + +其中 $L^0 = \{\varepsilon\}, L^1 = L$,$L^i(i \ge 2)$ 表示 $i$ 个 $L$ 的连接。 + +对于绝大多数语言 $L$ 而言,$L^*$ 通常是无穷的。**仅有两个** 特殊的语言,它们的闭包是有限的。 + +- $\varnothing^*$ + + 注意到对于 $i \ge 1$,$\varnothing^i$ 是空集,而 $\varnothing^0 = \{\varepsilon\}$。故 $\varnothing^* = \{\varepsilon\}$。 + +- $\{\varepsilon\}^*$ + + 注意到 $\{\varepsilon\}$ 无论连接多少次都不会改变它是 $\{\varepsilon\}$ 的事实,所以 $\{\varepsilon\}^* = \{\varepsilon\}$。 + +### 正则表达式的定义 + +正则表达式仍然采用递归的定义方法: + +**基础**: + +1. $\varepsilon$ 和 $\varnothing$ 是正则表达式,分别表示语言 $\{\varepsilon\}$ 和 $\varnothing$。也就是说,$L(\varepsilon) = \{\varepsilon\}, L(\varnothing) = \varnothing$。 +2. 若 $a$ 是任意 **符号**,则 $\textbf{a}$ 是正则表达式。这个表达式表示语言 $\{a\}$。也就是说,$L(\textbf{a}) = \{a\}$。 + +**归纳**: + +1. 如果 $E$ 和 $F$ 都是正则表达式,则 $E + F$ 是正则表达式,表示 $L(E)$ 和 $L(F)$ 的并。也就是说,$L(E + F) = L(E) \cup L(F)$。 +2. 如果 $E$ 和 $F$ 都是正则表达式,则 $EF$ 是正则表达式,表示 $L(E)$ 和 $L(F)$ 的连接。也就是说,$L(EF) = L(E)L(F)$。 +3. 如果 $E$ 是正则表达式,则 $E^*$ 是正则表达式,表示 $E$ 的闭包。也就是说,$L(E^*) = (L(E))^*$。 +4. 如果 $E$ 是正则表达式,则 $(E)$ 是正则表达式,表示和 $E$ 相同的语言。也就是说 $(L(E)) = L(E)$。 + +### 自动机与正则表达式间的关系 + +DFA、NFA、$\varepsilon$ - NFA 和正则表达式之间是等价的,它们都能表示相同的正则语言。 + +```mermaid +graph LR +A(NFA) --> |1| B(DFA) +B --> |2| C($\varepsilon$ - NFA) +C --> |3| B +B --> |4| D(RE) +D --> |5| C +``` + +其中 1、2、3 都已经被证明了。现在只需要证明 4 和 5。 + +#### 由 DFA 构建正则表达式 + +我们想要解决的问题是:给定一个 DFA $A$,记 $L = L(A)$,求一个正则表达式 $R$,使得 $L = L(R)$。 + +重新编号 $A$ 的状态为 $\{1, 2, \cdots, n\}$,使得 $1$ 为初始状态。设 $R_{ij}^{(k)}$ 表示满足以下条件的串 $w$ 所组成的集合:$w$ 是 $A$ 中从状态 $i$ 到状态 $j$ 的路径的标记,而且这条路径没有编号大于 $k$ 的 **中间顶点**。因此 $i$ 和 $j$ 没有必要不大于 $k$。 + +最终的 $R$,是所有 $R_{1j}^{(n)}$ 的并,使得状态 $j$ 为一个接受状态。 + +仍然考虑使用递归的思路来推导 $R_{ij}^{(k)}$。 + +**基础**:当 $k = 0$ 时,这条路径中不能包含除了 $i, j$ 以外的其他状态。也就是说,这条路径上最多只会包含两个状态。 + +- 如果 $i = j$,则 $R_{ii}^{(0)} = \varepsilon + \textbf{a}_1 + \textbf{a}_2 + \cdots + \textbf{a}_r$,其中状态 $i$ 有自环 $\textbf{a}_1, \textbf{a}_2, \cdots, \textbf{a}_r$ 的弧。 +- 如果 $i \neq j$,则 $R_{ij}^{(0)} = \textbf{a}_1 + \cdots + \textbf{a}_r$,其中状态 $i$ 到状态 $j$ 有 $\textbf{a}_1, \textbf{a}_2, \cdots, \textbf{a}_r$ 的弧。 + +**归纳**:假设有 $R_{ij}^{(k)}$,那么这条路径有两种情况: + +1. 这条路径根本不经过状态 $k$。 + 这种情况下 $R_{ij}^{(k)} \gets R_{ij}^{(k-1)}$。 + +2. 这条路径经过状态 $k$ 至少一次。 + 于是我们可以把整个路径分成几段: + + ```mermaid + graph LR + + style ... fill:none,stroke-width:0px + + A((i)) --> |"属于 $R_{ik}^{(k-1)}$"| B((k)) + subgraph "属于 $R_{kk}^{(k-1)}$ 的零个或多个串" + B((k)) --> C((k)) + C((k)) --> ... + ... --> E((k)) + end + E((k)) -->|"属于 $R_{kj}^{(k-1)}$"| F((j)) + ``` + + 那么这种路径可以表示成正则表达式 $R_{ik}^{(k - 1)}(R_{kk}^{(k - 1)})^*R_{kj}^{(k - 1)}$。 + +结合起来就有 $R_{ij}^{(k)} = R_{ij}^{(k - 1)} + R_{ik}^{(k - 1)}(R_{kk}^{(k - 1)})^*R_{kj}^{(k - 1)}$。这是一个递推式,所以我们可以从基础已知递推到所有的 $R_{1j}^{(n)}$。 + +比如考虑下图表示的 DFA: + +```mermaid +graph LR + +style Start fill:none,stroke-width:0px + +Start --> A(($1$)) +A --> |$1$| A +A --> |$0$| B((($2$))) +B --> |$0, 1$| B +``` + +由 **基础** 部分可得: + +| 表达式 | 值 | +| :------------: | :-------------------------------------: | +| $R_{11}^{(0)}$ | $\varepsilon + \mathbf{1}$ | +| $R_{12}^{(0)}$ | $\mathbf{0}$ | +| $R_{21}^{(0)}$ | $\varnothing$ | +| $R_{22}^{(0)}$ | $\varepsilon + \mathbf{0} + \mathbf{1}$ | + +然后通过 **归纳** 部分递推得出 $R_{ij}^{(1)}$: + +$$ +R_{ij}^{(1)} = R_{ij}^{(0)} + R_{i1}^{(0)}(R_{11}^{(0)})^*R_{1j}^{(0)} +$$ + +因此可以得到: + +| 表达式 | 通过直接带入 | 化简后的值 | +| :------------: | :----------------------------------------------------------: | :-------------------------------------: | +| $R_{11}^{(0)}$ | $\varepsilon + \mathbf{1} + (\varepsilon + \mathbf{1})(\varepsilon + \mathbf{1})^*(\varepsilon + \mathbf{1})$ | $\mathbf{1}^*$ | +| $R_{12}^{(0)}$ | $\mathbf{0} + (\varepsilon + \mathbf{1})(\varepsilon + \mathbf{1})^*\mathbf{0}$ | $\mathbf{1}^*\mathbf{0}$ | +| $R_{21}^{(0)}$ | $\varnothing + \varnothing(\varepsilon + \mathbf{1})^*(\varepsilon + \mathbf{1})$ | $\varnothing$ | +| $R_{22}^{(0)}$ | $\varepsilon + \mathbf{0} + \mathbf{1} + \varnothing(\varepsilon + \mathbf{1})^*\mathbf{0}$ | $\varepsilon + \mathbf{0} + \mathbf{1}$ | + +又有 + +$$ +R_{ij}^{(2)} = R_{ij}^{(1)} + R_{i2}^{(1)}(R_{22}^{(1)})^*R_{2j}^{(1)} +$$ + +因此可以得到: + +| 表达式 | 通过直接带入 | 化简后的值 | +| :------------: | :----------------------------------------------------------: | :-------------------------------------------------: | +| $R_{11}^{(1)}$ | $\mathbf{1}^* + \mathbf{1}^*\mathbf{0}(\varepsilon + \mathbf{0} + \mathbf{1})^*\varnothing$ | $\mathbf{1}^*$ | +| $R_{12}^{(1)}$ | $\mathbf{1}^*\mathbf{0} + \mathbf{1}^*\mathbf{0}(\varepsilon + \mathbf{0} + \mathbf{1})^*(\varepsilon + \mathbf{0} + \mathbf{1})$ | $\mathbf{1}^*\mathbf{0}(\mathbf{0} + \mathbf{1})^*$ | +| $R_{21}^{(1)}$ | $\varnothing + (\varepsilon + \mathbf{0} + \mathbf{1})(\varepsilon + \mathbf{0} + \mathbf{1})^*\varnothing$ | $\varnothing$ | +| $R_{22}^{(1)}$ | $\varepsilon + \mathbf{0} + \mathbf{1} + (\varepsilon + \mathbf{0} + \mathbf{1})(\varepsilon + \mathbf{0} + \mathbf{1})^*(\varepsilon + \mathbf{0} + \mathbf{1})$ | $(\mathbf{0} + \mathbf{1})^*$ | + +在此例中,$1$ 是初始状态,$2$ 是唯一一个接收状态,则整体的正则表达式为 $R_{12}^{(2)} = \mathbf{1}^*\mathbf{0}(\mathbf{0} + \mathbf{1})^*$。 + +它表示的是“至少含有一个 0 的 01 串”组成的集合。 + +#### 消除状态法 + +上述方法的复杂度太高,我们可以使用 **消除状态** 的方式来化简自动机。考虑下图中即将被消除的状态 $s$: + +```mermaid +graph LR + +A(($q_1$)) --> |"$R_{11}$"| B(($p_1$)) +A --> |"$R_{1m}$"| E +A --> |$Q_1$| C(($s$)) +C --> |$P_1$| B +C --> |$S$| C +C --> |$P_m$| E +D --> |$Q_k$| C +D --> |"$R_{k1}$"| B +D(($q_k$)) --> |"$R_{km}$"| E(($p_m$)) +``` + +消除状态 $s$ 时需要清除掉所有与状态 $s$ 相关的转移边。消除状态 $s$ 后如下: + +```mermaid +graph LR + +A(($q_1$)) --> |"$R_{11} + Q_1S^*P_1$"| B(($p_1$)) +A --> |"$R_{1m} + Q_1S^*P_m$"| E +D --> |"$R_{k1} + Q_kS^*P_1$"| B +D(($q_k$)) --> |"$R_{km} + Q_kS^*P_m$"| E(($p_m$)) +``` + +从有穷自动构造正则表达式的策略如下: + +1. 对于每个接受状态 $q$,应用上面的消除过程,消除除了 $q$ 和初始状态 $q_0$ 之外的所有其余状态,产生一个等价的自动机,转移边上带有正则表达式标记。 + +2. 如果 $q \neq q_0$,则剩下一个两状态自动机。可以用多种方法来描述所接受的串的正则表达式。一种方式是 $(R + SU^*T)^*SU^*$。 + + ```mermaid + graph LR + style Start fill:none,stroke-width:0px + + Start --> A((" ")) + A --> |$R$| A + A --> |$S$| B(((" "))) + B --> |$T$| A + B --> |$U$| B + ``` + +3. 如果初始状态也是接受状态,则必须去掉除了初始状态意外的所有其余状态。这样做了之后,只剩下一个单状态自动机,表示所接受的串的正则表达式是 $R^*$。 + + ```mermaid + graph LR + style Start fill:none,stroke-width:0px + + Start --> A(((" "))) + A --> |$R$| A + ``` + +4. 所求的正则表达式是对每个接受状态进行步骤 2 和步骤 3 所得出的所有表达式之和(并)。 + +#### 由正则表达式构造 $\varepsilon$ - NFA + +构造出来的自动机都是 **具有单个接受状态** 的 $\varepsilon$ - NFA。 + +**基础**:先构造 $\{\varepsilon\}, \varnothing, \mathbf{a}$ 对应的三个自动机: + +```mermaid +graph LR + +style Start fill:none,stroke-width:0px + +Start((" ")) --> A((" ")) + +subgraph "$\{\varepsilon\}$" +A --> | $\varepsilon$ | B(((" "))) +end +``` + +```mermaid +graph LR +style Start fill:none,stroke-width:0px + +Start((" ")) --> A((" ")) + +subgraph $\varnothing$ +A +B(((" "))) +end +``` + +```mermaid +graph LR +style Start fill:none,stroke-width:0px + +Start((" ")) --> A((" ")) + +subgraph "$\mathbf{a}$" +A --> | $a$ | B(((" "))) +end +``` + +**归纳**:接着,我们构造 $R + S, RS, R^*$: + +```mermaid +graph LR + +style Start fill:none,stroke-width:0px + +Start((" ")) --> A((" ")) + +A --> | $\varepsilon$ | B((" ")) +A --> | $\varepsilon$ | D((" ")) + +subgraph $R$ +B -.- C((" ")) +end + +subgraph $S$ +D -.- E((" ")) +end + +C --> | $\varepsilon$ | F(((" "))) +E --> | $\varepsilon$ | F +``` + +```mermaid +graph LR +style Start fill:none,stroke-width:0px + +Start((" ")) --> A((" ")) + +subgraph $R$ +A -.- B((" ")) +end + +B --> | $\varepsilon$ | C((" ")) + +subgraph $S$ +C -.- D(((" "))) +end +``` + +```mermaid +graph LR +style Start fill:none,stroke-width:0px + +Start((" ")) --> A((" ")) + +A --> | $\varepsilon$ | B((" ")) + +subgraph $R$ +C --> | $\varepsilon$ | B +B -.- C((" ")) +end + +C --> | $\varepsilon$ | D(((" "))) +A --> | $\varepsilon$ | D +``` + +通过自动机结构上的归纳法,我们可以得到与正则表达式表示相同语言的 $\varepsilon$ - NFA。 + +#### 消除 $\varepsilon$ 转移时的注意事项 + +在上述构造中,有些地方可以化简: + +1. 对于并运算符,不是构造新的初始状态和接收状态,而是把两个初始状态合并成一个具备两个初始状态的所有转移的状态。同样,合并两个接受状态,让所有的转移相应的地进入合并状态。 + + ```mermaid + graph LR + + style Start fill:none,stroke-width:0px + + Start((" ")) --> A((" ")) + + subgraph " " + A -.- | $R$ | B(((" "))) + A -.- | $S$ | B + end + ``` + +2. 对于连接运算符,把第一个自动机的接受状态与第二个自动机的初始状态合并。 + + ```mermaid + graph LR + style Start fill:none,stroke-width:0px + + Start((" ")) --> A((" ")) + + subgraph " " + A -.- | $R$ | B((" ")) + B -.- | $S$ | C(((" "))) + end + ``` + +3. 对于闭包运算符,只是增加从接受状态到初始状态的以及反方向的 $\varepsilon$ 转移。 + + ```mermaid + graph LR + style Start fill:none,stroke-width:0px + + Start((" ")) --> A((" ")) + + subgraph " " + B(((" "))) --> | $\varepsilon$ | A + A --> | $\varepsilon$ | B + A -.- | $R$ | B + end + ``` + +每一个这种化简 **本身** 仍然产生正确的构造,但它们 **组合在一起** 有时会产生错误的构造(例如 $R + S^*$)。 + +### 正则表达式代数定律 + +**定理**:设 $E$ 是带变量 $L_1, L_2, \cdots, L_m$ 的正则表达式。对于 $i = 1, 2, \cdots, m$,通过把 $L_i$ 的每次出现都换成符号 $a_i$ 形成具体的正则表达式 $C$。则 $\forall w = w_1w_2\cdots w_k \in L(E)$,其中每个 $w_i$ 都属于任意的语言之一(如 $L_{j_i}$),都有 $w$ 对应的正则表达式 $a_{j_1}a_{j_2}\cdots a_{j_k}$ 属于语言 $L(C)$。 + +这个定理揭示了语言和正则表达式的内蕴的等价性。 + +~~附赠一个可能会有用的公式~~ $(R^*S^*)^* = (R + S)^*$ + +### 练习题 + +**习题 1** 求正则表达式 $E$,满足 $L(E) = \{w|w\text{ 的开头字符和结尾字符相同}\}$。 + +$0(0+1)^*0+1(0+1)^*1+0+1$。一定不要忘了 $|w|=1$ 的两种情况。 + +**习题 2** 求正则表达式 $E$,满足 $L(E)= \{w|w\text{ 的前 5 位至少包含 1 个 1} \land |w|\ge 1\}$。 + +巧妙使用空串 $\varepsilon$:$(0+1+\varepsilon)^41(0+1)^*$。 + +## 第四章 正则语言的性质 + +### 泵引理 + +**定理**:设 $L$ 是正则语言,则存在与 $L$ 相关的正整数 $n$ 满足:$\forall w \in L$ 满足 $\left|w\right| \ge n$,均 $\exists x, y, z$ 满足 $w = xyz$ 且: + +1. $y \neq \varepsilon$ +2. $\left|xy\right| \le n$ +3. $\forall k \ge 0, xy^kz \in L$ + +**证明**:假设 $L$ 是正则语言,则存在 DFA $A$ 使得 $L = L(A)$。设 $A$ 有 $n$ 个状态,考虑 $w = a_1a_2\cdots a_m(m \ge n)$,其中 $a_i$ 为输入符号。 + +设 $p_i = \hat\delta(q_0, a_1a_2\cdots a_i)$,定义 $p_0 = q_0$ 为 $A$ 的初始状态。则 $p_0, p_1, \cdots, p_n$ 不可能两两不同,因此存在 $0 \le i < j \le n$ 使得 $p_i = p_j$。 + +所以可以画出如下的转移图: + +```mermaid +graph LR + +style Start fill:none,stroke-width:0px + +Start --> A(($p_0$)) +A -.-> |$x = a_1a_2\cdots a_i$| B(($p_i$)) +B -.-> |"$y = a_{i+1} \cdots a_j$"| B +B -.-> |"$z = a_{j + 1}\cdots a_m$"| C(((" "))) +``` + +由 $i < j$ 得 $y \neq \varepsilon$,由 $j \le n$ 得到 $\left|xy\right| \le n$。$k \ge 0$ 就是可以绕着 $p_i$ 得自环多走几圈。 + +### 正则语言的封闭性 + +#### 交运算的乘积构造法 + +已知正则语言 $L, M$,设 $A_L = \{Q_L, \Sigma, \delta_L, q_L, F_L\}$,$A_M = \{Q_M, \Sigma, \delta_M, q_M, F_M\}$,满足 $L = L(A_L), M = L(A_M)$。构造他们的乘积(笛卡尔积): + +$$ +A = (Q_L \times Q_M, \Sigma, \delta, q_L \times q_M, F_L \times F_M) +$$ + +其中 $\delta$ 满足 $\delta((p, q), a) = (\delta_L(p, a), \delta_M(q, a))$,返回一个二元组。$A$ 接受 $w$ 当且仅当 $\hat\delta((q_L, q_M), w)$ 是一对接受状态。这等价于 $\hat\delta(q_L, w)$ 和 $\hat\delta(q_M, w)$ 均为接受状态。所以说 $A$ 只接受 $L\cap M$。 + +#### 逆同态 + +定义 $L$ 对于 $h$ 的逆同态 $h^{-1}$ 如下: + +$$ +h^{-1}(L) = \{w \in \Sigma^* | h(w) \in L\} +$$ + +需要注意的是,$h(h^{-1}(L)) \subset L$,**并不一定等于** $L$! + +--- + +**定理**:已知 $h: \Sigma \to \Tau$,其中 $L$ 是 $\Tau$ 上的正则语言,求证 $h^{-1}(L)$ 是 $\Sigma$ 上的正则语言。 + +**证明**:设 $L$ 有一个 DFA $A = (Q, \Tau, \delta, q_0, F)$,现在的目标是用 $A$ 和 $h$ 构造 $h^{-1}(L)$ 的 DFA $B = (Q, \Sigma, \gamma, q_0, F)$。 + +定义 $\gamma(q, a) = \hat\delta(q, h(a))$,然后扩展 $\hat\gamma(q, w) = \hat(q, h(w))$。由于 $B$ 接受 $w$ 当且仅当 $A$ 接受 $h(w)$,故 $B$ 就是 $h^{-1}(L)$ 的 DFA。 + +注意 $\gamma(q, a)$ 是 $\hat\delta(q, h(a))$ 而非 $\delta(q, h(a))$,这是因为 $h(a)$ 有可能是一个串而非字符。 + +### 自动机的等价性和最小化 + +#### 测试状态的等价性 + +我们称 DFA 中的两个状态 $p, q$ 是 **等价的**,如果 $\hat\delta(p, w)$ 是可接受当且仅当 $\hat\delta(q, w)$ 是可接受的。 + +注意到这个定义并不要求 $\hat\delta(p, w) = \hat\delta(q, w)$,它仅仅要求二者要么同时都是可接受的,要么同时都是不可接受的。 + +我们称 DFA 中的两个状态 $p, q$ 是 **可区分的**,如果它们不是等价的。 + +--- + +至此,我们可以构造 **填表算法**,来测试状态的等价性: + +**基础**:如果 $p$ 和 $q$ 一个是可接受的,一个是不可接受的,那么 $p, q$ 是可区分的。 + +**归纳**:设 $p, q$ 满足 $\exists a$ 使得 $r = \delta(p, a)$ 与 $s = \delta(q, a)$ 是已知可区分的。假设 $w$ 可以区分 $r$ 和 $s$,那么 $aw$ 一定可以区分 $p, q$。按照归纳的步骤一步一步递推,则可得知所有状态两两间是否等价。 + +--- + +接下来,我们需要证明填表算法的正确性。 + +**定理**:如果通过填表算法不能区分两个状态,则这两个状态等价。 + +**证明**:使用反证法证明。我们称状态对 $\{p, q\}$ 为 *坏对*,如果 $\exists w \in L$,满足 $\hat\delta(p, w)$ 和 $\hat\delta(q, w)$ 本应可区分,但填表算法没有发现它们可区分。 + +设 $w = a_1a_2\cdots a_n$ 是所有可以区分坏对(无论区分的是哪一对坏对)的串中最短的那一个,且它区分的是 $\{p, q\}$。则 $\hat\delta(p, w)$ 和 $\hat\delta(q, w)$ 必恰有一个可接受。 + +注意到一个事实,$w \neq \varepsilon$,这是因为填表算法的基础部分对应的就是 $w = \varepsilon$ 的情况,可接受状态和不可接受的状态一定是可以区分的。接下来,考虑 $r = \delta(p, a_1), s = \delta(q, a_1)$,则串 $w' = a_2a_3 \cdots a_n$ 可区分 $r$ 和 $s$。 + +如果 $\{r, s\}$ 是坏对,则 $w'$ 比 $w$ 更短且能区分坏对,则产生矛盾。如果 $\{r, s\}$ 不是坏对,则 $\{r, s\}$ 一定是可区分的。此时算法已经发现 $\{r, s\}$ 是可区分的,那么一定会进行下去并计算出 $\{p, q\}$ 也是可区分的,这也产生矛盾。 + +所以填表算法是正确的。 + +#### 测试正则语言的等价性 + +至此,我们已经能够测试同一个 DFA 中的两个状态是否等价。对于两个正则语言 $L$ 和 $M$ 而言,构造 DFA $A, B$ 使得 $L = L(A), M = L(B)$。 + +设 $A$ 的初始状态为 $p_0$,$B$ 的初始状态为 $q_0$。构造 DFA $A' = A \cup B$,只需要判断 $p_0$ 和 $q_0$ 是否等价即可。 + +#### DFA 的最小化 + +用以下流程可以最小化一个 DFA: + +1. 排除所有不能从初始状态到达的状态 +2. 将所有等价的状态划分到同一个连通块 + +需要注意一点的是,如果 $p, q$ 等价,$r, s$ 等价,且 + +```mermaid +graph LR +A(($p$)) --> |$1$| C(($r$)) +B(($q$)) --> |$1$| C +``` + +即使此时无论是 $p$ 还是 $q$ 都不会通过 $1$ 转移到 $s$,我们仍然需要用上述算法划分等价类: + +```mermaid +graph LR +A(("$\{p, q\}$")) --> |$1$| B(("$\{r, s\}$")) +``` + +### 练习题 + +**习题 1** 语言 $L$ 由所有满足如下条件的 $0$ 和 $1$ 组成的串构成:$0$ 的数量是 $1$ 的两倍。试用泵引理证明 $L$ 不是正则语言。 + +考虑 $w = xyz = 0^{2n}1^n$,则 $y$ 全部由 $0$ 构成,则 $xz \neq L$。这题的重点在于,虽然 $0^{2n}1^n$ 并非 $L$ 的全部,但只要找到一个反例即可。 + +**习题 2** 证明 $L = \{0^{n^2} | n \in \mathbb{N}\}$ 不是正则语言。 + +考虑 $w = xyz = 0^{n^2}$,则 $1 \le |y| \le n$,构造 $xy^2z$,它的长度 $|xy^2z| \in [n^2 + 1, n^2 + n]$,但这个区域内不应有完全平方数。$n^2$ 后的第一个完全平方数为 $(n+1)^2 = n^2+2n+1 > n^2+n$。 + +**习题 3** 证明 $L = \{0^n | n \text{ 是质数}\}$ 不是正则语言。 + +考虑 $w = xyz = 0^p$,其中 $p \ge n + 2$ 且为质数。不妨设 $|y| = m \ge 1$。考虑 $w' = xy^{p-m}z$,则 $|xy^{p-m}z| = (m+1)(p-m)$。而 $m+1 \neq 1, p-m \ge n+2-m \ge 2$。因此 $|w'|$ 不为质数。 + +**习题 4** 证明 $L = \{0^{2^n}|n \in \mathbb{N}\}$ 不是正则语言。 + +考虑 $w = xyz = 0^{2^n}$。与习题 2 的做法类似,我们可以得到 $|y| \in [1, n]$。我们只需要证明 $|xz| = 2^n - |y|$ 一定不是 $2$ 的幂即可。考虑 $|xz|$ 的取值范围 $[2^n-n, 2^n-1]$,则限制 $2^{n-1} < 2^n-n$ 即可,即 $n \ge 3$。所以在泵引理中取 $w = xyz = 0^{2^n}(n \ge 3)$ 即可导出 $xz \notin L$。 + +## 第五章 上下文无关文法及上下文无关语言 + +### 上下文无关文法 + +#### 上下文无关文法的定义 + +一个上下文无关文法(CFG)由四个重要部分组成: + +1. 一个有穷字母表 $T$,由 $T$ 中的字母构成了这个文法所定义的语言中的串,这个字母表称为 **终结符**(Terminal)。 +2. 一个 **非终结符** (Variable)的有穷集合 $V$。 +3. 有一个非终结符 $S$ 称为 **初始符号**(Start Symbol),它代表语言开始被定义的地方。 +4. 一个 **产生式** (Production)的有穷集合 $P$,它用来表示语言的递归定义。每个产生式被定义为 ` -> `,具体的构造过程是,保持终结符不变,把任何所有的 `` 替换成 ``。 + +一个上下文无关文法可以表示为 $G = (V, T, P, S)$。 + +--- + +以下是可以表示语言 $(\textbf{a} +\textbf{b})(\textbf{a} + \textbf{b} + \textbf{0} + \textbf{1})^*$ 的一个上下文无关文法。 +$$ +\begin{aligned} +E & \to I \\ +E & \to E + E \\ +E & \to E * E \\ +E & \to (E) \\ +I & \to a \\ +I & \to b \\ +I & \to Ia \\ +I & \to Ib \\ +I & \to I0 \\ +I & \to I1 +\end{aligned} +$$ +产生式可以使用简捷表示法,比如上面的产生式可以化简为: +$$ +\begin{aligned} +E & \to I | E + E | E * E | (E) \\ +I & \to a | b | Ia | Ib | I0 | I1 +\end{aligned} +$$ + +#### 推导与递归推理 + +**推导** 的过程通过符号 $\implies$ 表示。设 $G = (V, T, P, S)$ 为一个 CFG,$\alpha A \beta$ 是一个包含终结符和非终结符的串,其中 $A$ 是一个非终结符,而 $\alpha, \beta \in (V \cup T)^*$。设 $A \to \gamma$ 是一个产生式,则我们称 $\alpha A \beta \underset{G}{\implies} \alpha\gamma\beta$。通常省略掉 $G$,而仅仅记作 $\alpha A \beta \implies \alpha\gamma\beta$。 多步推导则使用 $\overset{*}{\implies}$ 来表示。 + +**递归推理** 的过程类似于推导的逆过程,是从具体的 **产生式的体** 递归到抽象的 **产生式的头** 的过程。 + +#### 最左与最右推导 + +在每一步推导中,如果要求只讲最左边的非终结符替换成该非终结符的某个产生式的体,那么这种方式的推导称为 **最左推导**。类似地可以定义 **最右推导**。最左推导和最右推导分别用 $\underset{lm}{\implies}, \underset{lm}{\overset{*}{\implies}}$ 和 $\underset{rm}{\implies}, \underset{rm}{\overset{*}{\implies}}$ 表示。 + +个人认为,如果每次推导的时候按照随机的顺序来替换,那么整个推导的逻辑就会变得杂乱无章。最左推导和最右推导就限制了替换产生式的头的顺序:前者是从左往右,后者是从右往左。 + +#### 文法的语言 + +对于 CFG $G = (V, T, P, S)$,它的语言 $L(G)$ 被定义为所有终结符串的集合: +$$ +L(G) = \{w \in T^* | S \underset{G}{\overset{*}{\implies}}w\} +$$ +如果我们要证明某个文法 $G$ 确实定义了某个已经非形式化定义好的语言 $L$,通常需要分两步: + +1. 充分性:如果一个串 $w \in L$ 满足这个非形式化定义的性质,那么 $S \overset{*}{\implies}w$,来说明 $w \in L(G)$。通常,我们通过 **对 $w$ 的长度** 进行归纳证明。 +2. 必要性:如果 $S \overset{*}{\implies}w$,那么 $w$ 应该满足这个非形式化定义的性质,来说明 $w \in L$。通常,我们需要 **对推导的步数** 进行归纳证明。 + +#### 句型 + +由初始符号推导出来的串称为 **句型**(Sentence)。$G = (V, T, P, S)$ 的所有句型 $\alpha$ 组成的集合是 +$$ +\{\alpha \in (V \cup T)^* | S \overset{*}{\implies}\alpha\} +$$ +另外,如果 $S \underset{lm}{\overset{*}{\implies}} \alpha$ 则 $\alpha$ 是左句型,如果 $S \underset{rm}{\overset{*}{\implies}} \alpha$ 则 $\alpha$ 是右句型。句型可以包含非终结符。语言 $L(G)$ 是由所有属于 $T^*$ 的句型组成的。 + +### 语法分析树 + +#### 语法分析树的构造 + +对于 CFG $G = (V, T, P, S)$,$G$ 的 **语法分析树** 是满足下列条件的树: + +1. 每个内部节点的标号是 $V$ 中的一个非终结符。 +2. 每个叶节点的标号可以是一个非终结符,一个终结符,或者 $\varepsilon$。但是,如果叶节点的标号是 $\varepsilon$,那么它一定是其父节点唯一的子节点。 +3. 如果某个内部节点的标号是 $A$,并且它的子节点的标号从左到右分别为 $X_1, X_2, \cdots, X_k$,那么 $A \to X_1X_2\cdots X_k$ 一定是 $P$ 中的一个产生式。注意:如果其中某个 $X$ 为 $\varepsilon$,那么 $X$ 一定是 $A$ 唯一的子节点,并且 $A \to \varepsilon$ 是 $G$ 的一个产生式。 + +最重要的语法分析树,是那些 **所有叶节点的标号都是终结符或 $\varepsilon$,且根节点的标号是初始符号** 的语法分析树。 + +#### 递归推理、推导与语法分析树的等价性 + +```mermaid +graph LR + +A(语法分析树) --> B(最左推导) +A --> C(最右推导) +B --> D(推导) +C --> D +D --> E(递归推理) +E --> A +``` + +其中从最左推导到推导是显然的,而最右推导相关箭头都与最左推导类似,因此我们只需要证明以下三个等价性: + +##### 从递归推理到语法分析树 + +**定理**:设 CFG $G = (V, T, P, S)$。如果通过递归推理过程得出终结符串 $w$ 在非终结符 $A$ 的语言中,则一定存在一棵根为 $A$、产物为 $w$ 的语法分析树。 + +**证明**:对推理的步数进行归纳。 + +基础:如果该推理只有一步,则该推理过程只需要基础,因此一定存在产生式 $A \to w$。这样就能构造出: + +```mermaid +graph TD + +style A stroke:none,fill:none +style B stroke:none,fill:none +style C stroke:none,fill:none +style D stroke:none,fill:none + +A --> B($w_1$) +A --> C(...) +A --> D($w_k$) +``` + +其中 $w = w_1w_2 \cdots w_k$。 + +归纳:假定在 $n + 1$ 个推理步骤之后能够得出 $w$ 在 $A$ 的语言里这个事实,并且这个定理对于使得 $B$ 的语言中的 $x$ 成员用小于等于 $n$ 步推理推得的所有串 $x$ 和非终结符 $B$ 成立。考虑得出 $w$ 在 $A$ 的语言里的这个推理的最后一步,这一步使用了 $A$ 的某个产生式,不妨设为 $A \to X_1X_2 \cdots X_k$,其中 $X_i$ 是一个终结符或非终结符。 + +- 如果 $X_i$ 是终结符,那么 $X_i = w_i$。 +- 如果 $X_i$ 是非终结符,那么 $w_i$ 是一个先前推理出在 $X_i$ 语言中的串,而由于 $A \to X_1X_2 \cdots X_k$ 消耗了 $1$ 步,所以 $w_i$ 在 $X_i$ 中的推导最多只会有 $n$ 步,根据归纳假设则可得出存在一个根为 $X_i$,产物为 $w$ 的语法分析树。 + +```mermaid +graph TD + +style A stroke:none,fill:none +style B stroke:none,fill:none +style C stroke:none,fill:none +style D stroke:none,fill:none +style E stroke:none,fill:none +style F stroke:none,fill:none + +A --> B($X_1$) +A --> C(...) +A --> D($X_k$) +B -.- E($w_1$) +D -.- F($w_k$) +``` + +##### 从语法分析树到推导 + +**定理**:设 CFG $G = (V, T, P, S)$,假设有一棵语法分析树,它的根的标号为非终结符 $A$,产物为 $w \in T^*$。那么一定存在一个 $G$ 中的最左推导 $A \underset{lm}{\overset{*}{\implies}}w$。 + +**证明**:对树的高度进行归纳。设 $w = w_1w_2\cdots w_k$。 + +基础:如果树高为 $1$,那么 $G$ 一定包含 $A \to w$ 这一产生式,最左推导可以单步完成,即为 $A \underset{lm}{\implies}w$。 + +归纳:如果树高为 $n$,其中 $n > 1$,且定理对所有树高小于 $n$ 的树成立。考虑树: + +```mermaid +graph TD + +style A stroke:none,fill:none +style B stroke:none,fill:none +style C stroke:none,fill:none +style D stroke:none,fill:none + +A --> B($X_1$) +A --> C(...) +A --> D($X_k$) +``` + +- 如果 $X_i$ 是终结符,那么定义 $w_i$ 为只包含 $X_i$ 的串。 +- 如果 $X_i$ 是非终结符,那么 $X_i$ 一定是一个树高小于 $n$ 的子树的根节点,因此通过归纳假设,存在一个最左推导 $X_i \underset{lm}{\implies}w_i$。 + +##### 从推导到递归推理 + +**定理**:设 CFG $G = (V, T, P, S)$,假设有一个推导 $A \underset{G}{\overset{*}{\implies}}w$,其中 $w \in T^*$。那么应用于 $G$ 的递归推理过程决定了 $w$ 在非终结符 $A$ 的语言中。 + +**证明**:对推导 $A \overset{*}{\implies}w$ 的步数进行归纳。 + +基础:如果该推导只有一步,那么 $A \to w$ 一定是一个产生式。由于 $w$ 只包含终结符,因此 $w$ 一定在 $A$ 的语言中。 + +归纳:假设该推导包含 $n + 1$ 步,并且假定对于所有少于或等于 $n$ 步的推导来说命题都成立。把推导写为 $A \implies X_1X_2\cdots X_k \overset{*}{\implies}w = w_1w_2\cdots w_k$。 + +- 如果 $X_i$ 是终结符,那么 $w_i = X_i$。 +- 如果 $X_i$ 是非终结符,那么有 $X_i \overset{*}{\implies}w_i$,这是因为这个推导的步数少于或等于 $n$ 步。 + +现在已经有了产生式 $A \to X_1X_2\cdots X_k$,且对于 $w = w_1w_2\cdots w_k$ 有 $w_i$ 在 $X_i$ 的语言中。下一步即得 $w = w_1w_2\cdots w_k$ 在 $A$ 的语言中。 + +### 文法与语言的歧义性 + +#### 歧义文法 + +一个 CFG $G = (V, T, P, S)$ 是 **歧义的**,如果 $\exists w \in T^*$ 使得有两棵不同的语法分析树满足根为 $S$ 且产物为 $w$。 + +正如这篇博文最初给的例子,当产物 $w = a + a * a$ 时,有两棵语法分析树: + +```mermaid +graph TD + +subgraph " " +style S1 stroke:none,fill:none +style A1 stroke:none,fill:none +style B1 stroke:none,fill:none +style C1 stroke:none,fill:none +style D1 stroke:none,fill:none +style E1 stroke:none,fill:none +style F1 stroke:none,fill:none +style G1 stroke:none,fill:none +style H1 stroke:none,fill:none +style I1 stroke:none,fill:none +style J1 stroke:none,fill:none +style K1 stroke:none,fill:none +style L1 stroke:none,fill:none + +S1(E) --> A1(E) +S1 --> B1(+) +S1 --> C1(E) +A1 --> D1(I) +D1 --> E1(a) +C1 --> F1(E) +C1 --> G1(*) +C1 --> H1(E) +F1 --> I1(I) +I1 --> J1(a) +H1 --> K1(I) +K1 --> L1(a) +end + +subgraph " " +style S2 stroke:none,fill:none +style A2 stroke:none,fill:none +style B2 stroke:none,fill:none +style C2 stroke:none,fill:none +style D2 stroke:none,fill:none +style E2 stroke:none,fill:none +style F2 stroke:none,fill:none +style G2 stroke:none,fill:none +style H2 stroke:none,fill:none +style I2 stroke:none,fill:none +style J2 stroke:none,fill:none +style K2 stroke:none,fill:none +style L2 stroke:none,fill:none + +S2(E) --> A2(E) +S2 --> B2(*) +S2 --> C2(E) +A2 --> D2(E) +A2 --> E2(+) +A2 --> F2(E) +D2 --> G2(I) +G2 --> H2(a) +F2 --> I2(I) +I2 --> J2(a) +C2 --> K2(I) +K2 --> L2(a) +end + +``` + +这说明该文法是歧义的。 + +--- + +注意,并不是多种推导导致了歧义性,而是存在多棵不同的语法分析树导致的。比如 + +1. $E \implies E + E \implies I + E \implies a + E \implies a + I \implies a + b$ +2. $E \implies E + E \implies E + I \implies E + b \implies I + b \implies a + b$ + +这两个推导所提供的结构并没有本质的区别,它们对应同一棵语法分析树。 + +#### 去除文法的歧义性 + +**不存在算法能够判定某个文法的歧义性。**而且,存在一些文法,对它们而言只存在歧义的文法(即 [固有歧义](#固有歧义) 的文法)。对于这篇博文最初给的例子而言,有两个缺陷导致了文法的歧义性: + +1. 没有考虑运算符的优先级。我们需要使所有的 $*$ 操作在 $+$ 操作之前被结合。 +2. 一系列运算符既可从左到右也可以从右到左地结合。事实上,即使我们正确地保持了运算符优先级,$E+E+E$ 仍然会得到两棵不同的语法分析树。一个习惯的做法是坚持从左到右地结合,我们需要通过一些结构来固定这个顺序。 + +有三种常用策略来解决文法歧义性的问题:**运算符优先级联**、**左结合** 和 **最近嵌套匹配**。 + +事实上,我们可以引入几个不同的非终结符,来解决强制优先级的问题: + +1. **因子**(Factor)是不能被相邻的运算符(包括 $*$ 和 $+$)打断的表达式。在此例中,因子只会是标识符 $I$ 以及任何被括号括起来的表达式。 +2. **项**(Term)是不能被相邻的 $+$ 打断的表达式。在此例中,项只会是一个或多个因子的乘积。 +3. **表达式**(Expression)是指任何可能得串,其中包含可以被相邻的 $*$ 或 $+$ 打断的表达式。在此例中,表达式就是一个或多个项的和。 + +上述方法采用了 **运算符优先级联** 和 **左结合** 的方法。具体而言,前者是指 $*$ 和 $+$ 的优先级的区别;后者是指相同优先级的 $*$ 和 $*$、$+$ 和 $+$ 的优先级应为从左到右。 + +修改之后的 CFG 如下: + +$$ +\begin{aligned} +I & \to a | b | Ia | Ib | I0 | I1 \\ +F & \to I | (E) \\ +T & \to F | T * F \\ +E & \to T | E + T +\end{aligned} +$$ + +**最近嵌套匹配** 是指类似于括号匹配的题目中,$($ 只与最近的 $)$ 进行匹配的过程。此时需要一个非终结符来生成 $($ 和 $)$ 完全匹配的串。 + +例如 $S \to \varepsilon | iS | iSeS$ 这个生成所有合法 if-else 语法结构的 CFG。我们可以去除它的歧义: +$$ +\begin{aligned} +S & \to \varepsilon | iS | iMeS \\ +M & \to \varepsilon | iMeM +\end{aligned} +$$ +其中 $M$ 是完全匹配的 if-else 对。$S$ 中的 if 要么是孤立的,要么一定与第一个需要匹配的 else 相匹配。 + +再例如 $L = \{a^nb^m| m \ge n \ge 0\}$ 的 CFG: +$$ +\begin{aligned} +S & \to AB \\ +A & \to aAb | \varepsilon \\ +B & \to bB | \varepsilon +\end{aligned} +$$ +这里也保证了每个 $a$ 与左侧最近的一个 $b$ 进行匹配。 + +#### 固有歧义 + +如果一个上下文无关语言 $L$ 的所有文法都是歧义的,那么我们称它是 **固有歧义** 的。 + +### 练习题 + +**习题 1** 求 CFG,所有不是 $ww$ 形式的由 $a$ 和 $b$ 构成的串的集合,即不是把某个串重复一遍的串。 + +**解答** 首先,奇数长度的串都不是 $ww$ 的形式,这个容易处理。其次,偶数长度的串分成两个长度相等的段,不妨设每段的长度为 $n$;因为不具有 $ww$ 的形式,所以 $\exists i \in [1, n]$,该串第 $i$ 位和第 $n + i$ 位不同;分别以第 $i$ 位和第 $n + i$ 位为中心将该串重新划分为两段,长度分别为 $2(i - 1) + 1$ 和 $2(n - i) + 1$;这两段的中心不同,而围绕中心的其它位可以任意。 +$$ +\begin{aligned} +S & \to E | O \\ +O & \to a | b | COC \\ +E & \to AB | BA \\ +A & \to CAC | a \\ +B & \to CBC | b \\ +C & \to a | b +\end{aligned} +$$ +其中,开始符号为 $S$;非终结符 $O$ 负责产生奇数长度的串;非终结符 $E$ 负责产生偶数长度的串;非终结符 $A$ 负责产生以 $a$ 为中心的串;非终结符 $B$ 负责产生以 $b$ 为中心的串。 + +**习题 2** 设 $G = (\{S, A, B\}, \{a, b\}, P, S)$ 为一上下文无关文法,其中 $P$ 如下: +$$ +\begin{aligned} +S & \to \varepsilon | aB | bA \\ +A & \to a | aS | bAA \\ +B & \to b | bS | aBB +\end{aligned} +$$ +试证明 $L(G) = \{w | w \in \{a, b\}^*, \text{occur}(w, a) = \text{occur}(w, b)\}$。 + +**思路** 采用互归纳法,证明 $A$ 产生的串组成的语言,是 $\text{occur}(w, a) = \text{occur}(w, b) + 1$ 的语言; $B$ 产生的串组成的语言,是 $\text{occur}(w, b) = \text{occur}(w, a) + 1$ 的语言。 + +## 第六章 下推自动机 + +### 下推自动机的定义 + +#### 下推自动机的形式化定义 + +一个下推自动机(PDA)由七个部分组成: +$$ +P = (Q, \Sigma, \Gamma, \delta, q_0, Z_0, F) +$$ + +1. $Q$:状态的有穷集合。 + +2. $\Sigma$:输入符号的有穷集合。 + +3. $\Gamma$:有限的堆栈字母表,该部分是能够被推入堆栈的符号的集合。 + +4. $\delta$:转移函数,自变量为一个三元组 $\delta(q, a, X)$,其中 + + - $q \in Q$ + - $a \in \Sigma$ 或 $a = \varepsilon$ + - $X \in \Gamma$ + + $\delta$ 的输出是有序对 $(p, \gamma)$ 的有穷集合,其中 $p$ 是新状态,$\gamma$ 是堆栈符号串,$\gamma$ 用来代替栈顶符号 $X$。 + +5. $q_0$:初始状态。 + +6. $Z_0$:初始堆栈中的符号。 + +7. $F$:接受状态的集合。 + +PDA 相较于 DFA 的区别是引入了一个栈用于存储数据,以及多了一个参数(栈顶元素)来控制转移方向。 + +#### 下推自动机的瞬时描述 + +使用 $(q, w, \gamma)$ 三元组来表示 PDA 的配置,其中 $q$ 是状态,$w$ 是剩余的输入串,$\gamma$ 是堆栈的内容。这样的一个三元组被称为下推自动机的一个 **瞬时描述**。 + +我们定义 $\vdash_P$(如果 $P$ 已知,那么简写为 $\vdash$)为:假设 $(p, \alpha) \in \delta(q, a, X)$,那么对于所有 $\Sigma^*$ 中的串 $w$ 和 $\Gamma^*$ 中的串 $\beta$ 都有: +$$ +(q, aw, X\beta) \vdash (p, w, \alpha\beta) +$$ +这相当于处理了输入串 $aw$ 中最前面的一个字符 $a$,并且用 $\alpha$ 来替换栈顶的 $X$,这导致了一次从状态 $q$ 到状态 $p$ 的转移。 + +同样地,我们也使用符号 $\vdash_P^*$ 来表示 PDA 的零步或多步转移。 + +#### 输入串与栈底串的简化 + +**定理**:如果 $P = (Q, \Sigma, \Gamma, \delta, q_0, Z_0, F)$ 是一个 PDA,并且 $(q, x, \alpha) \vdash_P^* (p, y, \beta)$,那么对于所有 $\Sigma^*$ 中的串 $w$ 和 $\Gamma^*$ 中的串 $\beta$ 都有 +$$ +(q, xw, \alpha\gamma) \vdash_P^* (p, yw, \beta\gamma) +$$ +**证明**:由于 $(q, x, \alpha) \vdash_P^* (p, y, \beta)$ 的过程中都没有使用与 $w$ 和 $\gamma$ 相关的转移,所以只需要对 $(q, x, \alpha) \vdash_P^* (p, y, \beta)$ 进行转移步数上的归纳即可得证。 + +**补充 1**:定理的逆定理关于栈的简化的那一部分不成立。原因很好理解,因为我们在转移的过程中~~偷偷地~~从 $\gamma$ 中弹出一些符号,再在之后的过程中压回去,效果仍然是 $\gamma$ 不变,但是转移的过程改变了。 + +**补充 2**:定理的逆定理关于输入串的简化的那一部分成立。原因是输入串被消耗后没法重新添加回去。 + +**定理**:如果 $P = (Q, \Sigma, \Gamma, \delta, q_0, Z_0, F)$ 是一个 PDA,并且 $(q, xw, \alpha) \vdash_P^* (p, yw, \beta)$,那么对于所有 $\Sigma^*$ 中的串 $w$ 和 $\Gamma^*$ 中的串 $\beta$ 都有有 $(q, x, \alpha) \vdash_P^* (p, y, \beta)$。 + +### 下推自动机的语言 + +#### 以终结状态方式接受 + +设 $P = (Q, \Sigma, \Gamma, \delta, q_0, Z_0, F)$ 是一个 PDA,那么 $P$ **以终结状态方式接受的语言** $L(P)$ 是: +$$ +\{w | (q_0, w, Z_0) \vdash_P^* (q, \varepsilon, \alpha)\} +$$ +其中 $q \in F$ 为某个接受状态,$\alpha \in \Gamma^*$ 是任何堆栈符号串。 + +也就是说,以 $w$ 为等待输入的串从初始状态 $q_0$ 出发,消耗完了 $w$ 后进入了接受状态,**无论此时堆栈中的状态如何**。 + +#### 以空栈方式接受 + +设 $P = (Q, \Sigma, \Gamma, \delta, q_0, Z_0, F)$ 是一个 PDA,我们定义 $P$ **以空栈方式接受的语言** $N(P)$ 是 +$$ +N(P) = \{w | (q_0, w, Z_0) \vdash_P^* (q, \varepsilon, \varepsilon)\} +$$ +其中 $q \in Q$ 为**任意状态**。 + +也就是说,$N(P)$ 中的元素 $w$ 能在被 $P$ 消耗完的同时使堆栈为空。事实上,由于我们只关心堆栈是否为空而不关心接受状态,故我们可以去掉 PDA $P$ 的描述中的最后一个分量,而写成一个六元组 $(Q, \Sigma, \Gamma, \delta, q_0, Z_0)$。 + +#### 两种接受方式的等价性 + +##### 从空栈方式到终结状态方式 + +```mermaid +graph LR +style Start fill:none,stroke:none + +Start --> A(($p_0$)) +A --> | $\varepsilon, X_0/Z_0X_0$ | B(($q_0$)) + +subgraph $P_N$ +B -.- C((" ")) +B -.- D((" ")) +B -.- E((" ")) +end +B --> | $\varepsilon, X_0/\varepsilon$ | F((($p$))) +C --> | $\varepsilon, X_0/\varepsilon$ | F((($p$))) +D --> | $\varepsilon, X_0/\varepsilon$ | F +E --> | $\varepsilon, X_0/\varepsilon$ | F +``` + +构造初始状态 $p_0$,并且在堆栈中初始状态下压入不属于 $\Gamma$ 的符号 $X_0$。这样,在 $P_F$ 中不会弹出 $X_0$;且如果栈顶为 $X_0$,则说明此时 $P_F$ 的栈为空,因此 $P_F$ 接受该状态。在 $P_N$ 中,不仅包含所有 $P_F$ 中的转移,还要加上 $Q$ 中的任意状态 $q$,对 $P_F$ 的唯一接受状态 $p$ 的 $\varepsilon$ 转移:这样当 $P_F$ 中堆栈为空时,$P_N$ 能经过这条 $\varepsilon$ 转移边,弹出栈顶的标记符号 $X_0$,使得$P_N$ 能接受该状态。 + +$P_F$ 保证了,在$P_N$ 中使栈为空的输入串 $w$,才会使得栈顶为标记符号 $X_0$,然后经过 $\varepsilon$ 转移将 $X_0$ 弹出,转移到接受状态 $p$ 被 $P_F$ 接受;而无法使 $P_N$ 中栈为空的串 $w$,一定无法使栈底的 $X_0$ 被暴露出来,从而也不会经过 $\varepsilon$ 转移将 $X_0$ 弹出,转移到接受状态 $p$ 被 $P_F$ 接受。 + +##### 从终结状态方式到空栈方式 + +```mermaid +graph LR +style Start fill:none,stroke:none + +Start --> A(($p_0$)) +A --> | $\varepsilon, X_0/Z_0X_0$ | B(($q_0$)) + +subgraph $P_F$ +B -.- C(((" "))) +B -.- D(((" "))) +end + +C --> | $\varepsilon, any/\varepsilon$ | E(($p$)) +D --> | $\varepsilon, any/\varepsilon$ | E +E --> | $\varepsilon, any/\varepsilon$ | E +``` + +构造初始状态 $p_0$,并且在堆栈中初始状态下压入不属于 $\Gamma$ 的符号 $X_0$。这是为了防止在 $P_F$ 中出现栈被清空但又不是接受状态的情况。在 $P_F$ 中,不仅包含所有 $P_N$ 中的转移,还要加上 $P_F$ 的所有接受状态 $q$,对 $p$ 的 $\varepsilon$ 转移:这个 $\varepsilon$ 转移清空栈上的所有东西,使得输入串能够以空栈方式被接受。 + +$P_N$ 保证了,能在 $P_F$ 中达到接受状态的串 $w$,在达到接受状态后一定能将栈清空被空栈方式接受;而未达到接受状态的串,在转移过程中栈底一定有标记符号 $X_0$ 未被弹出,而不会被空栈方式接受。 + +### PDA 和 CFG 的等价性 + +#### 由 CFG 得 PDA + +考虑这个 CFG 的最左推导。构造一个 PDA,使得每一次推导的过程都是弹出栈顶上的非终结符(产生式的头),然后以产生式的体代替。此后,如果栈顶为终结符,则不断弹出直至暴露出第一个非终结符。继续上述过程直至栈被清空,以空栈方式接受。 + +形式化地,设 $G = (V, T, Q, S)$ 是一个 CFG,构造以空栈方式接受 $L(G)$ 的 PDA $P$ 如下: +$$ +P = (\{q\}, T, V \cup T, \delta, q, S) +$$ +其中转移函数 $\delta$ 的定义是: + +1. 对于每一个非终结符 $A$, + $$ + \delta(q, \varepsilon, A) = \{(q, \beta) | A \to \beta \text{ 是 } G \text{ 的一个产生式}\} + $$ + 这对应着弹出栈顶的产生式的头并以产生式的体代替的过程。 + +2. 对于每一个终结符 $a$, + $$ + \delta(q, a, a) = \{(q, \varepsilon)\} + $$ + 这对应着将栈顶的终结符不断弹出的过程。 + +#### 由 PDA 得 CFG + +![Y-x 图](https://img.picgo.net/2023/10/11/Y-x-graph9050a03d07a8b78a.jpeg) + +如图所示,从堆栈中弹出一系列的符号 $Y_1, Y_2, \cdots, Y_k$。当弹出 $Y_1$ 时读入了某个输入 $x_1$。应该注意的是这里的“弹出”实际上是许多移动的 **净效应**。例如,第一步移动也许会把 $Y$ 变为其他的符号 $Z$,接下来的移动也许会用 $UV$ 来替换 $Z$,后面的一些移动的效应是弹出了 $U$,再后面的一些动作的效应是弹出了 $V$。所有这些移动的净效应是把 $Y$ 用空来替换,即把它弹出,而在这个过程中所消耗的输入就是 $x_1$。这样的计算会不断继续下去,直到堆栈中的每一个符号都被去掉为止。 + +设 $P = (Q, \Sigma, \Gamma, \delta, q_0, Z_0)$ 是一个 PDA,构造 CFG $G = (V, \Sigma, R, S)$ 满足 $L(G) = N(P)$。其中非终结符的集合 $V$ 包含: + +1. 特殊的符号 $S$ 表示初始符号。 + +2. 所有 $[pXq]$ 形式的符号,其中 $p$ 和 $q$ 是 $Q$ 中的状态,$X$ 是 $\Gamma$ 中的堆栈符号。 + +$G$ 的产生式的集合 $R$ 如下: + +- 对于每个状态 $p$,$G$ 都有产生式 $S \to [q_0Z_0p]$。 + + 考虑 $w = [q_0Z_0p]$ 的作用,它将栈底 $Z_0$ 弹出,说明此时栈被清空,并且从状态 $q_0$ 转到状态 $p$。因此,初始符号 $S$ 生成所有导致 $P$ 在初始瞬时状态出发之后能进入空栈状态的串 $w$。 + + 为什么对于 $S$ 来说,要考虑所有的 $p$?这是因为 PDA 以空栈方式接受,可能到达任意状态,必须列举所有状态。 + +- 令 $\delta(q, a, X)$ 包含有序对 $(r_0, Y_1Y_2\cdots Y_k)$,其中: + + 1. $a$ 是 $\Sigma$ 中的一个符号,或者 $a = \varepsilon$。 + + 2. $k$ 可以是任何数。包括 $0$,此时 $(r_0, Y_1Y_2\cdots Y_k) = (r_0, \varepsilon)$。 + + 那么对 **所有的** 序列 $r_1, r_2, \cdots, r_k$,$G$ 都有产生式 + $$ + [q X r_k] \to a[r_0 Y_1 r_1][r_1Y_2r_3]\cdots[r_{k-1}Y_kr_k] + $$ + 这样的产生式有 $n^k$ 个。它的意思是,在栈顶弹出 $X$ 并且从 $q$ 转移到 $r_k$ 的一种方法是:读入 $a$ 并把状态转移到 $r$;接着通过消耗某个输入从堆栈中弹出 $Y_1$,同时从状态 $r$ 转移到状态 $r_1$;然后读入另一个输入来从堆栈中弹出 $Y_2$,同时从状态 $r_1$ 转到状态 $r_2$;依此类推。 + +### 确定性下推自动机(DPDA) + +![几类语言模型的计算能力对比](https://img.picgo.net/2023/10/11/models73ebb5a7a410ebe8.jpeg) + +#### 正则语言与 DPDA + +**定理**:如果 $L$ 是正则语言,则对于某个 DPDA $P$ 有 $L = L(P)$。 + +这就是显然的,因为 DFA 是一个没有使用堆栈的 DPDA。我们只需要额外设计一个初始状态来压入标记符号 $X_0$,一个 $\varepsilon$ 转移来弹出 $X_0$ 并连接 DFA 的接受状态和 DPDA 的接受状态即可。 + +另外,语言 $L$ 是某个 DPDA $P$ 的 $N(P)$ 当且仅当 $L$ 有 **前缀性质** 且 $L$ 是某个 DPDA $P'$ 的 $L(P')$。前缀性质是指 $L$ 中不存在不相等的两个串 $w_1, w_2$ 使得 $w_1$ 是 $w_2$ 的前缀。 + +#### 上下文无关语言与 DPDA + +**定理**:DPDA 以终结状态方式接受的语言 **真包含于** CFL。 + +例如 $L_{wwr}$,DPDA 为了判断是否回文,需要将串的对称部分的前半部分存放在栈里,然后对后半部分进行比较。**比较完一个回文串后一定会使栈清空。** 所以,类似于 $\{0^n10^n0^m10^m | n, m \in \mathbb{N}\}$ 的串,读完第一个回文串 $0^n10^n$ 后栈为空,接着读第二个回文串,读完第二个回文串后 DPDA 并不能确定 $m$ 是否等于 $n$,因为关于第一个回文串的信息都已经被弹出了。 + +#### DPDA 与歧义文法 + +**定理 1**:如果对于某个 DPDA $P$ 有 $L = N(P)$,则 $L$ 有无歧义的 CFG。 + +已经知道 PDA 可以生成一个 CFG,接下来只需要证明该文法的最左推导是唯一的即可。这几乎是显然的,因为 $P$ 是一个 **确定型** 下推自动机,对某个可被接受的串 $w$,$w$ 在上面进行的移动序列是唯一的,所以对应的最左推导也都是唯一的。因此该 CFG 是无歧义的。 + +**定理 2**:如果对于某个 DPDA $P$ 有 $L = L(P)$,则 $L$ 有无歧义的 CFG。 + +在 $L$ 的串的末尾全部加上不在字母表中出现的符号(例如 $\$$)作为终止符。令 $L' = L\$$,显然 $L'$ 具有前缀性质,则存在一个 DPDA $P'$,使得 $L' = N(P')$。由定理 1 知存在一个 CFG $G$,使得 $G$ 能产生 $N(P') = L'$。 + +接下来构造 CFG $G$ 使得 $L(G) = L$。在 $G'$ 中引入产生式 $\$ \to \varepsilon$ 成为 $G$,则 $L(G') = L' \implies L(G) = L$。而且 $G$ 中的最左推导恰好也是 $G'$ 中的最左推导,因为 $\$$ 在串的最右侧,一定是最后一个被替换的变元。 + +### 练习题 + +**习题 1** 构造接受下列语言的一个 PDA:$L = \{w \in \{a, b\}^*| w \text{ 中任何前缀中 } a \text{ 的数量至少 } 2 \text{ 倍于 } b \text{ 的数量}\}$。 + +在设计这道题的 PDA 的时候,一个重要的事情是,如果处理一个 $b$,需要连续弹出两个 $a$。我们可以引入辅助状态,加入 $\varepsilon$ 的转移边来连续弹出两次。 + +![习题 1](https://img.picgo.net/2023/12/22/exercise14611df897a671162.jpeg) + +**习题 2** 构造接受下列语言的一个 PDA:$L = \{w \in \{a, b\}^*| w \text{ 中 } a \text{ 的数量不等于 } b \text{ 的数量}\}$。 + +有的时候并不一定需要空栈接受,虽然空栈接受可能是更直观的“停止”的状态。因此,最后只要有剩余的 $X$ 或 $Y$ 作为栈顶符号,只需要弹出一个,即可转入终结状态(而非继续把栈中所有符号全部弹出,然后空栈接受)。 + +![习题 2](https://img.picgo.net/2023/12/22/exercise284b4b6bc4b733428.jpeg) + +**习题 3** 构造接受下列语言的一个 PDA:$L = \{w \in \{a, b\}^*| w \text{ 中 } a \text{ 的数量是 } b \text{ 的 } 2 \text{ 倍}\}$。 + +要么可以类似于习题 1 中的策略,引入一些辅助状态;而我选择添加栈中符号 $C$ 表示“半个 $B$”。转移表如下: +$$ +\begin{aligned} +a,& Z_0/AZ_0 & b,& Z_0/BZ_0 \\ +a,& A/AA & b,& A/C \\ +a,& B/C & b,& B/BB \\ +a,& C/\varepsilon & b,& C/CB\\ +\end{aligned} +$$ +其中 $b,C/CB$ 是为了让“半个 $B$”一直处于栈顶,这样就避免了栈中同时出现两个“半个 $B$”的情况。 + +本文主要包括以下内容: + +## 第七章 上下文无关语言的性质 + +### 上下文无关文法的范式 + +#### 去除无用的符号 + +**先去除不产生的符号,再去除不可达的符号。**不能以相反的顺序执行这两个操作,否则会保留一些不可达的非终结符,即使它们是产生的。 + +例:考虑文法 +$$ +\begin{aligned} +S &\to AB | a \\ +A &\to b +\end{aligned} +$$ +正确的做法是先去除不产生的 $B$ 导致的 $S \to AB$,再去除不可达的 $A$ 导致的 $A \to b$。这样只剩下了 $S \to a$。 + +错误的做法会导致在第一步检查时,没有不可达的符号;在第二步中仅去除了含有不产生的 $B$ 的产生式 $S \to AB$。此时仍然有冗余的 $A \to b$。 + +一个 CFG 类似于一个由产生式构建而成的森林,“去除不产生的符号”等价于切断为非终结符的叶节点及其父节点、父节点及其祖父节点……之间的边,“去除不可达的符号”等价于仅保留以 $S$ 为根的树。 + +由于“去除不产生的符号”在切断边的过程中,会产生新的树,而这些树的根节点不一定为 $S$,所以需要先去除不产生的符号,再去除不可达的符号。 + +#### 去除 $\varepsilon$ 产生式 + +定义可空符号: + +**基础**:如果 $A \to \varepsilon$ 是一个 $G$ 的产生式,那么 $A$ 是可空的。 + +**归纳**:如果 $B \to C_1C_2\cdots C_k$ 每个 $C_k$ 都是可空的,那么 $B$ 是可空的。 + +对于每个产生式,枚举产生式的体中的可空符号是否为空,产生 $2^n$ 个分支,这样能够去除所有的 $\varepsilon$ 产生式。 + +#### 去除单位式 + +我们需要找到所有满足如下条件的非终结符对 $(A, B)$:只用了一系列单位产生式使得 $A \overset{*}{\implies}B$。注意,**即使使用非单位产生式也可能有 $A \overset{*}{\implies} B$**,例如 $A \to BC, B \to \varepsilon$。 + +定义单位对: + +**基础**:对于任何非终结符 $A$,$(A, A)$ 是单位对。 + +**归纳**:假设 $(A, B)$ 是单位对,$B \to C$ 是产生式,其中 $C$ 是非终结符,则 $(A, C)$ 是单位对。 + +一旦我们确定了所有的这种对,就可以用一个直接从 $A$ 开始使用了非单位产生式 $B_n \to \alpha$ 的产生式 $A \to \alpha$ 来替换任何推导步骤序列 $A \implies B_1 \implies B_2 \implies \cdots \implies B_n \implies \alpha$。 + +#### 乔姆斯基范式(CNF) + +**定义**:任何非空且不含 $\varepsilon$ 的 CFL 都有一种特殊形式的文法 $G$,满足 $G$ 中的所有产生式都属于一下两个简单的形式之一: + +1. $A \to BC$,其中 $A, B, C$ 都是非终结符; +2. $A \to a$,其中 $A$ 是非终结符,$a$ 是终结符。 + +更进一步,$G$ 中没有无用符号。这样的文法称为乔姆斯基范式(CNF)。 + +构造 CNF 的步骤首先包括得到一个不含 $\varepsilon$ 的 CFL。一个可靠的顺序是: + +1. 去除 $\varepsilon$ 产生式; +2. 去除单位产生式; +3. 去除无用符号。 + +在此之后,我们需要改造产生式: + +1. 重新安排产生式,使得体的长度大于等于 $2$ 的产生式的体中只有变元(即 $A \to BC$); +2. 把体的长度大于等于 $3$ 的产生式打断为一组级联的产生式,其中每个产生式的体都只有两个变元。 + +对于步骤 1,如果有一个产生式 $A \to B_1bB_3\cdots B_k$,那么我们把其中的所有终结符拿出来构造一个非终结符产生它,即 $B_2 \to b, A \to B_1B_2B_3 \cdots B_k$,这样体的长度大于等于 $2$ 的产生式的体中只有变元。 + +对于步骤 2,我们可以把 $A \to B_1B_2B_3 \cdots B_k$ 改为 +$$ +\begin{aligned} +A \to& B_1C_1 \\ +C_1 \to& B_2 C_2 \\ +C_2 \to& B_3 C_3 \\ +&\vdots \\ +C_{k-1} \to& B_{k-1}B_k +\end{aligned} +$$ + +### 上下文无关语言的泵引理 + +**定理**:设 $L$ 是一个 CFL,则存在常数 $n$ 满足:如果 $L$ 中的串 $z$ 的长度 $\left|z\right| \ge n$,则可以把 $z$ 写作 $z = uvwxy$,其中: + +1. $\left|vwx\right| \le n$,也就是说,中间的部分不会很长; +2. $vx \neq \varepsilon$,因为 $v$ 和 $x$ 为被“泵”的部分,所以不能均为空串; +3. 对于所有的 $i \ge 0$,$uv^iwx^iy \in L$,也就是说,中间的两个串 $v$ 和 $x$ 可以被重复“泵”任意多次(包括 $0$ 次),所得的串仍然属于 $L$。 + +**证明**:先找到 $L$ 对应的 CNF $G$,得到一个二叉的语法分析树。设 $G$ 有 $m$ 个非终结符,取 $n = 2^m$。假设 $z \in L$ 且长度至少为 $n$。任何产物为 $z$ 的语法分析树都至少有一条长度不少于 $m + 1$ 的路径,因为如果某个语法分析树的最长路径长度仅为 $m$,则它的产物最长只能为 $2^{m-1} = \dfrac{n}{2} < n$。假设有一棵产物为 $z$ 的语法分析树的最长路径长度为 $k \ge m + 1$。由于 $k \ge m$,因此在该路径上至少出现了 $m + 1$ 次非终结符 $A_0, A_1, \cdots, A_k$。但由于 $V$ 中只有 $m$ 种非终结符,所以肯定有两个是同一种非终结符。不妨设 $A_i = A_j = A$,其中 $k - m \le i < j \le k$。注意,由于 $i \ge k -m$,所以这对 $A_i, A_j$ 是该路径上最靠近叶子的满足条件的 $A_i$ 和 $A_j$。 + +于是,我们可以使分别以 $A_i$ 和 $A_j$ 为根的这两棵子树相互替代,从而达到“泵”出 $v$ 和 $x$ 零次或多次的效果。 + +![“泵”出 v 和 x,重复 0 次和 2 次](https://img.picgo.net/2023/10/15/pump80177706fd416192.png) + +### 上下文无关语言的封闭性 + +CFL 在交运算(推论:补运算、差运算)下不封闭。 + +比如 $L_1 = \{0^m1^n2^n | n, m \in \mathbb{N}\}, L_2 = \{0^n1^n2^m | n, m \in \mathbb{N}\}$,则 $L_1 \cap L_2 = \{0^n1^n2^n | n \in \mathbb{N}\}$,但它不是 CFL。 + +但是 CFL 与一个 RE 的交仍然是 CFL,与一个 RE 的补仍然是 CFL。类似于两个 RE 的交,我们可以同步运行一个 PDA 和一个 DFA,来产生能表示二者语言交集的 PDA。 + +### 上下文无关语言的判定性质 + +#### CFG 和 PDA 之间相互转化的时间复杂度 + +从 CFG 到 PDA 的时间复杂度是线性的。这是因为在 [构造 $\delta$ 函数](https://leverimmy.top/2023/09/30/IATLC-Chap6/#由-cfg-得-pda) 时,步骤 1 最多只会额外加入域产生式个数相等的 $\delta$ 转移,步骤 2 最多只会额外加入与终结符个数相等的 $\delta$ 转移。 + +以终结状态方式接受的 PDA 和以空栈方式接受的 PDA 之间,相互转换的时间复杂度都是线性的。 + +比较复杂的是从 PDA 转化为 CFG 的时间复杂度,设 PDA 的状态个数为 $n$。由于单次 $(r_0, Y_1Y_2\cdots Y_k) \in \delta(q, a, X)$ 的转移规则会引出一组 $[qXr_k] \to [r_0Y_1r_1][r_1Y_2r_2]\cdots[r_{k-1}Y_kr_k]$ 的产生式,最坏情况下这组产生式的个数为 $n^n$,所以需要考虑使用别的方法:将所有的转移拆成不多于两个堆栈符号的转移。引入新的状态 $p_2, p_3, \cdots, p_{k-1}$,用 $(p_{k-1}, Y_{k-1}Y_k)$ 代替 $(r_0, Y_1Y_2\cdots Y_k)$,同时引入转移 +$$ +\delta(p_{k-1}, \varepsilon, Y_{k-1}) = \{(p_{k-2}, Y_{k-2}Y_{k-1})\}, \delta(p_{k-2}, \varepsilon, Y_{k-2}) = \{(p_{k-3}, Y_{k-3}Y_{k-2})\} +$$ +直到 $\delta(p_2, \varepsilon, Y_2) = \{(r_0, Y_1Y_2)\}$。 + +我们只引入了 $O(n)$ 个新状态,且由于新的转移规则中堆栈符号个数不多于 $2$,所以产生的产生式的个数为 $O(n^2)$。因此,总的时间复杂度为 $O(n^3)$。 + +#### CFG 变换到 CNF 的时间复杂度 + +- 去除所有的无用符号需要 $O(n)$ 的时间复杂度。 +- 去除所有的单位产生式需要 $O(n^2)$ 的时间复杂度。 +- 用产生式体中的变元来代替终结符需要 $O(n)$ 的时间复杂度,并且额外增加长度为 $O(n)$ 的文法。 +- 把所有产生式的体打断为长度为 $2$ 的体,构造级联的产生式,需要 $O(n)$ 的时间复杂度,并且额外增加长度为 $O(n)$ 的文法。 + +最后来考虑去除 $\varepsilon$ 产生式所需的时间复杂度。如果我们直接对原 CFG 除去 $\varepsilon$ 产生式,那么时间复杂度是 $O(2^n)$ 的,因为我们需要枚举某一条产生式中每个非终结符是否为空,而产生式的体的最大长度为 $O(n)$。但我们可以在 **把所有产生式的体打断为长度为 $2$ 的体之后** 去除 $\varepsilon$ 产生式,因为这样每个产生式枚举的代价仅为 $O(1)$,而总共的产生式的个数为 $O(n)$,这使得该步骤时间复杂度变为 $O(n)$。 + +#### 测试 CFL 的空性 + +对产生式的集合构造一个有向图,图中的每条边由 **产生式的头** 指向 **产生式的体** 中的每个 **非终结符** 和 **终结符**。对这个图进行 DFS: + +- 如果一个非终结符的所有后继都为终结符,那么这个非终结符是产生的。 +- 如果一个非终结符的所有非终结符后继都是产生的,那么这个非终结符也是产生的。 + +最后检查 $S$ 是否为产生的。这个 DFS 的时间复杂度为 $O(n)$,所以可以在线性时间内测试一个 CFL 是否为空。 + +#### 测试 CFL 的成员性:CYK 算法 + +在 CYK 算法中,构造一个三角形的表,如图所示: + +![由 CYK 算法构造的表](https://img.picgo.net/2023/10/15/cyk3b361d265918fbd2.png) + +水平轴对应 $w = a_1 a_2 \cdots a_n$ 中的位置,在图中假定 $\left|w\right| = 5$。表中的项 $X_{ij}$ 是满足 $A \overset{*}{\implies}a_{i}a_{i+1}\cdots a_{j}$ 的变元 $A$ 的集合。最后,我们只需要关心 $S$ 是否属于集合 $X_{1n}$,因为这等价于 $S$ 是否能推导出 $w = a_{1}\cdots a_{n}$。 + +**基础**:对于所有的 $i \in [1, n]$,$X_{ii}$ 是 $G$ 的产生式中满足 $A \to a_i$ 的非终结符 $A$ 的集合。 + +**归纳**:假设想要计算出 $X_{ij}$,**它处于从下往上数第 $j - i + 1$ 行**,这是因为 $X_{ii}$ 位于第 $1$ 行。本质上 $X_{ij}$ 所位于的行数,就是它能推导出的串的长度。假设已知它下面所有行的 $X_{i'j'}$,即已知所有长度小于 $j - i + 1$ 的串能由哪些非终结符推导而出。考虑 $A \overset{*}{\implies}a_{i}a_{i+1}\cdots a_{j}$。它一定能被分为 $A \implies BC$,其中 $B \overset{*}{\implies}a_{i}a_{i+1}\cdots a_{k}$,$C \overset{*}{\implies}a_{k+1}a_{k+2}\cdots a_{j}$,且 $i \le k < j$。因此,我们可以枚举 $k$,找到所有满足条件的 $B$ 和 $C$,再检查这样的组合 $BC$ 是否能被 $A$ 产生。 + +状态个数为 $O(n^2)$,枚举 $k$ 进行状态转移的时间复杂度为 $O(n)$,因此这个算法的时间复杂度为 $O(n^3)$。 + +#### 不可判定的 CFL 问题 + +1. 某个给定的 CFG $G$ 是歧义的吗? +2. 某个给定的 CFL $L$ 是固有歧义的吗? +3. 两个 CFL 的交为空吗? +4. 两个 CFL 相同吗? +5. 某个给定的 CFL 等于 $\Sigma^*$ 吗?其中 $\Sigma$ 是该语言的字母表。 + +### 练习题 + +**习题 1** 用 CFL 泵引理来证明下面的语言都不是上下文无关的:$\{ww^Rw | w \in \{0, 1\}^*\}$。 + +考虑 $z = uvwxy = 0^n1^n1^n0^n0^n1^n$,则 $vwx$ 不能完全含于某个 $0^n$ 或 $1^n$ 里(否则找不到可以“对折”的两个“折痕”),因此肯定跨过一个分界线,为 $0^n1^n$ 或 $1^n0^n$。不妨考虑前者,且为 $z$ 的开头,则 $v$ 和 $x$ 一定是“纯色”的 $0^t$ 和 $1^r$,否则会导致有更多相间的 $0101\cdots$ 出现,不满足 $ww^Rw$ 的样式。考虑 $uv^{k+1}wx^{k+1}y = 0^{n+kt}1^{n+kr}1^n0^n0^n1^n$ 不满足 $ww^Rw$ 的样式。因此该语言不为 CFL。 diff --git "a/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\350\256\241\347\256\227\346\234\272\347\247\221\345\255\246\346\246\202\350\256\272.md" "b/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\350\256\241\347\256\227\346\234\272\347\247\221\345\255\246\346\246\202\350\256\272.md" new file mode 100644 index 0000000..75d5c2c --- /dev/null +++ "b/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\350\256\241\347\256\227\346\234\272\347\247\221\345\255\246\346\246\202\350\256\272.md" @@ -0,0 +1,228 @@ +--- +title: 【学习笔记】计算机科学概论 +tags: + - 计算机科学概论 +categories: + - 笔记 +mathjax: true +toc: true +date: 2023-07-20 19:39:27 +password: +id: CSAO +--- + +这是《计算机科学概论(原书第13版)》的学习笔记,本文主要包括以下内容: + +**第一章 数据存储** + +- 逻辑门 +- C 中的字符常量 +- 二进制中的补码与余码 + - 补码记数法 + - 余码记数法 + +**第十二章 计算理论** + +- 可计算性 +- Bare Bones 语言 + - 复制操作 + - 交换操作 + - 分支结构 +- 停机问题 +- RSA + + + +## 第一章 数据存储 + +### 逻辑门 + +![逻辑门](https://img.picgo.net/2023/07/21/logic-gatesb7ebe6a28e57870c.png) + +这八个基础的逻辑门的符号需要记清楚。记忆的技巧也很简单,`N` 就是右侧加一个小圆圈,`X` 就是左侧加一条线。“与”和“或”的符号我总是弄混淆,后来问了一下 skyhappy,他跟我讲: + +> 我是这么记的,看输出端 +> 如果是与运算,就得有容乃大,所以开口得胖一点 +> 或运算就不需要了,所以窄一点就好了 + +我觉得很有道理。 + +~~于是联想到了一个经典Stack Overflow 笑话——[在 C# 语言中如何实现“同或 (XNOR) ”操作](https://stackoverflow.com/questions/7054124/is-there-an-xnor-logical-biconditional-operator-in-c)~~ + +### C 中的字符常量 + +在大一下学期学习《计算机程序设计基础》这门课的时候,老师上课说有同学将一个字符串定义成 `char str = '123';`,虽然 **他通过了编译**,但这是错误的。 + +关注的重点在于 **他通过了编译**,于是我上网查找了一下“单引号内如果包含多个字符为什么会编译成功”。 + +在 C/C++ 中,一个 `int` 类型占用的空间是 32 bit,即 4 个 byte。一个 `char` 类型占用的空间是 8 bit,即 1 个 byte。所以 `'` 内一共可以最多包含 4 个字符,它会被看做成一个 `int` 类型的常量。其实就是四个 `char` 并排组在一起就成为了一个 `int`。 + +例如,`('1' << 8) + '2'` 和 `'12'` 是一模一样的,均为 `(int)12594`。 + +如果 `'` 内字符大于或等于 2 个,编译器会警告: + +``` +warning: multi-character character constant [-Wmultichar] +``` + +如果大于或等于 5 个,编译器会警告: + +``` +warning: character constant too long for its type +``` + +### 二进制中的补码与余码 + +#### 补码记数法 + +在补码记数法中,一个 **有符号整数** 用一个 32 bit 二进制串来表示,其中最左侧被称为“最高位”,最右侧被称为“最低位”。最高位表示 $-2^{31}$,其余各位分别表示 $2^{30}, \cdots, 2^1, 2^0$。因此一个 32 bit 二进制串的表示范围为 $[-2^{31}, 2^{31}-1]$。 + +一个通过补码记数法记录的整数,通过“按位取反再加一”的方式可以得到自己的相反数。 + +#### 余码记数法 + +在余码记数法中,“0”被定义为最高位为 1,其余位均为 0 的数。这个数在所有 32 bit 二进制串中恰好排在“差不多”中间的位置。比它大的数即为正数,比它小的数即为负数。 + +余码记数法和补码记数法的唯一区别是最高位的值相反。 + +## 第十二章 计算理论 + +### 可计算性 + +一个函数,如果依据输入,通过算法,可以确定输出值,则它被称为 **可计算的**。事实上,存在那么一些函数,它们过于复杂以致找不到定义明确的、有限步骤的过程来根据输入确定输出。这样的函数计算超出了任何算法系统的能力范围,它们是 **不可计算的**。 + +一个函数是否可计算是非常重要的。如果确定了一个问题(以及数学建模后对应的函数)是不可计算的,那么人们就可以不必花更多精力研究如何用计算机来解决它,而是求助于其他更有效的方法。 + +### Bare Bones 语言 + +一个通用程序设计语言。 + +- 一种基本数据类型。 + + 所有的变量本质上都是二进制数。 + +- 三条赋值语句。 + + `clear name` 表示把 `name` 清零。 + `incr name` 表示使 `name` 自增 1。 + `decr name` 表示使 `name` 自减 1。 + +- 一条控制结构语句。 + + `while name not 0:` 在 `name` 不为 0 的时候,会一直做下方缩进的语句或语句序列(和 Python 类似)。 + +> **定理**:Bare Bones 语言能够用来表达计算所有图灵可计算函数的算法。 + +复制操作、交换操作、分支结构等特性都可以使用 Bare Bones 语言实现。 + +#### 复制操作 + +``` +while x not 0: + incr z +while z not 0: + incr x + incr y +``` + +这样就通过辅助变量 `z` 完成了 `y = x` 的复制操作。我们将其简写为 `copy x to y`。 + +#### 交换操作 + +既然能够完成复制操作,那么也一定能够完成交换操作。 + +#### 分支结构 + +我们现在想实现类似 + +``` +if x: + // ... do sth1 +else: + // ... do sth2 +``` + +的结构。 + +``` +copy x to z +clear w +incr w +while z not 0: + // do sth1 + clear z + decr w +while w not 0: + // do sth 2 +``` + +以上代码可以实现这样的 `if-else` 分支结构。 + +### 停机问题 + +如果程序中所有的变量都是用程序自身的编码表示(把字符全部转为二进制串)来进行初始化的,且这个程序在有限步骤后能够停止,则称这个 Bare Bones 程序是 **自终止的**。 + +停机问题指的是,是否存在一个算法,能够判断一个 Bare Bones 程序是否是自终止的。 + +答案是不存在。证明停机问题不可解,采取的方式是反证法。 + +假设有一个 Bare Bones 程序 `A`,它接受的输入是一段 Bare Bones 程序 `test`,产生的输出是 `test` 是否是自终止的:若是自终止的,则输出 `1`;若不是自终止的,则输出 `0`。 + +假设把 `A` 所得输出放入变量 `x`。考虑在 `A` 后添加 + +``` +// A... +// x = output +while x not 0: +``` + +我们称这个新的程序为 `B`。接下来我们要证明 `B` 既不是自终止的,也不是非自终止的,以此推导出矛盾。 + +- 若 `B` 是自终止的: + + 将 `B` 作为自己的输入,则 `x` 为 1。此时进入 `while` 死循环,则 `B` 不是自终止的。矛盾。 + +- 若 `B` 是非自终止的: + + 将 `B` 作为自己的输入,则 `x` 为 0。此时不进入 `while` 循环,则 `B` 是自终止的。矛盾。 + +所以,如果停机问题可解,也就是说,存在一个程序 `A`,使得它能判断一段 Bare Bones 程序是否是自终止的,那么我们就可以构造出一个矛盾的程序 `B`。因此停机问题不可解。 + +### RSA + +RSA 是一种经典的公钥加密系统,被广泛应用于加密信息传递。~~尤其是树洞上的信息加密。~~ + +#### RSA 密钥的生成与分发 + +> $\lambda(n)$ 为 [Carmichael function](https://en.wikipedia.org/wiki/Carmichael_function),是指最小的正整数 $m$,满足对于所有的与 $n$ 互质的 $a$,均有 $a^{m} \equiv 1 \pmod n$。 + +1. 选择两个大质数 $p, q$,记 $n = pq$。 +2. 计算 $\lambda(n) = \mathrm{lcm}(p - 1, q - 1)$。 +3. 选择一个 $e$ 使得 $e$ 与 $\lambda(n)$ 互质。 +4. 计算 $d$ 满足 $d \equiv e^{-1} \pmod{\lambda(n)}$。 + +$n, e$ 作为公钥,$d$ 作为密钥。 + +#### RSA 的加密与解密 + +由于所有的运算都会对 $n$ 取模,所以一个很自然的要求是明文 $m$ 的长度小于 $n$。 + +- 加密:密文 $c \equiv m^e \pmod n$ + +- 解密:明文 $m \equiv m^{de} \equiv c^d \pmod n$ + +#### RSA 的正确性 + +只需要证明 $m \equiv m^{de} \pmod {pq}$ 即可,更简化地说,只需要证明 $m \equiv m^{de} \pmod p$ 即可,对 $q$ 同理。 + +由于 $de \equiv 1 \pmod {\lambda(pq)}$,而 $\lambda(pq) = (p - 1)(q - 1)$。所以不妨记 $de - 1 = h(p - 1) = k(q - 1)$。 + +1. 若 $m \equiv 0 \pmod p$,则 $m^{ed} \equiv 0 \equiv m \pmod p$。 +2. 若 $m \not\equiv 0 \pmod p$,则由费马小定理 $m^{p-1} \equiv 1 \pmod p$。 + +$$ + m^{de} \equiv m^{1 + h(p - 1)} \equiv m \cdot (m^{p-1})^h \equiv m \cdot 1^{h} \equiv m \pmod p +$$ + +因此命题得证。 + diff --git "a/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\350\275\257\344\273\266\345\267\245\347\250\213-1.md" "b/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\350\275\257\344\273\266\345\267\245\347\250\213-1.md" new file mode 100644 index 0000000..e9c7bb8 --- /dev/null +++ "b/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\350\275\257\344\273\266\345\267\245\347\250\213-1.md" @@ -0,0 +1,586 @@ +--- +title: 【学习笔记】软件工程(1) +tags: + - 软件工程 +categories: + - 笔记 +mathjax: true +toc: true +date: 2024-04-20 15:10:11 +password: +id: SE_1 +--- + +这是清华大学计算机系春季课程《软件工程》期中考试复习笔记。 + + + +## 前端 + +### Typescript 初探 + +- `const` 和 `let` 的区别 + - 前者为常量,后者为变量 +- `==`、`!=`、`===` 和 `!==` + - 前两者会进行隐式转换,例如 `1 == true` 为真 + - 应尽量使用后两者 +- `forEach`、`map` 和 `filter` + - `arr.forEach((val, ind) => { })`,`val` 是值,`ind` 是下标 + - `arr.map(val => val * val)`,得到一个新的数组,其中每个元素为 `arr` 中对应下标元素的平方 + - `arr.filter(val => val % 2 == 0)`,得到一个新的数组,其中仅含偶数 + +### Next.js 路由 + +#### 基于文件系统的路由 + +``` +src +└── pages + ├── _app.tsx // 入口文件 + ├── index.tsx // / + ├── login.tsx // /login + └── list + ├── index.tsx // /list + ├── detail.tsx // /list/detail + └── edit.tsx // /list/edit +``` + +#### `useRouter` Hook + +**捕获路由参数**:`router.query.aaa` 对应着 `/list?aaa=bbb` 里的 `aaa` 字段,值为 `bbb`。 + +**实现页面跳转**:`router.push("/")` 和 `router.back()`。 + +### 副作用与网络请求 + +将耗时的数据获取操作从渲染本身中分离出来,这就是所谓的**副作用**。 + +#### `useEffect` Hook + +```typescript +useEffect(() => { + // 需要执行的副作用 + return () => { + // 副作用的清除 + }; +}, dependentList); // 依赖列表 +``` + +`dependentList` 是一个数组,用于控制副作用何时被触发: + +- 如果 `dependentList` 是 `undefined`,则副作用会在**每次渲染**时触发 +- 如果 `dependentList` 是空数组 `[]`,则副作用只会在**第一次渲染**时触发 +- 如果 `dependentList` 不为空,则副作用会在**第一次渲染**和 `dependentList` 中的变量**发生变化**时触发 + +#### 异步 + +声明为 `async` 的函数在调用时会**立即返回**,其函数体内容会在后台执行。 + +在一个异步函数的调用前面加上 `await` 关键字会**阻塞当前代码**,直到异步任务完成或报错。 + +因为 `await` 有阻塞代码执行的性质,所以**仅可以在异步函数体内使用**。 + +```typescript +request("/api/", "GET", false) + .then((res) => { + // ... + return {}; + }) + .then((res) => { + // ... + return {}; + }) + .catch((err) => { + // ... + }) + .finally(() => {}); +``` + +## 后端 + +### Git 的使用 + +#### 基本概念 + +- 工作区:工作目录(你的代码所在的文件夹); +- 暂存区:临时的缓存(做一个临时的标记) +- 分支:将暂存区中的内容提交到分支(做一次完整的记录) + +#### main(master), HEAD + +- main +- HEAD:指向工作区当前位置 commit 的指针,通常指向当前所在分支的最新的 commit + +#### commit, merge + +- commit:一次提交,每次 `git commit` 指令都会产生一个提交,该提交用一个独一无二的哈希值代表,伴随提交信息 +- merge:合并指定分支到当前分支 + - Fast-Forward + - 直接移动指针 + - Three-Way Merge + - 考虑两次提交的最近公共祖先,这样就能看出差异点是由谁修改而成的,进而自动合并 + - Squash & Merge + - 压缩分支的所有提交为一次 + +#### push, pull, fetch + +- push:提交到远程仓库 +- fetch:拉取远程仓库 +- pull:拉取远程仓库并合并(=fetch+merge) + +### 前后端交互中的鉴权问题 + +JWT(JSON Web Token)是一种开放标准(RFC 7519),用于安全地在两方之间传递信息作为 JSON 对象。 + +它可以用于身份验证和信息交换,提供了一种简洁的、自包含的方法用于在各方之间传递信息。 + +#### JWT 的结构 + +JWT 由三部分构成,并用 `.` 进行分割:`header.payload.signature`。 + +- **header** + - 通常由两部分构成:令牌类型 `typ` 和加密算法 `alg` + - 格式如下: + ```json + { + "alg": "HW256", + "typ": "JWT" + } + ``` + - 然后用 base64 编码 +- **payload** + - 载荷包含 JWT 的主要信息,比如用户的标识、令牌的签发时间等。 + - 可以包含多个预定义的字段,也可以包含自定义的字段。 + - 格式如下: + ```json + { + "sub": "1234567890", + "name": "John Doe", + "iat": 1516239022 + } + ``` + - 然后用 base64 编码 +- **signature** + - 签名用于验证消息的发送者身份并确保消息在传输过程中未被篡改。 + - 签名是通过对头部和载荷进行加密算法处理,并使用秘钥来生成。 + +#### 使用场景 + +- 身份验证 + - JWT 是进行身份验证的一种常见方法。当用户登录后,每个后续请求将包括 JWT,允许用户访问该令牌允许的路由、服务和资源 +- 信息交换 + - JWT 是安全地在各方之间传输信息的好方法,因为可以验证每一部分的签名 + +## 敏捷开发 + +软件项目的“不可能三角”:同一个项目,在团队、效能水平一定的情况下,范围、时间、成本,三者只能取其二。 + +### 瀑布模型 + +```mermaid +graph LR +A(Requirement) --> B(Design) +B --> C(Coding) +C --> D(Testing) +D --> E(Maintenance) +A <---> B +B <---> C +C <---> D +D <---> E +``` + +在每一步骤完成之后才开始下一步骤。 + +**原因**:越早找到 bug,修复它的成本就越低。 + +**问题**: + +- 软件的优势在于它能够快速修改(change)和适应(adapt);但瀑布模型无法做到这一点 +- 每个步骤用时很长,遇到问题时需要回溯到上一个步骤 + +### 敏捷开发的原则与特点 + +- Adaptive rather than predictive + - 不要一开始就计划项目的绝大部分;应该增强软件开发的可修改性 +- People-oriented rather than process-oriented + - 合作共赢,享受合作开发的过程,利用人性;而非与其作对 + +#### 12 条原则 + +1. Our highest priority is to satisfy the customer through the early and continuous delivery of valuable software. +2. Welcome changing requirements, even late in development. Agile processes harness change for the customer’s competitive advantage. +3. Deliver working software frequently, from a couple of weeks to a couple of months, with a preference to the shorter timescale. +4. Business people and developers must work together daily throughout the project. +5. Build projects around motivated individuals. Give them the environment and support they need, and trust them to get the job done. +6. The most efficient and effective method of conveying information to and within a development team is face-to-face conversation. +7. Working software is the primary measure of progress. +8. Agile processes promote sustainable development. The sponsors, developers, and users should be able to maintain a constant pace indefinitely. +9. Continuous attention to technical excellence and good design enhances agility. +10. Simplicity–the art of maximizing the amount of work not done–is essential. +11. The best architectures, requirements, and designs emerge from self-organizing teams. +12. At regular intervals, the team reflects on how to become more effective, then tunes and adjusts its behavior accordingly. + +#### 特点 + +合作共赢(Teamwork);所有人向同一个目标奋斗,没有任何一个个体是独自工作的。 + +### 敏捷开发中的用户故事 + +$$ +\text{Initiative} = n \cdot \text{Epics} = nm \cdot \text{Stories/Tasks} = nml \cdot \text{Subtasks} +$$ + +Stories 通常在 1~2 周内完成,Epic 通常在 1~3 个月内完成,Initiative 通常在 3~12 个月内完成。 + +#### 用户故事表达:卡片 + +**格式**:作为一名 `<角色>`,我可以 `<活动>`,使得 `<业务价值>`。 + +**例子**: + +用户故事卡片:作为一名*消费者*,我希望能够*查看我的日常能源使用量*,从而我可以*降低能源支出和使用率*。 + +验收标准: + +- 每 $10$ 秒钟读取 DecaWatt 计量表的数据,在门户上显示 $15$ 分钟的增量,在室内屏上显示每⼀读数; +- 随着新数据的产⽣读取 KiloWatt 计量表,并且每小时显示在门户上,在每次读取后显示在室内屏上。 + +#### INVEST 原则 + +- Independent(独立性) + - 故事不依赖于其他故事,可以被单独地开发、测试甚至交付。 +- Negotiable(可协商) + - 故事不是详尽的需求说明书(系统应该完成的事),而是可协商的意向表达。 +- Valuable(有价值) + - 聚焦于由用户规定的价值,而非功能分解结构。 +- Estimable(可估算) + - 故事相对而言更容易估算,可以快速确定实现相关功能的工作量。 +- Small(小型) + - 故事代表有价值功能的小型增量,可以在一到两周内交付。 +- Testable(可测试) + - 清晰可测试。 + +### 敏捷开发中的 Scheduling + +关键路径:项目用时的最长路径。 + +### 开发工具与敏捷开发概念的对应 + +| Agile artifact | GitLab feature | +| --------------------: | :--------------------------------- | +| User stories | Issues | +| Task | Task lists | +| Epics | Epics | +| Points and estimation | Issue weights | +| Product backlog | Issue lists and prioritized labels | +| Sprints/iterations | Milestones | +| Burndown charts | Burndown charts | +| Agile board | Issue boards | + +### Release.Version.Revision + +- Release Number:用户角度 +- Version Number:开发者角度 +- Revision Number:开发者角度 + - Change to a version that corrects only errors in the design/code, but does not affect the documented functionality. + +### 版本控制 + +集中式版本控制的问题:每个版本都提交到中心,性能瓶颈,冲突解决 + +分布式版本控制的好处:在本地就可以做跟踪和回滚,大大减少提交的数量,对中心服务器的依赖减少;提升系统工作的性能 + +## 软件测试 + +软件测试就是为程序能够按预期设想运行而建立足够的信心。 + +- Verification(验证):Did you build the thing right? 符合标准了吗? +- Validation(确认):Did you build the right thing? 标准满足用户需求了吗? + +测试用例: + +- 输入数据:交由待测试程序代码进行处理的数据 +- 前置条件:程序处理输入数据的运行上下文,即要满足前置条件 +- 测试步骤:程序代码对输入数据的处理可能涉及到一系列的步骤,其中的某些步骤需要用户的进一步输入 +- 预期输出:程序代码的预期输出结果 + +### Software Quality + +Quality Assurance: Processes/standards to produce product and to improve quality over time. + +Software Quality: + +- Satisfies customers' needs +- Easy for developer to debug and enhance + +### 软件测试方法分类 + +```mermaid +graph LR +A(Testing) --- B(AdHoc) +A --- C(Program Testing) +A --- D(System Testing) +A --- E(Acceptance Testing) +C --- F(Unit Testing) +C --- G(Integration Testing) +F --- H(Black Box) +F --- I(White Box) +H --- J(Equivalence) +H --- K(Boundary) +H --- L(Decision Table) +H --- M(State Transition) +H --- N(Use Case) +H --- O(Domain Analysis) +I --- P(Control Flow) +I --- Q(Data Flow) +G --- R(Top Down) +G --- S(Bottom Up) +G --- T(Big Bang) +G --- U(Sandwich) +D --- V(Function) +D --- W(Properties) +W --- X(Performance) +W --- Y(Relieability) +W --- Z(Availability) +W --- AA(Security) +W --- AB(Usability) +W --- AC(Documentation) +W --- AD(Portability) +W --- AE(Capacity) +E --- AF(Benchmark) +E --- AG(Pilot) +E --- AH(Alpha) +E --- AI(Beta) +``` + +### 软件测试中的错误率恒定定律与规模代价平方定律 + +为了减少错误修复的成本,要尽可能早地发现错误,并在尽量小的范围内定位并修复错误。 + +#### 错误率恒定定律 + +对某一个程序员来说,不考虑其水平的成长,错误产出比在很长一段时间内(项目周期内)是个常数。 + +#### 规模代价平方定律 + +定位并修复一个 bug 所需的代价正比于目标代码规模的平方。 + +> 假设每 $100$ 行有 $10$ 个 bug,则每 $1000$ 行代码有 $100$ 个 bug。 +> +> 假设找 $100$ 行代码中的 $1$ 个 bug 需要 $1$ 小时,则找 $1000$ 行代码中的 $1$ 个 bug 需要 $10^2 = 100$ 小时。 +> +> 找 $1000$ 行代码中的 $50$ 个 bug:$50 \times 100 = 5000$ 小时。 + +### 测试驱动开发(Test Driven Development)循环 + +```mermaid +graph LR +A("1. Write Test") --> B("2. Test Fails") +B --> C("3. Write Code") +C --> D("4. Test passes") +D --> E("5. Refactor") +E --> A +``` + +- Each new feature begins with writing a test. +- 在单测通过之前,不能写生产代码 +- 新的单测写到让现有代码通不过即可 +- 新的生产代码写到让现有单测通过即可 + +TDD uses same skills & techniques as conventional debugging - but more productive. + +Writing tests before code takes more time up-front, but often less time overall. + +### 软件测试的原则(FIRST 原则) + +- Fast: Run (subset of) tests quickly (since you'll be running them all the time). +- Independent: No tests depend on others, so can run any subset in any order. +- Repeatable: Consistent results every run (to isolate bugs and enable automation). +- Self-checking: Test can automatically detect if passed (no human checking of output). +- Timely: Written about the same time as code under test (with TDD, written first!). + +### 白盒测试:控制流测试 + +#### 判定覆盖($C_1$) + +分支整体取值为 `true` 和 `false` 都要覆盖到;如果为 `switch` 语句,则每一个 `case` 都需要被覆盖到。 + +在控制流图中,即为每条边都被遍历到。 + +#### 语句覆盖($C_0$) + +所有语句都要覆盖到。 + +在控制流图中,即为每个点都被遍历到。 + +### 黑盒测试:等价类测试 + +把不可穷举的数据,变成可穷举的类。 + +- 等价类是本质互斥的 +- 等价类中的数据遵循“类似的行为” +- 测试数据由等价类派生而成 + +#### 弱测试和强测试 + +- 弱测试 + - 每行都覆盖到,每列都覆盖到 +- 强测试 + - 每行且每列都覆盖到 +- General Testing + - 只有 valid 的测试点被覆盖到 +- Robust Testing + - 无论 valid 还是 invalid 的测试点都要被覆盖到 + +## 代码风格与重构 + +### 防御式编程的权衡取舍 + +Assume nothing. Unwritten assumptions continually cause faults, particularly as code grows. + +- Encourage programmers to include as many checks as possible + - Check the values of all data from external sources + - Check the values of all input parameters + - Decide how to handle bad inputs + +| AGAINST | FOR | +| ---------------------------: | -------------------------------------------------------- | +| 影响代码运行性能(速度) | 节省了很多调试的时间 | +| 有些防御式编程需要额外的工作 | 速度慢但可靠的代码,比速度快但**有时出错**的代码更有意义 | + +### 代码格式 + +代码是写给编译器、自己、**其他人**看的。 + +Good code does not require a lot of thinking to understand. If the code logic is not clear at the first glance, the code is probably not good enough. + +#### The Big Deal + +- Presentation makes a real impact on the quality of code. +- Programmers read meaning into code based on its layout. + - Good presentation: Illuminate and support your code’s structure, helping reader understand what’s going on. + - Bad presentation: Confuse, mislead, and hide the code's intent. +- Bad formatting not only makes code harder to follow; it may actually hide bugs from you. + +#### Good Presentation + +- Consistent + - Keep the style consistent across the project. +- Conventional + - To adopt one of the major styles currently in use in the industry rather than invent your own rules. +- Concise + - Easy to follow and pick up. + +### 命名规范 + +#### 要求 + +Accurate and easy-to-understand + +**命名的作用**: + +- Identity +- Behavior + - Roles, relationships, and interactions +- Recognition + - Elevate something from ethereal concept to well-defined reality + +**如何命名**: + +- Descriptive +- Technically correct +- Idiomatic +- Appropriate + +**禁止**: + +- Cryptic +- Verbose +- Inaccurate or misleading +- Ambiguous or vague + +#### 好处 + +People naturally read the meaning out of something based on its name. + +From the viewpoint of the use, hiding all the internal implementation. + +### 自文档代码 + +#### 要求 + +- Write simple code with good presentation + - Avoid too many nested statements + - Be wary of optimizing code so that it's no longer a clear expression of a basic algorithm. + - Never optimize code unless you've proved that it is a bottleneck to acceptable program function. +- Decompose into atomic functions +- Group related information +- Emphasize important code +- Choose meaningful names +- Choose descriptive types +- Name constants + - Avoid magic numbers. + +#### 好处 + +The only document that describes your code completely and correctly is the code itself. + +Even the smallest, most beautiful functions will need later maintenance. + +### 注释规范 + +#### 要求 + +We need to focus on comment quality, not quantity, so more important than the amount of comments we write are the contents of those comments. + +- Explain 'why', not 'how' +- Don't describe the code +- Don't replace the code +- Keep it useful + - Document the unexpected + - Tell the truth + - Are worthwhile + - Are clear + +#### 好处 + +Describe the intent of the code. + +Summarize the whole block of code. + +### 代码气味 + +- Continuous inspection +- Health + - Duplicated code + - Coding standards + - Code complexity + - Comments + - Bugs + - Security vulnerabilities + +#### ABC Complexity + +Assignments, Branches, Conditions. +$$ +\sqrt{A^2 + B^2 + C^2} \le 20 \quad(\text{per method}) +$$ + +#### 圈复杂度 + +Edge, Vertex, Decision, Region +$$ +\text{Cycle Complexity} = |E| - |V| + 2 = |D| + 1 = |R| +$$ + +### 代码重构的定义 + +A software transformation that + +- Preserves the external software behavior +- Improves the internal software structure + +Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior. + +- To enhance some non-functional quality – simplicity, flexibility, understandability, performance +- Its heart is a series of small behavior-preserving transformations. The system is kept fully working after each refactoring diff --git "a/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\350\275\257\344\273\266\345\267\245\347\250\213-2.md" "b/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\350\275\257\344\273\266\345\267\245\347\250\213-2.md" new file mode 100644 index 0000000..a189b7c --- /dev/null +++ "b/source/_posts/\343\200\220\345\255\246\344\271\240\347\254\224\350\256\260\343\200\221\350\275\257\344\273\266\345\267\245\347\250\213-2.md" @@ -0,0 +1,714 @@ +--- +title: 【学习笔记】软件工程(2) +tags: + - 软件工程 +categories: + - 笔记 +mathjax: true +toc: true +date: 2024-06-07 11:10:11 +password: +id: SE_2 +--- + +这是清华大学计算机系春季课程《软件工程》期末考试复习笔记。 + + + +## 软件架构 + +### 大型网站架构的演化发展历程 + +```mermaid +graph TD + +A(初始阶段) --> B(应用服务和数据服务分离) +B --> C(使用缓存改善网站性能) +C --> D(使用应用服务器集群改善网站的并发处理能力) +D --> E(数据库读写分离) +E --> F(使用反向代理和 CDN 加速网站响应) +F --> G(使用分布式文件系统和分布式数据库系统) +G --> H(使用 NoSQL 和搜索引擎) +H --> I(业务拆分) +I --> J(分布式服务) +``` + +#### 架构演化的价值观 + +- 大型网站架构技术的核心价值是随网站所需灵活应对 +- 驱动大型网站技术发展的主要力量是网站的业务发展 + +#### 架构设计误区 + +- 一味追随大公司的解决方案 +- 为了技术而技术 +- 企图用技术解决所有的问题 + +#### 并发处理能力的改善 + +- 通过负载均衡调度服务器,可将来自用户浏览器的访问请求分发到应用服务器集群中的任何一台服务器上,服务器的负载压力不再成为整个网站的瓶颈。 +- 部分数据库读操作(缓存访问不命中、缓存过期)和全部的写操作需要访问数据库。当负载压力过高时,数据库成为瓶颈。 + +#### 数据库读写分离 + +- 应用服务器在写数据的时候,访问主数据库,主数据库通过主从复制机制将数据更新同步到从数据库。 +- 应用服务器在读数据的时候,直接通过从数据库获得数据。 + +### 流媒体应用架构 + +#### CDN + +内容分发网络(Content Distribution Network, CDN)技术 + +**概念** + +CDN 是一种分布式网络系统,通过在地理上分散的多个服务器节点上缓存和传输互联网上的内容,以提高内容传输的性能和可用性。 + +**特点** + +CDN 会在 CDN 节点上存储内容的副本。 + +- 当用户请求内容时,服务提供商会返回一个清单文件(manifest) + - 客户端根据这个清单文件,选择能够支持的最高码率来获取内容 + - 如果网络路径出现拥塞,客户端可以选择不同的码率或副本进行获取 + +#### DASH + +动态自适应比特率视频流(Dynamic, Adaptive Streaming over HTTP, DASH)技术 + +**概念** + +服务器端: + +- 将视频文件划分为多个块 +- 对每个块编码成多个不同的码率 +- 不同码率的编码存储在不同的文件中 +- 这些文件复制到各个 CDN 节点上 +- 一个清单文件提供了不同块的 URL 地址 + +客户端: + +- 定期估算服务器到客户端的带宽 +- 根据清单文件,一次请求一个块 +- 选择当前带宽所支持的最高编码码率 +- 可以在不同时间点根据可用带宽选择不同的编码码率,并从不同的服务器获取 + +**特点** + +DASH 的“智能”体现在,客户端决定: + +- 何时请求视频块(以避免缓冲区耗尽或溢出) +- 请求何种编码码率(在带宽充足时请求更高质量) +- 从哪里请求视频块(可以选择离客户端较近或可用带宽较高的服务器 URL) + +Streaming Video = Encoding + DASH + Playout Buffering + +### Client-Server 和 P2P 架构 + +#### 两种架构的概念 + +**Client-Server 架构** + +- 客户端发起请求,服务器响应多个客户端的请求 +- 这种架构捕获了专业服务器和客户端的可重用行为,而不需要指定服务器和客户端的具体实现方式 + +**P2P 架构** + +- 所有实体都同时扮演客户端和服务器的角色 +- 这种架构更加灵活,但也使得实现专门做好客户端或服务器工作的软件变得更加困难 + +特点: + +- 没有常时在线的服务器,而是任意的终端系统直接进行通信 +- peers 向其他 peers 请求服务,并提供回报服务 +- 具有自我扩展性——新的 peers 带来新的服务能力和新的服务需求 +- peers 连接是间歇性的,IP 地址也会发生变化 +- 管理更加复杂 + +例子:BitTorrent(文件共享),看看网(流媒体),Skype(VoIP) + +#### 两种架构的区别 + +> 以软件分发问题为例。考虑将文件大小为 $F$ 的文件从一个服务器传输到 $N$ 个 clients/peers。记 $u_s$ 为服务器的上传速率,$u_i$ 为第 $i$ 个 client/peer 的上传速率,$d_i$ 为第 $i$ 个 client/peer 的下载速率。 + +**Client-Server 架构** + +服务器端,上传 $N$ 个 copies 需要 $NF/u_s$ 的时间。 + +客户端,由于并行下载,所以下载一个 copy 的时间由拥有最小下载速率 $d_{\min}$ 的客户端决定,需要 $F/d_{\min}$ 的时间。 + +$$ +t_{\text{Client-Server}} \ge \max\{\frac{NF}{u_s}, \frac{F}{d_\min}\}, +$$ +其中第一项随着 $N$ 线性增长。 + +**P2P 架构** + +服务器端,至少需要上传 $1$ 个 copy,需要 $F/u_s$ 的时间。 + +客户端,每个客户端下载一个 copy 需要 $F/d_{\min}$ 的时间。由于所有客户端加起来需要下载 $NF$ 大小的文件,所以还需要考虑所有客户端(再加上服务器)累计上传的时间,总计 $NF/(u_s + \sum u_i)$。 + +$$ +t_{\text{P2P}} \ge \max\{\frac{F}{u_s}, \frac{F}{d_{\min}}, \frac{NF}{u_s + \sum u_i}\}, +$$ +虽然最后一项分子随着 $N$ 线性增长,但是分母中的 $\sum u_i$ 也随着 $N$ 线性增长。 + +### 软件设计的五个原则 + +#### KISS = Keep It Simple and Stupid + +**概念** + +KISS 原则指的是在设计系统或解决问题时,应该保持设计的简单性和易懂性,避免过度复杂化。 + +**好处** + +1. 提高可靠性和稳定性:简单的设计往往更加可靠,因为减少了复杂性所带来的潜在问题。 +2. 降低维护成本:简单的设计更容易被理解和维护,减少了后期维护的负担。 +3. 提高效率和灵活性:简单的设计通常更加高效,并且更容易进行修改和扩展。 +4. 提高可读性和易用性:简单明了的设计更容易被使用者理解和掌握。 +5. 更快的开发周期:简单设计的开发和测试过程通常更加快捷。 + +#### Modularity + +**概念** + +Dividing complex system into simpler components. 强内聚,松耦合。 + +**好处** + +- 开发更容易进行规划 +- 可以定义和交付软件增量 +- 更容易适应变更 +- 测试和调试可以更有效地进行 +- 长期维护可以在没有严重副作用的情况下进行 + +#### Separation of Concerns(各司其职) + +**概念** + +“关注点分离”是一种软件设计原则,指的是将软件系统分解为相互独立的部分,每个部分负责特定的功能或职责。其主要包括: + +1. 分解(Decomposition) + - 将复杂的问题分解为多个相对独立的子问题或模块 + - 每个子问题或模块都应该是小规模的、简单的、可控的 +2. 综合(Synthesis) + - 将各个子问题或模块的解决方案组装成一个完整的系统解决方案 + - 各个模块之间通过定义良好的接口进行交互和协作 + +**好处** + +可以提高软件的模块化、可维护性和可扩展性。各个模块专注于自己的核心职责,降低了整体复杂度,便于理解和修改。 + +#### Design for CHANGE + +**概念** + +将可能发生的变化纳入系统设计的考虑范畴。 + +具体而言,需要将可能发生变化的部分隔离到软件的特定模块中,使得变更仅限于这些小的模块,而不会影响到整个系统。 + +Modifiability:可修改性是指软件系统能够适应变更的程度,它与变更的成本直接相关。 + +**好处** + +较高的可修改性有利于降低软件的长期运营成本,提高企业的敏捷性和竞争力。 + +#### Design for REUSE + +**概念** + +为了避免重复造轮子,我们需要遵循不重复自己(Don't Repeat Yourself, DRY)原则,避免重复劳动(Write Every Time, WET)。 + +软件开发是一项昂贵的工作,重用软件资产对于提高投资回报率(Return On Investment, ROI)至关重要。 + +可重用的软件资产包括: + +- 设计、代码、测试用例 +- 问题解决方案、设计解决方案 +- 工具和流程 +- 经验和最佳实践 + +**好处** + +- 降低生产和维护成本 +- 缩短交付周期 +- 提高软件质量 + +### 高可用的两个关键概念 + +#### 可用性 + +可用性指的是系统掩藏或修复故障的能力,使得在指定时间间隔内累计服务中断时间不超过要求的值。 + +#### 容错性 + +容错(Fault Tolerance)是指即使硬件/软件/网络可靠性较低,分布式系统也能保持可用性。容错不应有用户或系统管理员参与,可以通过以下两种方式实现: + +- Recovery (e.g., relying on equivalent services) +- Replication of components + +### 网站的高性能架构 + +#### 对比不同视角下的网站性能 + +**用户视角** + +用户在浏览器上直观感受到的网站响应速度。 + +- 用户计算机和网站服务器通信的时间 +- 网站服务器处理的时间 +- 用户计算机浏览器构造请求解析响应数据的时间 + +**开发人员视角** + +应用程序本身及其相关子程序的性能。 + +- 响应延迟 +- 系统吞吐量 +- 并发处理能力 +- 系统稳定性 + +**维护人员视角** + +基础设施性能和资源利用率。 + +- 网络运行商的带宽能力 +- 服务器硬件的配置 +- 数据中心网络架构 +- 服务器和网络带宽的资源利用率 + +#### 高性能缓存架构的三个问题 + +**缓存穿透** + +缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为 ID 为 $-1$ 的数据或 ID 特别大而不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。 + +解决方案: + +- 接口层增加校验,如用户鉴权校验,ID 做基础校验,ID $\le 0$ 的直接拦截; +- 从缓存取不到的数据,在数据库中也没有取到,这时也可以将 key-value 对写为 key-null,缓存有效时间可以设置短点,如 $30$ 秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个 ID 暴力攻击。 + +**缓存雪崩** + +当缓存失效(过期)后引起系统性能急剧下降的情况。当缓存过期被清除后,业务系统需要重新生成缓存,因此需要再次访问存储系统,再次进行运算,这个处理步骤耗时几十毫秒甚至上百毫秒。而对于一个高并发的业务系统来说,几百毫秒内可能会接到几百上千个请求。由于旧的缓存已经被清除,新的缓存还未生成,并且处理这些请求的线程都不知道另外有一个线程正在生成缓存,因此所有的请求都会去重新生成缓存,都会去访问存储系统,从而对存储系统造成巨大的性能压力。这些压力又会拖慢整个系统,严重的会造成数据库宕机,从而形成一系列连锁反应,造成整个系统崩溃。 + +解决方案: + +- 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。 +- 如果缓存数据库是分布式部署,将热点数据均匀分布在不同的缓存数据库中。 +- 设置热点数据永远不过期。 + +**缓存热点** + +虽然缓存系统本身的性能比较高,但对于一些特别热点的数据,如果大部分甚至所有的业务请求都命中同一份缓存数据,则这份数据所在的缓存服务器的压力也很大。例如,某明星微博发布“我们”来宣告恋爱了,短时间内上千万的用户都会来围观。 + +解决方案: + +- 复制多份缓存副本,将请求分散到多个缓存服务器上,减轻缓存热点导致的单台缓存服务器压力。以微博为例,对于粉丝数超过 $100$ 万的明星,每条微博都可以生成 $100$ 份缓存,缓存的数据是一样的,通过在缓存的 key 里面加上编号进行区分,每次读缓存时都随机读取其中某份缓存。 +- 缓存副本设计有一个细节需要注意,就是不同的缓存副本不要设置统一的过期时间,否则就会出现所有缓存副本同时生成同时失效的情况,从而引发缓存雪崩效应。正确的做法是设定一个过期时间范围,不同的缓存副本的过期时间是指定范围内的随机值。 + +#### 负载均衡技术及算法 + +在网站高并发访问的场景下,使用负载均衡技术为一个应用构建一个由多台服务器组成的服务器集群,将并发访问请求分发到多台服务器上处理,避免单一服务器因负载压力过大而响应缓慢,使用户请求具有更好的响应延迟特性。 + +- DNS 负载均衡 +- 硬件负载均衡 +- 软件负载均衡 + +**算法** + +- 轮询 + - 服务器不宕机、服务器与负载均衡器不断连 +- 加权轮询 + - 服务器性能有差异 +- 负载最低优先 + - 连接数、请求数、CPU 负载、I/O 负载 + - 需要采样 +- 性能最优优先 + - 处理速度 + - 需要采样 +- Hash + - 源地址 + - ID + +**Web 前端性能优化** + +- 浏览器访问优化 + - 减少 HTTP 请求 + - 使用浏览器缓存 + - 启用压缩 + - CSS 放在页面最上面,JavaScript 放在页面最下面 + - 减少 Cookie 传输 +- CDN 加速 + - 内容分发网络,将数据缓存在离用户最近的地方,使用户以最快速度获取数据,即所谓网络访问第一跳 +- 反向代理 + - 传统代理服务器位于浏览器一侧;反向代理位于网站机房一侧,代理网站 Web 服务器接收 HTTP 请求 + +**应用服务器性能优化** + +- 异步操作 + - 使用消息队列将调用异步 + - 不使用消息队列,用户的请求数据直接写入数据库,在高并发的情况下,会对数据库造成巨大的压力,响应延迟加剧。 + - 使用消息队列后,用户请求的数据发送给消息队列后立即返回,再由消息队列的消费者进程从消息队列中获取数据,异步写入数据库。 + - 消息队列有很好的削峰作用 + - 通过异步处理,将短时间高并发产生的事务消息存储在消息队列中,从而削平高峰期的并发事务。 + - 在电子商务网站促销活动中,合理使用消息队列,可有效抵御促销活动刚开始大量涌入的订单对系统造成的冲击。 + +### 微服务架构 + +#### 微服务架构的概念、特点 + +**概念** + +微服务架构是一种将单个应用程序开发为一套小型服务的方法,每个服务都在自己的进程中运行,并通过轻量级机制(通常是 HTTP 资源 API)进行通信。 + +这些服务是围绕业务功能构建的,可以通过完全自动化的部署机制独立部署。 + +**特点** + +- 在已发布的接口中将服务作为构建块(组件)使用 +- 围绕业务功能来组织 +- 开发团队完全负责生产环境中的软件 +- 智能端点和简单管道(Smart endpoints and dumb pipes) +- 语言的去中心化控制(Decentralized control of languages) + - 例如,去中心化的数据库 + +#### 对比单体(Monolith)应用和微服务应用的区别(数据库部署) + +![单体和微服务应用在数据库部署上的区别](https://img.picgo.net/2024/06/07/monolith-microservices-database-deployment1dc2050f3490eaa1.jpeg) + +## 软件需求 + +### 软件需求的概念 + +需求是对应当执行的任务的规范说明,描述系统的行为特性或属性,是一种对系统开发进程的约束。 + +开发软件系统的前提是要明确用户的期望和要求,即软件需求。 + +刻画软件边界,有所为有所不为:能做什么,不能做什么,哪些是力所能及的合理的期望,哪些是力所不及、而我们需要据理力拒的。然后把那些合理的期望描述清楚。 + +#### 需求工程的特点 + +- 知识密集型工作,需要交叉多学科的知识 +- 多方共同参与 +- 需求获取的多种形式和源头 +- 持续迭代和逐步推进 + +### 用户需求的获取过程 + +```mermaid +graph LR +A(识别用户类别) --> B(确定干系人代表) +B --> C(确定决策者) +C --> D(需求达成共识) +``` + +- 确定干系人代表:干系人是指积极参与项目的某个人、群体或组织,可能会受项目过程和结果的影响或影响项目的过程和结果。 +- 确定决策者:在软件项目中,需要在关键路径上做决定,或是解决一些冲突,接受(或拒绝)某个需求变更或者批准一组即将发布的需求。决策人或决策小组对决定工作方向、保证项目进度具有重要作用。 +- 需求达成共识:对需求或其中某部分达成一致是客户-开发关系的核心。 + - 客户确认:需求描述了他们的需要 + - 开发人员确认:理解需求并且可以实现 + - 测试人员确认:需求是可验证的 + - 管理层确认:需求满足业务目标 + +### 泳道图绘制 + +每类用户在一个泳道上。纵向描述的是业务过程。 横向表示他们之间的交互,纵向表示顺序。 泳道图与实现无关。 + +![泳道图](https://img.picgo.net/2024/06/07/swim-lane-diagram321900678935a83f.jpeg) + +### 判定树绘制 + +![判定树](https://img.picgo.net/2024/06/07/judgement-treecb968e54bab16456.jpeg) + +### 用例的识别和分析 + +#### 识别 + +1. 确定角色,分析角色和系统交互活动 +2. 分析业务过程,将场景概括为用例 +3. 识别系统外部事件,并关联到角色和用例 + +![识别用例](https://img.picgo.net/2024/06/07/use-case9d5f93e2476d5f36.png) + +#### 分析 + +**问题** + +- 用例用户看不懂用例 +- 用例过于复杂:应分解较长的流程 +- 用例内含设计 +- 用例内含数据定义:根据输入/输出关系区分功能,但用例说明中不应含有数据定义。 +- 用例过多 + +**条件** + +- 触发条件:事件,引发相关用例的执行 +- 前置条件:系统开始执行用例之前必须满足的先决条件 +- 后置条件:用例执行成功后系统的状态 + +### 顺序图绘制 + +主谓宾需要分清楚,把所有的主语和宾语全部拿出来作为每一列的名称,列与列之间用箭头来表示 $A \overset{\text{verb}}\to B$,$A$ 对 $B$ 进行了 $\text{verb}$。 + +![顺序图](https://img.picgo.net/2024/06/07/sequence-diagramcf7ccc0e69092d1a.jpeg) + +### 定义良好的需求(Well-Formed Requirement)的三个要求 + +#### 概念 + +- 可验证(Verifiable):可以被验证。 +- 必要(Necessary):指系统必须满足或拥有的条件,以解决利益相关方的问题或实现他们的目标。 +- 可量化(Quantifiable):通过可测量的条件和有约束条件来限定和限制某个特性或属性。 + +#### 需求改写 + +> When signal x is received [Condition], the system [Subject] shall set [Action] the signal x received bit [Object] within [Constraints] 2 seconds [Value]. + +> At sea state 1 [Condition], the Radar system [Subject] shall detect [Action] targets [Object] at ranges out to [Constraints] 100 nautical miles [Value]. + +> The Invoice system [Subject] shall display [Action] pending customer [Constraints] invoices [Object] in ascending order [Value] in which invoices are to be paid [Constraints]. + +### 需求缺陷的代价:戴维斯假设(Davis' Hypotheses) + +The later in the life-cycle that a fault will be discovered, the more expensive it will be to fix it. + +## 软件运维 + +### 软件运维在软件系统生命周期的开销占比 + +软件系统的生命周期中,使用阶段所占的时间比设计和实现阶段要长得多。软件系统总成本的 $40\%\sim 90\%$ 都发生在系统投入使用之后。 + +### SRE 的信条(Tenets of SRE) + +Site Reliability Engineer(SRE)teams are capability of doing Ops Automation, with the goal of “making the service run and repair itself”. + +通过合理分配资源,SRE 团队可以同时提高系统可靠性和团队效率。这种模式可以使得团队增长呈亚线性趋势。 + +- 保证持续对工程的关注 +- 在不违反服务 SLO 的情况下,追求最大变更速度 +- 监控的紧急程度:警报(Alerts)(立即行动)>工单(Tickets)(行动)>日志(FYI) +- 应急响应: + - 可靠性取决于平均无故障时间(MTTF)和平均修复时间(MTTR) + - 人工参与会增加响应延迟,尽可能实现自动化 + - 制定值班“手册”(可将 MTTR 变为原来的 $1/3$)和“灾难演练” +- 变更管理: + - $70\%$ 的中断是由于对生产系统的变更引起的 + - 减少人工参与: + - 实施渐进式发布 + - 快速准确地检测问题 + - 在出现问题时安全地回滚变更 +- 需求预测和容量规划: + - 确保有足够的容量和冗余,以满足未来预期需求并达到所需的可用性 + - 三个必要步骤: + 1. 准确的有机需求预测,覆盖获取容量所需的提前期 + 2. 准确地将非有机需求纳入需求预测 + 3. 定期进行系统负载测试,以关联原始容量(服务器、磁盘等)和服务容量 +- 供给(Provisioning): + - 结合变更管理和容量规划 +- 效率和性能: + - 有效利用资源可以节省大量成本 + - 应密切监控并维护性能(响应速度) + +### 拥抱风险原则 + +#### 可靠性(Reliability) + +用户无法区分 high reliability 和 extreme reliability。 + +- 需要平衡“有不可用的风险”与“快速迭代”、“高效服务” +- 用”管理风险(managing risk)“原则来管理服务的可靠性 + - 降低系统出错的风险 + - 用于保证”可靠性“的成本,会随着目标可靠性的增加而非线性上升(所以,控制 $99.99\%$ 即可,不需要更高) + - 多余的机器运行、计算成本 + - 机会成本(本来用这些资源可以去做 feature 的) +- 低可靠性会带来用户的不满意、不信任、资金、公司信誉等问题 + +#### MTBF 和 MTTR 的计算 + +MTBF 是 mean time between failures,MTTR 是 mean time to repair,也就是说, +$$ +\begin{align*} +\text{MTBF} & = \frac{\text{uptime}}{\# \text{ of failures}}, \\ +\text{MTTR} & = \frac{\text{downtime}}{\# \text{ of failures}}. +\end{align*} +$$ + +#### 基于时间的可用性(Time-Based Availability) + +$$ +\text{TBA} = \frac{\text{uptime}}{\text{uptime} + \text{downtime}}. +$$ + +等价地,$\text{TBA} = \text{MTBF}/(\text{MTBF} + \text{MTTR})$。 + +#### 合计可用性(Aggregate Availability) + +$$ +\text{AA} = \frac{\text{successful requests}}{\text{total requests}}. +$$ + +#### 错误预算 + +即容许错误次数,可以通过 SLO 来计算(总请求次数乘以 SLO 规定的比例)。好处在于可以决定发布版本的频率。 + +### 服务质量目标(Service Level Objectives) + +#### 相关术语 + +- 服务水平指标(Service Level Indicator,SLI):定量指标,用来测量某个方面的服务水平 + - 例如:请求延迟、错误率、系统吞吐量、可用性 + - 通常会在一个时间窗口内聚合计算,如速率、平均值或百分位数 +- 服务水平目标(Service Level Objective,SLO):针对某个 SLI 设定的目标值或值范围,应该是优先工作的主要驱动因素。 + - 例如:每个请求的平均延迟应该小于 $100\;\mathrm{ms}$ +- 服务水平协议(Service Level Agreements,SLA):与用户的明确或隐含的合同,包括达成 SLO 或未达成 SLO 的后果。 + +#### 实践中的指标 + +**哪些指标?** + +- 面向用户的服务系统(例如前端):可用性(availability),延迟(latency),吞吐量(throughput)。 +- 存储系统:延迟、可用性、持久性(durability)。 +- 大数据系统:吞吐量、端到端延迟(end-to-end latency)。 + +**如何收集?** + +- 服务端:Prometheus/Zabbix/Borgmon 系统、周期性日志分析 +- 客户端:客户端检测工具 + +### 琐事(Toil) + +#### 概念 + +与运营生产服务相关的工作,它往往是手动的(manual)、重复性的(repetitive)、可自动化的(automatable)、战术性的(tactical),没有持久价值(devoid of enduring value),随着服务的增长而呈线性增长。 + +#### 尽量消除琐事(Eliminating Toil)的相关目标 + +将每个 SRE 消耗在琐事上的时间控制在 $50\%$ 以下。至少 $50\%$ 的时间应该花在要么减少未来琐事,要么增加服务 feature 的项目上。 + +**SRE 的典型活动类别** + +- 软件工程:编写或修改代码,包括任何相关的设计和文档工作。 +- 系统工程:配置生产系统,修改配置等。 +- 琐事:直接与运行服务相关的重复性、手动等工作。 +- 日常工作:不直接与运行服务相关的行政工作。 + +### 分布式系统的监控 + +#### 黑盒监控 + +症状导向,代表实际出现的而非预测的问题,表示"系统现在无法正常工作"。是在测试中外部可见的一些异常行为。 + +**四大黄金监控信号** + +1. 延迟(Latency):服务请求的响应时间。 +2. 流量(Traffic):系统承受的请求量,用一个高层系统特定指标来衡量。 +3. 错误(Errors):失败请求的比率。 +4. 饱和度(Saturation):系统使用率,关注最受限的资源。 + - 例如:通过监控 $1$ 分钟内的 $99\%$ 响应时间来快速检测饱和度。 + +#### 白盒监控 + +依赖于对系统内部的检查。可以检测即将到来的问题、被重试掩盖的故障等。 + +是一些内部指标,例如 logs:JVM logs,HTTP logs 等。 + +### 紧急警报的基本哲学(Fundamental Philosophy on Pages) + +- 每当被 pager 唤醒时,我都应该以强烈的紧迫感做出反应。但一天之内只能有几次这种紧迫感,否则会疲惫不堪。 +- 每次被 pager 唤醒都应该是可采取行动的(actionable)。 +- 每次 page 都应该需要人类智能(human intelligence)。如果一次 page 只需要机器人式的响应,它就不应该触发 pager。 +- Pages 应该关注一个全新的问题或以前未见过的事件。 +- 应该找出问题的根源并消除它;如果无法解决根本问题,那么这种警报响应就应该被完全自动化。 + +### On-call 轮值原则(Being On-Call) + +#### 概念 + +轮值工程师需要在工作时间和**非工作时间**都保持联系。 + +**例子** + +- 接到 pager 通知后,轮值工程师需要立即进行问题诊断和解决,可能需要与其他团队成员协作,并根据需要进行升级。 +- 目标 $99.99\%$ 可用性 $\to$ 每季度错误预算 $13\;\mathrm{min}$ 分钟 $\to$ $5\;\mathrm{min}$ 内启动操作 +- 对于不紧急的事件,给予 $30\;\mathrm{min}$ 响应时间 +- 非 page 事件在工作时间内以较低优先级处理 + +#### 作用 + +保持服务的可靠性和可用性。 + +### 有效的故障排查手段(Effective Troubleshooting) + +#### 假说演绎法 + +```mermaid +graph TD +A(Problem Report) --> B[Triage] + +B --> C[Examine] +C --> D[Diagnose] +D --> E[Test/Treat] +E --> C +E -.->|Consider re-triaging if situation changes| B + +E --> F(Cure) +``` + +#### 常见错误 + +- 关注不相关的症状,或误解系统指标的含义 +- 误解如何改变系统、输入或环境来安全有效地验证假设 +- 提出非常不太可能的错误理论,或者死死抓住过去问题的原因,认为既然发生过一次就一定又发生了 + - 在多种可能解释中优先选择较简单的解释(奥卡姆剃刀原则) + +- 追踪虚假相关性,这可能只是巧合或由共同因素引起的相关性 + - **相关性并不等同于因果关系** + + +#### 过程 + +- Problem Report:有效的问题报告应包括预期行为、实际行为,以及尽可能重现问题的步骤。可以记录调查和修复活动的日志,方便未来参考。 +- Triage:评估问题的严重程度,首要任务是止血:尽可能让系统在当前环境下运行得更好。 +- Examine:检查系统中的每个组件,查看所有监控指标,例如各种 log。 +- Diagnose:关注组件之间的连接关系,或者数据流,来判断每个组件是否正常工作。 + - 从系统的一端开始,逐步向另一端检查每个组件。 + - 找出 What(出现问题的功能在做什么)Why(为什么会有这样的表现)Where(数据资源从哪里获得的,被存放到了哪里) + - 检查“最后改动了什么”。 + +#### 总结 + +**构建可观察性** + +- 从根本上为每个组件都建立白盒指标和结构化日志 +- 记录工作流程和变更情况 +- 设计组件之间有良好理解和可观察的接口 +- 确保系统内部信息以一致的方式可用,以加快问题诊断和恢复速度 + +**采取系统的故障排查方法** + +- 不要依赖运气或经验,而是采用系统的方法 +- 这可以帮助缩短服务恢复时间,提升用户体验 + +### 紧急事件响应(Emergency Response) + +#### 类型 + +- Test (Controlled failures)-induced emergency +- Change-induced emergency +- Process-induced emergency + +#### 注意事项 + +**所有问题都有解决方案** + +- 时间和经验都证明,系统不仅会出现故障,而且会以前所未有的方式出现故障 +- 多与团队成员合作,寻求帮助,采取各种必要措施,但要尽快行动 +- 在应急情况得到缓解后,一定要腾出时间进行清理、撰写事故报告 + +**从过去中吸取教训,不要重复犯错** + +- 记录历史中断事件,记录预防策略和方法 +- 提出大胆的“如果”假设性问题 +- 鼓励主动进行测试 diff --git "a/source/_posts/\343\200\220\346\270\270\350\256\260\343\200\2212022\345\271\264\345\233\236\347\234\270.md" "b/source/_posts/\343\200\220\346\270\270\350\256\260\343\200\2212022\345\271\264\345\233\236\347\234\270.md" new file mode 100644 index 0000000..b28c673 --- /dev/null +++ "b/source/_posts/\343\200\220\346\270\270\350\256\260\343\200\2212022\345\271\264\345\233\236\347\234\270.md" @@ -0,0 +1,325 @@ +--- +title: 【游记】2022 年回眸 +tags: + - 生活 + - 回眸 +categories: + - 游记 +mathjax: true +toc: true +date: 2022-12-31 14:38:14 +password: +id: 2022Lookback +--- + +2022 年就这么过去了, + +我也从一个高三学生变成了一个大一新生了。 + +---- + +一年发生了很多事情。现在,是时候回顾一下了? + +![换微信头像啦!](https://img.picgo.net/2022/12/31/cover53724a4b06b80249.png) + + + +## 一月至五月 + +**2022-02-05 自己的 18 岁生日** + +![蛋糕](https://img.picgo.net/2022/12/31/birthday414f754fc919dd46.jpeg) + +**各种调考** + +成绩不想贴出来,年级(和班级)排名单调下降,丢人。 + +## 六月 + +**2022-06-07 至 2022-06-09 高考** + +数学卷子好难。 + +**2022-06-16 回初中看老师** + +感觉外初变新了,装修得非常漂亮。 + +![一行人](https://img.picgo.net/2022/12/31/WFLS-middle1a154a8b78140cd8d.jpeg) + +![内景](https://img.picgo.net/2022/12/31/WFLS-middle2e79c5db67fc3f017.jpeg) + +![外景](https://img.picgo.net/2022/12/31/WFLS-middle3df9fb27ee05c6741.jpeg) + +**2022-06-25 高考出分** + +超常发挥吧。 + +## 七月 + +**2022-07-03 和高中朋友一起咸宁游** + +感谢 Q 宝的邀请 + +![大汉](https://img.picgo.net/2022/12/31/xianning191eea47b8f7a3893.jpeg) + +![小火车](https://img.picgo.net/2022/12/31/xianning276fcb4a1fad0e44d.jpeg) + +**2022-07-25 收到录取通知书** + +![二校门](https://img.picgo.net/2022/12/31/admissiond1dbbd370ad6b54f.jpeg) + +## 八月 + +**2022-08-18 删掉了全部的 QQ 好友** + +确实挺抱歉的,但我基本上不用 QQ 了。QQ 群我都没退。 + +**2022-08-19 开始军训** + +**2022-08-24 第一次定向越野** + +军训时的定向越野,我不熟路,甚至跑出了学校?出校也没拦我,入校才把我拦下来了。 + +![map](https://img.picgo.net/2022/12/31/orienting1bc25bea9b7c0a16a.jpeg) + +![成绩!](https://img.picgo.net/2022/12/31/orienting267f9e50d8f47a4a5.jpeg) + +我还哼哧哼哧地补了一个出入校审批。把我卡在校门外好久,大概半个小时吧。 + +![奇怪的出入校审批](https://img.picgo.net/2022/12/31/orienting38029f4720adc31ef.jpeg) + +**2022-08-28 参加 20km 拉练** + +走完全程,jio 十分酸痛。~~至少我坚持了下来。~~ + +![丑陋的背包](https://img.picgo.net/2022/12/31/20km1da40059414003fed.jpeg) + +![夜景](https://img.picgo.net/2022/12/31/20km2ae3e3caea3fbc256.jpeg) + +## 九月 + +**2022-09-12 参加清华的外高校友聚会** + +![可惜的是缺了 Jett 和罗总](https://img.picgo.net/2022/12/31/schoolmatesa59df8b69eba69e6.jpeg) + +**2022-09-17 参加篮球运动周** + +这波啊,这波赢麻了。三分大赛,获得了5中2的好成绩!~~校队最高水平也是5中2。~~ + +[点击这里跳转至 bilibili 观看](https://www.bilibili.com/video/BV18D4y15793/) + +**2022-09-22 在楚协吃正宗的热干面** + +![文学长在进行操作](https://img.picgo.net/2022/12/31/hot-dry1ca5c01a6921037d4.jpeg) + +![在享受](https://img.picgo.net/2022/12/31/hot-dry2c0a5327fe50a4184.jpeg) + +**2022-09-23 第一次背完 GRE 单词** + +问题就在于,背完了没太大用。 + +那么多单词,大概印象深刻的只有 20% 左右吧(不过这也很不错了) + +这 20% 是我在学习中经常碰到的,所以印象比较深刻。 + +~~有些单词,这辈子感觉是只有考 GRE 才会见到的。~~ + +![GRE](https://img.picgo.net/2022/12/31/gre60a11da638612426.jpeg) + +## 十月 + +**2022-10-01 在清华的中央主楼观看了升旗仪式** + +十分震撼。 + +![仪仗队在出旗](https://img.picgo.net/2022/12/31/ceremony2bfa11e384bc03835.jpeg) + +![国旗](https://img.picgo.net/2022/12/31/ceremony19e0081cff6e30067.jpeg) + +**2022-10-02 和一些高中朋友聚餐** + +![5人合影(我拍的)](https://img.picgo.net/2022/12/31/classmates47454a3d365c1c52.jpeg) + +下面这幅图是一个是清华学生的饮食消费记录,一个是北大学生的饮食消费记录。 + +~~什么叫物美价廉啊(战术后仰~~ + +![《差距》](https://img.picgo.net/2022/12/31/money7abc56161cede76c.jpeg) + +**2022-10-03 为课本剧《作家之死》添上了字幕** + +从暑假一直咕到十一放假才做完,感觉还是挺不错的。 + +[点击这里跳转至 bilibili 观看](https://www.bilibili.com/video/BV1St4y1a7Cw?share_source=copy_web) + +**2022-10-03 参观工字厅** + +四年能进工字厅的次数不多,有种好奇宝宝的感觉。 + +![外部](https://img.picgo.net/2022/12/31/gzt16aba09ee1058b3d4.jpeg) + +![内部1](https://img.picgo.net/2022/12/31/gzt21448ae75dfc5701c.jpeg) + +![内部2](https://img.picgo.net/2022/12/31/gzt3e7c98a981b1a72d8.jpeg) + +~~值得一提的是,偶遇了[邱宝](https://baike.baidu.com/item/%E9%82%B1%E5%8B%87/229950)~~ + +**2022-10-06 成功脱单** + +感谢我能遇见你。 + +update@2023-02-08: 她觉得我和她并不合适,于是我们分手了。 + +**2022-10-09 参加“奋进新时代”主题成就展** + +![外部](https://img.picgo.net/2022/12/31/fjxsd1f8c1b2c7c1fbc840.jpeg) + +![国旗飘扬](https://img.picgo.net/2022/12/31/fjxsd249651b0efbedc89d.jpeg) + +![武汉战疫](https://img.picgo.net/2022/12/31/fjxsd33ea2a77fe6315bd5.jpeg) + +**2022-10-09 参加“新生赤足运动会”** + +勇夺全校并列第七! + +![选手照片](https://img.picgo.net/2022/12/31/barefoot1ea05c64c5bc093b0.jpeg) + +![并列第7!](https://img.picgo.net/2022/12/31/barefoot27a0ea18ec380d01c.jpeg) + +比我初一时候的成绩提高了大概 40 个(确信 + +## 十一月 + +**2022-11-01 写了一首诗** + +> To Autumn +> +> --- +> +> Golden leaves of autumn +> +> danced and drifted to the ground. +> +> They dotted the picturesque view of mother nature, +> +> when the color of gold conquered the world. +> +> Leaves are leaving, +> +> but I'm not. +> +> --- +> +> My hand holds yours, +> +> your hand fits mine. +> +> By chance, +> +> my eyes meet thine. + +~~诗是写给女朋友的。~~ 诗是写给前女友的。 + +自己写完后还对自己第二段的韵脚洋洋得意? + +后来感觉很眼熟,发现这应该是原来看过的 Emily Dickenson 的 *I Keep My Pledge* 里的最后一段蹦到我脑海里被我化用了。 + +> Blossom and I - +> +> Her oath, and mine - +> +> Will surely come again. + +**2022-11-10 代表工物系参加马约翰杯** + +能代表系里参加马杯,属实是我的荣幸。 + +![在排队参赛](https://img.picgo.net/2022/12/31/JohnMaCup11dfb093693e9de87.jpeg) + +![横幅](https://img.picgo.net/2022/12/31/JohnMaCup2c7be1d0ad4f94657.jpeg) + +还不错,甲组全校第四! + +![第四!](https://img.picgo.net/2022/12/31/JohnMaCup3aaa36821084cdc9a.jpeg) + +**2022-11-27 完成《算法设计及其复杂性分析》课程的课程报告** + +学到许多。 + +$\LaTeX$ 熟练度增加了! + +![算法课报告](https://img.picgo.net/2022/12/31/algorithme4daa5c70e6eb8a7.jpeg) + +**2022-11-27 第一次在篮球赛中绝杀翻盘** + +我们班的篮球队最后 3 秒的边线球战术配合得相当精彩,每个人都是不可或缺的一环。我竟然顶住了压力罚篮全进,压哨翻盘? + +~~当然,我超常发挥也可能是因为女朋友来看比赛了。~~ 当然,我超常发挥也可能是因为前女友来看比赛了。 + +![最后的罚篮](https://img.picgo.net/2022/12/31/basketball-cupb13c49671edb8988.jpeg) + +**2022-11-28 第一次封寝** + +早晨被走廊里的警报吵醒,我们宿舍楼有一例十混一阳性。但这样封寝的日子是再也不会重来了吧? + +其他室友在寝室里上网课,我反正窝在中厅里自习。 + +![自习位置](https://img.picgo.net/2022/12/31/dormf6c936abf1e8d037.jpeg) + +## 十二月 + +**2022-12-03 第一次参加志愿服务** + +人生中第一次参加志愿服务,是返乡“送站专线”。早晨四点半就起来了。 + +![空空旷旷](https://img.picgo.net/2022/12/31/volunteer10795815861bbcd2f.jpeg) + +~~和女朋友一起参加志愿服务!~~ 和前女友一起参加志愿服务。 + +![合照!你能找到我吗?](https://img.picgo.net/2022/12/31/volunteer272cd74135fd1f56a.jpeg) + +送完第二波大巴之后,天刚刚亮。 + +![送完大巴之后,天也亮了](https://img.picgo.net/2022/12/31/volunteer3fbbb94edbb45beb3.jpeg) + +**2022-12-08 返乡** + +![在寝室清东西](https://img.picgo.net/2022/12/31/hometown1d7751fe1975f2c40.jpeg) + +没想到,以前是我送大巴,现在是其他志愿者送我。 + +![返乡大巴](https://img.picgo.net/2022/12/31/hometown23004ee63acb4644a.jpeg) + +回到家后的第一个早晨,当然是吃热!干!面! + +~~实名diss听涛园的热干面不咋地~~ + +![热!干!面!](https://img.picgo.net/2022/12/31/hometown3485eec21aec3255a.jpeg) + +**2022-12-16 感染新冠病毒** + +我倒是我们家最后一个阳的。没测抗原,也就没图。 + +周五下午开始头疼+发烧,一直到周日晚上。然后屁颠屁颠地继续上周一的课了。 + +喉咙不疼但有痰,我觉得我其实挺过了发烧的几天,之后就还好。 + +![蒸橙子](https://img.picgo.net/2022/12/31/orangefc95b0b61d4387da.jpeg) + +**2022-12-20 复习期末** + +线代好难。 + +微积分好难。 + +基物好难。 + +我想睡觉。 + +## 总结 + +学习方面,感觉学习确实有点吃亏,觉得自己身边的同学们都好厉害。 + +生活方面,感觉自己还把自己照顾得挺好的。 + +新的一年里继续努力吧! diff --git "a/source/_posts/\343\200\220\346\270\270\350\256\260\343\200\2212022\346\255\246\346\261\211\345\244\226\345\233\275\350\257\255\345\255\246\346\240\241\347\220\206\347\247\221\345\210\206\347\217\255\350\200\203\350\257\225\344\271\213\347\233\221\350\200\203\345\210\222\346\260\264\350\256\260.md" "b/source/_posts/\343\200\220\346\270\270\350\256\260\343\200\2212022\346\255\246\346\261\211\345\244\226\345\233\275\350\257\255\345\255\246\346\240\241\347\220\206\347\247\221\345\210\206\347\217\255\350\200\203\350\257\225\344\271\213\347\233\221\350\200\203\345\210\222\346\260\264\350\256\260.md" new file mode 100644 index 0000000..be3af8a --- /dev/null +++ "b/source/_posts/\343\200\220\346\270\270\350\256\260\343\200\2212022\346\255\246\346\261\211\345\244\226\345\233\275\350\257\255\345\255\246\346\240\241\347\220\206\347\247\221\345\210\206\347\217\255\350\200\203\350\257\225\344\271\213\347\233\221\350\200\203\345\210\222\346\260\264\350\256\260.md" @@ -0,0 +1,273 @@ +--- +title: 【游记】2022 武汉外国语学校理科分班考试之监考划水记 +tags: + - 数学 + - 物理 + - 化学 + - 生活 +categories: + - 游记 +mathjax: true +toc: true +date: 2022-07-25 14:38:14 +password: +id: 2022WFLS-Invigilate +--- + +为什么叫划水记呢? + +因为我以划水的心态~~做了~~看了考试的卷子,所以叫划水记(确信)。 + +---- + +老老实实监考并且坐牢 $100 + 100 + 150 = 350 \mathrm{ min}$ ~~(不是)~~ + +~~试着做做卷子顺便监考一下再吃大餐(是)~~ + + + +## 准备工作 + +![@全体成员](https://img.picgo.net/2023/07/26/prepreb34611f75ef2ec4c.png) + +~~(后面两次@没有@上)~~ + +支持母校招生工作! + +被梅老师拉进一个群,然后他再三强调晚饭他请客,那就不客气了。 + +![吃吃吃](https://img.picgo.net/2023/07/26/pref7015fe411ed65ec.png) + +## 物理 + +**8:10** + +把答题卡、草稿纸、卷子分成每份 $6$ 张的 $5$ 份。 + +开始发答题卡和草稿纸。 + +**8:15** + +开始发卷子。 + +**8:20** + +考生们开始答题,我也看看题。 + +我一看第二题: + +![物理卷子T2](https://img.picgo.net/2023/07/26/physics-T2e7c2fdb25c062080.jpeg) + +这绝对是 may 卷。等效嘛……感觉这可以算是 may 的标志了。 + +于是顺着开始做选择题。 + +**9:00** + +下去巡逻一圈。有个人东张西望企图干些什么,我瞪了他一眼。他就“唯唯诺诺”了。 + +继续看题: + +![物理卷子T6](https://img.picgo.net/2023/07/26/physics-T67cf08af8a9eb6ddd.jpeg) + +这个我会!侧面切成 $\text{d}h$ 的很多层,对每一层算压强然后积分! + +cyx:我也在积,诶我这个 $h$ 写成 $H$ 了,嗯改改,ok 了。 + +我:有啥简单方法吗? + +cyx:草草草,我们都降智了。 + +cyx:总压力是 $3G$,重力提供 $G$,剩下的就是侧面提供的 $2G$。 + +我:嗯我是蠢蛋。 + +**9:20** + +再看实验题。都是电学实验,用 $\dfrac{1}{3}$ 准则判断了一下第一题的电表,感觉难度不小,然后就没做了。 + +考试怎么还不结束啊。 + +**9:30** + +考试怎么还不结束啊。 + +那再下去巡逻一圈。 + +这些人怎么计算器用的都不是 991 啊,那做个锤子的物理题。 + +**9:40** + +站起来看看大家专注而茫然的表情。 + +怎么有人开始检查了?世界真参差啊。 + +**10:00** + +~~收卷了,收卷了!物理答题卡交上来!~~ + +收好了物理答题卡、卷子和草稿纸。 + +## 化学 + +收完了物理卷子,李彬主任和王老师直接帮我们把化学卷子送到班上来了。 + +~~不用自己数三十份卷子出来就是方便哈。~~ + +**10:10** + +把答题卡、草稿纸、卷子分成每份 $6$ 张的 $5$ 份。 + +开始发答题卡和草稿纸。 + +**10:15** + +开始发卷子。 + +**10:20** + +考生们开始答题。我看着他们看题。我也看看题。 + +题目长这个样子。 + +![化学卷子P1,P2](https://img.picgo.net/2023/07/26/chem-12ed2d84f4154c691b.jpeg) + +看到卷子的我:??????????????????????????????? + +怎么都是湖北高考从不会出现的选四原理选择题? + +怎么还有 $6$ 道多选题?怎么还有 $3$ 道计算题? + +~~每题都要计算是吧,那我摆烂算了。~~ 遂没做化学卷子。 + +**10:35** + +笑着下去巡视。 + +非常满意。一刻钟过去了,没有多少人做到第三题。 + +![笑谈化学卷子](https://img.picgo.net/2023/07/26/wechat-chemc608489ccb7dfac7.jpeg) + +**11:00** + +睡了一大半。瞌睡是有传染性的。我也想睡。 + +“你们再看看~~卷子~~我,我再看看你们。” + +大眼瞪小眼。 + +**12:00** + +收好了化学答题卡、卷子和草稿纸。 + +## 吃午饭 + +~~先去的老成都,只可惜已经倒闭了?电梯里只有第三层的按钮坏了,去不了老成都的那一层楼。~~ + +老汉口餐厅,李彬主任请客。 + +竟然还有三楼? + +我和 cyx:这个词能拿 20 分,还行。 + +cyx 和 cdz:你看我这个英雄…… + +xqy、lbx、skc:数学&##啊这题$数学&@数学 + +xyx、clx:不知道在说啥。 + +吃完饭就返回学校数数学卷子了。 + +## 数学 + +~~lbx、xqy在抱着数学卷子去考场的途中就已经口胡出来了两题。~~ + +![细致入微](https://img.picgo.net/2023/07/26/maths-fix1cdead7e8a6fa5f6.png) + +写了几道能力范围之内的题目。 + +> 1. (10分)求所有的正整数 $n$,使得 $1\underbrace{44\cdots4}_{n 个 4}$ 是一个完全平方数. + +先除以 $4$ 然后模 $4$ 就可以知道 $n \ge 4$ 均不符合条件。枚举 $n = 1, 2, 3$ 即可。 + +> 6. (25分)设正实数 $x, y, z$ 满足 $xyz = 1$,证明: +> $$ +> \dfrac{2}{(x+1)^2+y^2+1} + \dfrac{2}{(y+1)^2+z^2+1} + \dfrac{2}{(z+1)^2+x^2+1} \le 1 +> $$ + +注意到 +$$ +\dfrac{1}{x^2+xy+1} + \dfrac{1}{y^2+yz+1} + \dfrac{1}{z^2+zx+1} = 1 +$$ +则 +$$ +\begin{aligned} +& \dfrac{2}{(x+1)^2+y^2+1} + \dfrac{2}{(y+1)^2+z^2+1} + \dfrac{2}{(z+1)^2+x^2+1} \\\\ +\le & \dfrac{1}{x^2+xy+1} + \dfrac{1}{y^2+yz+1} + \dfrac{1}{z^2+zx+1} \\\\ += & 1 +\end{aligned} +$$ + +>7. (30分)设 $m = d_0 + d_1\cdot3 + d_2\cdot3^2+\cdots+d_n\cdot3^n$ 为一个正整数的平方,且 $d_i\in\\{0, 1, 2\\}, i = 0, 1, 2, \cdots, n$. 证明:至少有一个 $d_i = 1$. + +设 $m = 3^{\alpha}\cdot n$,其中 $3 \nmid n$。因 $m$ 为完全平方数,则 $\alpha$ 必为偶数。 + +因 $n$ 也为完全平方数且 $3\nmid n$,则 $n \equiv 1 (\bmod3)$,则 $d_{\alpha} = 1$。 + +---- + +当我不知道干啥的时候,我看到了这个 + +![来了来了](https://img.picgo.net/2023/07/26/dinner9b334dc4a5b23b5b.png) + +大家都表示不知道该吃啥。先等一手。 + +## 帮梅老师改物理卷子 + +每人分配任务,不一会儿就改完了。 + +~~电学实验他们是真的做得差啊。~~ + +想找到人与人之间的差距,总是能找到的。 + +以前总是听说小六选手有多么多么厉害,但看到七八十分的答题卡我是真的傻了。 + +保守估计我高三巅峰状态做这张卷子应该是 80-85 的水平。 + +恐怖如斯。 + +~~还有个90+的高分。~~ + +## 吃晚饭 + +~~你以为的梅老板请客:梅老板和我们围在一个餐桌旁嘻嘻哈哈。~~ + +~~事实上的梅老板请客:梅老板告诉我们去哪里吃,吃完后我们报告给他,他汇款给cdz付钱。~~ + +吃饭前: + +![海底捞吃饭前](https://img.picgo.net/2023/07/26/hdl-empty8f36081cc9bde989.jpeg) + +吃吃吃: + +![杯盘狼藉](https://img.picgo.net/2023/07/26/hdl-full7e1ba2d82de46012.jpeg) + +大家喜欢抢的几样东西:血旺、饼。 + +没人吃的东西:娃娃菜。 + +粉丝下在辣锅里好呛人! + +第一次感受到了自己吃辣的能力在下降。 + +好吃好吃: + +![椰子](https://img.picgo.net/2023/07/26/hdl-coconut750dc4979eadf915.jpeg) + +~~嗯,属于是我们九个人把游标卡尺的饭钱全部消耗完了。~~ + +## 总结 + +![监考老师们的合照](https://img.picgo.net/2023/07/26/us353c5edbc7a58145.jpeg) + +嗝。 diff --git "a/source/_posts/\343\200\220\346\270\270\350\256\260\343\200\2212023\345\271\264\345\233\236\347\234\270.md" "b/source/_posts/\343\200\220\346\270\270\350\256\260\343\200\2212023\345\271\264\345\233\236\347\234\270.md" new file mode 100644 index 0000000..d9d68a8 --- /dev/null +++ "b/source/_posts/\343\200\220\346\270\270\350\256\260\343\200\2212023\345\271\264\345\233\236\347\234\270.md" @@ -0,0 +1,311 @@ +--- +title: 【游记】2023 年回眸 +tags: + - 生活 + - 回眸 +categories: + - 游记 +mathjax: true +toc: true +date: 2023-12-28 14:38:14 +password: +id: 2023Lookback +--- + +2023 年就这么过去了。我做梦也没有想到,这一年将会对我接下来的大学生活(乃至人生)产生如此巨大的影响。 + +一年中,我从一个懵懵懂懂的大一新生,摇身一变,变为了一只大二老狗。算是在大学里是越活越通透了。 + +---- + +一年发生了很多事情。现在,是时候回顾一下了? + + + +## 一月 + +在家里卷。学了学 OOP。 + +## 二月 + +**2023-02-23 第一次听杨一龙老师的《高等线性代数选讲(英)》** + +自然的表述、inspiring 的思路,真的给我耳目一新的感觉! + +![非常好!](https://img.picgo.net/2023/12/28/class-yylc2bc29e816fe7cda.jpeg) + +可惜的是……他不再在清华教书了。 + +![可惜](https://img.picgo.net/2023/12/28/farewell-yyldde4cfaf75275a85.jpeg) + +## 三月 + +**2023-03-05 人生中第一次献血** + +抽血的过程还真挺疼的,但医务人员一直在跟我聊天分散我注意力。 + +~~体验十分良好~~ + +![合照](https://img.picgo.net/2023/12/28/blood-donation11d04ab5827807448.jpeg) + +吐槽一下你清各种吉祥物的名字。“布拉”是 blood 的谐音,但怎么越看越觉得离谱。~~就像生命科学学院的吉祥物“莱福” 是 life 的谐音一样,化工系的微信公众号“卡安” 是 chemical engineering 不知道哪几个音节拼起来的一样。~~ + +就很怪。 + +![第一次被缠这么多绷带](https://img.picgo.net/2023/12/28/blood-donation23e966e8fce9f5e8b.jpeg) + +**2023-03-09 在清华里第一次国旗下讲话** + +[致敬英雄,铭记使命——工程物理系参加升旗仪式](https://mp.weixin.qq.com/s/v0THevSxs8NCAk61bcPpbw) + +~~没想到,为了新生舞会专门准备的西装,在这个时候发挥了作用。~~ + +![帅照(确信)](https://img.picgo.net/2023/12/28/speech83f566ccbe99bdc7.png) + +感觉自己皱着个眉头,看起来严肃又滑稽( + +**2023-03-26 代表工物系参加2022-2023学年度马杯乒乓球比赛** + +![乒乓球马杯](https://img.picgo.net/2023/12/28/pingpong247b3198d020b0cc.jpeg) + +可惜小组赛没出线。 + +## 四月 + +**2023-04-01 愚人节的 THUInfo** + +![睡大觉。](https://img.picgo.net/2023/12/28/fool5e54ad495e3db30a.jpeg) + +我倒也想选这门课啊,甚至 5 学分呢。 + +**2023-04-13 代表工物系参加2022-2023学年度马杯毽球比赛** + +![我们可是甲组季军呢](https://img.picgo.net/2023/12/28/shuttlecock87edf70961021e2a.jpeg) + +~~非常好毽球,爱来自工物。~~ + +最后拿到了甲组季军。现在回想起来,致理和电子都那么强,真不知道当时是怎么赢的( + +**2023-04-23 线下麻将友人场的国士无双** + +![国士无双!](https://img.picgo.net/2023/12/28/mahjongf0094aff62857af2.jpeg) + +逆天极了。我四暗刻一向听,对家国士无双听绝张白板。还得是 sjx 啊,高手胡绝张。 + +ctl 也是倒霉,摸到了绝张白板,放了炮。 + +~~线下友人局离役满最近的一次~~ + +**2023-04-25 第一次考英语四级,出分了** + +咱就是说,给武汉外国语学校丢脸了。才 610 多一点。 + +![CET-4](https://img.picgo.net/2023/12/28/cet-449ecac9a9eabce93.jpeg) + +**2023-04-25 写沟突然换老师?** + +太逆天了。上了八周的写沟,老师突然不见了。~~最后推测难道是去出高考卷子了?还有人说被挖去北大了。~~ + +![逆天](https://img.picgo.net/2023/12/28/change-1bea8b56a3faa5f5c.jpeg) + +然后还让我们电子签名。好正式。搞得我好怕。 + +![哈人](https://img.picgo.net/2023/12/28/change-2d3df805277f2268e.jpeg) + +**2023-04-25 第一次参加的小清心的心理团体辅导结束** + +主题是亲密关系。 + +分手让我痛苦了很久,所以我就开始尝试寻求帮助,最后在清华小清心公众号上找到了这个团体辅导。 + +参加心理团体真的很有用,既让我了解到了知识,也使我收获了友谊。 + +![合照!](https://img.picgo.net/2023/12/28/group77faffd6ec3524b5.png) + +## 五月 + +**2023-05-01 清华开放校园** + +各种游客络绎不绝,奇葩也很多。林子大了什么鸟都有。 + +**2023-05-20 转专业成功** + +![三卡](https://img.picgo.net/2023/12/28/transfer2c7ea716cc14bc8c.jpeg) + +~~成为第一个一年内获得三种校园卡的人。~~ + +**2023-05-24 清华大学第二次退课规则修改** + +期中之后不能退课了。爷青结。~~不过无所谓,不就是从记 W 改为记 F 嘛。~~ + +## 六月 + +**2023-06-02 第一次参加学生节** + +![好好好](https://img.picgo.net/2023/12/28/festivalfdd3e155268193fb.jpeg) + +二胡的音色完美阐释了《风居住的街道》中内蕴的悲伤。 + +美极了! + +**2023-06-03 看 CUBAL 篮球半决赛(清华-北大)** + +很喜欢一句话:一二三四,清华第一;五六七八,北大回家(确信 + +![展示军火(确信)](https://img.picgo.net/2023/12/28/cubal-1648f5e9e37a167c6.jpeg) + +![比分](https://img.picgo.net/2023/12/28/cubal-2e813a96c67ff383b.jpeg) + +**2023-06-05 清华大学秀钟书院成立** + +[清华大学成立秀钟书院](https://mp.weixin.qq.com/s/EgR6swpdhtlwoe5ZI4g0gw) + +什么时候成立远方书院(合并计算机系、软件学院、交叉信息研究院、自动化系) + +~~“远方”出自“莘莘学子来远方”,意指这个书院的学子全部都会润,有专门提供出国留学相关指导的活动。~~ + +**2023-06-17 第一次考英语六级** + +六级翻译真恶心死我了。 + +![CET-6](https://img.picgo.net/2023/12/28/cet-63b293b930c8b51d1.jpeg) + +**2023-06-25 做招生志愿者** + +![赢](https://img.picgo.net/2023/12/28/entrance-19d0105a6fe8abb63.jpeg) + +![又赢](https://img.picgo.net/2023/12/28/entrance-2864a9a253599d01d.jpeg) + +~~成功说服状元报清华,赢!~~ + +**2023-06-28 大一下期末考试,出分了** + +实现绩点自由了。学不懂一点物理,基物毁我人生。 + +## 七月 + +**2023-07-03 前往重庆璧山进行乡村振兴社会实践** + +[回顾一下我的游记](https://leverimmy.top/2023/07/01/2023Chongqing-SocialPractice/) + +**2023-07-08 第一次完成 Sedecordle** + +来点小小的武汉外国语学校学生的英语水平的震撼。 + +![Sedecordle](https://img.picgo.net/2023/07/15/sedecordle0bf968ddcda72642.png) + +**2023-07-11 第一次在抖音上直播** + +[来看帅气照片](https://leverimmy.top/2023/07/01/2023Chongqing-SocialPractice/#day-9) + +## 八月 + +**2023-08-17 收到了小礼物** + +可爱吧! + +![熊!](https://img.picgo.net/2023/12/28/presentbe279d91ecbb3b54.jpeg) + +## 九月 + +**2023-09-10 完成 Java 小学期的大作业** + +GitHub repo: [LeverImmy/NewsApp](https://github.com/LeverImmy/NewsApp) + +博客: [【课程报告】清华大学计算机系暑期课程《程序设计训练》(Java) 大作业报告(2023 夏)](https://leverimmy.top/2023/09/10/2023Summer-Java/) + +**2023-09-17 和学弟学妹们吃饭** + +武外人,无外人! + +![合照](https://img.picgo.net/2023/12/28/schoolmate7a11be6910be71b5.jpeg) + +**2023-09-22 第一次参加学校里的英语角** + +![英语角](https://img.picgo.net/2023/12/28/english-corner0ee5f0d5d2b3741c.jpeg) + +**2023-09-29 第一次由于压力太大 gap 一天** + +> 既然今天准备 GAP 一天,那就得好好利用起来。 +> +> 早上睡到了 10:30 才起床,整个人都舒服了许多。翻了翻我手环上的睡眠记录,我已经差不多两周每天睡眠时长不超过 6 小时了。今天可算是让我好好补了回来。 +> +> 下午本来准备去找老师指导学习和科研方向的,结果到了东主楼门口才发现今天是节假日。这次讨论,也就顺理成章地被咕到了 8 号,因为“那天上周五的课”。 +> +> 一个人晃晃悠悠去五道口解决了晚餐。去喜家德吃了一份水饺,还有几个肉丸。可能是店员看到我中秋节居然一个人肯定好孤独吧,临走之前还祝福我了一句“中秋节快乐,欢迎下次光临!”不知道为啥,但我当时哭了。 +> +> 晚上迫不及待地跟外婆、爷爷奶奶、父母(还有我!弟!)打了电话。这次我先主动跟老人家们打了电话问候了几句,而不是被动地让爸妈提醒我,我还有点小自豪,觉得自己长大了懂事了。 +> +> 最后去紫操逗留了一会儿,然后去打篮球了。熄灯后跟风给月亮来了张特写。我觉得我这个手机只能拍出最难看的月亮吧。不对,是最难看的光斑。 +> +> 我不太会用文字细腻地抒发自己的情感,写的英文诗也都是隐喻之类的。今年中秋的感想也大抵如此吧? +> +> “但愿人长久,千里共婵娟。”也祝朋友圈的各位中秋快乐! + +## 十月 + +**2023-10-11 高中时的转笔哥在武大被记过了** + +[关于我在武汉大学图书馆受到性骚扰这件事](https://mp.weixin.qq.com/s/Cxcc1eciR-MA7MRNv3mbvA) + +**2023-10-13 学会了手巾花** + +**2023-10-17 加入校答疑坊,第一次线下值班!** + +![终于加入校答疑坊了!](https://img.picgo.net/2023/12/28/volunteerb51844dd76d97200.png) + +**2023-10-22 参加了第十五届北京市体育大会毽球选拔赛** + +14 支队伍,分为 A B C D 四个组,每组前两名出线。我们在 C 组,只有三支队伍,其中有一支弃权,没来参赛。 + +小组内打那个没弃权的队伍,没赢;出线(晋级八强)后的淘汰赛,也没赢。 + +结果是一局没赢的我们最后并列第五。 + +~~不知道这是什么运气。~~ + +![野少有事儿先走了,缺他的合影](https://img.picgo.net/2023/12/28/bj-shuttlecockdcd89b43708b474f.jpeg) + +**2023-10-27 李克强总理逝世** + +愿逝者安息。 + +## 十一月 + +**2023-11-23 代表计算机系参加2022-2023学年度马杯毽绳比赛** + +![转系后的第一次](https://img.picgo.net/2023/12/28/shuttlecock-loop9d88c5efd679ddc4.jpeg) + +三人围踢 3 分钟,甲组第二。菜就多练!明年继续挑战。 + +**2023-11-27 人大在烤鹅腿卡脖子技术上遥遥领先!** + +[自主研发,抢先上市,人大食堂突破烤鹅腿卡脖子技术](https://mp.weixin.qq.com/s/zyQ2LmCZw8xzkU00fQ5kgA) + +## 十二月 + +**2023-12-11 第一次见到这么大的雪** + +![你就说帅不帅吧](https://img.picgo.net/2023/12/28/snowman46eba5251875095b.jpeg) + +自己搞了个雪人。 + +**2023-12-16 参加第二次英语六级考试并被人挂在小红书上了** + +**2023-12-22 王希勤卸任清华大学校长** + +最佳梗图: + +![1](https://img.picgo.net/2023/12/28/emoji-19d945499c88aa2c1.jpeg) + +![2](https://img.picgo.net/2023/12/28/emoji-2a046537180cf0dec.jpeg) + +## 总结 + +转专业成功了。 + +遇见了志同道合的知心朋友。 + +感觉自己融入了新的集体。 + +也不知道新的一年,又会是怎样的情况呢? diff --git "a/source/_posts/\343\200\220\346\270\270\350\256\260\343\200\2212023\346\232\221\345\201\207\351\207\215\345\272\206\347\222\247\345\261\261\344\271\241\346\235\221\346\214\257\345\205\264\345\256\236\350\267\265.md" "b/source/_posts/\343\200\220\346\270\270\350\256\260\343\200\2212023\346\232\221\345\201\207\351\207\215\345\272\206\347\222\247\345\261\261\344\271\241\346\235\221\346\214\257\345\205\264\345\256\236\350\267\265.md" new file mode 100644 index 0000000..de57e23 --- /dev/null +++ "b/source/_posts/\343\200\220\346\270\270\350\256\260\343\200\2212023\346\232\221\345\201\207\351\207\215\345\272\206\347\222\247\345\261\261\344\271\241\346\235\221\346\214\257\345\205\264\345\256\236\350\267\265.md" @@ -0,0 +1,526 @@ +--- +title: 【游记】2023 暑假重庆璧山乡村振兴实践 +tags: + - 生活 + - 重庆 + - 璧山 + - 乡村振兴 + - 暑期实践 +categories: + - 游记 +mathjax: true +toc: true +date: 2023-07-01 21:41:16 +password: +id: 2023Chongqing-Social-Practice +--- + +暑期实践?这是什么?参加一个! + +乡村振兴?这是什么?了解一下! + +重庆璧山?这是哪里?拜访一次! + + + +## 2023-07-01 Day -1 + +窝在家里修整自己的博客,似乎这样在进行实践的时候就能留下一些记忆。 + +~~虽然但是咱支队也有宣传组,那我自封为宣传组副副副副副副副组员好了。~~ + +清理自己的行李箱。并不知道该干啥。 + +不如睡大觉。 + +## 2023-07-02 Day 0 + +早上 06:30 起床,已经很久没有这么早起床了。似乎我早就已经成为懒狗大学牲了。 + +![汉口站](https://img.picgo.net/2023/07/03/hankoub29bd177e526a4cb.jpeg) + +人是真的多。 + +![多](https://img.picgo.net/2023/07/03/crowded85b25028ae40d35a.jpeg) + +中午实在是饿得不行,早上忘记买泡面了,结果一个傻傻的怨种在高铁上斥重金买了盒饭(但有一说一,cvoodoo 推荐的还真没错,这个红烧肉还挺好吃)。 + +![枣香红烧肉盒饭](https://img.picgo.net/2023/07/03/stupid-lunch7d12bca2d67e5817.jpeg) + +在高铁上看了一章多一点的《数理逻辑与集合论(第2版)》,觉得开头很容易,但简略地翻了一下后面的章节,感觉形式化的语言总归还是晦涩的。 + +重庆是山城吧。沿路能看见远处的山脉像水粉一般淡淡地作为背景。 + +![高楼背后的山](https://img.picgo.net/2023/07/03/mountain16d7fb18dd72177b0.jpeg) + +下午搬行李办住宿手续。这里的住宿条件是真的好,不是民宿,而是公寓。~~唯一的缺点可能是没有 Wi-Fi?并且流量的信号也不是很好。~~ + +![我的卧室](https://img.picgo.net/2023/07/03/apartment1193170499eb1e473.jpeg) + +![客厅甚至有个大电视](https://img.picgo.net/2023/07/03/apartment246bd9d1d283cc855.jpeg) + +晚上和支队长 zzc,初中同班同学(且高中同学)gyc 在公寓旁边找了一家餐馆吃饭,属实是给了我这个武汉人一点小小的重庆震撼。 + +首先是时蔬汤。12元一大碗清水煮白菜,其实挺划算,汤也挺好喝,主要是这个白菜是真的好吃,而且量真的多。 + +![时蔬汤](https://img.picgo.net/2023/07/03/vegetable-soupef07179a7351f8db.jpeg) + +其次是来凤鱼。超大一盘,量多味辣,十分好吃。 + +![来凤鱼](https://img.picgo.net/2023/07/03/laifeng-fish87f62296bb273f42.jpeg) + +~~我们三个都不敢相信 150 块钱能吃到这么多。感觉被北京 PUA 了。~~ + +回到寝室里继续看《数理逻辑与集合论(第2版)》。然后补了补博客,帮同学调了调代码。 + +## 2023-07-03 Day 1 + +呃呃,凌晨一点钟了还没睡觉。在干嘛?在学 [麻将](https://www.bilibili.com/read/cv2841976)。 + +早上参观了两个公园。 + +![云中巴士](https://img.picgo.net/2023/07/04/skyshuttlea16c1a745d55184f.jpeg) + +解锁了新的交通工具——“云中巴士”。我觉得这大概是公交车的大小的轻轨。重庆地铁在璧山区只有一站,而且该站处于璧山区的边缘(中心城区和璧山区的接合部)。由于璧山区没有资格/实力/地位修建属于自己的地铁/轻轨线路,因此,“云中巴士”应运而生。 + +![花](https://img.picgo.net/2023/07/04/flower1095fdb88ff8f2591.jpeg) + +这个是由花构成的梯田,镶嵌性的布局展示出了层次感。 + +以下是从两个视角拍的同一座亭子的风景照。 + +![你看右下角湖面上的蜗牛石塑](https://img.picgo.net/2023/07/04/tree1e8b1fc86aeca3c28.jpeg) + +![哇](https://img.picgo.net/2023/07/04/tree2806908af907da385.jpeg) + +下午参观了高新产业园区。~~byd 参观 byd 是吧。~~ + +我们参观的厂房是电池以及新能源相关,我啥都不会。磷酸铁锂的化学式都差点忘了。 + +![BYD](https://img.picgo.net/2023/07/04/byd10497423e929d1a8.jpeg) + +晚上和政府对接人员一起吃正宗的重!庆!火!锅! + +![重庆火锅](https://img.picgo.net/2023/07/04/hotpot12bb3c398013b9ca0.jpeg) + +我觉得比较有特色的是它的碟,被称为油碟,因为最重要的是“香油”。~~但这里没有芝麻酱。很难想象没有芝麻酱怎么吃火锅,对吧?~~ + +![碗1](https://img.picgo.net/2023/07/04/plate1081e5d3885051f34.jpeg) + +![碗2](https://img.picgo.net/2023/07/04/plate2338af4b3ba7c520d.jpeg) + +你看这个碗,它有两段。右边这一段是用来滤油的。太高级了。 + +回到公寓,洗了澡之后又是学麻将+帮同学调代码一直干到了凌晨。困。 + +## 2023-07-04 Day 2 + +美滋滋睡懒觉,早上八点二十才起床。匆匆忙忙吃完早餐,乘坐大巴到区政府参加座谈会。 + +人生中第一次,我的名字竟然能被写在名牌上,倍感荣幸。 + +![名牌](https://img.picgo.net/2023/07/04/meeting7c079dcd27184522.jpeg) + +还是说说我对“乡镇引入优秀人才”这一政策的思考吧。就个人而言,我觉得所有的政策都是很好的,给的福利也很多;但是,我觉得 **子女受教育机会** 这一点很难得到满足与保障。乡镇最大的困难可能是教育资源贫乏,而受良好教育(尤其是义务教育阶段)又是我比较看重的,所以我以后可能就不会考虑选调下沉农乡基层。哦,当然我以后的思维观念也有可能转变,不过到时候再说吧。 + +中午去政府单位的食堂吃了午饭,然后回公寓睡了一觉。很爽。 + +下午参观大圆祥博物馆。“一个博物馆,就是一所大学校。”此言不假。 + +![风景](https://img.picgo.net/2023/07/04/tree2141c17db35d54a98.jpeg) + +![大圆祥博物馆](https://img.picgo.net/2023/07/04/museumf13cc9b954741648.jpeg) + +大圆祥博物馆不同于其他常见的博物馆,它取址与自然中,展览的物品大多是石雕、木雕(包括木门、木牌匾、木床、木桌椅板凳等),它们都没有被放入玻璃橱窗中,而是真切地被展览在你的面前。~~理论上可以直接摸到这些展览品,但有警告标语禁止触碰。~~ 而且室外也有展览,石狮子、石门。~~有的上面甚至有蜘蛛网。~~ + +![石雕1](https://img.picgo.net/2023/07/04/skulpture956074b8b61cbf47.jpeg) + +![石雕2](https://img.picgo.net/2023/07/04/skulpture2decc6f965d93187f.jpeg) + +这是什么?这是“情侣凳”。一对情侣坐在上面,视线夹角就是 $90^\circ$ 而不是并排坐的 $0^\circ$ 了,这样~~更加暧昧~~能增进感情。 + +而且这玩意儿一个人会坐不稳,必须得两个人平衡重量。 + +![情侣凳](https://img.picgo.net/2023/07/04/bench3290e654cf691d9e.jpeg) + +哦,忘了说,一个桌子加一个情侣凳要两万块钱。买不起。 + +![牌匾](https://img.picgo.net/2023/07/05/wood1582cb476bf279129.jpeg) + +![木制品](https://img.picgo.net/2023/07/05/wood2f12c60dd31ab8be5.jpeg) + +晚上在博物馆旁边吃的农家乐。 + +![大碗菜](https://img.picgo.net/2023/07/04/foodfa8e76e5c8b07313.jpeg) + +还久违地碰到了只因哥哥。不知道他是否能够挺过这段时间。 + +![只因](https://img.picgo.net/2023/07/04/rooster9f7d8fd72832d13a.jpeg) + +晚上很累。在楼底下超市买了一些水果和饼干,但发现并不好吃。不如睡大觉。 + +## 2023-07-05 Day 3 + +早上到达喜观振兴驿站。这里是重庆市璧山区七塘镇。 + +感觉这个驿站类似于党员群众服务中心,设施挺齐全的。 + +![里边](https://img.picgo.net/2023/07/05/insidea0e810e46688bcb8.jpeg) + +![外边](https://img.picgo.net/2023/07/05/outside150f67db02c20b08.jpeg) + +田间有很多民间艺术家就地取材,用稻梗制作出了一件件艺术品。这里确实和川美合作很多。 + +![这应该是狗……吧?](https://img.picgo.net/2023/07/05/dogb8618324dcaa9645.jpeg) + +![惬意地躺在地上的人](https://img.picgo.net/2023/07/05/lay2a00e76ec8ab7bad.jpeg) + +化身成草帽吉米。准备入户调研采访。 + +![这是带着草帽的我](https://img.picgo.net/2023/07/05/selfie6ccbc8bbbe7faa2f.jpeg) + +![这也是带着草帽的我](https://img.picgo.net/2023/07/05/shadow1ff87d538f87fd54.jpeg) + +呃呃,“四体不勤五谷不分”说的就是我。~~我说武汉话,这位爷爷说重庆话,我们竟然能对话?~~ + +{% video ../../../../gallery/journal-2023-07-03-Chongqing/day3/interview.mp4 %} + +这是村民养的鸭。有纯白的鸭鸭。 + +![鸭鸭](https://img.picgo.net/2023/07/05/duckbdfeda7cf477ac48.jpeg) + +采访完毕后,感慨颇深。怎么说呢。政府政策是很好,乡村振兴这战略那战略,但是落到每家每户上呢?墙的外表是刷了新的墙面,但是内部还是原来的样子;未经村民同意,在村民不在家的时候把厨房拆了,之后再还建到别处;电线报给物业修理 3 月份的事儿现在还没办成…… + +哎,哥哥。 + +![只应](https://img.picgo.net/2023/07/05/stone-chicken9808f53e0ad9a3d5.jpeg) + +晚上外卖点了西瓜果切和两斤荔枝。比超市里的好吃多了。 + +## 2023-07-06 Day 4 + +早上八点钟闹钟响了,我延时了 5min,然后睡着了。然后就没有然后了。 + +The next thing I knew was that 支队长在敲公寓的大门(我在卧室里被吵醒了)。 + +迟到了 10 分钟。我愧疚的很。 + +早上和艺术家座谈,感受到了艺术家们想尝试改变整个乡村发展的热忱。 + +![与艺术家座谈](https://img.picgo.net/2023/07/08/artist-meetingf5519c46fb292d20.md.jpeg) + +![问问题](https://img.picgo.net/2023/07/08/i-ask-artist30fe99c845ad977b.md.jpeg) + +我这个毛小子还问了个问题。挺好。 + +下午在干啥?下午其他人是在为之后的“助农直播”进行筹备。我应该是在整理早上的会议记录。 + +看看晚霞吧! + +![晚霞](https://img.picgo.net/2023/07/08/sunsetc83cd54f030a811a.jpeg) + +看看乡村的鸡鸭。鸭子没有在喝水,而是在用水梳理自己的羽毛。右边的鸡啄了左边的鸡一下。 + +唉,哥哥。 + +{% video ../../../../gallery/journal-2023-07-03-Chongqing/day4/chicken.mp4 %} + +晚上开始准备明天和重庆医科大学的同学交流会的 PPT。睡的挺晚的。 + +哎,一整理出来,感觉这一天我没干啥事儿。这比昨天的事儿可少多了。 + +## 2023-07-07 Day 5 + +好消息:今天早上没迟到。但早饭不是很好吃。有烧麦,但真难吃。纯米,没有肉。 + +早上去拜访大兴镇白深富故居进行党性教育。太阳是真的大。 + +![白深富故居](https://img.picgo.net/2023/07/07/old-house1459e43d47e5e9546.jpeg) + +我们是在类似于一个四合院里,顶着大太阳,听一个老师傅讲解故事。大概听了 1 个小时吧。之后我们才进入故居进行参观。虽然带有重庆口音的普通话我不能完全听懂,但是大致意思我理解了。我们也为白深富同志默哀了半分钟。我几乎要被热到融化了,但最终还是挺了下来,感觉这也能算是党性教育的一部分吧。 + +![入团宣言和入党宣言](https://img.picgo.net/2023/07/07/old-house24e87b0f9e152e13a.jpeg) + +![白深富的床](https://img.picgo.net/2023/07/07/old-house3a7a4857e1700d3e6.jpeg) + +![白深富的灶台](https://img.picgo.net/2023/07/07/old-house4302259907e982577.jpeg) + +下午和重庆医科大学的同学们进行交流学习。这是一个突然插播的项目,起因是我们在振兴驿站里碰到了他们,对方老师很热情,希望和我们进行一些交流,于是就有了这么一个交流会。我作为汇报人,讲了好长时间。首先是大约说了一下前几天我们支队对艺术乡建的调研成果;然后我还分享我查找到的关于“数字化乡村振兴新模式”的一些已有成果(上知网查的论文)和我自己的看法;最后进行了破冰会,认识了一些新的同学吧。 + +![我做的逆天 PPT](https://img.picgo.net/2023/07/07/PPT88808d34db0c9e2f.png) + +![合影](https://img.picgo.net/2023/07/15/CQMU9c78b958469f6335.jpeg) + +晚上在写 Wordle,完成度似乎还可以?一共写了 7kB 的代码,就当是代码能力复健吧。 + +实际上是练习使用 STL,有一说一,`std::string` 是真好用。~~妈的,字符数组就应该被废除掉。~~ + +![代码长度](https://img.picgo.net/2023/07/07/code-lengthd3d342bd1e9e5c6f.png) + +自己玩了一下,感觉这单词的难度一言难尽。 + +![垃圾数据](https://img.picgo.net/2023/07/07/rubbishc65eab1b105a5cff.png) + +~~其实倒数第二次的猜测表明我的代码有问题,第一个 p 应该是红色的。~~ + +不知不觉,又已经十二点了。一天又结束了。 + +## 2023-07-08 Day 6 + +早上与重庆校友会的学长学姐进行了交流座谈。个人感觉收获很多。 + +> 刘书记 +> 1. 安徽待了六个星期,听不懂话。大学的传承,社会实践的深度传承下去。 +> 2. 乡镇党委书记,乡村振兴是我工作的主业之一。结合我的工作,跟大家聊一下乡村振兴的看法。今天你们分享的,是直观观感上的感受。其实,乡村振兴是有顶层设计的。 +> - 产业振兴。文创,是产业的一部分。第一要务:我种什么。文化与旅游附着的基础是什么?是基础。安全垫在哪里?在种植产业。粮食安全。为什么有荒地?种一亩亏一亩。粮食一年内间种蔬菜。产业振兴的基础是什么?是种植业。 +> - 人才振兴。很少有年轻人。人才是需要有回报的,使用市场化的方式撬动。先富带后富。“村民永远不会相信你说什么,只会看你干成了什么。”更重要的是运营人才。 +> - 文化振兴。接受市场,接受契约。 +> - 生态振兴。深入农村的时候,有没有臭味儿。有没有蚊虫。 +> - 组织振兴。组织是什么?村委会和党支部合一。小合作社带动大合作社。 +> 3. 乡村振兴的三个层次。 +> - 获得一些新的认知。 +> - 体会一种生活方式。 +> - 认识一种价值体系。 + +哎,也不知道自己会不会走选调这条路。 + +中午想着自己既然已经写过 [Wordle](http://wordlegame.org/) 了,不如继续玩玩。于是尝试玩了一下 [Sedecordle](https://sedecordlegame.org/)。个人认为宝刀未老。一局足足让我玩了半个小时。 + +![Sedecordle](https://img.picgo.net/2023/07/15/sedecordle0bf968ddcda72642.png) + +下午去玩了一下振兴驿站旁边的昆虫王国。 + +{% video ../../../../gallery/journal-2023-07-03-Chongqing/day6/playground.mp4 %} + +这儿的儿童游乐设施还挺多。身边的很多同学都说我很“天真”,我觉得也是,我希望能在我逐渐长大的过程中仍保存我内心中最柔弱、最青春的那一部分。~~比如看看我体验儿童游乐设施。~~ + +![荡秋千](https://img.picgo.net/2023/07/16/swing1851446318cdee27.jpeg) + +![练平衡力1](https://img.picgo.net/2023/07/16/balance1cfd28f96c274789e.jpeg) + +![练平衡力2](https://img.picgo.net/2023/07/16/balance2eb652383dfc16f4e.jpeg) + +拍了一张很有意思的帅照(我认为挺帅的)。 + +![帅照](https://img.picgo.net/2023/07/15/handsomedd39ad2e5390625c.jpeg) + +看看只因哥哥。 + +![鸡](https://img.picgo.net/2023/07/15/chicken1b333eed6cc77a94.jpeg) + +夕阳真美呀。 + +![夕阳](https://img.picgo.net/2023/07/15/sunsetd30257d8bba23101.jpeg) + +晚饭在“农家小院”吃的。柴火鸡还是很好吃的。这相当于一个灶台,直接在灶台边吃饭,锅边还能贴很多类似于锅盔的“玉米粑粑”。这样做有一个巧妙的地方,就是可以通过观察粑粑的颜色(以及是否烤枯了)来判断柴火鸡的火候是否到位。 + +![玉米粑粑](https://img.picgo.net/2023/07/15/corn58d6741d76ba18f7.jpeg) + +![柴火](https://img.picgo.net/2023/07/15/firewood0e9f91a8b1390373.jpeg) + +然后就回公寓了。晚上干了啥?看了看一本 Python 的入门书籍,然后就睡大觉了。 + +## 2023-07-09 Day 7 + +早上参观了葡萄园。我们看到了阳光玫瑰葡萄。还有夏黑葡萄。 + +值得一提的是,我两种都吃了。很好吃。 + +![阳光玫瑰葡萄](https://img.picgo.net/2023/07/15/green36e48b7cf2a3a6d4.jpeg) + +![夏黑葡萄](https://img.picgo.net/2023/07/15/black756a201db920ef05.jpeg) + +{% video ../../../../gallery/journal-2023-07-03-Chongqing/day7/grapes.mp4 %} + +下午在振兴驿站修整。然后又看了很长时间的 Python 入门书籍。 + +晚上在写直播文案。大概想了想自己会说啥,以及整个的流程。 + +## 2023-07-10 Day 8 + +一整天都在准备直播的事情。 + +感觉没啥好写的。 + +~~真的不是因为我懒。~~ + +下午试播了一次。天气真的是热。我被烤熟了。 + +## 2023-07-11 Day 9 + +> 直播日。 + +![早上的点赞](https://img.picgo.net/2023/07/15/data14b205f8024c60a06.jpeg) + +下午我就去直播了。天气是真**热。比昨天还热。整张照片贴上来算了。真的累。 + +![下午直播](https://img.picgo.net/2023/07/16/afternoon19ece15476532616.jpeg) + +晚上在“农家小院”吃播。 + +![晚上吃播](https://img.picgo.net/2023/07/15/eat95407edc6e113d48.jpeg) + +我也有分享学习经验。跟 gyc 一起文理双子星嘎嘎乱说话。 + +![分享学习经验](https://img.picgo.net/2023/07/15/study02d692468a3ea592.jpeg) + +![总直播数据](https://img.picgo.net/2023/07/15/data2a0fb26904f5878fa.jpeg) + +~~累计 9.8 万赞呢。~~ + +其实我们下播是因为说了某个人的名字,我们也只是在歌颂他的英明政策的时候提及了他的名字。然后就被封禁了 10 分钟。~~封禁信息可以从上面那张截图里看到。~~ + +好累。晚上睡大觉! + +## 2023-07-12 Day 10 + +昨天的直播意犹未尽。早上昏昏沉沉地去了振兴驿站。 + +然后开始直播咱支队策划的艺术品展览。 + +中途抽了两次奖品。~~我过硬的手速使得~~我抽中了一份纪念品。 + +中午把 Python 的一本入门书籍看完了。自我感觉良好。准备回家之后学会怎么写爬虫。 + +下午结束之后把展览撤掉了。拿到了纪念品。嘻嘻。 + +![纪念品](https://img.picgo.net/2023/07/15/souvenir68aa3ce795cb7e6d.jpeg) + +晚上跟 wyq(a.k.a. 永琪哥)一起吃了“外婆面”的重庆小面。去之前买了香酥芝麻鸭。好吃。 + +![香酥芝麻鸭1](https://img.picgo.net/2023/07/15/sesame-duck1ea5a8d812d316776.jpeg) + +![香酥芝麻鸭2](https://img.picgo.net/2023/07/15/sesame-duck23ed11a448341a3f0.jpeg) + +![重庆小面](https://img.picgo.net/2023/07/15/Chongqing-Xiaomian526a0114f75beca6.jpeg) + +偶遇颜值很高的猫学姐。 + +![猫学姐1](https://img.picgo.net/2023/07/15/cat133a009fc6a7647f3.jpeg) + +![猫学姐2](https://img.picgo.net/2023/07/15/cat29683d9bd836c9559.jpeg) + +![猫学姐3](https://img.picgo.net/2023/07/15/cat363359a8d22d7aa19.jpeg) + +晚上在跟支队的部分同学一起打牌。虽然我斗地主一直输,但德州扑克还是赢了几把的。 + +明天没有事儿,那就睡大觉! + +## 2023-07-13 Day 11 + +很难想象我是几点钟起床的。11:50!准确地讲,是 8:50 闹钟响了,起来看了眼手机,然后又躺了下去。~~再次睁眼已经是中午了。~~ + +cvoodoo 说得好,这个时间点起床反而比 10:00 起床要舒服,~~因为不用纠结要不要吃早饭了。~~ + +吃完午饭水了一下 B 站,然后粗略地看了看 [计算机系学生科协技能引导文档](https://docs.net9.org/),觉得这个暑假能学的东西还挺多。 + +然后又想到这几天 [计算机系暑期培训](https://summer23.net9.org/) 似乎漏了一两节课。 + +看一眼讲义。原来是 Web 啊。不会。 + +再看一眼讲义,还是不会。~~再多看一眼就会爆炸。~~ + +不想用流量看回放。这些还是回家再说吧。 + +然后就开始睡午觉了。此时 15:40。 + +一觉醒来已经是 17:00。出门准备去昨天吃的那家面馆吃豌杂面。结果关门了~~(当然,也有可能是还没开门)~~。 + +于是去旁边的一家面馆吃了红油抄手。好吃。 + +![还加了个煎蛋,美滋滋](https://img.picgo.net/2023/07/15/chaoshoub04b951d22b9321b.jpeg) + +旁边有一家蜜雪冰城。是熟悉的芝士奶盖绿茶,当初是高中每周放学帅会带我喝的。~~现在帅带我喝瑞幸。喝的东西变了,兄弟没变。~~ + +失误了,没说要半糖,店员给我加了全糖。太甜了。 + +晚上开始补博客。我给了一个比喻是“像是高三拖欠了很久作业就再也不想补以前作业的感觉”。 + +cvoodoo 锐评: + +> 不用高三 +> 像是两个月前拖欠了几节课就再也不想去上课的感觉x + +晚上没事儿干,于是和支队里部分同学一起出去吃了海底捞。~~店里有芝麻酱,好评!~~ + +![海底捞](https://img.picgo.net/2023/07/15/hotpot819b4bf10fc9ac69.jpeg) + +![凌晨人还很多](https://img.picgo.net/2023/07/15/peoplec8a3eda96233f2ed.jpeg) + +![吃吃吃](https://img.picgo.net/2023/07/15/eatfbf8ace0ac36deef.jpeg) + +和海底捞的店员互动,石头剪刀布三局两胜,我 2-0 获得了一个小玩具。 + +![拼装恐龙](https://img.picgo.net/2023/07/15/dine-sauraeb9c3327fd2a099.jpeg) + +~~《适龄:3 岁及以上》~~ + +然后回公寓一直打牌到了凌晨四五点。斗地主和德州扑克都挺好玩的,而且我运气挺好,感受到了赢的乐趣。~~但感觉还是不如日麻。~~ + +明天应该也确实没我啥事儿。我不用说话,只需要听支队长汇报就行了。~~我只需要保证自己不在会上睡着就行(~~ + +## 2023-07-14 Day 12 + +呃呃。今天要去向政府汇报了。 + +早上十点五十起床的。还行,起码睡了五个半小时(多)。 + +傻了吧唧地到政府机关吃午饭,肚子其实挺饱的,也没吃多少。 + +吃完了午饭速速到达会议室,然后开始等待。~~毕竟我们是十二点半到达的会议室,但会议两点才开始。~~ + +![会议室](https://img.picgo.net/2023/07/15/meeting-roome529bec0014dffd1.jpeg) + +~~唉,支队汇报。没意思。~~ + +晚上支队一起吃了顿饭。其他菜都挺好吃的,就是小龙虾不太行。~~不如回武汉再多吃几顿小龙虾。~~ + +![饭饭](https://img.picgo.net/2023/07/15/diningc6b78bf8ced611ce.jpeg) + +然后走到洪崖洞拍了拍照,夜景十分华丽。~~人也是真的多。~~ + +![傍晚](https://img.picgo.net/2023/07/15/dusk01582280da64fb3f.jpeg) + +![洪崖洞](https://img.picgo.net/2023/07/15/Hongyadong5aecd6a57293ac65.jpeg) + +![桥](https://img.picgo.net/2023/07/15/bridgec3c4c7c90770ea1a.jpeg) + +之后又走到鹅岭二厂去了。拍了几张店铺都关门了的照片。下次得早点来游玩,晚上关门了之后黑灯瞎火的,有点吓人。Errie. + +![鹅岭二厂](https://img.picgo.net/2023/07/15/ELECb17b5db0fd065abf.jpeg) + +很难想象今日步数突破 2 万。很久没有走过这么多的路了,腿确实挺累的。 + +晚上和永琪哥在名茗姐房里消灭买多了的冰棒。我吃了一根绿色心情,还吃了一根核桃牛奶。个人认为“天友”这个重庆本土品牌的乳制品还是十分不错的。 + +一起聊天聊到一点钟,~~讲了很多八卦吃到了很多有意思的瓜,~~然后我就回去睡觉了。 + +## 2023-07-15 Day 13 + +早上七点钟永琪哥把他的房门钥匙交给我了,让我帮他还给物业。唉,永琪哥人又帅性格又好。 + +然后又睡到八点。醒了。然后看了看微信,又睡着了。 + +九点零五分正式醒来,收拾好东西回家! + +高铁上没啥意思。一直就在更现在你正在看的[这篇博客](./)。似乎我写了近 6 千字。 + +我一直在想,这一次到重庆璧山的暑期实践到底给我带来了什么。 + +第一次看见田野。 + +第一次参观蔬菜大棚。 + +第一次差点通宵。 + +第一次吃重庆火锅。 + +第一次在政府大楼里开会。 + +第一次使用抖音。 + +第一次进行露脸直播。~~(寒假时我在 b 站上共享屏幕直播过植物大战僵尸)~~ + +这次暑期实践,结识了一帮好朋友,也治好了我“四体不勤五谷不分”的坏毛病。 + +> 谨以此博客,献给 2023 年去重庆璧山实践的时光。 diff --git "a/source/_posts/\343\200\220\350\256\262\344\271\211\343\200\221Android-\345\205\245\351\227\250.md" "b/source/_posts/\343\200\220\350\256\262\344\271\211\343\200\221Android-\345\205\245\351\227\250.md" new file mode 100644 index 0000000..7f7e639 --- /dev/null +++ "b/source/_posts/\343\200\220\350\256\262\344\271\211\343\200\221Android-\345\205\245\351\227\250.md" @@ -0,0 +1,90 @@ +--- +title: 【讲义】Android 入门 +tags: + - Android +categories: + - 讲义 +mathjax: true +toc: true +date: 2024-06-25 00:16:27 +password: +id: Introduction-to-Android +--- + +这是 [2024 年清华大学计算机系学生科协暑期培训](https://summer24.net9.org/) Android 部分的讲义。 + +**前置知识**:Git、Java。 + + + +## Android 简介 + + + +## 课前准备 + +### 环境配置 + +[安装 Android Studio | Android Developers (google.cn)](https://developer.android.google.cn/studio/install?hl=zh-cn) + +[下载 Android Studio 和应用工具 - Android 开发者 | Android Developers (google.cn)](https://developer.android.google.cn/studio?hl=zh-cn) + +> **注意**:目前不支持采用 ARM CPU 的 Windows/Linux 计算机。 + +### Welcome + +```properties title="gradle-wrapper.properties" +distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.9-all.zip +``` + +```kotlin title="settings.gradle.kts" +pluginManagement { + repositories { + google { + content { + includeGroupByRegex("com\\.android.*") + includeGroupByRegex("com\\.google.*") + includeGroupByRegex("androidx.*") + } + } + + maven { url = uri("https://maven.aliyun.com/repository/gradle-plugin") } + maven { url = uri("https://maven.aliyun.com/repository/google") } + maven { url = uri("https://maven.aliyun.com/repository/jcenter") } + maven { url = uri("https://maven.aliyun.com/repository/public") } + mavenLocal() + mavenCentral() + // Modified + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + maven { url = uri("https://maven.aliyun.com/repository/gradle-plugin") } + maven { url = uri("https://maven.aliyun.com/repository/google") } + maven { url = uri("https://maven.aliyun.com/repository/jcenter") } + maven { url = uri("https://maven.aliyun.com/repository/public") } + mavenLocal() + // Modified + mavenCentral() + } +} + +// ... +``` + + + +## 基础知识 + +## 参考资料 + +- 感谢 [Clancy](https://github.com/Clancy-Zhu/) 在 2023 年暑期培训中的 [Android 部分的讲义](https://summer23.net9.org/frontend/android/)。 +- 感谢[菜鸟教程 - Android](https://www.runoob.com/android/),提供了一份详尽但略显复杂的讲义框架。 + +## 课后作业 + +详情请见 [sast-summer-training-2024/sast2024-android](https://github.com/sast-summer-training-2024/sast2024-android)。 + diff --git "a/source/_posts/\343\200\220\350\256\262\344\271\211\343\200\221Java-\345\205\245\351\227\250.md" "b/source/_posts/\343\200\220\350\256\262\344\271\211\343\200\221Java-\345\205\245\351\227\250.md" new file mode 100644 index 0000000..3861734 --- /dev/null +++ "b/source/_posts/\343\200\220\350\256\262\344\271\211\343\200\221Java-\345\205\245\351\227\250.md" @@ -0,0 +1,1484 @@ +--- +title: 【讲义】Java 入门 +tags: + - Java +categories: + - 讲义 +mathjax: true +toc: true +date: 2024-06-25 00:15:14 +password: +id: Introduction-to-Java +--- + +这是 [2024 年清华大学计算机系学生科协暑期培训](https://summer24.net9.org/) Java 部分的讲义。 + +**前置知识**:Git、C/C++、OOP。 + + + +## Java 简介 + +Java 是一种广泛使用的计算机编程语言,于 1995 年由 Sun Microsystems 公司推出。它是一种面向对象的编程语言,旨在减少编程中可能出现的错误,并易于理解和维护。 + +尽管近年来面临一些新兴语言的挑战,Java 由于它的跨平台性、良好的安全性、前向兼容性以及不算差的性能,仍是一门历史地位和业界地位都极其崇高的语言。庞大的 Java 社区和海量的 Java 项目,使得对任何想要接触业界的贵系同学来说,你也许可以不精通它,但至少应当对这门简单、强大、通用的语言有一些了解。 + +![编程语言排名](https://img.picgo.net/2024/07/24/rank3f7238361e89b876.jpeg) + +### 发展历史 + +Java 发明于 20 世纪 90 年代初,由 Sun Microsystems(后来被 Oracle 收购)的工程师团队开发。最初的目标是创建一种用于家电设备的编程语言。1995 年,Java 1.0 正式发布,带来了跨平台的能力,也就是“Write Once, Run Anywhere”(一次编写,随处运行)。这一特性是通过将 Java 代码编译为中间表示形式(字节码)实现的,然后在任何支持 Java 虚拟机(JVM)的平台上运行。 + +随着时间的推移,Java 不仅仅成为一种用于嵌入式系统的语言,它还发展成为一种强大的服务器端、企业级应用、Web 和移动应用的开发语言。 + +### 优势与不足 + +#### 优势 + +1. **跨平台性**:Java 采用“一次编写,到处运行”的理念,代码可以在不同操作系统(Windows、macOS、Linux 等)上运行,无需重新编写。这得益于 Java 虚拟机(Java Virtual Machine,JVM)的设计。 +2. **面向对象**:Java 是一种**纯粹的面向对象编程语言**,支持封装、继承和多态等 OOP 特性,有利于代码的复用和维护。 +3. **安全性**:Java 具有强大的安全机制,如垃圾回收机制(Garbage Collection,GC)、异常处理等,可以有效地防范程序运行过程中的安全隐患。 +4. **丰富的标准库**:Java 附带了大量的标准库,涵盖了网络、图形界面、数据库等各个方面,开发者可以直接调用这些库(而无需重复造轮子),提高开发效率。 +5. **广泛的应用领域**:Java 可用于开发桌面应用程序、Web 应用程序、移动应用程序、大数据处理、机器学习等各种类型的软件。 + +#### 不足 + +1. **性能**:与编译成本地机器代码的语言(例如 C、C++)相比,Java 的性能通常较低。这是因为 Java 程序需要在 JVM 上运行,这增加了额外的抽象层。 +2. **内存消耗**:Java 应用程序通常比其他编程语言的应用程序消耗更多的内存。这是由于其“面向对象”导向的设计和垃圾回收机制。 +3. **冗长的代码**:与一些现代编程语言(例如 Rust)相比,Java 的代码可能显得冗长和繁琐,这也可能会使开发过程变得复杂和耗时。 + +尽管存在这些不足,Java 仍然是世界上最受欢迎和广泛使用的编程语言之一。它在企业级应用程序、移动应用程序(尤其是 Android)和大型系统中得到了广泛应用。 + +## 课前准备 + +### 环境配置 + +要运行 Java 程序,你需要先安装 Java Developer Kit(JDK)。Windows 或 Mac 用户建议直接在 Oracle 官网[下载 JDK21](https://www.oracle.com/java/technologies/downloads/#java21);而 Linux 用户(这里以 Ubuntu 为例,其余平台请自行百度 / Google)则可以使用如下命令: + +```bash +sudo add-apt-repository ppa:linuxuprising/java +sudo apt update +sudo apt install oracle-java21-installer --install-recommends +``` + +本教程将使用 JDK21 这一版本。请使用 `java -version` 命令来确认 JDK 是否安装完成(以下输出仅供参考): + +``` +java version "21.0.3" 2024-04-16 LTS +Java(TM) SE Runtime Environment (build 21.0.3+7-LTS-152) +Java HotSpot(TM) 64-Bit Server VM (build 21.0.3+7-LTS-152, mixed mode, sharing) +``` + +你可以使用如下命令编译运行 Java 程序: + +```bash +javac YourProgram.java # 编译 +java YourProgram # 运行 +java YourProgram.java # 编译 & 运行 +``` + +同时,本教程将使用,也强烈推荐使用 [IntelliJ IDEA](https://www.jetbrains.com.cn/idea/) 作为 IDE 来辅助开发。如果你就读于清华大学,建议使用 `<你的邮箱名>@mail.thu.edu.cn` 来获取[面向学生和教师的个人许可证](https://www.jetbrains.com.cn/community/education/#students),以获得“Ultimate Experience”(类似于 Professional 版本)。 + +### Hello world! + +在 IntelliJ IDEA 中,点击 File-New-New Project... 新建一个新的项目,项目名为 `hello-world`: + +![新建一个新的项目](https://img.picgo.net/2024/07/24/create-new-projecta43ca141ce16cc4e.jpeg) + +IDEA 会自动生成一个 demo 代码,代码内容如下: + +```java Main.java +public class Main { + public static void main(String[] args) { + System.out.println("Hello world!"); + } +} +``` + +点击右上角的“编译并运行”按钮。 + +![编译并运行后的输出界面](https://img.picgo.net/2024/07/24/compile-and-run55c1c0b56df66150.jpeg) + +如果你的程序输出:`Hello world!`,那么,你已经能够成功编译并运行 Java 程序了! + +最后,请在 GitHub 上 fork [sast-summer-training-2024/sast2024-java](https://github.com/sast-summer-training-2024/sast2024-java) 至自己的账户,并使用 Git 将**自己账号**下的仓库 clone 至本地。 + +至此,课前准备环节结束。 + +> 另外,[sast-summer-training-2024/sast2024-java](https://github.com/sast-summer-training-2024/sast2024-java) 中的代码是使用 Gradle 构建的,并且带有单元测试。具体而言,使用 Gradle 构建的代码结构可以按照以下方式创建: +> +> ![创建带有测试的代码结构](https://img.picgo.net/2024/07/24/create-with-tests09feaa6ac3eea616.jpeg) +> +> 你也可以尝试运行 demo 代码。你可能会发现,输出十分冗长,但是其中应该也是有 `Hello world!` 的。 + +## 基础语法 + +Java 的基础语法与 C++ 较为类似。以下代码均包含于 `src/main/java/examples/introduction` 中。 + +### 输入输出 + +```java IOExample.java +package examples.introduction; + +import java.util.Scanner; + +public class IO { + public static void main(String[] args) { + // Console Output + System.out.println("This is an output with a new line."); + System.out.print("This is an output without a new line."); + System.out.println("So this sentence will appear right after the last one."); + + // Console Input + Scanner input = new Scanner(System.in); + System.out.print("Enter your name: "); + String name = input.nextLine(); + System.out.print("Enter your age: "); + int age = input.nextInt(); + System.out.println("Hello " + name + ", you are " + age + " years old!"); + } +} +``` + +这个程序中展现了 Java 中基础的输入输出方式。相较于 C++ 而言,输入输出所用函数名较长,但也并不繁琐。 + +### 变量 + +Java 中的变量类型和 C++ 类似,但也有细微的差别。 + +#### 整型数:`byte`、`short`、`int` 和 `long` + +| 类型 | 大小 | 最小值 | 最大值 | +| :-----: | :------: | :---------------------: | :-------------------: | +| `byte` | $1$ 字节 | $-2^7 = -128$ | $2^7-1 = 127$ | +| `short` | $2$ 字节 | $-2^{15}=-32768$ | $2^{15}-1=32767$ | +| `int` | $4$ 字节 | $-2^{31} = -2147483648$ | $2^{31}-1=2147483647$ | +| `long` | $8$ 字节 | $-2^{63}$ | $2^{63}-1$ | + +#### 浮点数:`float` 和 `double` + +在 Java 中,浮点数字面量可以写为 `123.45`、`.5`,或 `321.4f` 等。其中以 `f` 结尾的浮点数字面量是 `float` 类型,其余均为 `double` 类型。因此,以下的语句是不合法的: + +```java +float doubleVariable = 3.1415; +``` + +#### 布尔型变量:`boolean` + +在 Java 中,布尔型变量用 `boolean` 来定义,而非像 C++ 一样使用关键字 `bool`。 + +#### 字符:`char` + +在 Java 中,`char` 类型用于表示 Unicode 字符,而不是 ASCII。每个 `char` 类型的变量可以存储一个 Unicode 码点,其数值范围从 $0$ 到 $65535$(即 $\text{0xFFFF}$)。这意味着 Java 的 `char` 类型甚至能够表示汉字。 + +#### 数组 + +在 Java 中,推荐将数组的定义(`[]`)写在类型后面,例如 `int[] arr`、`String[][] array_2d` 等,而非 `double xs[]`。 + +#### 代码示例 + +```java VariablesExample.java +package examples.introduction; + +public class Variables { + public static void main(String[] args) { + // Integers + byte byteVariable = 123; + short shortVariable = 12345; + int intVariable = 1234567890; + long longVariable = 1234567890123456789L; + + // Floating-point Numbers + float floatVariable = 3.14f; + double doubleVariable = 3.14159265358979; + + // Character + char charVariable = 'A'; + + // Boolean + boolean booleanVariable = true; + + // Printing the values + System.out.println("byte: " + byteVariable); + System.out.println("short: " + shortVariable); + System.out.println("int: " + intVariable); + System.out.println("long: " + longVariable); + System.out.println("float: " + floatVariable); + System.out.println("double: " + doubleVariable); + System.out.println("char: " + charVariable); + System.out.println("boolean: " + booleanVariable); + + // Integer array + int[] intArray = {1, 2, 3, 4, 5}; + + // Accessing array elements + System.out.println("First element: " + intArray[0]); + System.out.println("Last element: " + intArray[intArray.length - 1]); + + // Iterating through the array + System.out.println("Iterating through the array:"); + for (int i = 0; i < intArray.length; i++) { + System.out.println(intArray[i]); + } + + // Character array + char[] charArray = {'a', 'b', 'c', 'd', 'e'}; + + // Iterating through the character array + System.out.println("Iterating through the character array:"); + for (char c : charArray) { + System.out.println(c); + } + } +} +``` + +### 运算符 + +运算符中可能仅有 `>>>` 不常见。`>>>` 是专门针对**有符号数**设计的“逻辑右移”。 + +和 `>>`(算术右移)不同的是,逻辑右移在最高位补 0;而算术右移补的是符号位(即,符号位为 1 则补 1,符号位为 0 则补 0)。 + +例如,`int x = -4;`,即 `11111111 11111111 11111111 11111100`,则: + +- `x >>> 1` 为 `01111111 11111111 11111111 11111110`,即 $2147483646$; +- `x >> 1` 为 `11111111 11111111 11111111 11111110`,即 $-2$。 + +```java OperatorsExample.java +package examples.introduction; + +public class Operators { + public static void main(String[] args) { + int a = 114; + int b = 514; + System.out.println("a + b = " + (a + b)); + System.out.println("a - b = " + (a - b)); + System.out.println("a * b = " + (a * b)); + + // int / int = int + System.out.println("a / b = " + (a / b)); + // int / double = double + System.out.println("a / b = " + (a / (double) b)); + + System.out.println("a % b = " + (a % b)); + System.out.println("a++ = " + (a++)); + System.out.println("++a = " + (++a)); + System.out.println("b += 100 = " + (b += 100)); + System.out.println("a == b = " + (a == b)); + System.out.println("a != b = " + (a != b)); + System.out.println("a > b = " + (a > b)); + System.out.println("a >= b = " + (a >= b)); + System.out.println("a & b = " + (a & b)); + System.out.println("a | b = " + (a | b)); + System.out.println("a ^ b = " + (a ^ b)); + System.out.println("~a = " + (~a)); + System.out.println("a << 2 = " + (a << 2)); + + int x = -4; + // Arithmetic shift + System.out.println("x >> 2 = " + (x >> 1)); + // Logical shift + System.out.println("x >>> 2 = " + (x >>> 1)); + + boolean c = true; + boolean d = false; + System.out.println("c && d = " + (c && d)); + System.out.println("c || d = " + (c || d)); + System.out.println("!c = " + (!c)); + System.out.println("c ? 'T' : 'F' = " + (c ? 'T' : 'F')); + } +} +``` + +### 控制流语句 + +Java 和 C++ 的控制流语句大同小异,可以结合以下例子进行学习。 + +```java ControlFlowExample.java +package examples.introduction; + +public class ControlFlow { + public static void main(String[] args) { + // if-else example + int age = 18; + if (age >= 18) { + System.out.println("You are an adult."); + } else { + System.out.println("You are a minor."); + } + + // switch example + int month = 3; + String monthName; + switch (month) { + case 1: + monthName = "January"; + break; + case 2: + monthName = "February"; + break; + case 3: + monthName = "March"; + break; + default: + monthName = "Invalid month"; + } + System.out.println("The month is " + monthName); + + // for loop example + System.out.println("Counting from 1 to 5:"); + for (int i = 1; i <= 5; i++) { + System.out.println(i); + } + + // while loop example + int counter = 0; + while (counter < 3) { + System.out.println("Counter value: " + counter); + counter++; + } + + // do-while loop example + int number = 5; + do { + System.out.println("Number value: " + number); + number--; + } while (number > 0); + + // break example + for (int i = 0; i < 10; i++) { + if (i == 5) { + System.out.println("Breaking the loop at i = 5"); + break; + } + System.out.println("i = " + i); + } + + // continue example + for (int i = 0; i < 10; i++) { + if (i % 2 == 0) { + continue; + } + System.out.println("Odd number: " + i); + } + } +} +``` + +### 异常处理 + +Java 将异常分为两大类: + +**受检异常(Checked Exceptions)**: + + - 编译器会检查这些异常是否被处理或声明抛出。 + - 如果方法可能抛出受检异常,调用者必须要么捕获该异常,要么在方法签名中声明抛出该异常。 + - 常见的受检异常有 `IOException`、`SQLException`、`ClassNotFoundException` 等。 + +**非受检异常(Unchecked Exceptions)**: + + - 这些异常不会被编译器检查。 + - 包括 `RuntimeException` 及其子类,如 `NullPointerException`、`ArrayIndexOutOfBoundsException`、`IllegalArgumentException` 等。 + - 非受检异常可以不被显式捕获,也可以在方法签名中不声明抛出。 + +对于非受检异常,Java 并不要求开发者必须显式捕获或声明抛出。这是因为非受检异常通常是由于程序逻辑错误或输入数据错误导致的,应该在代码设计和编写时就尽量避免这类异常的发生。 + +相比之下,受检异常通常是由于外部原因(如 I/O 错误、网络异常等)导致的,开发者无法完全控制。因此,Java 要求开发者必须处理这些异常,以确保程序的健壮性和可靠性。 + +```java ExceptionHandlingExample.java +package examples.introduction; + +import java.util.InputMismatchException; +import java.util.Scanner; + +public class ExceptionHandling { + public static void main(String[] args) { + Scanner sc = new Scanner(System.in); + System.out.println("Enter a non-negative integer n, and I will try to calculate 100 / n: "); + try { + int n = sc.nextInt(); + int result = 100 / n; // if n = 0 then `ArithmeticException` will be thrown + if (n < 0) + throw new IllegalArgumentException("Number is negative."); // custom exception + System.out.println("Result: " + result); + } catch (ArithmeticException e) { // will be executed if n = 0 + System.out.println("Number is zero."); + } catch (InputMismatchException e) { + System.out.println("Number is not a integer."); + } catch (Exception e) { // will be executed if other exception occurs + e.printStackTrace(); + } finally { // will be executed always + System.out.println("Finally block is always executed."); + sc.close(); + } + } +} +``` + +不过,在程序开发过程中,即使出现了未捕获的异常导致程序发生 Runtime Error,也可以通过**查看调用栈**中的调试信息,来找到问题出错的根源。 + +## 标准库 + +正如 C++ 中的 STL 一样,Java 也有很多标准库。以下代码均包含于 `src/main/java/examples/datastructures` 中。 + +### `BigInteger` 和 `BigDecimal` + +`BigInteger` 和 `BigDecimal` 是 Java 中用于处理大数和高精度计算的两个类。它们属于 `java.math` 包。 + +- **`BigInteger`** 类用于表示整数值,它不受 Java 内置的 `int` 和 `long` 类型所受的固定大小限制。`BigInteger` 可以处理任意精度的整数,包括非常大的数值,例如在示例代码中展示的 `123456789012345678901234567890`。 + +- **`BigDecimal`** 类用于表示具有精确小数位的小数值,它提供了对小数点后任意位数的精确控制。`BigDecimal` 常用于需要高精度计算的金融领域。 + +示例代码展示了 `BigInteger` 和 `BigDecimal` 的基本使用,包括创建实例、执行基本的算术操作(加、减、乘、除),以及展示 `BigDecimal` 的精度控制。 + +```java BigIntegerAndBigDecimalExample.java +package examples.datastructures; + +import java.math.BigDecimal; +import java.math.BigInteger; + +public class BigIntegerAndBigDecimalExample { + public static void main(String[] args) { + // Example usage of BigInteger + BigInteger bigInt = new BigInteger("123456789012345678901234567890"); + System.out.println("BigInteger: " + bigInt); + + // Arithmetic operations with BigInteger + BigInteger bigInt1 = new BigInteger("987654321098765432109876543210"); + BigInteger bigInt2 = new BigInteger("100"); + BigInteger sum = bigInt1.add(bigInt2); + BigInteger difference = bigInt1.subtract(bigInt2); + BigInteger product = bigInt1.multiply(bigInt2); + BigInteger quotient = bigInt1.divide(bigInt2); + + System.out.println("Sum: " + sum); + System.out.println("Difference: " + difference); + System.out.println("Product: " + product); + System.out.println("Quotient: " + quotient); + + // Example usage of BigDecimal + BigDecimal bigDec = new BigDecimal("1234567890.12345678901234567890"); + System.out.println("BigDecimal: " + bigDec); + + // Arithmetic operations with BigDecimal + BigDecimal bigDec1 = new BigDecimal("987654321.098765432109876543210"); + BigDecimal bigDec2 = new BigDecimal("0.0012345"); + BigDecimal sumBD = bigDec1.add(bigDec2); + BigDecimal differenceBD = bigDec1.subtract(bigDec2); + BigDecimal productBD = bigDec1.multiply(bigDec2); + BigDecimal quotientBD = bigDec1.divide(bigDec2, 10, BigDecimal.ROUND_HALF_UP); + + System.out.println("BigDecimal Sum: " + sumBD); + System.out.println("BigDecimal Difference: " + differenceBD); + System.out.println("BigDecimal Product: " + productBD); + System.out.println("BigDecimal Quotient (rounded to 10 scale): " + quotientBD); + + // Demonstrate precision of BigDecimal + BigDecimal pi = new BigDecimal(Math.PI); + System.out.println("Pi (to 10 scale): " + pi.setScale(10, BigDecimal.ROUND_HALF_UP)); + } +} +``` + +### `String`、`StringBuffer` 和 `StringBuilder` + +Java 中的 `String` 类表示**不可变字符串**,这意味着对 `String` 对象的任何修改都会生成一个**新的 `String` 对象**。`StringBuffer` 和 `StringBuilder` 都是可变的字符串缓冲区,允许在不创建新对象的情况下修改字符串。 + +- **`String`** 类的示例代码展示了字符串的不可变性。每次使用 `+` 操作符连接字符串时,都会创建一个新的 `String` 对象。 + +- **`StringBuffer`** 是线程安全的,可以在多线程环境中使用。示例代码展示了如何使用 `append`、`insert` 和其他方法来修改 `StringBuffer` 的内容。 + +- **`StringBuilder`** 与 `StringBuffer` 类似,但它不是线程安全的,因此在单线程环境中使用时通常比 `StringBuffer` 更快。示例代码演示了 `StringBuilder` 的使用,包括清空内容、追加字符串、插入字符串等操作。 + +```java StringAndStringBufferAndStringBuilderExample.java +package examples.datastructures; + +public class StringAndStringBufferAndStringBuilderExample { + public static void main(String[] args) { + // String array + String[] stringArray = {"apple", "banana", "cherry"}; + + // Iterating through the string array + System.out.println("Iterating through the string array:"); + for (String s : stringArray) { + System.out.println(s); + } + + // Demonstrating String immutability + String str = "Hello"; + System.out.println("Original String: " + str); + str += " World"; // New String object is created + System.out.println("After concatenation: " + str); + + // Demonstrating StringBuffer usage + StringBuffer stringBuffer = new StringBuffer("Initial"); + stringBuffer.append(" String"); // Appending to StringBuffer + stringBuffer.insert(0, "Another "); // Inserting into StringBuffer + System.out.println("StringBuffer: " + stringBuffer); + + // Demonstrating StringBuilder usage + StringBuilder stringBuilder = new StringBuilder("Initial"); + stringBuilder.append(" String"); // Appending to StringBuilder + stringBuilder.insert(0, "Another "); // Inserting into StringBuilder + System.out.println("StringBuilder: " + stringBuilder); + + // StringBuilder is generally faster than StringBuffer + // because it is not synchronized, making it ideal for single-threaded scenarios. + + // Example of using StringBuilder for complex string manipulations + System.out.println("Complex StringBuilder operations:"); + stringBuilder.setLength(0); // Clear the StringBuilder content + stringBuilder.append("Looping and "); + stringBuilder.append("building a long "); + stringBuilder.append("string in a "); + stringBuilder.append("StringBuilder."); + System.out.println(stringBuilder); + + // Convert StringBuilder to String + String finalString = stringBuilder.toString(); + System.out.println("StringBuilder converted to String: " + finalString); + } +} +``` + +### `Arrays` 和 `ArrayList` + +`Arrays` 类提供了一系列静态方法来操作数组,而 `ArrayList` 是一个基于数组实现的可调整大小的集合。 + +- **`Arrays`** 类的示例代码展示了如何使用 `Arrays` 类来打印数组内容、获取数组长度、执行二分查找、复制数组、排序以及填充数组。 + +- **`ArrayList`** 是 `java.util` 包中的一个类,提供了动态数组的功能。示例代码展示了如何向 `ArrayList` 中添加元素、检查元素是否存在、获取和设置元素、移除元素以及清空列表。 + +```java ArraysAndArrayListExample.java +package examples.datastructures; + +import java.util.ArrayList; +import java.util.Arrays; + +public class ArraysAndArrayListExample { + public static void main(String[] args) { + // Example usage of Arrays + int[] numbersArray = {1, 1, 4, 5, 1, 4}; + + // Print the length of the array + System.out.println("numbersArray.length = " + numbersArray.length); + + // Print the first element of the array + System.out.println("numbersArray[0] = " + numbersArray[0]); + + // Use Arrays.toString to print the contents of the array + System.out.println("Arrays.toString(numbersArray) = " + Arrays.toString(numbersArray)); + + // Check if the array is equal to itself + System.out.println("Arrays.equals(numbersArray, numbersArray) = " + Arrays.equals(numbersArray, numbersArray)); + + // Use Arrays.binarySearch to perform binary search for the element 4 + System.out.println("Arrays.binarySearch(numbersArray, 4) = " + Arrays.binarySearch(numbersArray, 4)); + + // Use Arrays.copyOf to create a new array containing the first 3 elements of the original array + System.out.println("Arrays.copyOf(numbersArray, 3) = " + Arrays.toString(Arrays.copyOf(numbersArray, 3))); + + // Use Arrays.copyOfRange to create a subarray from index 1 to 3 + System.out.println("Arrays.copyOfRange(numbersArray, 1, 3) = " + Arrays.toString(Arrays.copyOfRange(numbersArray, 1, 3))); + + // Use Arrays.sort to sort the array + Arrays.sort(numbersArray); + System.out.println("Arrays.sort(numbersArray) = " + Arrays.toString(numbersArray)); + + // Use Arrays.fill to fill the array with zeros + Arrays.fill(numbersArray, 0); + System.out.println("Arrays.fill(numbersArray, 0) = " + Arrays.toString(numbersArray)); + + // Print the hash code of the array after filling with zeros + System.out.println("Arrays.hashCode(numbersArray) = " + Arrays.hashCode(numbersArray)); + + // Example usage of ArrayList + ArrayList sitesList = new ArrayList<>(); + + // Add elements to the ArrayList + sitesList.add("Google"); + sitesList.add("Runoob"); + sitesList.add("Taobao"); + sitesList.add("Weibo"); + + // Print all elements in the ArrayList + System.out.println("ArrayList sitesList = " + sitesList); + + // Example of other ArrayList operations + // Check if the ArrayList contains a specific element + System.out.println("sitesList.contains(\"Runoob\") = " + sitesList.contains("Runoob")); + + // Get the size of the ArrayList + System.out.println("sitesList.size() = " + sitesList.size()); + + // Remove an element from the ArrayList + sitesList.remove("Taobao"); + System.out.println("sitesList after removing \"Taobao\" = " + sitesList); + + // Get an element at a specific index + System.out.println("sitesList.get(1) = " + sitesList.get(1)); + + // Set an element at a specific index + sitesList.set(1, "Baidu"); + System.out.println("sitesList after setting index 1 to \"Baidu\" = " + sitesList); + + // Clear all elements in the ArrayList + sitesList.clear(); + System.out.println("sitesList after clear() = " + sitesList); + } +} +``` + +### `LinkedList` + +`LinkedList` 是 Java 中的一个双向链表实现,允许对列表中的元素进行高效的插入、删除操作。 + +示例代码展示了如何创建 `LinkedList` 实例、添加和删除元素、访问首尾元素、以及遍历链表。 + +```java LinkedListExample.java +package examples.datastructures; + +import java.util.LinkedList; +import java.util.List; + +public class LinkedListExample { + public static void main(String[] args) { + // Create a new LinkedList instance + List linkedList = new LinkedList<>(); + + // Add elements to the LinkedList + linkedList.add("Element 1"); + linkedList.add("Element 2"); + linkedList.add("Element 3"); + + // Print the LinkedList + System.out.println("Initial LinkedList: " + linkedList); + + // Access the first element + String firstElement = linkedList.get(0); + System.out.println("First Element: " + firstElement); + + // Access the last element + String lastElement = linkedList.get(linkedList.size() - 1); + System.out.println("Last Element: " + lastElement); + + // Remove the first occurrence of an element + linkedList.remove("Element 2"); + System.out.println("LinkedList after removing 'Element 2': " + linkedList); + + // Add an element at the beginning + linkedList.addFirst("New First Element"); + System.out.println("LinkedList after adding new first element: " + linkedList); + + // Add an element at the end + linkedList.addLast("New Last Element"); + System.out.println("LinkedList after adding new last element: " + linkedList); + + // Remove the first element + linkedList.removeFirst(); + System.out.println("LinkedList after removing the first element: " + linkedList); + + // Remove the last element + linkedList.removeLast(); + System.out.println("LinkedList after removing the last element: " + linkedList); + + // Get the size of the LinkedList + int size = linkedList.size(); + System.out.println("Size of the LinkedList: " + size); + + // Check if the LinkedList is empty + boolean isEmpty = linkedList.isEmpty(); + System.out.println("Is the LinkedList empty? " + isEmpty); + + // Clear all elements from the LinkedList + linkedList.clear(); + System.out.println("LinkedList after clear(): " + linkedList); + + // Demonstrate iteration over LinkedList elements + System.out.println("Iterating over LinkedList elements:"); + for (String element : linkedList) { + System.out.println(element); + } + } +} +``` + +### `HashSet` + +`HashSet` 是 Java 中的一个不允许重复元素的集合实现。它基于 `HashMap` 实现,因此具有快速的查找速度。 + +示例代码中的 `HashSetExample` 应为 `HashSetExample` 而不是 `HashMapExample`。代码应该展示如何使用 `HashSet` 来添加元素、检查元素是否存在、移除元素以及遍历集合。 + +```java HashSetExample.java +package examples.datastructures; + +import java.util.HashMap; +import java.util.Map; + +public class HashMapExample { + public static void main(String[] args) { + // Create a new HashMap instance + Map map = new HashMap<>(); + + // Put key-value pairs into the HashMap + map.put("One", 1); + map.put("Two", 2); + map.put("Three", 3); + + // Print the HashMap + System.out.println("Initial HashMap: " + map); + + // Get the value associated with a key + Integer value = map.get("Two"); + System.out.println("Value for key 'Two': " + value); + + // Check if a key exists in the HashMap + boolean containsKey = map.containsKey("Three"); + System.out.println("Does the key 'Three' exist? " + containsKey); + + // Remove a key-value pair from the HashMap + map.remove("One"); + System.out.println("HashMap after removing 'One': " + map); + + // Get the size of the HashMap + int size = map.size(); + System.out.println("Size of the HashMap: " + size); + + // Check if the HashMap is empty + boolean isEmpty = map.isEmpty(); + System.out.println("Is the HashMap empty? " + isEmpty); + + // Clear all key-value pairs from the HashMap + map.clear(); + System.out.println("HashMap after clear(): " + map); + + // Demonstrate iteration over HashMap entries + System.out.println("Iterating over HashMap entries:"); + for (Map.Entry entry : map.entrySet()) { + System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue()); + } + } +} +``` + +### `HashMap` + +`HashMap` 是 Java 中的一个键值对集合,它允许存储唯一的键和对应的值。`HashMap` 不保证元素的顺序,并且不是线程安全的。 + +示例代码展示了如何创建 `HashMap` 实例、添加键值对、获取与键关联的值、检查键是否存在、移除键值对、获取 `HashMap` 的大小、检查 `HashMap` 是否为空以及清空 `HashMap`。 + +```java HashMapExample.java +package examples.datastructures; + +import java.util.HashMap; +import java.util.Map; + +public class HashMapExample { + public static void main(String[] args) { + // Create a new HashMap instance + Map map = new HashMap<>(); + + // Put key-value pairs into the HashMap + map.put("One", 1); + map.put("Two", 2); + map.put("Three", 3); + + // Print the HashMap + System.out.println("Initial HashMap: " + map); + + // Get the value associated with a key + Integer value = map.get("Two"); + System.out.println("Value for key 'Two': " + value); + + // Check if a key exists in the HashMap + boolean containsKey = map.containsKey("Three"); + System.out.println("Does the key 'Three' exist? " + containsKey); + + // Remove a key-value pair from the HashMap + map.remove("One"); + System.out.println("HashMap after removing 'One': " + map); + + // Get the size of the HashMap + int size = map.size(); + System.out.println("Size of the HashMap: " + size); + + // Check if the HashMap is empty + boolean isEmpty = map.isEmpty(); + System.out.println("Is the HashMap empty? " + isEmpty); + + // Clear all key-value pairs from the HashMap + map.clear(); + System.out.println("HashMap after clear(): " + map); + + // Demonstrate iteration over HashMap entries + System.out.println("Iterating over HashMap entries:"); + for (Map.Entry entry : map.entrySet()) { + System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue()); + } + } +} +``` + +## 面向对象程序设计 + +Java 最初的设计目标之一就是成为一种纯粹的面向对象语言。所有的代码都必须包含在类(Class)中,基本上所有元素都是对象(基本数据类型除外)。它支持封装、继承和多态等面向对象的核心概念,并鼓励开发者使用这些概念构建模块化和可重用的代码。具体地说,**所有的 Java 代码都需要封装在类里,每一个 `.java` 文件恰有一个与其同名的 `public` 类**。 + +> 面向对象编程的基本流程为: +> +> 1. 设计类 `class Car { /* ... */ }` +> 2. 创建/实例化对象 `Car myCar = new Car();` +> 3. 向对象发送消息 `myCar.move();` + +Java 使用垃圾回收(Garbage Collection,GC)机制进行内存管理。开发者不需要显式地分配和释放内存,这减轻了开发负担并减少了内存泄漏和悬挂指针等常见的错误。也就是说,**Java 没有指针的概念**。函数传参**只有传值没有传引用**。 + +Java 程序员只需要关心何时 `new` 一个对象,而不需要考虑何时 `delete` 它。 + +Java 通过封装的概念将数据和操作封装在对象中。对象可以隐藏其内部状态和实现细节,只暴露出对外提供的接口。这种封装性可以保护数据的安全性和一致性,并提供更好的模块化和代码组织。 + +以下代码均包含于 `src/main/java/examples/oop` 中。 + +### Package + +Java 通过包(package)来组织代码。 + +- 包名使用 `.` 建立层次结构,应当与文件目录结构相同。 +- 包名通常全小写且单词之间无分隔。 + +```java package1/package2/PackageExample.java +package examples.oop.package1.package2; + +public class PackageExample { + public static void main(String[] args) { + System.out.println("This is a package example"); + } +} +``` + +以上代码在目录中的组织结构为: + +``` +examples +│ +└───oop + │ + └───package1 + │ + └───package2 + │ + └───PackageExample.java +``` + +### `class` + +Java 中的 `class` 和 C++ 中的 `class` 比较类似。 + +#### 类修饰符:`public`、`protected` 和 `private` + +与 C++ 中相同,Java 中也有 `public`、`protected` 和 `private` 修饰符。 + +#### 构造函数 + +Java 中**构造函数**的声明与 C++ 相同。 + +```java +class Test { + private int variable_1; + private String variable_2; + + public Test(int variable_1, String variable) { // 构造函数 + this.variable = variable_1; // 与参数同名,则需要显式写出 this + variable_2 = variable; // 不同名,则不需要显式写出 this + } +} +``` + +#### 析构函数 + +Java 语言本身并没有像 C++ 中那样明确定义的**析构函数**。Java 采用的是垃圾回收机制(Garbage Collection,GC)来自动管理内存,因此不需要程序员手动释放对象占用的内存。 + +虽然 Java 中也有类似于析构函数的 `finalize()` 语句,但它并不被推荐使用,具体的原因也不在这里多做介绍。感兴趣的同学可以查找 `finalize()` 方法、`try-with-resource` 语句和 `AutoClosable` 接口等相关资料。 + +#### `static` + +`static` 是 Java 编程语言中的一个关键字,用于表示某个成员(变量或方法)属于类本身,而不是类的某个特定对象(实例)。这意味着使用 `static` 修饰的成员可以在不创建类实例的情况下被访问和使用。 + +**主要特点** + +1. **类级别的属性**:`static` 变量是类的所有实例共享的,称为类变量或静态变量。 +2. **无需实例化**:可以直接通过类名访问 `static` 方法和变量,无需创建类的实例。 +3. **存储位置**:`static` 变量存储在 Java 堆内存的方法区,而非某个具体对象的内存空间。 +4. **生命周期**:`static` 变量和方法的生命周期与类加载和卸载的过程相关联。 +5. **不变性**:`static` 方法不能访问类的非静态成员变量和方法,因为它们与任何具体对象的状态无关。 + +**代码示例** + +在下面这份代码中,在 `Car` 这个类里,`counter` 是一个静态变量。 + +- **静态变量作为计数器**:`counter` 作为静态变量,用于跟踪创建的 `Car` 实例数量。每次创建 `Car` 实例时,`counter` 都会递增。这说明,静态变量在实例化过程中具有“共享”的特性。 +- **无需实例化访问**:直接使用类名 `Car`,可以访问静态变量 `counter`。即使没有创建类的实例,也可以访问和操作静态成员。 + +```java StaticExample.java +package examples.oop; + +public class StaticExample { + static class Car { + static int counter = 0; + String name; + + Car(String name) { + this.name = name; + counter++; + } + } + public static void main(String[] args) { + Car a = new Car("Benz"); + System.out.println("First car: " + a + ". Total car count: " + Car.counter); + Car b = new Car("Honda"); + System.out.println("Second car: " + b + ". Total car count: " + Car.counter); + Car c = new Car("Volkswagen"); + System.out.println("Third car: " + c + ". Total car count: " + Car.counter); + } +} +``` + +#### 实例初始化块 + +在类中直接使用 `{}` 扩起来的部分称为实例初始化块,它会在任何构造器运行之前运行。 + +```java +class Test { + { System.out.println("This is an Instance Initialization Block."); } + public Test() { + System.out.println("This is a constructor."); + } +} +``` + +当实例化一个 `Test` 类型的对象时,运行结果将会是 + +``` +This is an Instance Initialization Block. +This is a constructor. +``` + +#### `final` + +`final` 修饰的成员变量是**常量**,因此除了声明赋值、构造函数、实例初始化块之外,不允许对其进行其他修改。 + +通常使用 `static final` 来定义**静态常量**。一般使用 SCREAMING_SNAKE_CASE(全字母大写,用下划线分隔)来命名。例如: + +```java +public class Wordle { + static final int ALPHABET_SIZE = 26; // The size of the alphabet + static final int WORD_LENGTH = 5; // The length of words + static final int TOTAL_CHANCES = 6; // The chances in total + // ... +} +``` + +### 组合与继承 + +#### 组合 + +- **概念**:组合是一种对象包含其他对象的关系,展示了“has-a”关系。例如,一个汽车对象可能包含引擎和轮胎对象。 +- **实现**:通过在类中创建其他类的实例作为成员变量来实现。 +- **优点**:提供了更大的灵活性,因为组合的对象可以独立于组合类存在,并且可以在运行时动态地替换或修改。 + +**代码示例** + +在这份代码中,一个汽车对象包含了一个引擎对象和一个轮胎对象。每个类(`Engine`、`Tyre` 和 `Car`)都封装了自己的属性和行为,提供了一个清晰的接口来与外部世界交互。 + +```java CompositionExample.java +package examples.oop; + +public class CompositionExample { + static class Engine { + int typeCode; + + Engine(int typeCode) { + this.typeCode = typeCode; + } + @Override + public String toString() { + return "Engine [typeCode=" + typeCode + "]"; + } + } + static class Tyre { + int radius; + + Tyre(int radius) { + this.radius = radius; + } + @Override + public String toString() { + return "Tyre [radius=" + radius + "]"; + } + } + static class Car { + Engine engine; + Tyre tyre; + + Car(int engineTypeCode, int tyreRadius) { + this.engine = new Engine(engineTypeCode); + this.tyre = new Tyre(tyreRadius); + } + @Override + public String toString() { + return "Car {" + engine + ", " + tyre + "}"; + } + } + public static void main(String[] args) { + Car car = new Car(3, 5); + System.out.println(car); + } +} +``` + +#### 继承 + +- **概念**:继承是一种类与类之间的层级关系,展示了“is-a”关系。例如,狗类和猫类可以继承动物类的特性。 +- **实现**:通过使用 `extends` 关键字来实现基类(父类)的继承。 +- **优点**:支持代码复用,允许新类自动拥有基类的属性和方法。 + +**代码示例** + +以下代码展示了 `Dog` 类和 `Cat` 类对于 `Animal` 类的继承关系。 + +1. **`Animal` 类**:这是一个父类,代表动物,有两个属性 `age` 和 `weight`,以及一个 `makeSound()` 方法,该方法在被调用时打印 "Make sound"。 +2. **`Dog` 类**:这个类继承自 `Animal` 类,是子类。它添加了一个新属性 `color`,并在其构造函数中调用了父类的构造函数 `super(age, weight)` 来初始化继承的属性。它还重写了 `makeSound()` 方法,以打印 "Bark bark."。 +3. **`Cat` 类**:与 `Dog` 类似,`Cat` 类也继承自 `Animal` 类,添加了新属性 `name`。它同样调用了父类的构造函数来初始化继承的属性,并重写了 `makeSound()` 方法,以打印 "Meow meow."。 + +```java InheritanceExample.java +package examples.oop; + +public class InheritanceExample { + static class Animal { + int age, weight; + + public Animal(int age, int weight) { + this.age = age; + this.weight = weight; + } + void makeSound() { + System.out.println("Make sound"); + } + } + static class Dog extends Animal { + String color; + + Dog(int age, int weight, String color) { + super(age, weight); + this.color = color; + } + @Override + void makeSound() { + System.out.println("Bark bark."); + } + } + static class Cat extends Animal { + String name; + + Cat(int age, int weight, String name) { + super(age, weight); + this.name = name; + } + @Override + void makeSound() { + System.out.println("Meow meow."); + } + } + public static void main(String[] args) { + Dog dog = new Dog(3, 25, "White"); + Cat cat = new Cat(4, 4, "Kitty"); + dog.makeSound(); + cat.makeSound(); + } +} +``` + +### 抽象类 + +事实上,在“继承”的代码示例中,我们会发现,`Animal` 类的 `makeSound()` 方法并没有被调用;这个方法被所有继承 `Animal` 类的子类都重载了。我们还会发现一个逻辑上的问题——世界上不存在一个仅仅是“动物”的对象。它可以是“狗”、可以是“猫”,但它不能仅仅是“动物”。 + +因此,我们应该将 `Animal` 类实现为一个**抽象类**。抽象类是一种**不能被实例化**的类,它通常被用作其他类的基类。抽象类可以包含抽象方法,这些方法没有具体的实现,就像 C++ 中的纯虚函数一样。 + +而 `Animal` 类中的 `makeSound()` 方法就是一个抽象方法。它只需要被声明,而不需要被定义。 + +更改后的代码如下: + +```java AbstractClassExample.java +package examples.oop; + +public class AbstractClassExample { + abstract static class Animal { + int age, weight; + + public Animal(int age, int weight) { + this.age = age; + this.weight = weight; + } + abstract void makeSound(); + } + static class Dog extends Animal { + String color; + + Dog(int age, int weight, String color) { + super(age, weight); + this.color = color; + } + @Override + void makeSound() { + System.out.println("Bark bark."); + } + } + static class Cat extends Animal { + String name; + + Cat(int age, int weight, String name) { + super(age, weight); + this.name = name; + } + @Override + void makeSound() { + System.out.println("Meow meow."); + } + } + public static void main(String[] args) { + Dog dog = new Dog(3, 25, "White"); + Cat cat = new Cat(4, 4, "Kitty"); + dog.makeSound(); + cat.makeSound(); + // Animal animal = new Animal(1, 2); // This is prohibited + } +} +``` + +### 多重继承与接口 + +#### 多重继承 + +多重继承是指一个类可以同时继承多个父类。然而,在 Java 中,类的多重继承是不被支持的,这意味着 Java 类不能直接从多个类继承。这是因为多重继承可能导致所谓的“菱形问题”(Diamond Problem)。 + +假设其中继承的两个父类可能都定义了相同的方法,那么应该从哪个接口中继承该方法呢?这没有办法确定。 + +#### 接口 + +由于 Java 不支持类的多重继承,接口提供了一种替代方案来实现类似多重继承的特性。接口是一组抽象方法的集合,它可以被任何类实现,而不受这个类继承体系的限制。 + +~~如果你学过 Rust,那么你会发现,这类似于 Rust 里的 `trait`。~~ + +```java InterfaceExample.java +package examples.oop; + +public class InterfaceExample { + interface Flyable { + void fly(); + } + + interface Drivable { + void drive(); + } + + static class Vehicle implements Flyable, Drivable { + @Override + public void fly() { + System.out.println("Flying"); + } + + @Override + public void drive() { + System.out.println("Driving"); + } + } + public static void main(String[] args) { + Vehicle vehicle = new Vehicle(); + vehicle.fly(); + vehicle.drive(); + } +} +``` + +### `java.lang.Object` + +> 所有对象都是它的对象。 + +在 Java 中,`java.lang.Object` 是所有类的根类,它位于类继承层次结构的顶端。每个 Java 类(除了 `Object` 本身)都隐式地继承自 `Object` 类。`Object` 类提供了一些基本方法,这些方法必须在子类中正确实现,以确保正确处理“判断两个对象是否相等”这一问题。 + +#### 对象的字符串描述:`toString()` + +- `toString()` 方法默认返回 `<类型名>@<哈希码的十六进制表示>` 的形式,例如 `Student@68be2bc2`。这种默认实现通常没有实际用途。 + +- 为了提供更有用的字符串描述,通常需要重写 `toString()` 方法。例如 + + ```java + @Override + public String toString() { + return "Person [name=" + name + ", age=" + age + "]"; + } + ``` + +#### 比较二者是否相等:`equals()` + +`equals()` 方法用于比较两个对象的**内容是否相等**,而不是它们的内存地址。 + +- **自反性**:`x.equals(x)` 应返回 `true`。 +- **对称性**:`x.equals(y)` 应与 `y.equals(x)` 相等。 +- **传递性**:如果 `x.equals(y)` 和 `y.equals(z)` 都返回 `true`,则 `x.equals(z)` 也应返回 `true`。 +- **一致性**:多次调用 `equals()` 方法的结果应保持一致。 +- **非空性**:`x.equals(null)` 应返回 `false`。 + +推荐的 `equals()` 的重载方法如下: + +```java +@Override +public boolean equals(Object o) { + if (this == o) return true; // 如果两个对象引用相同,那内容一定相同 + if (o == null || getClass() != o.getClass()) return false; // 如果不是这个类的对象,那么一定不相同 + Student student = (Student) o; // 强制转换为此类对象 + if (studentID != student.studentID) return false; // 依次比较各个域 + if (age != student.age) return false; // 依次比较各个域 + // ... + // 依次比较各个域 + return true; +} +``` + +#### 哈希码:`hashCode()` + +哈希码是用于哈希表(如 `HashMap` 和 `HashSet`)中快速查找对象的关键。正确实现哈希码对于这些数据结构的性能至关重要。 + +- **一致性**:如果两个对象通过 `equals()` 方法比较相等,则它们的哈希码也必须相等。 +- **不同对象的哈希码应尽可能不同**:这有助于减少哈希冲突。 + +为了减轻程序员设计哈希函数的负担,`Objects.hash()` 已经提供了一种哈希函数: + +```java +@Override +public int hashCode() { + return Objects.hash( /* 填入各个成员域 */ ); +} +``` + +#### 代码示例 + +```java ObjectExample.java +package examples.oop; + +import java.util.Objects; + +public class ObjectExample { + static abstract class Person { + String name; + int age; + + public Person(String name, int age) { + this.name = name; + this.age = age; + } + @Override + public String toString() { + return "Person [name=" + name + ", age=" + age + "]"; + } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Person person = (Person) o; + if (age != person.age) return false; + return Objects.equals(name, person.name); + } + @Override + public int hashCode() { + return Objects.hash(name, age); + } + } + static class Student extends Person { + int studentID; + + public Student(String name, int age, int studentID) { + super(name, age); + this.studentID = studentID; + } + @Override + public String toString() { + return "Student [name=" + name + ", age=" + age + ", studentID=" + studentID + "]"; + } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Student student = (Student) o; + if (studentID != student.studentID) return false; + if (age != student.age) return false; + return Objects.equals(name, student.name); + } + @Override + public int hashCode() { + return Objects.hash(name, age, studentID); + } + } + static class Teacher extends Person { + int teacherID; + + public Teacher(String name, int age, int teacherID) { + super(name, age); + this.teacherID = teacherID; + } + @Override + public String toString() { + return "Teacher [name=" + name + ", age=" + age + ", teacherID=" + teacherID + "]"; + } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Teacher teacher = (Teacher) o; + if (teacherID != teacher.teacherID) return false; + if (age != teacher.age) return false; + return Objects.equals(name, teacher.name); + } + } + public static void main(String[] args) { + Student student_1 = new Student("Alice", 18, 2023000000); + Teacher teacher_1 = new Teacher("Bob", 50, 2000000000); + Teacher teacher_2 = new Teacher("Carol", 45, 2000000001); + Teacher teacher_3 = new Teacher("Bob", 50, 2000000000); + System.out.println("student_1 = " + student_1); + System.out.println("teacher_1 = " + teacher_1); + System.out.println("teacher_2 = " + teacher_2); + System.out.println("student_1 == teacher_1 ? " + student_1.equals(teacher_1)); + System.out.println("teacher_1 == teacher_2 ? " + teacher_1.equals(teacher_2)); + System.out.println("teacher_1 == teacher_3 ? " + teacher_1.equals(teacher_3)); + } +} +``` + +### 包装类 + +在 Java 中,基本数据类型是预定义的,它们是原始类型,直接存储在内存中,而不是对象。Java 提供了一种特殊的类,称为**包装类**(Wrapper Class),用于将基本类型包装为对象。 + +以下是 Java 中的基本类型及其对应的包装类: + +| 基本类型 | 包装类 | +| :-------: | :---------: | +| `int` | `Integer` | +| `double` | `Double` | +| `float` | `Float` | +| `char` | `Character` | +| `byte` | `Byte` | +| `short` | `Short` | +| `long` | `Long` | +| `boolean` | `Boolean` | + +基本类型不能直接参与面向对象的编程,但包装类可以。这些包装类允许基本类型参与到面向对象的编程中,例如在集合框架中使用。这意味着,`HashSet` 其实是不合法的,你应写 `HashSet`。 + +#### 举例:`Integer` 类 + +`Integer` 类是 `int` 类型的包装类。以下是一些常用的 `Integer` 类方法: + +- **`parseInt(String s)`**:将字符串解析为整数。 +- **`toString(int i)`**:将整数转换为字符串。 +- **`valueOf(String s)`**:将字符串转换为 `Integer` 对象。 +- **`compare(int x, int y)`**:比较两个整数的大小。 +- **`max(int a, int b)`** 和 **`min(int a, int b)`**:返回两个整数中的最大值或最小值。 + +#### 其他包装类 + +其他包装类如 `Double`、`Float`、`Character` 等也提供了类似的功能。例如: + +- **`Double.parseDouble(String s)`**:将字符串解析为双精度浮点数。 +- **`Character.isDigit(char ch)`**:检查字符是否为数字。 +- **`Byte.parseByte(String s, int radix)`**:将字符串解析为 `byte` 类型的整数。 + +#### 自动装箱和拆箱 + +Java 5 引入了自动装箱(Autoboxing)和拆箱(Unboxing)的概念,使得基本类型和其对应的包装类之间的转换更加方便: + +- **自动装箱**:将基本类型自动转换为相应的包装类对象。 + + ```java + int i = 5; + Integer iObject = i; // 自动装箱 + ``` + +- **自动拆箱**:将包装类对象自动转换为基本类型。 + + ```java + Integer iObject = new Integer(5); + int i = iObject; // 自动拆箱 + ``` + +虽然自动装箱和拆箱使得代码更简洁,但过度使用可能会导致性能问题,尤其是在循环中。此外,包装类也有缓存机制,例如 `Integer.valueOf(int i)` 方法在 `-128` 到 `127` 范围内的值会被缓存。 + +### 枚举类 + +Java 中的枚举类型是一种特殊的类,它允许定义**一组固定的常量**。枚举类型提供了一种方式来定义一个类型安全的枚举,并且可以包含字段、方法和构造函数。 + +#### 常见方法 + +枚举类中有以下常见方法: + +- **`values()`**:返回枚举类型的所有枚举常量的数组。 +- **`toString()`**:返回枚举常量的字符串表示形式。默认情况下,它返回枚举常量的名称。 +- **`hashCode()`**:返回枚举常量的哈希码。 +- **`ordinal()`**:返回枚举常量在枚举声明中的顺序,从零开始。 + +对于枚举类中更多的方法,详情请见 [Enum (Java SE 21 & JDK 21)](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Enum.html#hashCode())。 + +#### 特点 + +枚举类型在需要一组固定的常量时非常有用,例如星期、月份、颜色、方向等,枚举类能使得代码更加清晰和易于维护。 + +- 枚举类型是**单例的**,每个枚举项都是唯一的实例。 +- 枚举可以包含字段、方法和构造函数,但**构造函数不能是公开的**。 +- 枚举类型默认继承自 `java.lang.Enum` 类。 + +#### 代码示例 + +```java EnumExample.java +package examples.oop; + +public class EnumExample { + public enum Color { + RED, GREEN, YELLOW, BLACK, WHITE + } + public enum ColorWithAbbr { + RED("R"), GREEN("G"), YELLOW("Y"), BLACK("B"), WHITE("W"); + + private final String abbr; + ColorWithAbbr(String abbr) { // equivalent to `private ColorWithAbbr(...)` + this.abbr = abbr; + } + public String getAbbr() { + return abbr; + } + } + public static void main(String[] args) { + Color[] colors = Color.values(); + for (Color color : colors) { + System.out.println(color + " toString() = " + color.toString()); + System.out.println(color + " hashCode() = " + color.hashCode()); + System.out.println(color + " ordinal() = " + color.ordinal()); + } + + ColorWithAbbr[] colorsWithAbbr = ColorWithAbbr.values(); + for (ColorWithAbbr color : colorsWithAbbr) { + System.out.println(color + " getAbbr() = " + color.getAbbr()); + System.out.println(color + " toString() = " + color); + System.out.println(color + " hashCode() = " + color.hashCode()); + System.out.println(color + " ordinal() = " + color.ordinal()); + } + } +} +``` + +## 参考资料 + +- 感谢 [Clancy](https://github.com/Clancy-Zhu/) 在 2023 年暑期培训中的 [Java 部分的讲义](https://summer23.net9.org/frontend/java/)。 +- 感谢 [xsun2001](https://github.com/xsun2001/) 的 [tour-of-java](https://github.com/xsun2001/tour-of-java)。 +- 感谢[菜鸟教程 - Java](https://www.runoob.com/java/),提供了一份详尽但略显复杂的讲义框架。 + +## 课后作业 + +详情请见 [sast-summer-training-2024/sast2024-java](https://github.com/sast-summer-training-2024/sast2024-java)。 + diff --git "a/source/_posts/\343\200\220\350\257\276\347\250\213\346\212\245\345\221\212\343\200\221\346\270\205\345\215\216\345\244\247\345\255\246\350\256\241\347\256\227\346\234\272\347\263\273\346\232\221\346\234\237\350\257\276\347\250\213\343\200\212\347\250\213\345\272\217\350\256\276\350\256\241\350\256\255\347\273\203\343\200\213-Java-\345\244\247\344\275\234\344\270\232\346\212\245\345\221\212-2023-\345\244\217.md" "b/source/_posts/\343\200\220\350\257\276\347\250\213\346\212\245\345\221\212\343\200\221\346\270\205\345\215\216\345\244\247\345\255\246\350\256\241\347\256\227\346\234\272\347\263\273\346\232\221\346\234\237\350\257\276\347\250\213\343\200\212\347\250\213\345\272\217\350\256\276\350\256\241\350\256\255\347\273\203\343\200\213-Java-\345\244\247\344\275\234\344\270\232\346\212\245\345\221\212-2023-\345\244\217.md" new file mode 100644 index 0000000..e6120dc --- /dev/null +++ "b/source/_posts/\343\200\220\350\257\276\347\250\213\346\212\245\345\221\212\343\200\221\346\270\205\345\215\216\345\244\247\345\255\246\350\256\241\347\256\227\346\234\272\347\263\273\346\232\221\346\234\237\350\257\276\347\250\213\343\200\212\347\250\213\345\272\217\350\256\276\350\256\241\350\256\255\347\273\203\343\200\213-Java-\345\244\247\344\275\234\344\270\232\346\212\245\345\221\212-2023-\345\244\217.md" @@ -0,0 +1,432 @@ +--- +title: 【课程报告】清华大学计算机系暑期课程《程序设计训练》(Java) 大作业报告(2023 夏) +tags: + - Java + - Android + - 程序设计训练 +categories: + - 课程报告 +mathjax: true +toc: true +date: 2023-09-10 13:16:13 +password: +id: 2023Summer-Java +--- + +清华大学计算机系暑期课程《程序设计训练》(Java) 大作业报告(2023 夏)。 + +[NewsApp(头条大师) 下载地址](https://cloud.tsinghua.edu.cn/d/4757cf947e964d1797e4/files/?p=%2FNewsApp.apk) + +GitHub repo 在 [LeverImmy/News-App](https://github.com/LeverImmy/News-App/) + +**目录** + +- News App(头条大师) + - 作业描述 + - 代码结构 + - 具体实现 + - 新闻详情获取 + - 新闻列表上拉刷新下划加载 + - 图片展示和视频播放 + - 修改列表分类时的抖动特效 + - 新闻查找 + - 浏览记录以及收藏夹的本地存储以及新闻列表的展示顺序 + - 对手机“返回键”行为的处理 + - 遇到的问题及其解决方法 + - JDK 安装包重复导入的问题 + - 如何通过报错信息查找 bug + - 查找新闻时的时间范围设置 + - 视频播放问题 + - repo 回滚 + - 总结和心得 + + + +## 作业描述 + +互联网科技的发展让新闻的传播从报纸、广播、电视等方式发展到了网页以及最近几年兴起的手机 app 客户端,人们获取新闻的方式变得异常容易。手机上的新闻 app 让大家随时随地掏出手机即可看天下事,手机新闻 app 不再是一个简简单单的新闻获取工具,许多 app 已经利用数据挖掘构建出了新闻推荐引擎,为用户提供个性化、更有价值的新闻,例如 [今日头条](https://www.toutiao.com/)、[天天快报](http://www.ttkbao.com/) 等。 + +现在让我们也来尝试一下做一个新闻 app!本次大作业的任务就是实现一款浏览新闻的工具类软件。其中,抓取新闻由 [清华大学计算机系知识工程实验室](https://keg.cs.tsinghua.edu.cn/) 进行,并提供了访问新闻的接口,同学们根据网络接口文档和作业要求利用课上所学的 Java 和 Android 开发知识实现一个新闻客户端即可。 + +## 代码结构 + +代码结构如下图所示。 + +```mermaid +flowchart LR + A{{News App}} --> B(data) + A --> C(service) + A --> D(ui) + A --> E[MainActivity.java] + A --> F[MyApplication.java] + + B --> G[Category.java] + B --> H[News.java] + B --> I[Page.java] + B --> J[User.java] + + C --> K[DBManager.java] + C --> L[FetchFromAPIManager.java] + C --> M[MySQLiteOpenHelper.java] + C --> N[NewsManager.java] + C --> O[PictureLoader.java] + C --> P[TaskRunner.java] + C --> Q[Utils.java] + + D --> R[EndlessRecyclerViewScrollListener.java] + D --> S[NewsDetailFragment.java] + D --> T[NewsListAdapter.java] + D --> U[NewsListFragment.java] + D --> V[RecordListFragment.java] + D --> W[SearchFragment.java] + D --> X[SearchListFragment.java] + D --> Y[SelectPaddleAdapter.java] + D --> Z[SelectPaddleFragment.java] + D --> AA[TabListFragment.java] + D --> AB[UserPageFragment.java] + D --> AC[VideoFragment.java] +``` + +- `data` + - `Category.java` 是一个枚举类,包含可被搜索的八个分类。 + - `News.java` 是一个类,用于描述一篇新闻,包含 `title`,`content` 等属性。 + - `Page.java` 是一个枚举类,包含当前页面可能处于的状态(如“新闻详情界面”“新闻列表界面”“搜索界面”等)。 + - `User.java` 是一个类,用于描述用户个性化信息(如选择的分类)的读写。 +- `service` + - `DBManager.java` 用于数据库管理。 + - `FetchFromAPIManager.java` 用于新闻详情获取。 + - `MySQLiteOpenHelper.java` 用于数据库管理。 + - `NewsManager.java` 用于新闻相关处理,包含已浏览新闻列表的读写。 + - `PictureLoader.java` 用于展示图片。 + - `TaskRunner.java` 用于管理进程。 + - `Utils.java` 是一个类,包含了很多辅助的函数,如将一个枚举数组转化为字符串等。 +- `ui` + - `EndlessRecyclerViewScrollListener.java` 是展示新闻列表所需要的 Listener。 + - `NewsDetailFragment.java` 是展示新闻详情的 Fragment。 + - `NewsListAdapter.java` 是辅助展示新闻列表的 Adapter。 + - `NewsListFragment.java` 是展示推荐界面新闻列表的 Fragment。 + - `RecordListFragment.java` 是展示浏览记录、收藏夹新闻列表的 Fragment。 + - `SearchFragment.java` 是搜索界面的 Fragment。 + - `SearchListFragment.java` 是展示搜索结果新闻列表的 Fragment。 + - `SelectPaddleAdapter.java` 是辅助修改分类界面的 Adapter。 + - `SelectPaddleFragment.java` 是修改分类界面的 Fragment。 + - `TabListFragment.java` 是推荐界面上方分类栏的 Fragment。 + - `UserPageFragment.java` 是用户主页的 Fragment。 + - `VideoFragment.java` 是播放视频的 Fragment。 +- `MainActivity.java` +- `MyApplication.java` + +## 具体实现 + +### 新闻详情获取 + +新闻详情获取部分我使用了 `URLConnection` 和 `JSONObject` 等库,这样能方便地向学校提供的接口发送请求,以及获取返回的 JSON 格式的数据。 + +```java +static JSONObject getUrlResponse(String url) { + try { + URLConnection connection = new URL(url).openConnection(); + BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + StringBuilder builder = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + builder.append(line); + } + return new JSONObject(builder.toString()); + } catch (IOException | JSONException e) { + e.printStackTrace(); + return new JSONObject(); + } +} +``` + +由于我在 `data/News.java` 这个类中重载了由 `JSONObject` 构造 `News` 的构造函数,所以可以在之后的过程中,直接由获取到的 JSONObject 中的 data 项构造每条新闻: + +```java +try { + JSONArray data = getUrlResponse(url).getJSONArray("data"); // 获取 data 项 + List newsFeed = new ArrayList<>(); + for (int i = 0; i < data.length(); i++) { + JSONObject jsonObject = data.getJSONObject(i); + newsFeed.add(new News(jsonObject)); // 通过构造函数直接构造新闻 + } + return newsFeed; +} catch (JSONException e) { + e.printStackTrace(); + return null; +} +``` + +### 新闻列表上拉刷新下划加载 + +在 `ui/EndlessRecyclerViewScrollListener.java` 中,通过重载 `onScrolled()` 方法,来实现下划加载更多新闻的功能。 + +```java +@Override +public void onScrolled(RecyclerView view, int dx, int dy) { + int lastVisibleItemPosition = 0; + int totalItemCount = mLayoutManager.getItemCount(); + + if (mLayoutManager instanceof StaggeredGridLayoutManager) { + int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(null); + + lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions); + } else if (mLayoutManager instanceof GridLayoutManager) { + lastVisibleItemPosition = ((GridLayoutManager) mLayoutManager).findLastVisibleItemPosition(); + } else if (mLayoutManager instanceof LinearLayoutManager) { + lastVisibleItemPosition = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition(); + } + + if (totalItemCount < previousTotalItemCount) { + this.currentPage = this.startingPageIndex; + this.previousTotalItemCount = totalItemCount; + if (totalItemCount == 0) { + this.loading = true; + } + } + + + if (loading && (totalItemCount > previousTotalItemCount)) { + loading = false; + previousTotalItemCount = totalItemCount; + } + + if (!loading && (lastVisibleItemPosition + visibleThreshold) > totalItemCount) { + currentPage++; + onLoadMore.onLoadMore(currentPage, totalItemCount, view); + loading = true; + } +} +``` + +通过在 `ui/NewsListFragment.java` 和 `ui/SearchListFragment.java` 中对 `SwipeRefreshLayout` 和 `RecyclerView` 设置 Listener,程序就能在合适的情况下调用 `reloadNews()` 方法从而达到新闻列表刷新的效果。 + +### 图片展示和视频播放 + +图片展示使用的是 Glide 和 ImageView。在 `service/PictureLoader.java` 中,设置了随机占位图片,来解决图片还未加载出来时的图片显示问题。 + +视频播放使用的是 VideoView。`ui/VideoFragment.java` 中的 `onCreateView()` 重载如下: + +```java +@Override +public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + View view = inflater.inflate(R.layout.fragment_video, container, false); + + try { + VideoView videoView = view.findViewById(R.id.videoView); + Uri uri = Uri.parse(videoWebPath); + + videoView.setVideoURI(uri); + videoView.setMediaController(new MediaController(getContext())); + videoView.requestFocus(); + videoView.setOnCompletionListener(mp -> { + + }); + videoView.setOnErrorListener((mp, what, extra) -> false); + videoView.start(); + + Log.d("VideoFragment", "isPlaying: " + videoView.isPlaying()); + } catch (Exception e) { + Log.d("VideoFragment", "failed" ); + } + + return view; +} +``` + +### 修改列表分类时的抖动特效 + +我在 `res/anim/shake_animation.xml` 中设置了每个分类的抖动特效: + +```xml + + + + +``` + +但若直接设置,会导致每个分类抖动的行为 **一模一样**。所以我在 `ui/SelectPaddleAdapter.java` 中设置了动画的持续时间为随机,这样就能够控制抖动的频率各不相同,实现 **随机抖动** 的效果: + +```java +Random random = new Random(); + +Animation shakeAnimation = AnimationUtils.loadAnimation(mContext, R.anim.shake_animation); +shakeAnimation.setDuration(random.nextInt(200) + 300); // 设置随机的持续时间 +view.setAnimation(shakeAnimation); +``` + +### 新闻查找 + +首先,我设置了一个 SearchView 文本输入框,来接受关键词查询。 + +其次,我设置了 **可复选的** 分类选择框。在查询时,多个分类用 `,`(半角逗号)隔开,可以同时查询“并”操作后的结果。 + +同时,我设置了比传统的 TextEdit **更加用户友好** 的 DatePicker 组件来接受查询的时间范围。 + +接收到了这些查询的信息之后,利用 `service/FetchFromAPIManager.java` 中的 `handleSearch()` 方法来获取新闻列表及详情。 + +### 浏览记录以及收藏夹的本地存储,以及新闻列表的展示顺序 + +具体的新闻详情使用 SQLite 数据库进行存储,`service/DBManager.java` 展示了这一过程。 + +程序使用 SharedPreference 来本地存储一个从新闻列表的 `newsID` 到最近一次访问/收藏它们的时间戳的 Map,`service/NewsManager.java` 中展示了这一过程。而通过一个新闻的 `newsID`,就可以在数据库中读取的数据中通过另一个 Map 来找到对应它新闻详情。 + +```java +private static Map news = new HashMap<>(); // 从 newsID 到新闻的 Map +private static Map historyNews = new HashMap<>(); // 从 newsID 到时间戳的 Map +private static Map favoriteNews = new HashMap<>(); // 从 newsID 到时间戳的 Map +``` + +应用实现了按照最后一次访问时间降序来排列浏览记录,按照最后一次收藏时间来排列收藏夹。在展示这两个列表的时候,就按照这两个 Map 的 key 升序添加到列表中(那么就是降序从上到下展示的)即可。 + +```java +public List getRecords(boolean mode) { // 0 for history, 1 for favorite + + Log.d("NewsManager", "Trying to get news records."); + + Map operand = mode ? favoriteNews : historyNews; + List> entryList = new ArrayList<>(operand.entrySet()); + entryList.sort(Comparator.comparingLong(Map.Entry::getValue)); + + List response = new ArrayList<>(); + + for (Map.Entry entry : entryList) { + response.add(getNews(entry.getKey())); + } + + return response; +} +``` + +### 对手机“返回键”行为的处理 + +在 `app/MainAcitivity.java` 中,我重载了 `onBackButtonClicked()` 函数,用于处理在各个页面中按下“返回键”这一行为的处理方法。它的前提是,我使用 `MyApplication.page` 维护了当前页面是哪个页面。 + +对于推荐页面、搜索页面、用户页面,**按下“返回键”会提示“再按一次返回键退出”**,它能通过检查在此情况下 2 秒内连续两次按下返回键之间的时间间隔来判断是否应该退出程序。在 `app/MainActivity.java` 中维护了第一次按下“返回键”的时间戳 `firstTime`。 + +```java +long secondTime = System.currentTimeMillis(); +if (secondTime - firstTime >= 2000) { + Toast.makeText(MainActivity.this, "再按一次返回键退出", Toast.LENGTH_SHORT).show(); + firstTime = secondTime; +} else { + finish(); +} +``` + +对于其他页面,只需要正确维护 `MyApplication.page` 的值(比如,当前页是浏览记录新闻列表页面,那么就应该改为用户主页;当前页是收藏夹中的新闻详情,那么就应该改为收藏夹新闻列表页面),并且执行 `super.onBackPressed()` 方法即可。 + +## 遇到的问题及其解决方法 + +### JDK 安装包重复导入的问题 + +由于新版本的 JDK 移除了 `org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0` 和 `org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0`,但老版本的 Android 库仍在使用它们,所以在导入时会产生重复导入同一个安装包的问题。 + +经过查找相关资料,我通过 [运行Android项目时出现重复类错误 - 大数据知识库](https://www.saoniuhuo.com/question/detail-2652728.html) 和 [I get a Duplicate Class error when running my Android project - StackOverflow](https://stackoverflow.com/questions/76191980/i-get-a-duplicate-class-error-when-running-my-android-project) 两个网站检索到了解决方案。 + +在 `app/build.gradle.kts` 中添加以下代码即可解决此问题。 + +```kts +constraints { + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0") { + because("kotlin-stdlib-jdk7 is now a part of kotlin-stdlib") + } + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0") { + because("kotlin-stdlib-jdk8 is now a part of kotlin-stdlib") + } +} +``` + +### 如何通过报错信息查找 bug + +查找 bug 以及调试的过程是非常复杂的。我最后使用 `Log.d(FILE_NAME, MSG);` 的方式在必要的步骤前进行日志的记录。其中 `FILE_NAME` 是当前文件名,这样我能知道日志信息的来源;`MSG` 是个性化的调试信息,一般为某个数据,或者是“Button Clicked”这样的信息。 + +### 查找新闻时的时间范围设置 + +我在为用户提供设置查找记录时间范围的功能时,使用了 [DatePicker](https://developer.android.com/reference/android/widget/DatePicker) 插件,但我希望能够 **使起始时间的 DatePicker 能够选择的范围不晚于结束时间的 DatePicker 显示的范围**。 + +最后的解决办法是,在结束时间的 DatePicker 上加一个 Listener,每当该 DatePicker 上的日期改变时,就检查开始时间的 DatePicker 上的时间是否不晚于结束时间的 DatePicker 上日期。如果晚于,则将开始时间的 DatePicker 的日期调整为结束时间。同时,每当结束时间的 DatePicker 的日期改变时,就将开始时间的 DatePicker 的最大选择日期改为结束时间的 DatePicker 的日期。这样设置,可以让搜索界面设置时间的功能对用户更加友好。 + +```java +endDatePicker.init(endDatePicker.getYear(), endDatePicker.getMonth(), endDatePicker.getDayOfMonth(), (view12, year, monthOfYear, dayOfMonth) -> { + + Calendar calendar1 = Calendar.getInstance(); + calendar1.set(startDatePicker.getYear(), startDatePicker.getMonth(), startDatePicker.getDayOfMonth()); + + Calendar calendar2 = Calendar.getInstance(); + calendar2.set(year, monthOfYear, dayOfMonth); + + // 如果起始时间的 DatePicker 晚于结束时间的 DatePicker + if (calendar1.compareTo(calendar2) > 0) { + calendar1 = calendar2; + } + startDatePicker.setMaxDate(calendar2.getTimeInMillis()); + startDatePicker.updateDate(calendar1.get(Calendar.YEAR), calendar1.get(Calendar.MONTH), calendar1.get(Calendar.DAY_OF_MONTH)); + +}); +``` + +### 视频播放问题 + +在完善视频播放功能时,我发现视频无法播放。通过 Logcat 我查询到了该视频的地址为 `http://flv3.people.com.cn/dev1/mvideo/vodfiles/2021/09/07/2eb63e58f8c0b6cee1c2c1dde92940ef_c.mp4`。这说明,获取视频地址的过程没有问题;问题出在 **播放视频** 的过程中。经过我查阅相关资料: + +> 默认情况下,Android 9(API 级别 28)及更高版本不允许应用程序发送或接收不加密的网络流量(即明文流量)。 +> 这是为了提高应用程序的安全性和数据保护,然而,某些情况下可能需要允许明文流量,例如 **与非加密的服务器通信或调试时**。 + +由于该视频以 `HTTP` 而非 `HTTPS` 传输,所以需要将 `res/xml/network_security_config.xml` 中的代码更改为: + +```xml + + + + +``` + +### 应用切换到后台时当前界面及数据如何保留 + +最初我遇到了一个 bug:如果当前处于新闻详情页面,在应用切换到后台后,再切换到前台,会导致页面展示分类选项栏。最后,我重载了 `ui/NewsDetailFragment.java` 中的 `onStop()` 和 `onResume()` 方法来控制分类选项栏的显示和隐藏。 + +```java +@Override +public void onStop() { + + super.onStop(); + Log.d("NewsDetailFragment", "onStop"); + MyApplication.getBottomNavigationView().setVisibility(View.VISIBLE); + if (MyApplication.page == Page.NEWS) + MyApplication.getTopFragmentContainer().setVisibility(View.VISIBLE); + +} + +@Override +public void onResume() { + + super.onResume(); + Log.d("NewsDetailFragment", "onResume"); + MyApplication.getBottomNavigationView().setVisibility(View.GONE); + MyApplication.getTopFragmentContainer().setVisibility(View.GONE); + +} +``` + +### repo 回滚 + +整个开发过程中,我将代码托管在了 GitHub 上 [LeverImmy/News-App](https://github.com/LeverImmy/News-App/),并使用 Git 作为版本控制工具。临近开发结束时,我的程序出现了闪退的 bug,并且我逐步排查 Logcat 也毫无头绪。 + +虽然当时我没有找到解决办法,但幸亏我每次 commit 的信息都写得比较清楚,我最终选择 **直接回滚到一个没有出现这个 bug 的版本**,然后重新对比代码进行复查。最后我发现这是由于线程进度不同使得一个 listener 没有得到 notify 导致的。 + +## 总结和心得 + +在整个开发过程中,我遇到了 [许多困难](#遇到的问题及其解决方法),但能够一步一步地在网络上查找资料并且最终摸索出解决办法的经历,是十分有教育意义的。通过这次大作业,我增加了对 Java 的熟练程度,并且初步认识到了 Android 应用开发的过程。在找身边的同学、朋友试用我的 App 并且反馈 bug 的过程中,我体会到了测试的重要性~~以及调试代码的艰辛~~。 + +感谢清华大学计算机系 [许斌](http://keg.cs.tsinghua.edu.cn/persons/xubin/) 老师的指导,助教们在微信群中的答疑,以及 [清华大学计算机系知识工程研究室](https://keg.cs.tsinghua.edu.cn/) 提供的 [新闻搜索接口](https://api2.newsminer.net/svc/news/queryNewsList?size=&startDate=&endDate=&words=&categories=&page=)。 diff --git "a/source/_posts/\343\200\220\351\232\217\347\254\224\343\200\221\344\273\216\345\244\252\345\255\220\346\271\226\345\210\260\344\270\207\346\235\276\345\233\255\342\200\224\342\200\224\347\272\252\345\277\265\346\255\246\346\261\211\345\244\226\345\233\275\350\257\255\345\255\246\346\240\241\345\273\272\347\253\213-60-\345\221\250\345\271\264.md" "b/source/_posts/\343\200\220\351\232\217\347\254\224\343\200\221\344\273\216\345\244\252\345\255\220\346\271\226\345\210\260\344\270\207\346\235\276\345\233\255\342\200\224\342\200\224\347\272\252\345\277\265\346\255\246\346\261\211\345\244\226\345\233\275\350\257\255\345\255\246\346\240\241\345\273\272\347\253\213-60-\345\221\250\345\271\264.md" new file mode 100644 index 0000000..47baac2 --- /dev/null +++ "b/source/_posts/\343\200\220\351\232\217\347\254\224\343\200\221\344\273\216\345\244\252\345\255\220\346\271\226\345\210\260\344\270\207\346\235\276\345\233\255\342\200\224\342\200\224\347\272\252\345\277\265\346\255\246\346\261\211\345\244\226\345\233\275\350\257\255\345\255\246\346\240\241\345\273\272\347\253\213-60-\345\221\250\345\271\264.md" @@ -0,0 +1,59 @@ +--- +title: 【随笔】从太子湖到万松园——纪念武汉外国语学校建立 60 周年 +tags: + - 生活 +categories: + - 随笔 +mathjax: true +toc: true +date: 2024-04-30 00:56:40 +password: +id: From-Taizihu-to-Wansongyuan +--- + +武汉外国语学校是在周恩来、陈毅等老一代国家领导人亲切关怀下,于 1964 创建的全国首批七所外国语学校之一。作为一名从外小、外初到外高,在武汉外国语学校中度过了十二个春秋的学生,我深受外校的滋养:外校不仅含辛茹苦地哺育了我,还启迪了我的思想,塑造了我的性格。今年,这所名校终于迎来了它的 60 周年校庆。在这个值得纪念的校庆之际,我写下这篇文章,献给我深爱的母校。 + + + +## 一 + +> “太子湖畔,清风鸣蝉” + +在小学部的学习生活给予了我广阔的国际视野。 + +记得在那纯真的小学时光里,每年的“圣诞国际日”是我们最期待的活动。那一天,校园仿佛成为了世界的缩影,变成了一个五彩斑斓的世界地图;每个班级都代表着不同的国家,展示着各自的特色美食和文化。我们这些小小探险家,手持着收集印章的小本子,兴奋地在不同的国度间穿梭,体验着一场无需护照的环球旅行。 + +我记得有一次我们班级被分配到了“印度”这一国家。在活动开始前,我们充满热情地搜集关于印度的资料,学习它的历史、文化和风俗。当天,我们的教室被装饰成了印度风格;女生身着莎丽,成为了印度文化的使者。最令人兴奋的是,我们还特别请来了一位擅长制作印度飞饼的厨师。他现场展示了制作飞饼的技艺,那旋转飞扬的面团,那在空中翻腾的飞饼,让我们目不转睛。当香喷喷的飞饼出锅时,我们都忍不住上前品尝,那酥脆可口的美味让我们回味无穷。 + +虽然那个特别的日子已经成为了过去,但它在我心中留下的印记却是永恒的。“圣诞国际日”不仅让我对世界各地的风土人情有了初步的认识,更让我懂得了尊重和欣赏每一种文化的价值。在那段美好的时光里,我的视野被无限地拓展,我的知识面也在潜移默化中变得更加宽广。外小给了我一个探索世界的起点,让我在未来的日子里,总是怀揣着对未知的好奇和对世界的热爱。 + +## 二 + +> “巍巍龟蛇哺育着世纪的学子,滚滚长江回荡着母亲的叮咛。” + +在初中部的学习生活为我提供了众多展示自己的机会。 + +记得每次英语课上的 Duty Show,那是我们最期待的五分钟。在每节英语课的最初的 5 分钟,都会有一位同学针对某个主题发表自己的看法,或是分享自己的兴趣和生活见闻。这个常规的语言训练项目锻炼了我们的语言表达能力和组织能力,每当轮到我上台,我总是积极展示自己,锻炼自己的英语口语能力,享受展示自我的过程。 + +为了进一步提高我们对英语 Duty Show 的兴趣和制作能力,初二英语年级组的老师们精心安排了一场 Duty Show 大赛。我记得我和季瑞灼同学一起,以“Is Admiring Someone OK?”为主题,通过类似脱口秀的形式,展示了我们对“早恋”这一话题的看法。我们的脱口秀赢得了全场的掌声,最终获得了全场最高票,赢得了“最佳风采奖”。这次比赛不仅让我们的校园生活更加生动有趣,还提供了展示自我、锻炼能力的机会,我们无论是语言表达能力、公众演讲能力还是自信心,都得到了提高。 + +除了 Duty Show 大赛,我在外初时还经历了英语卡拉 OK 大赛、课本剧大赛、英语配音大赛等活动。感谢外初给予我的这些宝贵机会,它们让我在英语学习的道路上更加自信,也为我未来的发展奠定了坚实的基础。 + +## 三 + +> “从这里走向世界和未来。” + +在高中部的学习生活提高了我的综合素质和学习能力。 + +外高拥有着一流的师资力量和先进的教育资源。老师们不仅专业知识深厚,教学经验丰富,也注重培养学生的创新思维和批判性思考能力。除此之外,老师们的教学方法也极具特色。以我的班主任梅军老师为例,他曾在高一时就提出一个挑战:如果在任何一次大考中,班上所有人都能准确完成游标卡尺读数题目,他就请全班同学吃大餐。这个看似简单的目标,却是对我们细致入微、严谨治学的最好考验。遗憾的是,直到高考,我们班始终未能实现这一目标。虽然我们高中三年一次也没有完美过,但是高考结束后的 6 月 10 日,拍完毕业照之后,他邀请全班 30 名同学在天街享用了一顿烤肉自助餐,以此作为对我们高中三年努力的认可和奖励。 + +这一道“小小的难题”,让我们明白了细节决定成败的道理。梅老师通过这个简单的例子,教会了我们对待学习要一丝不苟,对待生活要乐观向上。在他的影响下,我学会了如何面对挑战,如何在困难中坚持,如何在失败中汲取教训。 + +## 四 + +十二载春秋,转瞬即逝,在武汉外国语学校中度过的日子,甚至超越了我生命旅程的一半。太子湖畔的一花一木,万松园里的一草一树,都成为我记忆中不可或缺的部分;作为一个住读生,它们陪伴我的时光,甚至超过了我与父母共度的岁月。这些岁月里,我在武汉外国语学校这片沃土上播种梦想,收获知识,塑造自我,我做的每一件事都凝聚着学校的滋养和教诲。 + +我仍然忘不了外小教学楼的一至五号门,不能记错它们各有各的开放时间;也忘不了每天下午“阳光空间”的课外锻炼时间,同学们在操场上奔跑跳跃的模样;我仍然忘不了外初悠长的上课铃和下课铃,也忘不了每周被“独立作业”所“折磨”的日子。记忆中最令我难忘的,是曾经位于外高操场上的秋千,还有和朋友们在操场上散步谈心的时光。 + +愿武汉外国语学校在未来的岁月里继续她的辉煌,不断推动教育事业的发展,为国家培养出更多、更优秀的国际化人才;希望“爱国,好学,自强,图新”的校训激励一代又一代学子,为祖国的繁荣昌盛贡献力量。衷心祝贺我的母校——武汉外国语学校建校 60 周年校庆快乐! + diff --git "a/source/_posts/\343\200\220\351\232\217\347\254\224\343\200\221\345\220\254\350\257\264\351\233\206\351\275\220\344\270\211\344\270\252\344\270\223\344\270\232\347\232\204\346\240\241\345\233\255\345\215\241\345\260\261\350\203\275\345\217\254\345\224\244\347\245\236\351\276\231.md" "b/source/_posts/\343\200\220\351\232\217\347\254\224\343\200\221\345\220\254\350\257\264\351\233\206\351\275\220\344\270\211\344\270\252\344\270\223\344\270\232\347\232\204\346\240\241\345\233\255\345\215\241\345\260\261\350\203\275\345\217\254\345\224\244\347\245\236\351\276\231.md" new file mode 100644 index 0000000..84c5366 --- /dev/null +++ "b/source/_posts/\343\200\220\351\232\217\347\254\224\343\200\221\345\220\254\350\257\264\351\233\206\351\275\220\344\270\211\344\270\252\344\270\223\344\270\232\347\232\204\346\240\241\345\233\255\345\215\241\345\260\261\350\203\275\345\217\254\345\224\244\347\245\236\351\276\231.md" @@ -0,0 +1,294 @@ +--- +title: 【随笔】听说集齐三个专业的校园卡就能召唤神龙 +tags: + - 转专业 + - 生活 +categories: + - 随笔 +mathjax: true +toc: true +date: 2024-01-29 14:06:40 +password: +id: Major-Transfer +typora-root-url: ./.. +--- + +从转专业公示名单到现在已经有九个月了。 + +在为转专业做准备的时候,总觉得同步记录下当时的心情会很做作,万一转专业失败了呢;但等到所有尘埃落定之后再回忆,却已经有些忘记了。 + +截至目前,转专业是我大学生活中最重要的一件事。因此,我想以时间顺序,叙述我从开学到转专业成功这一年来的心路历程和所做的准备。 + +![三张校园卡](https://img.picgo.net/2024/01/29/cards55d1294178325d92.png) + + + +## 高考后的暑假 + +### 突如其来的变故 + +由于我的父亲是一名软件工程师,因此我从小就对计算机相关专业比较感兴趣。我曾在初三至高一参加过信息学竞赛,获得湖北省一等奖。最终,我选择了高一的时候退役——对于当时省队无望的我而言,回归文化课可能是更合适的选择。 + +在 2022 年湖北省高考中,我获得了理科省前 50 名的好成绩。计算机系、软院肯定无望;想学计算机相关专业的我左思右想,最后选择“曲线救国”,将“数理类”作为我的第一志愿。当时 QY 的时候我还不理解,马马虎虎地写了“数理类”;最后回到家了才发现,我应该直接写“数学科学系”这一专业的。我追悔莫及;这也为后文埋下了伏笔。 + +我很天真,以为学好了数学就像为高楼大厦夯实了地基,接下来转码学计算机会简简单单;事实上,我本身不适合学理科,我讨厌严谨的证明而喜爱实践与归纳。我整个暑假一直在 B 站上看《数学分析》和《高等代数学》的相关网课,但是似懂非懂。 + +开学报到后,我突然发现数学科学系需要“零分流”。室友们由于 QY 的时候直接写的“数学科学系”,所以免“零分流”了。于是我也只能硬着头皮去参加“零分流”面试了。 + +![分流面试后收到的短信](https://img.picgo.net/2024/01/29/byebye6d11af161f882e5a.png) + +不出意料,由于我没参加过数学竞赛,暑假也没学多少东西;更可怕地,我暑假学的东西也没掌握牢固——我被分流到了工程物理系。 + +### 心态调整 + +我在发现“数理类”除了数学系、物理系外还有工物系之后,我也搜索了工物系的相关资料。但受限于工物系各个研究方向的保密性,我在网络上搜索到的资料甚少。简而言之,我当时以为工物系的主要研究方向是核科学与核技术,毕业后的工作岗位包括核电站工程师。“我要学核物理了我要被发配到边疆搞原子弹实验了我可能要隐姓埋名了我还有可能会因受辐射过多死亡”——虽然这一刻板印象在我加入工物系仔细了解各个方向后被证伪,但这在当时对我十分有冲击力。 + +我想逃离工物系——至少这个专业所学的内容与我希望我在大学生活中能学习到的知识相差甚远。 + +既然被分流到了工物系,那我能做什么呢?**答案只有转系。**于是,在我被分流到工物系后的第二天,哼哧哼哧地换完宿舍之后,我就定下了转专业到计算机系的目标。 + +### 军训 + +要想转系成功,首要的事情是把 GPA 稳定在全系前列;而要想获得一个高的 GPA,军训自然是要满绩通过。 + +《军事训练》这门课想要获得 4.0 很难——尤其是对于身体素质本身就不够硬的同学。这里有两个小技巧: + +1. 申请成为连宣传员 +2. 申请参与绘画军训板报 + 虽然我完全没有绘画功底,但是我主动请缨,参与了我们连军训板报的设计。最终我获得了“军训先进个人”的称号以及 2 学分的 4.0。 + +![军训板报](/gallery/Major-Transfer/poster.jpg) + +《军事理论》相较而言就比较简单了——拟合往年题,然后了解教材的目录脉络即可。反正是开卷,把往年题全部打印好带着,遇到不会的就翻往年题;往年题里找不到的,就对应着教材目录开始翻教材。 + +## 大一上学期 + +### 选课 + +大一上学期还懵懵懂懂,完全不知道该如何安排选课,所以最后,我还是按照工物系大一上学期的课程计划进行选课。 + +为了填补课表,我选修了一门中通识课科学课组中的一门“硬核”课——雍俊海老师开设的《算法设计及其复杂性分析》。这门课是真的硬,每周四个学时,前八周上课。所有工作在 **课下** 完成,课上每位同学 **汇报上一周完成的工作**。第一周过后退课人数 **超过一半**;但认真学下来将会受益匪浅。慎选! + +我大一上学期的课表大概如下,后来把工程物理概论退了: + +![大一上学期课表](https://img.picgo.net/2024/01/29/schedule225fbbafe3a1d222.png) + +### 社工 + +我初中三年一直都是班长;高中三年一直是物理课代表。 + +到了大学后,我听说团支书工作量很大,所以我立即选择竞选班长。意料之外的是班上没有其他人竞选班长,所以我以全票当选。班长的职责其实也不少: + +- 集体生日会 +- 主题党团日 +- 男生节/女生节 + +最让人头疼的其实是男生节/女生节。我们班有二十多位男生,只有一位女生,该如何是好?十月底的时候我是真的很头疼,因为男生节的活动一定是要办的——这是无法越过的一道坎。最后,我在寝室里抓耳挠腮想到了一个解决办法:尝试联系一下就读于外文系的高中同学,看能不能两个班一起举办。 + +感谢我那位好兄弟,最后几个班一起成功举办了男生节。感觉效果还不错? + +### 学习 + +除了社工之外,大一上学期剩下的应该只有学习二字了。所幸微积分没有出大问题,线性代数(理科类)的期末考试由于蒙对了一道题而原始分遥遥领先;唯一的不足是物理我是真学不懂。绩点大概也就这样了吧。 + +| 课程名 | 学分 | 等级 | 主讲教师 | +| :----------------------------------------: | :--: | :----: | :------: | +| 微积分A(1) | 5 | A/4.0 | 杨利军 | +| 线性代数(理科类) | 4 | A/4.0 | 郑志伟 | +| 党的知识概论 | 2 | P | 魏晶 | +| 新生导引课 | 1 | P | 王学武 | +| 算法设计及其复杂性分析 | 2 | A/4.0 | 雍俊海 | +| 思想道德与法治 | 3 | A-/4.0 | 肖巍 | +| 形势与政策(1)-秋 | 1 | P | 李蕉 | +| 体育(1) | 1 | A-/4.0 | 王俊华 | +| 基础物理学(1) | 5 | B+/3.6 | 蒋硕 | +| 工程应用中的物理奥妙与物理探索中的工程实践 | 1 | P | 倪建平 | +| 能源专家讲座 | 1 | P | 陈涛 | +| **总绩点** | 26 | 3.90 | - | + +## 大一寒假 + +既然已经要决定转专业了,我选课的时候就激进了许多:除了《面向对象程序设计基础》这门课没选上之外,我把计算机系在大一下学期教学计划上的课都选了。 + +在寒假期间,我参加了工物系举办的新生 C 语言大赛,获得了一等奖的好成绩;也学了点面向对象程序设计的基础知识,至少了解了什么是“封装”“继承”与“多态”。 + +## 大一下学期 + +大一下学期的主线是向各种资源寻求帮助,我将我曾经求助过的资源整理如下: + +### 参加“乐学”公众号的转专业讲座 + +> 注:关注“乐学”公众号中的相关推送。 + +在每个春季学期,“乐学”应该都会发一篇转专业相关讲座的推送,届时注意即可。我参加的这一次讲座是由一位转入软件学院的学长主持的。他全方位地介绍了转专业的流程,并且从材料准备、自我介绍、老师提问三个方面给出了一些建议。我当时写的笔记大概如下: + +#### 材料准备 + +- 转专业理由 +- 学习情况与个人能力自评 + - 学习成绩排名 + - 专业技能掌握情况 + - 性格和能力优势 +- 社会工作情况 + - 班委 + - 院系社工骨干 + - 校学生会/校团委/社团/艺术团骨干 + - 志愿经历 +- 获奖情况 + +在准备材料的时候需要注意 **重点突出,条理清晰**。重要的内容靠前写,必要时可以 **加粗**。 + +#### 自我介绍 + +主要由个人基本情况、转专业的原因、知识储备和能力、兴趣爱好和长处四个部分来切入。比较重要的技巧是 **少讲自己曾经获得过的荣誉,多提及自己所具备的能力**。 + +#### 老师提问 + +最重要的是 **实话实说,保持谦虚**。 + +如果有老师问到“为什么要从原专业转出?为什么要转到我们专业?”: + +- 原院系与我的什么什么期望不符 +- 新院系与我的什么什么期望相符 +- 自己怎么怎么技能更适合新院系 +- 不要说“不喜欢”,说“不合适” + +如果碰到老师问比较刁钻的问题怎么办? + +- 承认错误 +- 解释原因 +- 未来展望 + +--- + +我以为会人满为患,结果只来了包括我在内的两位同学。我还记得那天晚上我从四教骑车回宿舍的途中吹过的风。我是迷糊的:为什么对于我而言这么重要的讲座,最后只有两个人来听?另外那个同学甚至还没有确定自己想转入哪个目标院系。 + +道路两旁的树木仿佛被压得更加沉默寂静。我骑着车,对抗着风,感受到了一阵阵凉意。曾经我也像那些树木一样高大挺拔,在前进的路上充满信心和勇气,但是现在却觉得一切都变得模糊不清,迷失了方向。 + +不过,其他人是否注重转系这件事,其实也不是我需要关注的,不是吗? + +### 填写转专业申请表 + +这也是个麻烦事儿——我该怎么控制页数和字数,让老师在阅读我的材料的时候,能抓住我的闪光点呢?我的转专业申请表如下: + +{% pdf https://leverimmy.top/pdf/major-transfer.pdf [500px] %} + +### 预约学习指导发展中心的面试咨询 + +除了听讲座以外,学习指导发展中心也提供了转专业面试的相关咨询条件。 + +> 注:在“乐学”公众号里进行预约。 + +由于大一上学期的新生导引课时,王学武老师曾邀请 [詹逸思](https://learning.tsinghua.edu.cn/info/1007/1038.htm) 老师分享她曾经求学时的一些经验,所以我在学生学习与发展指导中心预约面试咨询时优先向她进行咨询。以下是詹老师给予我的建议: + +**面试时的着装:** + +- 衬衣,带领子的,西装正式不为过。这说明你很重视这次面试。 + + 事实上,我是为数不多的穿西装参加面试的人之一。 + +**提前准备一些问题,以提高应对能力:** + +- 高考怎么没能如愿考好? + + 高考时数学难度加大许多,看到不会的题,心态也不是很淡定。后来通过一定的调整,我还是做出了大部分题。但就差一道数学选择题,我就能来到了计算机系。 + +- 你对计算机系感兴趣的点在哪里?举个例子。 + + 如果提问涉及到的领域你不是很会,就回答:我知道我不会的还有很多,我也希望能在计算机系里进行更深一步的学习。 + +- 如果你在学习生活中遇到了困难,你会怎么调整? + + 重点在调整!然后顺着说进入数学系后分流失败的我是怎么处理这次失败的。 + +**在回答问题的时候,应该抓一个点,然后展开一个例子,见好就收,而不是泛泛而谈。** + +**同时准备一份英文版的自我介绍,这样回答问题可能可以用的上。** + +**如果遇到棘手的、尖锐的问题(比如:“有的同学转系成功后就放纵了,天天打游戏,你会这样吗?你怎么证明你不会这样?”),应该怎么迂回地回答?** + +- 谢谢老师您提的问题,我之前没有考虑过。的确有其他同学出现这样,他们的问题都是个性化的。 + - 我之前也遇到过类似的情况。(谈我以前是怎么解决的) + - 我没有遇到类似的情况,但我坚信,办法总比问题多。生活中一定会有不如意的状态,我会先找同学、更有经验的老师和辅导员寻求帮助。我相信他们一定会给我很好的建议。 +- 这个知识点我不会,希望以后能够学习。 + +**在面试的末尾,一般都有自由交流的时间。此时也可以问一些问题,来表示你对进入目标院系学习的兴趣:** + +- 您看我目前的学习进度,是否需要降转? +- 在某某知识点方面,您推荐我修哪些课程? + +**最后,詹老师建议我把自我介绍的稿子改顺,脱稿对着镜子多练几遍,让室友提问模拟面试的场景。** + +值得一提的是,我后来选修了詹老师的《大学生心理训练与潜能开发》,同样收获颇丰。 + +### 向学长学姐求助 + +> 注:直接问自己高中的学长学姐!或者是加入转系群! + +我是幸运的。我有一位学姐曾经转系成功过,所以我向她请教了许多转系相关的问题,我十分感谢她给予我的帮助;不过如果没有可以联系的学长学姐也没关系,可以加入转系群然后在群里找学长学姐求助。~~快点关注“文刀日肥”公众号加入转系群!~~ + +### 面试 + +在做好了以上种种准备之后,相较而言,面试还是比较顺利的。在我熟练地背诵完自我介绍之后,老师和辅导员问了我几个问题: + +Q1:你这个《算法设计及其复杂性分析》的课程,具体是讲什么的呀? + +我:大概是数值分析相关内容。具体而言,我们在研究一元多次方程所得公式解的准确性。(然后我扯了点舍入误差之类的内容) + +【老师:哦。】 + +Q2:你当班长,最有成就感的一件事情是什么? + +我:工物系 **极其夸张的男女比** 使得办男生节和女生节相关活动十分棘手。我来自武汉外国语学校,所以就读于清华的我的高中同学大部分都保送到外文系。我联想到外文系女生多男生少,正好可以相互平衡(笑)。我随即联系我的一个高中同学,他恰好是他们班的团支书,然后我们就一起举办了男生节和女生节。大家都玩得很开心。我觉得挺好的,还能多认识一些新朋友。 + +【老师和辅导员纷纷大笑】 + +Q3:(调侃)诶你是工物系毽球队的呀,我记得计算机系毽球队也挺厉害的,你会不会加入呀? + +我:去年马杯毽球比赛工物系获得甲组第三就是因为半决赛被计算机打败了。听您这么一说,这下不得不“打不过就加入”了。 + +【老师和辅导员又纷纷大笑】 + +### 等待录取 + +面试完毕之后,我长舒了一口气。 + +> 一切就这么结束了? + +至此,我再也无法左右转专业的结果了。主观能动性也不会有任何作用了。是否接受我的转专业申请,是院系老师以及辅导员所需要考虑的事情——这一切的一切,都与我无关了。 + +那天下午我回寝后倒头就睡,也没吃晚饭,大概晚上八点多的时候才睡醒。感觉这一切的一切都像是一场梦,我为转专业所做的一切准备,都在今天下午的那场面试中得到了体现。但面试结束之后,我还是得老老实实继续学习;附加的,只是对一纸通知的期盼罢了。 + +就像《终末之诗》中所提及的那样: + +> And the game was over and the player woke up from the dream. And the player began a new dream. And the player dreamed again, dreamed better. And the player was the universe. And the player was love. +> +> You are the player. +> +> Wake up. + +是时候该醒了。滚回去做微积分作业去吧! + +### 转专业结果公示 + +我是幸运的。我最终在那份长长的转专业公示名单中找到了我的名字。 + +更幸运的是,我身边的好友也都纷纷转专业/分流成功了。 + +## 现状 + +现在,我已经成为清华大学计算机系的一员。但这并不是终点;恰恰相反,成为清华大学计算机系的一员仅是我大学生活的起点。 + +转系成功后,有更多的事情需要我去考虑: + +- 怎么与新同学、新室友相处? +- 又该如何与老同学、老室友相处? +- 平转后缺的大一课程该如何补? +- 计算机系学习压力很大该怎么办? + +转系成功也有转系成功的烦恼:计算机系是真的卷,每天活着都很累。我作为工物系绩点 top,转入计算机系后摇身一变位于年级 40%-50%,甚至评不上综合奖学金。我也曾经被各种压力压垮过,但,这是我向往学习的专业,所以无憾无悔。 + +--- + +最后,祝愿屏幕前的你,也能顺利转入自己心仪的专业。 + diff --git a/source/about/index.md b/source/about/index.md new file mode 100644 index 0000000..03ac203 --- /dev/null +++ b/source/about/index.md @@ -0,0 +1,14 @@ +--- +title: 关于 +date: 2023-07-01 11:45:02 +type: "about" +mathjax: true +--- + +嗨!大家好,我是 Clever_Jimmy,大二学生。 + +在高中时曾短暂地参加过信息竞赛,并获得湖北省(弱省)省级一等奖。 + +高中来自于武汉外国语学校,现在就读于清华大学计算机系。 + +邮箱:xze22@mails.tsinghua.edu.cn diff --git a/source/categories/index.md b/source/categories/index.md new file mode 100644 index 0000000..317d0aa --- /dev/null +++ b/source/categories/index.md @@ -0,0 +1,5 @@ +--- +title: 所有分类 +date: 2020-03-16 10:27:16 +type: "categories" +--- diff --git a/source/gallery/2022Lookback/20km1.jpg b/source/gallery/2022Lookback/20km1.jpg new file mode 100644 index 0000000..c4c5939 Binary files /dev/null and b/source/gallery/2022Lookback/20km1.jpg differ diff --git a/source/gallery/2022Lookback/20km2.jpg b/source/gallery/2022Lookback/20km2.jpg new file mode 100644 index 0000000..d1d1f20 Binary files /dev/null and b/source/gallery/2022Lookback/20km2.jpg differ diff --git a/source/gallery/2022Lookback/JohnMaCup1.jpg b/source/gallery/2022Lookback/JohnMaCup1.jpg new file mode 100644 index 0000000..5515363 Binary files /dev/null and b/source/gallery/2022Lookback/JohnMaCup1.jpg differ diff --git a/source/gallery/2022Lookback/JohnMaCup2.jpg b/source/gallery/2022Lookback/JohnMaCup2.jpg new file mode 100644 index 0000000..bdc5a3e Binary files /dev/null and b/source/gallery/2022Lookback/JohnMaCup2.jpg differ diff --git a/source/gallery/2022Lookback/JohnMaCup3.jpg b/source/gallery/2022Lookback/JohnMaCup3.jpg new file mode 100644 index 0000000..4652506 Binary files /dev/null and b/source/gallery/2022Lookback/JohnMaCup3.jpg differ diff --git a/source/gallery/2022Lookback/WFLS-middle1.jpg b/source/gallery/2022Lookback/WFLS-middle1.jpg new file mode 100644 index 0000000..967384a Binary files /dev/null and b/source/gallery/2022Lookback/WFLS-middle1.jpg differ diff --git a/source/gallery/2022Lookback/WFLS-middle2.jpg b/source/gallery/2022Lookback/WFLS-middle2.jpg new file mode 100644 index 0000000..025e436 Binary files /dev/null and b/source/gallery/2022Lookback/WFLS-middle2.jpg differ diff --git a/source/gallery/2022Lookback/WFLS-middle3.jpg b/source/gallery/2022Lookback/WFLS-middle3.jpg new file mode 100644 index 0000000..85aac31 Binary files /dev/null and b/source/gallery/2022Lookback/WFLS-middle3.jpg differ diff --git a/source/gallery/2022Lookback/admission.jpg b/source/gallery/2022Lookback/admission.jpg new file mode 100644 index 0000000..3d7daf5 Binary files /dev/null and b/source/gallery/2022Lookback/admission.jpg differ diff --git a/source/gallery/2022Lookback/algorithm.jpg b/source/gallery/2022Lookback/algorithm.jpg new file mode 100644 index 0000000..1bae2c6 Binary files /dev/null and b/source/gallery/2022Lookback/algorithm.jpg differ diff --git a/source/gallery/2022Lookback/barefoot1.jpg b/source/gallery/2022Lookback/barefoot1.jpg new file mode 100644 index 0000000..2ddc43a Binary files /dev/null and b/source/gallery/2022Lookback/barefoot1.jpg differ diff --git a/source/gallery/2022Lookback/barefoot2.jpg b/source/gallery/2022Lookback/barefoot2.jpg new file mode 100644 index 0000000..3b2bacf Binary files /dev/null and b/source/gallery/2022Lookback/barefoot2.jpg differ diff --git a/source/gallery/2022Lookback/basketball-cup.jpg b/source/gallery/2022Lookback/basketball-cup.jpg new file mode 100644 index 0000000..4139ed7 Binary files /dev/null and b/source/gallery/2022Lookback/basketball-cup.jpg differ diff --git a/source/gallery/2022Lookback/birthday.jpg b/source/gallery/2022Lookback/birthday.jpg new file mode 100644 index 0000000..788e6f9 Binary files /dev/null and b/source/gallery/2022Lookback/birthday.jpg differ diff --git a/source/gallery/2022Lookback/ceremony1.jpg b/source/gallery/2022Lookback/ceremony1.jpg new file mode 100644 index 0000000..55de9b5 Binary files /dev/null and b/source/gallery/2022Lookback/ceremony1.jpg differ diff --git a/source/gallery/2022Lookback/ceremony2.jpg b/source/gallery/2022Lookback/ceremony2.jpg new file mode 100644 index 0000000..87007ec Binary files /dev/null and b/source/gallery/2022Lookback/ceremony2.jpg differ diff --git a/source/gallery/2022Lookback/classmates.jpg b/source/gallery/2022Lookback/classmates.jpg new file mode 100644 index 0000000..c0ca633 Binary files /dev/null and b/source/gallery/2022Lookback/classmates.jpg differ diff --git a/source/gallery/2022Lookback/cover.png b/source/gallery/2022Lookback/cover.png new file mode 100644 index 0000000..ef8de7f Binary files /dev/null and b/source/gallery/2022Lookback/cover.png differ diff --git a/source/gallery/2022Lookback/dorm.jpg b/source/gallery/2022Lookback/dorm.jpg new file mode 100644 index 0000000..0095a3e Binary files /dev/null and b/source/gallery/2022Lookback/dorm.jpg differ diff --git a/source/gallery/2022Lookback/fjxsd1.jpg b/source/gallery/2022Lookback/fjxsd1.jpg new file mode 100644 index 0000000..9f50dd0 Binary files /dev/null and b/source/gallery/2022Lookback/fjxsd1.jpg differ diff --git a/source/gallery/2022Lookback/fjxsd2.jpg b/source/gallery/2022Lookback/fjxsd2.jpg new file mode 100644 index 0000000..2bd5d01 Binary files /dev/null and b/source/gallery/2022Lookback/fjxsd2.jpg differ diff --git a/source/gallery/2022Lookback/fjxsd3.jpg b/source/gallery/2022Lookback/fjxsd3.jpg new file mode 100644 index 0000000..f1ae505 Binary files /dev/null and b/source/gallery/2022Lookback/fjxsd3.jpg differ diff --git a/source/gallery/2022Lookback/gre.jpg b/source/gallery/2022Lookback/gre.jpg new file mode 100644 index 0000000..8c8a95f Binary files /dev/null and b/source/gallery/2022Lookback/gre.jpg differ diff --git a/source/gallery/2022Lookback/gzt1.jpg b/source/gallery/2022Lookback/gzt1.jpg new file mode 100644 index 0000000..dae8a34 Binary files /dev/null and b/source/gallery/2022Lookback/gzt1.jpg differ diff --git a/source/gallery/2022Lookback/gzt2.jpg b/source/gallery/2022Lookback/gzt2.jpg new file mode 100644 index 0000000..36cec06 Binary files /dev/null and b/source/gallery/2022Lookback/gzt2.jpg differ diff --git a/source/gallery/2022Lookback/gzt3.jpg b/source/gallery/2022Lookback/gzt3.jpg new file mode 100644 index 0000000..7c87fc5 Binary files /dev/null and b/source/gallery/2022Lookback/gzt3.jpg differ diff --git a/source/gallery/2022Lookback/hometown1.jpg b/source/gallery/2022Lookback/hometown1.jpg new file mode 100644 index 0000000..4179a86 Binary files /dev/null and b/source/gallery/2022Lookback/hometown1.jpg differ diff --git a/source/gallery/2022Lookback/hometown2.jpg b/source/gallery/2022Lookback/hometown2.jpg new file mode 100644 index 0000000..03d93ca Binary files /dev/null and b/source/gallery/2022Lookback/hometown2.jpg differ diff --git a/source/gallery/2022Lookback/hometown3.jpg b/source/gallery/2022Lookback/hometown3.jpg new file mode 100644 index 0000000..dffc4b5 Binary files /dev/null and b/source/gallery/2022Lookback/hometown3.jpg differ diff --git a/source/gallery/2022Lookback/hot-dry1.jpg b/source/gallery/2022Lookback/hot-dry1.jpg new file mode 100644 index 0000000..6732460 Binary files /dev/null and b/source/gallery/2022Lookback/hot-dry1.jpg differ diff --git a/source/gallery/2022Lookback/hot-dry2.jpg b/source/gallery/2022Lookback/hot-dry2.jpg new file mode 100644 index 0000000..12b26a0 Binary files /dev/null and b/source/gallery/2022Lookback/hot-dry2.jpg differ diff --git a/source/gallery/2022Lookback/money.jpg b/source/gallery/2022Lookback/money.jpg new file mode 100644 index 0000000..bb3f8b1 Binary files /dev/null and b/source/gallery/2022Lookback/money.jpg differ diff --git a/source/gallery/2022Lookback/orange.jpg b/source/gallery/2022Lookback/orange.jpg new file mode 100644 index 0000000..4d7c80c Binary files /dev/null and b/source/gallery/2022Lookback/orange.jpg differ diff --git a/source/gallery/2022Lookback/orienting1.jpg b/source/gallery/2022Lookback/orienting1.jpg new file mode 100644 index 0000000..485a01c Binary files /dev/null and b/source/gallery/2022Lookback/orienting1.jpg differ diff --git a/source/gallery/2022Lookback/orienting2.jpg b/source/gallery/2022Lookback/orienting2.jpg new file mode 100644 index 0000000..84b8200 Binary files /dev/null and b/source/gallery/2022Lookback/orienting2.jpg differ diff --git a/source/gallery/2022Lookback/orienting3.jpg b/source/gallery/2022Lookback/orienting3.jpg new file mode 100644 index 0000000..4722642 Binary files /dev/null and b/source/gallery/2022Lookback/orienting3.jpg differ diff --git a/source/gallery/2022Lookback/poem.jpg b/source/gallery/2022Lookback/poem.jpg new file mode 100644 index 0000000..c92857a Binary files /dev/null and b/source/gallery/2022Lookback/poem.jpg differ diff --git a/source/gallery/2022Lookback/schoolmates.jpg b/source/gallery/2022Lookback/schoolmates.jpg new file mode 100644 index 0000000..7bbba35 Binary files /dev/null and b/source/gallery/2022Lookback/schoolmates.jpg differ diff --git a/source/gallery/2022Lookback/thumbnail.png b/source/gallery/2022Lookback/thumbnail.png new file mode 100644 index 0000000..ef8de7f Binary files /dev/null and b/source/gallery/2022Lookback/thumbnail.png differ diff --git a/source/gallery/2022Lookback/volunteer1.jpg b/source/gallery/2022Lookback/volunteer1.jpg new file mode 100644 index 0000000..0ec2833 Binary files /dev/null and b/source/gallery/2022Lookback/volunteer1.jpg differ diff --git a/source/gallery/2022Lookback/volunteer2.jpg b/source/gallery/2022Lookback/volunteer2.jpg new file mode 100644 index 0000000..12a81ea Binary files /dev/null and b/source/gallery/2022Lookback/volunteer2.jpg differ diff --git a/source/gallery/2022Lookback/volunteer3.jpg b/source/gallery/2022Lookback/volunteer3.jpg new file mode 100644 index 0000000..7fa5f03 Binary files /dev/null and b/source/gallery/2022Lookback/volunteer3.jpg differ diff --git a/source/gallery/2022Lookback/xianning1.jpg b/source/gallery/2022Lookback/xianning1.jpg new file mode 100644 index 0000000..17af327 Binary files /dev/null and b/source/gallery/2022Lookback/xianning1.jpg differ diff --git a/source/gallery/2022Lookback/xianning2.jpg b/source/gallery/2022Lookback/xianning2.jpg new file mode 100644 index 0000000..82d0a3f Binary files /dev/null and b/source/gallery/2022Lookback/xianning2.jpg differ diff --git a/source/gallery/2022WFLS-Invigilate/chem-1,2.jpg b/source/gallery/2022WFLS-Invigilate/chem-1,2.jpg new file mode 100644 index 0000000..248f2dd Binary files /dev/null and b/source/gallery/2022WFLS-Invigilate/chem-1,2.jpg differ diff --git a/source/gallery/2022WFLS-Invigilate/dinner.png b/source/gallery/2022WFLS-Invigilate/dinner.png new file mode 100644 index 0000000..72e210b Binary files /dev/null and b/source/gallery/2022WFLS-Invigilate/dinner.png differ diff --git a/source/gallery/2022WFLS-Invigilate/hdl-coconut.jpg b/source/gallery/2022WFLS-Invigilate/hdl-coconut.jpg new file mode 100644 index 0000000..c9ac7a6 Binary files /dev/null and b/source/gallery/2022WFLS-Invigilate/hdl-coconut.jpg differ diff --git a/source/gallery/2022WFLS-Invigilate/hdl-empty.jpg b/source/gallery/2022WFLS-Invigilate/hdl-empty.jpg new file mode 100644 index 0000000..b78d8fb Binary files /dev/null and b/source/gallery/2022WFLS-Invigilate/hdl-empty.jpg differ diff --git a/source/gallery/2022WFLS-Invigilate/hdl-full.jpg b/source/gallery/2022WFLS-Invigilate/hdl-full.jpg new file mode 100644 index 0000000..2f2ba8a Binary files /dev/null and b/source/gallery/2022WFLS-Invigilate/hdl-full.jpg differ diff --git a/source/gallery/2022WFLS-Invigilate/maths-fix.png b/source/gallery/2022WFLS-Invigilate/maths-fix.png new file mode 100644 index 0000000..bac494f Binary files /dev/null and b/source/gallery/2022WFLS-Invigilate/maths-fix.png differ diff --git a/source/gallery/2022WFLS-Invigilate/physics-T2.jpg b/source/gallery/2022WFLS-Invigilate/physics-T2.jpg new file mode 100644 index 0000000..95de42d Binary files /dev/null and b/source/gallery/2022WFLS-Invigilate/physics-T2.jpg differ diff --git a/source/gallery/2022WFLS-Invigilate/physics-T6.jpg b/source/gallery/2022WFLS-Invigilate/physics-T6.jpg new file mode 100644 index 0000000..650afbb Binary files /dev/null and b/source/gallery/2022WFLS-Invigilate/physics-T6.jpg differ diff --git a/source/gallery/2022WFLS-Invigilate/pre.png b/source/gallery/2022WFLS-Invigilate/pre.png new file mode 100644 index 0000000..fd304b4 Binary files /dev/null and b/source/gallery/2022WFLS-Invigilate/pre.png differ diff --git a/source/gallery/2022WFLS-Invigilate/prepre.png b/source/gallery/2022WFLS-Invigilate/prepre.png new file mode 100644 index 0000000..096a427 Binary files /dev/null and b/source/gallery/2022WFLS-Invigilate/prepre.png differ diff --git a/source/gallery/2022WFLS-Invigilate/us.jpg b/source/gallery/2022WFLS-Invigilate/us.jpg new file mode 100644 index 0000000..5e91ba3 Binary files /dev/null and b/source/gallery/2022WFLS-Invigilate/us.jpg differ diff --git a/source/gallery/2022WFLS-Invigilate/wc.jpg b/source/gallery/2022WFLS-Invigilate/wc.jpg new file mode 100644 index 0000000..165414b Binary files /dev/null and b/source/gallery/2022WFLS-Invigilate/wc.jpg differ diff --git a/source/gallery/2022WFLS-Invigilate/wechat-chem.jpg b/source/gallery/2022WFLS-Invigilate/wechat-chem.jpg new file mode 100644 index 0000000..b2a61ec Binary files /dev/null and b/source/gallery/2022WFLS-Invigilate/wechat-chem.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day0/apartment1.jpg b/source/gallery/2023Chongqing-Social-Practice/Day0/apartment1.jpg new file mode 100644 index 0000000..08c37bc Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day0/apartment1.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day0/apartment2.jpg b/source/gallery/2023Chongqing-Social-Practice/Day0/apartment2.jpg new file mode 100644 index 0000000..3f36539 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day0/apartment2.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day0/crowded.jpg b/source/gallery/2023Chongqing-Social-Practice/Day0/crowded.jpg new file mode 100644 index 0000000..b5e5d95 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day0/crowded.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day0/hankou.jpg b/source/gallery/2023Chongqing-Social-Practice/Day0/hankou.jpg new file mode 100644 index 0000000..8ccc789 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day0/hankou.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day0/laifeng-fish.jpg b/source/gallery/2023Chongqing-Social-Practice/Day0/laifeng-fish.jpg new file mode 100644 index 0000000..90b0ec6 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day0/laifeng-fish.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day0/mountain1.jpg b/source/gallery/2023Chongqing-Social-Practice/Day0/mountain1.jpg new file mode 100644 index 0000000..3a56bdd Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day0/mountain1.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day0/stupid-lunch.jpg b/source/gallery/2023Chongqing-Social-Practice/Day0/stupid-lunch.jpg new file mode 100644 index 0000000..8ded1c1 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day0/stupid-lunch.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day0/vegetable-soup.jpg b/source/gallery/2023Chongqing-Social-Practice/Day0/vegetable-soup.jpg new file mode 100644 index 0000000..6a08d24 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day0/vegetable-soup.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day1/byd.jpg b/source/gallery/2023Chongqing-Social-Practice/Day1/byd.jpg new file mode 100644 index 0000000..2f11aa4 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day1/byd.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day1/flower1.jpg b/source/gallery/2023Chongqing-Social-Practice/Day1/flower1.jpg new file mode 100644 index 0000000..84a390b Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day1/flower1.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day1/hotpot1.jpg b/source/gallery/2023Chongqing-Social-Practice/Day1/hotpot1.jpg new file mode 100644 index 0000000..d0f6b7a Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day1/hotpot1.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day1/plate1.jpg b/source/gallery/2023Chongqing-Social-Practice/Day1/plate1.jpg new file mode 100644 index 0000000..cb0e564 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day1/plate1.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day1/plate2.jpg b/source/gallery/2023Chongqing-Social-Practice/Day1/plate2.jpg new file mode 100644 index 0000000..2ad2e1c Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day1/plate2.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day1/skyshuttle.jpg b/source/gallery/2023Chongqing-Social-Practice/Day1/skyshuttle.jpg new file mode 100644 index 0000000..298cd33 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day1/skyshuttle.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day1/tree1.jpg b/source/gallery/2023Chongqing-Social-Practice/Day1/tree1.jpg new file mode 100644 index 0000000..8c99cba Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day1/tree1.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day1/tree2.jpg b/source/gallery/2023Chongqing-Social-Practice/Day1/tree2.jpg new file mode 100644 index 0000000..c8f2a55 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day1/tree2.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day10/Chongqing-Xiaomian.jpg b/source/gallery/2023Chongqing-Social-Practice/Day10/Chongqing-Xiaomian.jpg new file mode 100644 index 0000000..69a00e6 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day10/Chongqing-Xiaomian.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day10/cat1.jpg b/source/gallery/2023Chongqing-Social-Practice/Day10/cat1.jpg new file mode 100644 index 0000000..52a9d0f Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day10/cat1.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day10/cat2.jpg b/source/gallery/2023Chongqing-Social-Practice/Day10/cat2.jpg new file mode 100644 index 0000000..e0dedcd Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day10/cat2.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day10/cat3.jpg b/source/gallery/2023Chongqing-Social-Practice/Day10/cat3.jpg new file mode 100644 index 0000000..bbf93a5 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day10/cat3.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day10/sesame-duck1.jpg b/source/gallery/2023Chongqing-Social-Practice/Day10/sesame-duck1.jpg new file mode 100644 index 0000000..a7f5e42 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day10/sesame-duck1.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day10/sesame-duck2.jpg b/source/gallery/2023Chongqing-Social-Practice/Day10/sesame-duck2.jpg new file mode 100644 index 0000000..7111328 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day10/sesame-duck2.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day10/souvenir.jpg b/source/gallery/2023Chongqing-Social-Practice/Day10/souvenir.jpg new file mode 100644 index 0000000..20e4548 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day10/souvenir.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day11/chaoshou.jpg b/source/gallery/2023Chongqing-Social-Practice/Day11/chaoshou.jpg new file mode 100644 index 0000000..db74ce6 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day11/chaoshou.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day11/dine-saur.jpg b/source/gallery/2023Chongqing-Social-Practice/Day11/dine-saur.jpg new file mode 100644 index 0000000..7ef1f3c Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day11/dine-saur.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day11/eat.jpg b/source/gallery/2023Chongqing-Social-Practice/Day11/eat.jpg new file mode 100644 index 0000000..7412e6c Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day11/eat.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day11/hotpot.jpg b/source/gallery/2023Chongqing-Social-Practice/Day11/hotpot.jpg new file mode 100644 index 0000000..85f9d45 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day11/hotpot.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day11/people.jpg b/source/gallery/2023Chongqing-Social-Practice/Day11/people.jpg new file mode 100644 index 0000000..6d7d0c2 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day11/people.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day12/ELEC.jpg b/source/gallery/2023Chongqing-Social-Practice/Day12/ELEC.jpg new file mode 100644 index 0000000..4e0cc27 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day12/ELEC.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day12/Hongyadong.jpg b/source/gallery/2023Chongqing-Social-Practice/Day12/Hongyadong.jpg new file mode 100644 index 0000000..d28d3d0 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day12/Hongyadong.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day12/bridge.jpg b/source/gallery/2023Chongqing-Social-Practice/Day12/bridge.jpg new file mode 100644 index 0000000..e4291d2 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day12/bridge.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day12/cloud-bus.jpg b/source/gallery/2023Chongqing-Social-Practice/Day12/cloud-bus.jpg new file mode 100644 index 0000000..79bfd5f Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day12/cloud-bus.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day12/dining.jpg b/source/gallery/2023Chongqing-Social-Practice/Day12/dining.jpg new file mode 100644 index 0000000..02e73cd Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day12/dining.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day12/dusk.jpg b/source/gallery/2023Chongqing-Social-Practice/Day12/dusk.jpg new file mode 100644 index 0000000..30436ec Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day12/dusk.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day12/meeting-room.jpg b/source/gallery/2023Chongqing-Social-Practice/Day12/meeting-room.jpg new file mode 100644 index 0000000..e5936be Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day12/meeting-room.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day2/bench.jpg b/source/gallery/2023Chongqing-Social-Practice/Day2/bench.jpg new file mode 100644 index 0000000..0d86cf4 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day2/bench.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day2/food.jpg b/source/gallery/2023Chongqing-Social-Practice/Day2/food.jpg new file mode 100644 index 0000000..459728e Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day2/food.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day2/meeting.jpg b/source/gallery/2023Chongqing-Social-Practice/Day2/meeting.jpg new file mode 100644 index 0000000..644a8ef Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day2/meeting.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day2/museum.jpg b/source/gallery/2023Chongqing-Social-Practice/Day2/museum.jpg new file mode 100644 index 0000000..f5181dc Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day2/museum.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day2/rooster.jpg b/source/gallery/2023Chongqing-Social-Practice/Day2/rooster.jpg new file mode 100644 index 0000000..f8f1212 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day2/rooster.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day2/skulpture.jpg b/source/gallery/2023Chongqing-Social-Practice/Day2/skulpture.jpg new file mode 100644 index 0000000..78b9970 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day2/skulpture.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day2/skulpture2.jpg b/source/gallery/2023Chongqing-Social-Practice/Day2/skulpture2.jpg new file mode 100644 index 0000000..f01d4fa Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day2/skulpture2.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day2/slogan.jpg b/source/gallery/2023Chongqing-Social-Practice/Day2/slogan.jpg new file mode 100644 index 0000000..e89e11d Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day2/slogan.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day2/ta.jpg b/source/gallery/2023Chongqing-Social-Practice/Day2/ta.jpg new file mode 100644 index 0000000..36492f5 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day2/ta.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day2/toilet.jpg b/source/gallery/2023Chongqing-Social-Practice/Day2/toilet.jpg new file mode 100644 index 0000000..a04f732 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day2/toilet.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day2/tree2.jpg b/source/gallery/2023Chongqing-Social-Practice/Day2/tree2.jpg new file mode 100644 index 0000000..be7f1cd Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day2/tree2.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day2/wood1.jpg b/source/gallery/2023Chongqing-Social-Practice/Day2/wood1.jpg new file mode 100644 index 0000000..eeac1d3 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day2/wood1.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day2/wood2.jpg b/source/gallery/2023Chongqing-Social-Practice/Day2/wood2.jpg new file mode 100644 index 0000000..5442995 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day2/wood2.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day3/dog.jpg b/source/gallery/2023Chongqing-Social-Practice/Day3/dog.jpg new file mode 100644 index 0000000..c7ddf1f Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day3/dog.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day3/duck.jpg b/source/gallery/2023Chongqing-Social-Practice/Day3/duck.jpg new file mode 100644 index 0000000..852d114 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day3/duck.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day3/inside.jpg b/source/gallery/2023Chongqing-Social-Practice/Day3/inside.jpg new file mode 100644 index 0000000..7b1ef39 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day3/inside.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day3/interview.mp4 b/source/gallery/2023Chongqing-Social-Practice/Day3/interview.mp4 new file mode 100644 index 0000000..5cdee5c Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day3/interview.mp4 differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day3/lay.jpg b/source/gallery/2023Chongqing-Social-Practice/Day3/lay.jpg new file mode 100644 index 0000000..5d6205e Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day3/lay.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day3/outside.jpg b/source/gallery/2023Chongqing-Social-Practice/Day3/outside.jpg new file mode 100644 index 0000000..7efcc9e Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day3/outside.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day3/selfie.jpg b/source/gallery/2023Chongqing-Social-Practice/Day3/selfie.jpg new file mode 100644 index 0000000..346b62d Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day3/selfie.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day3/shadow.jpg b/source/gallery/2023Chongqing-Social-Practice/Day3/shadow.jpg new file mode 100644 index 0000000..7d81684 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day3/shadow.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day3/stone-chicken.jpg b/source/gallery/2023Chongqing-Social-Practice/Day3/stone-chicken.jpg new file mode 100644 index 0000000..1ff817d Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day3/stone-chicken.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day4/artist-meeting.jpg b/source/gallery/2023Chongqing-Social-Practice/Day4/artist-meeting.jpg new file mode 100644 index 0000000..3eb94e1 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day4/artist-meeting.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day4/chicken.mp4 b/source/gallery/2023Chongqing-Social-Practice/Day4/chicken.mp4 new file mode 100644 index 0000000..eb4c255 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day4/chicken.mp4 differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day4/i-ask-artist.jpg b/source/gallery/2023Chongqing-Social-Practice/Day4/i-ask-artist.jpg new file mode 100644 index 0000000..ea48f03 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day4/i-ask-artist.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day4/sunset.jpg b/source/gallery/2023Chongqing-Social-Practice/Day4/sunset.jpg new file mode 100644 index 0000000..9bcb68a Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day4/sunset.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day5/CQMU.jpg b/source/gallery/2023Chongqing-Social-Practice/Day5/CQMU.jpg new file mode 100644 index 0000000..9bb8376 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day5/CQMU.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day5/PPT.png b/source/gallery/2023Chongqing-Social-Practice/Day5/PPT.png new file mode 100644 index 0000000..ee484f0 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day5/PPT.png differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day5/code-length.png b/source/gallery/2023Chongqing-Social-Practice/Day5/code-length.png new file mode 100644 index 0000000..b8f6c6f Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day5/code-length.png differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day5/old-house1.jpg b/source/gallery/2023Chongqing-Social-Practice/Day5/old-house1.jpg new file mode 100644 index 0000000..c032842 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day5/old-house1.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day5/old-house2.jpg b/source/gallery/2023Chongqing-Social-Practice/Day5/old-house2.jpg new file mode 100644 index 0000000..c1f8ddc Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day5/old-house2.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day5/old-house3.jpg b/source/gallery/2023Chongqing-Social-Practice/Day5/old-house3.jpg new file mode 100644 index 0000000..a010de8 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day5/old-house3.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day5/old-house4.jpg b/source/gallery/2023Chongqing-Social-Practice/Day5/old-house4.jpg new file mode 100644 index 0000000..5e3ae4f Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day5/old-house4.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day5/rubbish.png b/source/gallery/2023Chongqing-Social-Practice/Day5/rubbish.png new file mode 100644 index 0000000..e46db10 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day5/rubbish.png differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day6/chicken.jpg b/source/gallery/2023Chongqing-Social-Practice/Day6/chicken.jpg new file mode 100644 index 0000000..8bf95a8 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day6/chicken.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day6/corn.jpg b/source/gallery/2023Chongqing-Social-Practice/Day6/corn.jpg new file mode 100644 index 0000000..4a7b6fa Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day6/corn.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day6/firewood.jpg b/source/gallery/2023Chongqing-Social-Practice/Day6/firewood.jpg new file mode 100644 index 0000000..cc6071c Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day6/firewood.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day6/handsome.jpg b/source/gallery/2023Chongqing-Social-Practice/Day6/handsome.jpg new file mode 100644 index 0000000..c7eba9b Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day6/handsome.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day6/playground.mp4 b/source/gallery/2023Chongqing-Social-Practice/Day6/playground.mp4 new file mode 100644 index 0000000..3d98343 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day6/playground.mp4 differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day6/sedecordle.png b/source/gallery/2023Chongqing-Social-Practice/Day6/sedecordle.png new file mode 100644 index 0000000..3180dc0 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day6/sedecordle.png differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day6/sunset.jpg b/source/gallery/2023Chongqing-Social-Practice/Day6/sunset.jpg new file mode 100644 index 0000000..36ee1c6 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day6/sunset.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day7/black.jpg b/source/gallery/2023Chongqing-Social-Practice/Day7/black.jpg new file mode 100644 index 0000000..fa6ddf5 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day7/black.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day7/grapes.mp4 b/source/gallery/2023Chongqing-Social-Practice/Day7/grapes.mp4 new file mode 100644 index 0000000..58c51b2 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day7/grapes.mp4 differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day7/green.jpg b/source/gallery/2023Chongqing-Social-Practice/Day7/green.jpg new file mode 100644 index 0000000..f894af1 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day7/green.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day9/afternoon.jpg b/source/gallery/2023Chongqing-Social-Practice/Day9/afternoon.jpg new file mode 100644 index 0000000..2e1bf99 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day9/afternoon.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day9/balance1.jpg b/source/gallery/2023Chongqing-Social-Practice/Day9/balance1.jpg new file mode 100644 index 0000000..94a6f3a Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day9/balance1.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day9/balance2.jpg b/source/gallery/2023Chongqing-Social-Practice/Day9/balance2.jpg new file mode 100644 index 0000000..a920870 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day9/balance2.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day9/data1.jpg b/source/gallery/2023Chongqing-Social-Practice/Day9/data1.jpg new file mode 100644 index 0000000..33539fb Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day9/data1.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day9/data2.jpg b/source/gallery/2023Chongqing-Social-Practice/Day9/data2.jpg new file mode 100644 index 0000000..2661887 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day9/data2.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day9/eat.jpg b/source/gallery/2023Chongqing-Social-Practice/Day9/eat.jpg new file mode 100644 index 0000000..9c0a60a Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day9/eat.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day9/study.jpg b/source/gallery/2023Chongqing-Social-Practice/Day9/study.jpg new file mode 100644 index 0000000..b020b60 Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day9/study.jpg differ diff --git a/source/gallery/2023Chongqing-Social-Practice/Day9/swing.jpg b/source/gallery/2023Chongqing-Social-Practice/Day9/swing.jpg new file mode 100644 index 0000000..4a9d20f Binary files /dev/null and b/source/gallery/2023Chongqing-Social-Practice/Day9/swing.jpg differ diff --git a/source/gallery/2023Lookback/bj-shuttlecock.jpg b/source/gallery/2023Lookback/bj-shuttlecock.jpg new file mode 100644 index 0000000..dd5be78 Binary files /dev/null and b/source/gallery/2023Lookback/bj-shuttlecock.jpg differ diff --git a/source/gallery/2023Lookback/blood-donation1.jpg b/source/gallery/2023Lookback/blood-donation1.jpg new file mode 100644 index 0000000..d517463 Binary files /dev/null and b/source/gallery/2023Lookback/blood-donation1.jpg differ diff --git a/source/gallery/2023Lookback/blood-donation2.jpg b/source/gallery/2023Lookback/blood-donation2.jpg new file mode 100644 index 0000000..5a94b8f Binary files /dev/null and b/source/gallery/2023Lookback/blood-donation2.jpg differ diff --git a/source/gallery/2023Lookback/cet-4.jpg b/source/gallery/2023Lookback/cet-4.jpg new file mode 100644 index 0000000..6f9077f Binary files /dev/null and b/source/gallery/2023Lookback/cet-4.jpg differ diff --git a/source/gallery/2023Lookback/cet-6.jpg b/source/gallery/2023Lookback/cet-6.jpg new file mode 100644 index 0000000..b1de620 Binary files /dev/null and b/source/gallery/2023Lookback/cet-6.jpg differ diff --git a/source/gallery/2023Lookback/change-1.jpg b/source/gallery/2023Lookback/change-1.jpg new file mode 100644 index 0000000..2856d24 Binary files /dev/null and b/source/gallery/2023Lookback/change-1.jpg differ diff --git a/source/gallery/2023Lookback/change-2.jpg b/source/gallery/2023Lookback/change-2.jpg new file mode 100644 index 0000000..7d0582b Binary files /dev/null and b/source/gallery/2023Lookback/change-2.jpg differ diff --git a/source/gallery/2023Lookback/class-yyl.jpg b/source/gallery/2023Lookback/class-yyl.jpg new file mode 100644 index 0000000..933d632 Binary files /dev/null and b/source/gallery/2023Lookback/class-yyl.jpg differ diff --git a/source/gallery/2023Lookback/cubal-1.jpg b/source/gallery/2023Lookback/cubal-1.jpg new file mode 100644 index 0000000..361d42a Binary files /dev/null and b/source/gallery/2023Lookback/cubal-1.jpg differ diff --git a/source/gallery/2023Lookback/cubal-2.jpg b/source/gallery/2023Lookback/cubal-2.jpg new file mode 100644 index 0000000..559873b Binary files /dev/null and b/source/gallery/2023Lookback/cubal-2.jpg differ diff --git a/source/gallery/2023Lookback/emoji-1.jpg b/source/gallery/2023Lookback/emoji-1.jpg new file mode 100644 index 0000000..da08b53 Binary files /dev/null and b/source/gallery/2023Lookback/emoji-1.jpg differ diff --git a/source/gallery/2023Lookback/emoji-2.jpg b/source/gallery/2023Lookback/emoji-2.jpg new file mode 100644 index 0000000..365ab25 Binary files /dev/null and b/source/gallery/2023Lookback/emoji-2.jpg differ diff --git a/source/gallery/2023Lookback/emoji.png b/source/gallery/2023Lookback/emoji.png new file mode 100644 index 0000000..22f8a32 Binary files /dev/null and b/source/gallery/2023Lookback/emoji.png differ diff --git a/source/gallery/2023Lookback/english-corner.jpg b/source/gallery/2023Lookback/english-corner.jpg new file mode 100644 index 0000000..16e2391 Binary files /dev/null and b/source/gallery/2023Lookback/english-corner.jpg differ diff --git a/source/gallery/2023Lookback/entrance-1.jpg b/source/gallery/2023Lookback/entrance-1.jpg new file mode 100644 index 0000000..5859318 Binary files /dev/null and b/source/gallery/2023Lookback/entrance-1.jpg differ diff --git a/source/gallery/2023Lookback/entrance-2.jpg b/source/gallery/2023Lookback/entrance-2.jpg new file mode 100644 index 0000000..1872a6e Binary files /dev/null and b/source/gallery/2023Lookback/entrance-2.jpg differ diff --git a/source/gallery/2023Lookback/farewell-yyl.png b/source/gallery/2023Lookback/farewell-yyl.png new file mode 100644 index 0000000..184474d Binary files /dev/null and b/source/gallery/2023Lookback/farewell-yyl.png differ diff --git a/source/gallery/2023Lookback/festival.jpg b/source/gallery/2023Lookback/festival.jpg new file mode 100644 index 0000000..cc66163 Binary files /dev/null and b/source/gallery/2023Lookback/festival.jpg differ diff --git a/source/gallery/2023Lookback/fool.jpg b/source/gallery/2023Lookback/fool.jpg new file mode 100644 index 0000000..730840b Binary files /dev/null and b/source/gallery/2023Lookback/fool.jpg differ diff --git a/source/gallery/2023Lookback/group.png b/source/gallery/2023Lookback/group.png new file mode 100644 index 0000000..2fc2ea4 Binary files /dev/null and b/source/gallery/2023Lookback/group.png differ diff --git a/source/gallery/2023Lookback/mahjong.jpg b/source/gallery/2023Lookback/mahjong.jpg new file mode 100644 index 0000000..b9583b5 Binary files /dev/null and b/source/gallery/2023Lookback/mahjong.jpg differ diff --git a/source/gallery/2023Lookback/pingpong.jpg b/source/gallery/2023Lookback/pingpong.jpg new file mode 100644 index 0000000..d9fbecb Binary files /dev/null and b/source/gallery/2023Lookback/pingpong.jpg differ diff --git a/source/gallery/2023Lookback/present.jpg b/source/gallery/2023Lookback/present.jpg new file mode 100644 index 0000000..9122b6a Binary files /dev/null and b/source/gallery/2023Lookback/present.jpg differ diff --git a/source/gallery/2023Lookback/schoolmate.jpg b/source/gallery/2023Lookback/schoolmate.jpg new file mode 100644 index 0000000..349500a Binary files /dev/null and b/source/gallery/2023Lookback/schoolmate.jpg differ diff --git a/source/gallery/2023Lookback/shuttlecock-loop.jpg b/source/gallery/2023Lookback/shuttlecock-loop.jpg new file mode 100644 index 0000000..f06175a Binary files /dev/null and b/source/gallery/2023Lookback/shuttlecock-loop.jpg differ diff --git a/source/gallery/2023Lookback/shuttlecock.jpg b/source/gallery/2023Lookback/shuttlecock.jpg new file mode 100644 index 0000000..3e98118 Binary files /dev/null and b/source/gallery/2023Lookback/shuttlecock.jpg differ diff --git a/source/gallery/2023Lookback/snowman.jpg b/source/gallery/2023Lookback/snowman.jpg new file mode 100644 index 0000000..9e48d14 Binary files /dev/null and b/source/gallery/2023Lookback/snowman.jpg differ diff --git a/source/gallery/2023Lookback/speech.png b/source/gallery/2023Lookback/speech.png new file mode 100644 index 0000000..943493a Binary files /dev/null and b/source/gallery/2023Lookback/speech.png differ diff --git a/source/gallery/2023Lookback/transfer.jpg b/source/gallery/2023Lookback/transfer.jpg new file mode 100644 index 0000000..8cf8897 Binary files /dev/null and b/source/gallery/2023Lookback/transfer.jpg differ diff --git a/source/gallery/2023Lookback/volunteer.png b/source/gallery/2023Lookback/volunteer.png new file mode 100644 index 0000000..42bc830 Binary files /dev/null and b/source/gallery/2023Lookback/volunteer.png differ diff --git a/source/gallery/CSAO/Chap1/logic-gates.png b/source/gallery/CSAO/Chap1/logic-gates.png new file mode 100644 index 0000000..f2c0d3b Binary files /dev/null and b/source/gallery/CSAO/Chap1/logic-gates.png differ diff --git a/source/gallery/CSAPP/03-02.png b/source/gallery/CSAPP/03-02.png new file mode 100644 index 0000000..cc05835 Binary files /dev/null and b/source/gallery/CSAPP/03-02.png differ diff --git a/source/gallery/CSAPP/03-04.png b/source/gallery/CSAPP/03-04.png new file mode 100644 index 0000000..d1024e5 Binary files /dev/null and b/source/gallery/CSAPP/03-04.png differ diff --git a/source/gallery/CSAPP/03-12.png b/source/gallery/CSAPP/03-12.png new file mode 100644 index 0000000..32b237b Binary files /dev/null and b/source/gallery/CSAPP/03-12.png differ diff --git a/source/gallery/CSAPP/09-02.png b/source/gallery/CSAPP/09-02.png new file mode 100644 index 0000000..93558c5 Binary files /dev/null and b/source/gallery/CSAPP/09-02.png differ diff --git a/source/gallery/CSAPP/09-03.png b/source/gallery/CSAPP/09-03.png new file mode 100644 index 0000000..58986a1 Binary files /dev/null and b/source/gallery/CSAPP/09-03.png differ diff --git a/source/gallery/CSAPP/09-04.png b/source/gallery/CSAPP/09-04.png new file mode 100644 index 0000000..9784261 Binary files /dev/null and b/source/gallery/CSAPP/09-04.png differ diff --git a/source/gallery/CSAPP/09-10.png b/source/gallery/CSAPP/09-10.png new file mode 100644 index 0000000..9200ac6 Binary files /dev/null and b/source/gallery/CSAPP/09-10.png differ diff --git a/source/gallery/CSAPP/09-12.png b/source/gallery/CSAPP/09-12.png new file mode 100644 index 0000000..8fa09e6 Binary files /dev/null and b/source/gallery/CSAPP/09-12.png differ diff --git a/source/gallery/CSAPP/09-13.png b/source/gallery/CSAPP/09-13.png new file mode 100644 index 0000000..309347a Binary files /dev/null and b/source/gallery/CSAPP/09-13.png differ diff --git a/source/gallery/CSAPP/09-15.png b/source/gallery/CSAPP/09-15.png new file mode 100644 index 0000000..ce83806 Binary files /dev/null and b/source/gallery/CSAPP/09-15.png differ diff --git a/source/gallery/CSAPP/09-16.png b/source/gallery/CSAPP/09-16.png new file mode 100644 index 0000000..5e27d56 Binary files /dev/null and b/source/gallery/CSAPP/09-16.png differ diff --git a/source/gallery/CSAPP/09-26.png b/source/gallery/CSAPP/09-26.png new file mode 100644 index 0000000..d431dd4 Binary files /dev/null and b/source/gallery/CSAPP/09-26.png differ diff --git a/source/gallery/CSAPP/09-27.png b/source/gallery/CSAPP/09-27.png new file mode 100644 index 0000000..7cb4227 Binary files /dev/null and b/source/gallery/CSAPP/09-27.png differ diff --git a/source/gallery/CSAPP/09-28.png b/source/gallery/CSAPP/09-28.png new file mode 100644 index 0000000..79fe994 Binary files /dev/null and b/source/gallery/CSAPP/09-28.png differ diff --git a/source/gallery/CSAPP/09-30.png b/source/gallery/CSAPP/09-30.png new file mode 100644 index 0000000..18567d2 Binary files /dev/null and b/source/gallery/CSAPP/09-30.png differ diff --git a/source/gallery/CSAPP/09-35.png b/source/gallery/CSAPP/09-35.png new file mode 100644 index 0000000..0b31080 Binary files /dev/null and b/source/gallery/CSAPP/09-35.png differ diff --git a/source/gallery/CSAPP/09-36.png b/source/gallery/CSAPP/09-36.png new file mode 100644 index 0000000..4db67f5 Binary files /dev/null and b/source/gallery/CSAPP/09-36.png differ diff --git a/source/gallery/CSAPP/12-19.png b/source/gallery/CSAPP/12-19.png new file mode 100644 index 0000000..9479ecc Binary files /dev/null and b/source/gallery/CSAPP/12-19.png differ diff --git a/source/gallery/CSAPP/12-20.png b/source/gallery/CSAPP/12-20.png new file mode 100644 index 0000000..ca5449e Binary files /dev/null and b/source/gallery/CSAPP/12-20.png differ diff --git a/source/gallery/CSAPP/12-21.png b/source/gallery/CSAPP/12-21.png new file mode 100644 index 0000000..04a3538 Binary files /dev/null and b/source/gallery/CSAPP/12-21.png differ diff --git a/source/gallery/CSAPP/12-44.png b/source/gallery/CSAPP/12-44.png new file mode 100644 index 0000000..0ea2aa6 Binary files /dev/null and b/source/gallery/CSAPP/12-44.png differ diff --git a/source/gallery/CSAPP/12-45.png b/source/gallery/CSAPP/12-45.png new file mode 100644 index 0000000..b46aea4 Binary files /dev/null and b/source/gallery/CSAPP/12-45.png differ diff --git a/source/gallery/IATLC/Chap1/exercise1.png b/source/gallery/IATLC/Chap1/exercise1.png new file mode 100644 index 0000000..9796919 Binary files /dev/null and b/source/gallery/IATLC/Chap1/exercise1.png differ diff --git a/source/gallery/IATLC/Chap6/Y-x-graph.png b/source/gallery/IATLC/Chap6/Y-x-graph.png new file mode 100644 index 0000000..8d03cb9 Binary files /dev/null and b/source/gallery/IATLC/Chap6/Y-x-graph.png differ diff --git a/source/gallery/IATLC/Chap6/exercise1.png b/source/gallery/IATLC/Chap6/exercise1.png new file mode 100644 index 0000000..f584bf1 Binary files /dev/null and b/source/gallery/IATLC/Chap6/exercise1.png differ diff --git a/source/gallery/IATLC/Chap6/exercise2.png b/source/gallery/IATLC/Chap6/exercise2.png new file mode 100644 index 0000000..09f23df Binary files /dev/null and b/source/gallery/IATLC/Chap6/exercise2.png differ diff --git a/source/gallery/IATLC/Chap6/models.jpg b/source/gallery/IATLC/Chap6/models.jpg new file mode 100644 index 0000000..d516c69 Binary files /dev/null and b/source/gallery/IATLC/Chap6/models.jpg differ diff --git a/source/gallery/IATLC/Chap6/models.pptx b/source/gallery/IATLC/Chap6/models.pptx new file mode 100644 index 0000000..e24db3e Binary files /dev/null and b/source/gallery/IATLC/Chap6/models.pptx differ diff --git a/source/gallery/IATLC/Chap7/cyk.png b/source/gallery/IATLC/Chap7/cyk.png new file mode 100644 index 0000000..a47b948 Binary files /dev/null and b/source/gallery/IATLC/Chap7/cyk.png differ diff --git a/source/gallery/IATLC/Chap7/pump.png b/source/gallery/IATLC/Chap7/pump.png new file mode 100644 index 0000000..2c65a0a Binary files /dev/null and b/source/gallery/IATLC/Chap7/pump.png differ diff --git a/source/gallery/Introduction-to-Java/compile-and-run.png b/source/gallery/Introduction-to-Java/compile-and-run.png new file mode 100644 index 0000000..45e0446 Binary files /dev/null and b/source/gallery/Introduction-to-Java/compile-and-run.png differ diff --git a/source/gallery/Introduction-to-Java/create-new-project.png b/source/gallery/Introduction-to-Java/create-new-project.png new file mode 100644 index 0000000..88df696 Binary files /dev/null and b/source/gallery/Introduction-to-Java/create-new-project.png differ diff --git a/source/gallery/Introduction-to-Java/create-with-tests.png b/source/gallery/Introduction-to-Java/create-with-tests.png new file mode 100644 index 0000000..f48c48e Binary files /dev/null and b/source/gallery/Introduction-to-Java/create-with-tests.png differ diff --git a/source/gallery/Introduction-to-Java/rank.png b/source/gallery/Introduction-to-Java/rank.png new file mode 100644 index 0000000..a98daaa Binary files /dev/null and b/source/gallery/Introduction-to-Java/rank.png differ diff --git a/source/gallery/Major-Transfer/byebye.png b/source/gallery/Major-Transfer/byebye.png new file mode 100644 index 0000000..f4fb110 Binary files /dev/null and b/source/gallery/Major-Transfer/byebye.png differ diff --git a/source/gallery/Major-Transfer/cards.png b/source/gallery/Major-Transfer/cards.png new file mode 100644 index 0000000..479064f Binary files /dev/null and b/source/gallery/Major-Transfer/cards.png differ diff --git a/source/gallery/Major-Transfer/poster.jpg b/source/gallery/Major-Transfer/poster.jpg new file mode 100644 index 0000000..8735544 Binary files /dev/null and b/source/gallery/Major-Transfer/poster.jpg differ diff --git a/source/gallery/Major-Transfer/schedule.png b/source/gallery/Major-Transfer/schedule.png new file mode 100644 index 0000000..23c67ed Binary files /dev/null and b/source/gallery/Major-Transfer/schedule.png differ diff --git a/source/gallery/SE/judgement-tree.png b/source/gallery/SE/judgement-tree.png new file mode 100644 index 0000000..4ae2a40 Binary files /dev/null and b/source/gallery/SE/judgement-tree.png differ diff --git a/source/gallery/SE/monolith-microservices-database-deployment.png b/source/gallery/SE/monolith-microservices-database-deployment.png new file mode 100644 index 0000000..27cad01 Binary files /dev/null and b/source/gallery/SE/monolith-microservices-database-deployment.png differ diff --git a/source/gallery/SE/sequence-diagram.png b/source/gallery/SE/sequence-diagram.png new file mode 100644 index 0000000..794592e Binary files /dev/null and b/source/gallery/SE/sequence-diagram.png differ diff --git a/source/gallery/SE/swim-lane-diagram.png b/source/gallery/SE/swim-lane-diagram.png new file mode 100644 index 0000000..765806e Binary files /dev/null and b/source/gallery/SE/swim-lane-diagram.png differ diff --git a/source/gallery/SE/use-case.png b/source/gallery/SE/use-case.png new file mode 100644 index 0000000..f1a3e7f Binary files /dev/null and b/source/gallery/SE/use-case.png differ diff --git a/source/gallery/Shuliluoji-Yu-Jihelun/cut-kernel-boundary-support.png b/source/gallery/Shuliluoji-Yu-Jihelun/cut-kernel-boundary-support.png new file mode 100644 index 0000000..10a07ec Binary files /dev/null and b/source/gallery/Shuliluoji-Yu-Jihelun/cut-kernel-boundary-support.png differ diff --git a/source/gallery/Shuliluoji-Yu-Jihelun/example1.png b/source/gallery/Shuliluoji-Yu-Jihelun/example1.png new file mode 100644 index 0000000..80b801a Binary files /dev/null and b/source/gallery/Shuliluoji-Yu-Jihelun/example1.png differ diff --git a/source/gallery/Shuliluoji-Yu-Jihelun/example2.png b/source/gallery/Shuliluoji-Yu-Jihelun/example2.png new file mode 100644 index 0000000..cad90a6 Binary files /dev/null and b/source/gallery/Shuliluoji-Yu-Jihelun/example2.png differ diff --git a/source/gallery/Shuliluoji-Yu-Jihelun/hasse.png b/source/gallery/Shuliluoji-Yu-Jihelun/hasse.png new file mode 100644 index 0000000..2404b96 Binary files /dev/null and b/source/gallery/Shuliluoji-Yu-Jihelun/hasse.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/1-ascii-code.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/1-ascii-code.png new file mode 100644 index 0000000..5a1ac38 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/1-ascii-code.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/1-gray-code.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/1-gray-code.png new file mode 100644 index 0000000..653408e Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/1-gray-code.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/2-any.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/2-any.png new file mode 100644 index 0000000..2b1cc5a Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/2-any.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/2-karnaugh-1.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/2-karnaugh-1.png new file mode 100644 index 0000000..091d7b5 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/2-karnaugh-1.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/2-karnaugh-2.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/2-karnaugh-2.png new file mode 100644 index 0000000..5cd258e Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/2-karnaugh-2.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/2-prime-implicants-1.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/2-prime-implicants-1.png new file mode 100644 index 0000000..88ea4dd Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/2-prime-implicants-1.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/2-prime-implicants-2.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/2-prime-implicants-2.png new file mode 100644 index 0000000..19ca9da Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/2-prime-implicants-2.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-1-transceiver.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-1-transceiver.png new file mode 100644 index 0000000..d162b43 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-1-transceiver.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-4-transceiver.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-4-transceiver.png new file mode 100644 index 0000000..96c7c76 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-4-transceiver.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-D-t_Pd_G.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-D-t_Pd_G.png new file mode 100644 index 0000000..4e7aa5d Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-D-t_Pd_G.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-D-t_su-t_h.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-D-t_su-t_h.png new file mode 100644 index 0000000..5154daf Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-D-t_su-t_h.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-E-D-positive-R-S.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-E-D-positive-R-S.png new file mode 100644 index 0000000..b946787 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-E-D-positive-R-S.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-E-D-positive.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-E-D-positive.png new file mode 100644 index 0000000..c906c13 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-E-D-positive.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-L-D.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-L-D.png new file mode 100644 index 0000000..0e4d1d0 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-L-D.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-L-R-S.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-L-R-S.png new file mode 100644 index 0000000..b98b1c0 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-L-R-S.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-Latch-1.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-Latch-1.png new file mode 100644 index 0000000..c6399b2 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-Latch-1.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-Latch-2.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-Latch-2.png new file mode 100644 index 0000000..d62a689 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-Latch-2.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-Latch-3.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-Latch-3.png new file mode 100644 index 0000000..093f7ac Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-Latch-3.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-bus.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-bus.png new file mode 100644 index 0000000..9a8b710 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-bus.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-example.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-example.png new file mode 100644 index 0000000..5d34f74 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-example.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-noise-margin.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-noise-margin.png new file mode 100644 index 0000000..7971469 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-noise-margin.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-oc-gate.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-oc-gate.png new file mode 100644 index 0000000..9a0c84e Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-oc-gate.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-tri-state-gate.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-tri-state-gate.png new file mode 100644 index 0000000..cf990b3 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-tri-state-gate.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-two-fundamental.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-two-fundamental.png new file mode 100644 index 0000000..549f3dd Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-two-fundamental.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-v-in-v-out.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-v-in-v-out.png new file mode 100644 index 0000000..4eb55b1 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/3-v-in-v-out.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-16-adder-parallel.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-16-adder-parallel.png new file mode 100644 index 0000000..cca9403 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-16-adder-parallel.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-2-4-1-E.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-2-4-1-E.png new file mode 100644 index 0000000..b81c2f3 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-2-4-1-E.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-2-4-3-8.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-2-4-3-8.png new file mode 100644 index 0000000..b6d2ec3 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-2-4-3-8.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-2-4-4-16.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-2-4-4-16.png new file mode 100644 index 0000000..6e4cf8e Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-2-4-4-16.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-2-4-E.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-2-4-E.png new file mode 100644 index 0000000..3c20a40 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-2-4-E.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-2-9-digit-8-digit-even-odd.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-2-9-digit-8-digit-even-odd.png new file mode 100644 index 0000000..8f4154e Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-2-9-digit-8-digit-even-odd.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-3-8-4-16-E.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-3-8-4-16-E.png new file mode 100644 index 0000000..6303897 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-3-8-4-16-E.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-3-8-4-16.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-3-8-4-16.png new file mode 100644 index 0000000..c1f331b Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-3-8-4-16.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-3-8.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-3-8.png new file mode 100644 index 0000000..1832c02 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-3-8.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-1-16-1-E.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-1-16-1-E.png new file mode 100644 index 0000000..450d652 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-1-16-1-E.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-1-16-1.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-1-16-1.png new file mode 100644 index 0000000..3e85ca7 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-1-16-1.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-1-E.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-1-E.png new file mode 100644 index 0000000..038facf Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-1-E.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-1.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-1.png new file mode 100644 index 0000000..c1be74a Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-1.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-16-E.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-16-E.png new file mode 100644 index 0000000..4bdbae9 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-16-E.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-2-encoder.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-2-encoder.png new file mode 100644 index 0000000..c9a2530 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-2-encoder.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-ALU-1.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-ALU-1.png new file mode 100644 index 0000000..4c175b5 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-ALU-1.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-ALU-2(1).png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-ALU-2(1).png new file mode 100644 index 0000000..112edb5 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-ALU-2(1).png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-ALU-2(2).png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-ALU-2(2).png new file mode 100644 index 0000000..3b2bac2 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-ALU-2(2).png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-adder(c)(d).png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-adder(c)(d).png new file mode 100644 index 0000000..52a1b0d Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-adder(c)(d).png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-adder-parallel-thumbnail.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-adder-parallel-thumbnail.png new file mode 100644 index 0000000..4eca06f Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-adder-parallel-thumbnail.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-adder-parallel.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-adder-parallel.png new file mode 100644 index 0000000..0073845 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-adder-parallel.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-adder.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-adder.png new file mode 100644 index 0000000..75feb55 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-adder.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-compare-8-compare.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-compare-8-compare.png new file mode 100644 index 0000000..3bc5862 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-compare-8-compare.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-compare.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-compare.png new file mode 100644 index 0000000..e56413d Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-4-compare.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-8-3-16-4.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-8-3-16-4.png new file mode 100644 index 0000000..bd0f9d2 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-8-3-16-4.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-8421-encoder.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-8421-encoder.png new file mode 100644 index 0000000..83e96df Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-8421-encoder.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-9-digit-even-odd.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-9-digit-even-odd.png new file mode 100644 index 0000000..2ee04ea Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-9-digit-even-odd.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-J-K.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-J-K.png new file mode 100644 index 0000000..ef63dbb Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-J-K.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-M-S-J-K-by-R-S.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-M-S-J-K-by-R-S.png new file mode 100644 index 0000000..4d20364 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-M-S-J-K-by-R-S.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-M-S-J-K.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-M-S-J-K.png new file mode 100644 index 0000000..b71ffb9 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-M-S-J-K.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-M-S-R-S.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-M-S-R-S.png new file mode 100644 index 0000000..9b24b0d Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-M-S-R-S.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-T.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-T.png new file mode 100644 index 0000000..66d3a7a Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-T.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-buffer.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-buffer.png new file mode 100644 index 0000000..7ea1986 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-buffer.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-compare.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-compare.png new file mode 100644 index 0000000..0a0c879 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-compare.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-complete-BCD.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-complete-BCD.png new file mode 100644 index 0000000..48e05d4 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-complete-BCD.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-decoder-selector.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-decoder-selector.png new file mode 100644 index 0000000..d8fb398 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-decoder-selector.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-demultiplexer.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-demultiplexer.png new file mode 100644 index 0000000..21a4c32 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-demultiplexer.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-display.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-display.png new file mode 100644 index 0000000..79a3a9d Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-display.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-full-adder.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-full-adder.png new file mode 100644 index 0000000..aea397b Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-full-adder.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-incomplete-BCD.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-incomplete-BCD.png new file mode 100644 index 0000000..04a7a5c Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-incomplete-BCD.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-multilevel-1.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-multilevel-1.png new file mode 100644 index 0000000..ee3162b Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-multilevel-1.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-multilevel-2.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-multilevel-2.png new file mode 100644 index 0000000..61e1485 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-multilevel-2.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-multilevel-3.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-multilevel-3.png new file mode 100644 index 0000000..5bac0d8 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-multilevel-3.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-multilevel-4.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-multilevel-4.png new file mode 100644 index 0000000..42bb431 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-multilevel-4.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-overload.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-overload.png new file mode 100644 index 0000000..852d2ef Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-overload.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-selector-function1.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-selector-function1.png new file mode 100644 index 0000000..ff63b5f Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-selector-function1.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-selector-function2.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-selector-function2.png new file mode 100644 index 0000000..00c467f Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-selector-function2.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-spike-overlap.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-spike-overlap.png new file mode 100644 index 0000000..0325835 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/4-spike-overlap.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-4D-register-enable.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-4D-register-enable.png new file mode 100644 index 0000000..9e3d0f9 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-4D-register-enable.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-4D-register.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-4D-register.png new file mode 100644 index 0000000..b4068c4 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-4D-register.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-74163.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-74163.png new file mode 100644 index 0000000..ac584c7 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-74163.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-analysis-example-logic-graph.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-analysis-example-logic-graph.png new file mode 100644 index 0000000..9186900 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-analysis-example-logic-graph.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-analysis-example-time-diagram.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-analysis-example-time-diagram.png new file mode 100644 index 0000000..32cdf61 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-analysis-example-time-diagram.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-counter-integrated-p.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-counter-integrated-p.png new file mode 100644 index 0000000..e2f0ed0 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-counter-integrated-p.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-counter-integrated-t.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-counter-integrated-t.png new file mode 100644 index 0000000..4ec5041 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-counter-integrated-t.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-example-110-combination.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-example-110-combination.png new file mode 100644 index 0000000..c0d1879 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-example-110-combination.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-example-final-diagram.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-example-final-diagram.png new file mode 100644 index 0000000..5417eb9 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-example-final-diagram.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-shift-register-parallel-in-parallel-out.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-shift-register-parallel-in-parallel-out.png new file mode 100644 index 0000000..d32fd30 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-shift-register-parallel-in-parallel-out.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-shift-register-sequence-in-parallel-out.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-shift-register-sequence-in-parallel-out.png new file mode 100644 index 0000000..7a9888e Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-shift-register-sequence-in-parallel-out.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-sslc.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-sslc.png new file mode 100644 index 0000000..190df0f Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-sslc.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-state-diagram.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-state-diagram.png new file mode 100644 index 0000000..de46da0 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/5-state-diagram.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/7-PLA.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/7-PLA.png new file mode 100644 index 0000000..583d430 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/7-PLA.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/7-PROM.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/7-PROM.png new file mode 100644 index 0000000..936f094 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/7-PROM.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/7-ROM-classification.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/7-ROM-classification.png new file mode 100644 index 0000000..e7eabc8 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/7-ROM-classification.png differ diff --git a/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/7-ROM.png b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/7-ROM.png new file mode 100644 index 0000000..956d882 Binary files /dev/null and b/source/gallery/Shuziluoji-Yu-Shuzijichengdianlu/7-ROM.png differ diff --git a/source/gallery/misc/icp.png b/source/gallery/misc/icp.png new file mode 100644 index 0000000..3b5539d Binary files /dev/null and b/source/gallery/misc/icp.png differ diff --git a/source/pdf/calculus-1-solution.pdf b/source/pdf/calculus-1-solution.pdf new file mode 100644 index 0000000..d7a11d2 Binary files /dev/null and b/source/pdf/calculus-1-solution.pdf differ diff --git a/source/pdf/calculus-2-solution.pdf b/source/pdf/calculus-2-solution.pdf new file mode 100644 index 0000000..0551a81 Binary files /dev/null and b/source/pdf/calculus-2-solution.pdf differ diff --git a/source/pdf/major-transfer.pdf b/source/pdf/major-transfer.pdf new file mode 100644 index 0000000..8cfaad1 Binary files /dev/null and b/source/pdf/major-transfer.pdf differ diff --git a/source/robots.txt b/source/robots.txt new file mode 100644 index 0000000..c2aab7e --- /dev/null +++ b/source/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / \ No newline at end of file diff --git a/source/services/index.md b/source/services/index.md new file mode 100644 index 0000000..6e96d20 --- /dev/null +++ b/source/services/index.md @@ -0,0 +1,8 @@ +--- +title: 服务 +date: 2020-02-02 20:00:02 +type: "about" +mathjax: true +--- + +[教材答案](homework-ans/site) diff --git a/source/tags/index.md b/source/tags/index.md new file mode 100644 index 0000000..f4d2bb0 --- /dev/null +++ b/source/tags/index.md @@ -0,0 +1,5 @@ +--- +title: 所有标签 +date: 2020-02-02 20:00:02 +type: "tags" +--- diff --git a/themes/next/.editorconfig b/themes/next/.editorconfig new file mode 100644 index 0000000..759150b --- /dev/null +++ b/themes/next/.editorconfig @@ -0,0 +1,11 @@ +# editorconfig.org + +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 2 diff --git a/themes/next/.eslintrc.json b/themes/next/.eslintrc.json new file mode 100644 index 0000000..a59531c --- /dev/null +++ b/themes/next/.eslintrc.json @@ -0,0 +1,4 @@ +{ + "extends": "@next-theme", + "root": true +} diff --git a/themes/next/.gitattributes b/themes/next/.gitattributes new file mode 100644 index 0000000..3524dac --- /dev/null +++ b/themes/next/.gitattributes @@ -0,0 +1 @@ +test/* linguist-vendored diff --git a/themes/next/.gitignore b/themes/next/.gitignore new file mode 100644 index 0000000..b400ff4 --- /dev/null +++ b/themes/next/.gitignore @@ -0,0 +1,10 @@ +.DS_Store +.idea/ +.vscode/ +*.log +*.iml +yarn.lock +package-lock.json +node_modules/ +.nyc_output/ +coverage/ diff --git a/themes/next/.stylelintrc b/themes/next/.stylelintrc new file mode 100644 index 0000000..ac551e9 --- /dev/null +++ b/themes/next/.stylelintrc @@ -0,0 +1,20 @@ +{ + "plugins": [ + "stylelint-stylus" + ], + "extends": [ + "stylelint-stylus/standard" + ], + "rules": { + "stylus/semicolon": "always", + "stylus/pythonic": "never", + "stylus/declaration-colon": "always", + "stylus/number-leading-zero": "never", + "stylus/selector-list-comma": "always", + "stylus/selector-list-comma-newline-after": "never-multi-line", + "stylus/media-feature-colon": "always", + "stylus/single-line-comment": false, + "stylus/single-line-comment-no-empty": false, + "stylus/block-closing-brace-newline-after": "never-single-line" + } +} diff --git a/themes/next/LICENSE.md b/themes/next/LICENSE.md new file mode 100644 index 0000000..2d04283 --- /dev/null +++ b/themes/next/LICENSE.md @@ -0,0 +1,59 @@ +#
«NexT» – Elegant and powerful theme for Hexo.
+ +

Copyright © 2017 «NexT».

+ +

Detail attribution information for «NexT»
+ is contained in the 'docs/AUTHORS.md' file.

+ + This program is free software; you can redistribute it and/or modify +it under the terms of the [GNU Affero General Public License version 3][AGPL3] +as published by the Free Software Foundation with the addition of the +following permission added to [Section 15][AGPL3-15] as permitted in [Section 7(a)][AGPL3-7]: +FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY «NEXT», +«NEXT» DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. + + 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 Affero General Public License for more details. +You should have received a copy of the GNU Affero General Public License +along with this program; if not, see: https://www.gnu.org/licenses/agpl.txt + + In accordance with [Section 7(b)][AGPL3-7] of the GNU Affero General Public License: + +* a) It is not necessary to specify copyright in each source file of + this program because GitHub fully save commits of all modified files + with their authors and provides to see for this changes publicly. + +* b) For any part of the covered work in which the copyright not specified, + will mean this part owned by «NexT» in accord with terms in this file. + +* c) A covered work must retain «NexT» official website link + (https://theme-next.js.org) in footer section of every website created, + modified or manipulated by using «NexT». + «NexT» theme configuration must be: + ```yml + footer: + theme: + enable: true + ``` + Collaborators, best contributors and all authors specified in the + '[docs/AUTHORS.md][AUTHORS]' file of «NexT» repository under the + 'https://github.com/next-theme' organization can ignore theme info link + requirements. + +Anyone can be released from the requirements of the license by purchasing +a commercial license. Buying such a license is mandatory as soon as you +develop commercial activities involving the «NexT» software without +disclosing the source code of your own applications. +These activities include: + 1. Access to private repository with various premium features. + 2. Priority support for resolve all possible issues with «NexT». + 3. Priority support for implement all possible features to «NexT». + +

This license also available in text format.

+ +[AUTHORS]: docs/AUTHORS.md +[AGPL3]: docs/AGPL3.md +[AGPL3-7]: docs/AGPL3.md/#7-additional-terms +[AGPL3-15]: docs/AGPL3.md/#15-disclaimer-of-warranty diff --git a/themes/next/README.md b/themes/next/README.md new file mode 100644 index 0000000..36864fc --- /dev/null +++ b/themes/next/README.md @@ -0,0 +1,185 @@ +
+ Language: + 🇺🇸 + 🇨🇳 + 🇷🇺 +
+ + + + + NexT preview + + +NexT logo + +# NexT + +> «NexT» is a high quality elegant [Hexo](https://hexo.io) theme. It is crafted from scratch with love. + +[![NPM version](https://img.shields.io/npm/v/hexo-theme-next?color=red&logo=npm&style=flat-square)](https://www.npmjs.com/package/hexo-theme-next) +[![Required Hexo version](https://img.shields.io/badge/hexo-%3E=5.3.0-blue?style=flat-square&logo=hexo)](https://hexo.io) +[![License](https://img.shields.io/badge/license-%20AGPL-orange?style=flat-square&logo=gnu)](https://github.com/next-theme/hexo-theme-next/blob/master/LICENSE.md) +[![Build Status](https://img.shields.io/github/actions/workflow/status/next-theme/hexo-theme-next/linter.yml?branch=master&label=test&logo=github&style=flat-square)](https://github.com/next-theme/hexo-theme-next/actions?query=workflow%3ALinter) +[![Build Status](https://img.shields.io/github/actions/workflow/status/next-theme/hexo-theme-next/tester.yml?branch=master&logo=github&style=flat-square)](https://github.com/next-theme/hexo-theme-next/actions?query=workflow%3ATester) +[![Coverage Status](https://img.shields.io/coveralls/github/next-theme/hexo-theme-next?logo=coveralls&style=flat-square)](https://coveralls.io/github/next-theme/hexo-theme-next) + +## Live Preview + +

+ 💟 Muse | 🔯 Mist | ♓️ Pisces | ♊️ Gemini +
+
+ More «NexT» examples here. +

+ +## Installation + +If you're using Hexo 5.0 or later, the simplest way to install is through npm: + +```sh +$ cd hexo-site +$ npm install hexo-theme-next +``` + +Or you can clone the entire repository: + +```sh +$ cd hexo-site +$ git clone https://github.com/next-theme/hexo-theme-next themes/next +``` + +See [detailed installation instructions][docs-installation-url] if you want any other variant. + +After the installation, open Hexo config file and set `theme` variable to `next`. + +```yml +theme: next +``` + +## Configuration + +It is not recommended to directly modify any files in the NexT theme. Because this may cause errors (e.g. merge conflicts), and the modified files may be discarded when upgrading the theme. + +At present, NexT encourages users to use the [Alternate Theme Config][docs-configuration-url] to configure NexT. And it's easy to customize the layout or style of NexT using [Custom Files][docs-custom-files-url]. + +## Plugins + +Plugins extend and expand the functionality of NexT. There are two types of plugins: core plugins and third-party plugins. The core plugins are required by the basic functions of NexT. Third-party plugins provide a large number of optional features. + +Configuring these plugins is very easy. For example, if you want to enable `pjax` on your site, just set `pjax` to `true` in NexT config file: + +```yml +# Easily enable fast Ajax navigation on your website. +# For more information: https://github.com/next-theme/pjax +pjax: true +``` + +### Configure CDN + +Third-party plugins are loaded from [CDNJS](https://cdnjs.com) CDN by default. We also provide other optional CDNs, including the famous [UNPKG](https://unpkg.com) and [jsDelivr](https://www.jsdelivr.com). + +For example, if you want to use `unpkg` instead of `cdnjs` as the default CDN provider, you need to edit the following settings in NexT config file: + +```yml +vendors: + # ... + # Some contents... + # ... + plugins: unpkg +``` + +## Update + +A new version of NexT will be released every month. Please read the [release notes][docs-release-url] before updating the theme. You can update NexT by the following command. + +Install the latest version through npm: + +```sh +$ cd hexo-site +$ npm install hexo-theme-next@latest +``` + +Or update to the latest master branch: + +```sh +$ cd themes/next +$ git pull +``` + +**If you want to update from v5.x / v7.x to the latest version, read [this][docs-upgrade-url].** + +## Feedback + +* Visit the [Awesome NexT][awesome-next-url] list to share plugins and tutorials with other users. +* Join our [GitHub discussions][discussions-url] / [Gitter][gitter-url] chats. +* [Add or improve translation][i18n-url] in few seconds. +* Report a bug in [GitHub Issues][issues-bug-url]. +* Request a new feature on [GitHub][issues-feat-url]. +* Vote for [popular feature requests][feat-req-vote-url]. + +## Contributing + +We welcome you to join the development of NexT. Please see [contributing document][contributing-document-url]. 🤗 + +Also, we welcome Issue or PR to our [official-plugins][official-plugins-url]. + +## Contributors + +[![Contributors][contributors-image]][contributors-url] + +## Thanks + +«NexT» send special thanks to these great services that sponsor our core infrastructure: + + + +> GitHub allows us to host the Git repository and run the test suite. + + + + + + Netlify Logo + + + +> Netlify allows us to distribute the documentation. + + + +> Crowdin allows us to translate conveniently the documentation. + + + + + + CDNJS Logo + + + +> Thanks CDNJS for providing public CDN service. + +## License + +[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fnext-theme%2Fhexo-theme-next.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fnext-theme%2Fhexo-theme-next?ref=badge_large) + +[docs-installation-url]: https://theme-next.js.org/docs/getting-started/installation.html +[docs-configuration-url]: https://theme-next.js.org/docs/getting-started/configuration.html +[docs-custom-files-url]: https://theme-next.js.org/docs/advanced-settings/custom-files.html +[docs-release-url]: https://github.com/next-theme/hexo-theme-next/releases +[docs-upgrade-url]: https://theme-next.js.org/docs/getting-started/upgrade.html + +[awesome-next-url]: https://github.com/next-theme/awesome-next +[discussions-url]: https://github.com/next-theme/hexo-theme-next/discussions +[gitter-url]: https://gitter.im/hexo-next +[i18n-url]: https://crowdin.com/project/hexo-theme-next + +[issues-bug-url]: https://github.com/next-theme/hexo-theme-next/issues/new?assignees=&labels=Bug&template=bug-report.md +[issues-feat-url]: https://github.com/next-theme/hexo-theme-next/issues/new?assignees=&labels=Feature+Request&template=feature-request.md +[feat-req-vote-url]: https://github.com/next-theme/hexo-theme-next/issues?q=is%3Aopen+is%3Aissue+label%3A%22Feature+Request%22 + +[contributing-document-url]: https://github.com/next-theme/hexo-theme-next/blob/master/.github/CONTRIBUTING.md +[official-plugins-url]: https://github.com/next-theme +[contributors-image]: https://raw.githubusercontent.com/next-theme/contributors/master/contributors.svg +[contributors-url]: https://github.com/next-theme/hexo-theme-next/blob/master/docs/AUTHORS.md diff --git a/themes/next/_config.yml b/themes/next/_config.yml new file mode 100644 index 0000000..07a2865 --- /dev/null +++ b/themes/next/_config.yml @@ -0,0 +1,940 @@ +# =============================================================== +# It's recommended to use Alternate Theme Config to configure NexT +# Modifying this file may result in merge conflict +# See: https://theme-next.js.org/docs/getting-started/configuration +# =============================================================== + +# --------------------------------------------------------------- +# Theme Core Configuration Settings +# See: https://theme-next.js.org/docs/theme-settings/ +# --------------------------------------------------------------- + +# Allow to cache content generation. +cache: + enable: true + +# Remove unnecessary files after hexo generate. +minify: false + +# Define custom file paths. +# Create your custom files in site directory `source/_data` and uncomment needed files below. +custom_file_path: + head: source/_data/head.swig + #header: source/_data/header.njk + #sidebar: source/_data/sidebar.njk + #postMeta: source/_data/post-meta.njk + #postBodyEnd: source/_data/post-body-end.njk + #footer: source/_data/footer.njk + #bodyEnd: source/_data/body-end.njk + # variable: source/_data/variables.styl + #mixin: source/_data/mixins.styl + #style: source/_data/styles.styl + + +# --------------------------------------------------------------- +# Scheme Settings +# --------------------------------------------------------------- + +# Schemes +# scheme: Muse +# scheme: Mist +# scheme: Pisces +scheme: Gemini + +# Dark Mode +darkmode: false + + +# --------------------------------------------------------------- +# Site Information Settings +# --------------------------------------------------------------- + +favicon: + # small: /images/favicon-16x16-next.png + small: /images/favicon.svg + # medium: /images/favicon-32x32-next.png + medium: /images/favicon.svg + # apple_touch_icon: /images/apple-touch-icon-next.png + apple_touch_icon: /images/favicon.svg + safari_pinned_tab: /images/logo.svg + #android_manifest: /manifest.json + +# Custom Logo (Warning: Do not support scheme Mist) +custom_logo: #/uploads/custom-logo.png + +# Creative Commons 4.0 International License. +# See: https://creativecommons.org/about/cclicenses/ +creative_commons: + # Available values: by | by-nc | by-nc-nd | by-nc-sa | by-nd | by-sa | cc-zero + license: by-nc-sa + # Available values: big | small + size: small + sidebar: true + post: true + # You can set a language value if you prefer a translated version of CC license, e.g. deed.zh + # CC licenses are available in 39 languages, you can find the specific and correct abbreviation you need on https://creativecommons.org + language: deed.zh + +# Open graph settings +# See: https://hexo.io/docs/helpers#open-graph +open_graph: + enable: true + options: + #twitter_card: + #twitter_id: + #twitter_site: + #twitter_image: + #google_plus: + #fb_admins: + #fb_app_id: + + +# --------------------------------------------------------------- +# Menu Settings +# --------------------------------------------------------------- + +# Usage: `Key: /link/ || icon` +# Key is the name of menu item. If the translation for this item is available, the translated text will be loaded, otherwise the Key name will be used. Key is case-sensitive. +# Value before `||` delimiter is the target link, value after `||` delimiter is the name of Font Awesome icon. +# External url should start with http:// or https:// +menu: + home: / || fa fa-home + archives: /archives/ || fa fa-archive + tags: /tags/ || fa fa-tags + categories: /categories/ || fa fa-th + about: /about/ || fa fa-user + '服务': /services/ || fa fa-concierge-bell + #sitemap: /sitemap.xml || fa fa-sitemap + #commonweal: /404/ || fa fa-heartbeat + +# Enable / Disable menu icons / item badges. +menu_settings: + icons: true + badges: false + + +# --------------------------------------------------------------- +# Sidebar Settings +# See: https://theme-next.js.org/docs/theme-settings/sidebar +# --------------------------------------------------------------- + +sidebar: + # Sidebar Position. + position: left + #position: right + + # Manual define the sidebar width. If commented, will be default for: + # Muse | Mist: 320 + # Pisces | Gemini: 240 + #width: 300 + + # Sidebar Display (only for Muse | Mist), available values: + # - post expand on posts automatically. Default. + # - always expand for all pages automatically. + # - hide expand only when click on the sidebar toggle icon. + # - remove totally remove sidebar including sidebar toggle. + display: post + + # Sidebar padding in pixels. + padding: 18 + # Sidebar offset from top menubar in pixels (only for Pisces | Gemini). + offset: 12 + +# Sidebar Avatar +avatar: + # Replace the default image and set the url here. + url: https://img.picgo.net/2023/07/27/avatar2b2cde04a2f690ac.png + # If true, the avatar will be displayed in circle. + rounded: false + # If true, the avatar will be rotated with the cursor. + rotated: false + +# Posts / Categories / Tags in sidebar. +site_state: true + +# Social Links +# Usage: `Key: permalink || icon` +# Key is the link label showing to end users. +# Value before `||` delimiter is the target permalink, value after `||` delimiter is the name of Font Awesome icon. +social: + GitHub: https://github.com/LeverImmy || fab fa-github + E-Mail: mailto:xze22@mails.tsinghua.edu.cn || fa fa-envelope + #Weibo: https://weibo.com/yourname || fab fa-weibo + #Twitter: https://twitter.com/yourname || fab fa-twitter + #FB Page: https://www.facebook.com/yourname || fab fa-facebook + #StackOverflow: https://stackoverflow.com/yourname || fab fa-stack-overflow + #YouTube: https://youtube.com/yourname || fab fa-youtube + #Instagram: https://instagram.com/yourname || fab fa-instagram + #Skype: skype:yourname?call|chat || fab fa-skype + +social_icons: + enable: true + icons_only: false + transition: false + +# Blog rolls +links_settings: + icon: fa fa-globe + # Available values: block | inline + layout: block + +links: + #Title: https://example.com + +# Table of Contents in the Sidebar +# Front-matter variable (nonsupport wrap expand_all). +toc: + enable: true + # Automatically add list number to toc. + number: true + # If true, all words will placed on next lines if header width longer then sidebar width. + wrap: true + # If true, all level of TOC in a post will be displayed, rather than the activated part of it. + expand_all: false + # Maximum heading depth of generated toc. + max_depth: 6 + + +# --------------------------------------------------------------- +# Footer Settings +# See: https://theme-next.js.org/docs/theme-settings/footer +# --------------------------------------------------------------- + +# Show multilingual switcher in footer. +language_switcher: false + +footer: + # Specify the year when the site was setup. If not defined, current year will be used. + since: 2022 + + # Icon between year and copyright info. + icon: + # Icon name in Font Awesome. See: https://fontawesome.com/icons + name: fa fa-heart + # If you want to animate the icon, set it to true. + animated: false + # Change the color of icon, using Hex Code. + color: "#ff0000" + + # If not defined, `author` from Hexo `_config.yml` will be used. + copyright: + + # Powered by Hexo & NexT + powered: true + + # Beian ICP and gongan information for Chinese users. See: https://beian.miit.gov.cn, http://www.beian.gov.cn + beian: + enable: true + icp: 京ICP备2024046776号-2 + # The digit in the num of gongan beian. + gongan_id: 11010802044639 + # The full num of gongan beian. + gongan_num: 京公网安备11010802044639号 + # The icon for gongan beian. See: http://www.beian.gov.cn/portal/download + gongan_icon_url: /gallery/misc/icp.png + + +# --------------------------------------------------------------- +# Post Settings +# See: https://theme-next.js.org/docs/theme-settings/posts +# --------------------------------------------------------------- + +# Automatically excerpt description in homepage as preamble text. +excerpt_description: true + +# Read more button +# If true, the read more button will be displayed in excerpt section. +read_more_btn: true + +# Post meta display settings +post_meta: + item_text: true + created_at: false + updated_at: + enable: true + another_day: true + categories: true + +# Post wordcount display settings +# Dependencies: https://github.com/next-theme/hexo-word-counter +symbols_count_time: + separated_meta: true + item_text_total: false + +# Use icon instead of the symbol # to indicate the tag at the bottom of the post +tag_icon: true + +# Donate (Sponsor) settings +# Front-matter variable (nonsupport animation). +reward_settings: + # If true, a donate button will be displayed in every article by default. + enable: false + animation: false + +reward: + #wechatpay: /images/wechatpay.png + #alipay: /images/alipay.png + #paypal: /images/paypal.png + #bitcoin: /images/bitcoin.png + +# Subscribe through Telegram Channel, Twitter, etc. +# Usage: `Key: permalink || icon` (Font Awesome) +follow_me: + #Twitter: https://twitter.com/username || fab fa-twitter + #Telegram: https://t.me/channel_name || fab fa-telegram + #WeChat: /images/wechat_channel.png || fab fa-weixin + #RSS: /atom.xml || fa fa-rss + +# Related popular posts +# Dependencies: https://github.com/sergeyzwezdin/hexo-related-posts +related_posts: + enable: false + icon: fa fa-signs-post + +# Post edit +# Easily browse and edit blog source code online. +post_edit: + enable: false + url: https://github.com/user-name/repo-name/tree/branch-name/subdirectory-name/ # Link for view source + #url: https://github.com/user-name/repo-name/edit/branch-name/subdirectory-name/ # Link for fork & edit + +# Show previous post and next post in post footer if exists +# Available values: left | right | false +post_navigation: left + + +# --------------------------------------------------------------- +# Custom Page Settings +# See: https://theme-next.js.org/docs/theme-settings/custom-pages +# --------------------------------------------------------------- + +# TagCloud settings for tags page. +tagcloud: + min: 12 # Minimum font size in px + max: 30 # Maximum font size in px + amount: 200 # Total amount of tags + orderby: name # Order of tags + order: 1 # Sort order + +# Google Calendar +# Share your recent schedule to others via calendar page. +calendar: + calendar_id: # Your Google account E-Mail + api_key: + orderBy: startTime + showLocation: false + offsetMax: 72 # Time Range + offsetMin: 4 # Time Range + showDeleted: false + singleEvents: true + maxResults: 250 + + +# --------------------------------------------------------------- +# Misc Theme Settings +# See: https://theme-next.js.org/docs/theme-settings/miscellaneous +# --------------------------------------------------------------- + +# Preload styles and preconnect CDN for fonts and plugins. +# For more information: https://www.w3.org/TR/resource-hints/#preconnect +preconnect: false + +# Set the text alignment in posts / pages. +text_align: + # Available values: start | end | left | right | center | justify | justify-all | match-parent + desktop: justify + mobile: justify + +# Reduce padding / margin indents on devices with narrow width. +mobile_layout_economy: false + +# Browser header panel color. +theme_color: + light: "#222" + dark: "#222" + +# Override browsers' default behavior. +body_scrollbar: + # Place the scrollbar over the content. + overlay: false + # Present the scrollbar even if the content is not overflowing. + stable: false + +codeblock: + # Code Highlight theme + # All available themes: https://theme-next.js.org/highlight/ + theme: + light: github + dark: stackoverflow-dark + prism: + light: prism + dark: prism-dark + # Add copy button on codeblock + copy_button: + enable: true + # Available values: default | flat | mac + style: mac + +back2top: + enable: true + # Back to top in sidebar. + sidebar: false + # Scroll percent label in b2t button. + scrollpercent: false + +# Reading progress bar +reading_progress: + enable: false + # Available values: left | right + start_at: left + # Available values: top | bottom + position: top + reversed: false + color: "#37c6c0" + height: 3px + +# Bookmark Support +bookmark: + enable: false + # Customize the color of the bookmark. + color: "#222" + # If auto, save the reading progress when closing the page or clicking the bookmark-icon. + # If manual, only save it by clicking the bookmark-icon. + save: auto + +# `Follow me on GitHub` banner in the top-right corner. +github_banner: + enable: false + permalink: https://github.com/LeverImmy + + +# --------------------------------------------------------------- +# Font Settings +# --------------------------------------------------------------- +# Find fonts on Google Fonts (https://fonts.google.com) +# All fonts set here will have the following styles: +# light | light italic | normal | normal italic | bold | bold italic +# Be aware that setting too much fonts will cause site running slowly +# --------------------------------------------------------------- +# Web Safe fonts are recommended for `global` (and `title`): +# Arial | Tahoma | Helvetica | Times New Roman | Courier New | Verdana | Georgia | Palatino | Garamond | Comic Sans MS | Trebuchet MS +# --------------------------------------------------------------- + +font: + enable: true + + # Uri of fonts host, e.g. https://fonts.googleapis.com (Default). + host: + + # Font options: + # `external: true` will load this font family from `host` above. + # `family: Times New Roman`. Without any quotes. + # `size: x.x`. Use `em` as unit. Default: 1 (16px) + + # Global font settings used for all elements inside . + global: + external: true + family: Times New Roman + size: 1.1 + + # Font settings for site title (.site-title). + title: + external: true + family: + size: + + # Font settings for headlines (

to

). + headings: + external: true + family: + size: + + # Font settings for posts (.post-body). + posts: + external: true + family: + size: + + # Font settings for and code blocks. + codes: + external: true + family: Source Code Pro + + +# --------------------------------------------------------------- +# SEO Settings +# See: https://theme-next.js.org/docs/theme-settings/seo +# --------------------------------------------------------------- + +# If true, site-subtitle will be added to the title of index page. +# Remember to set up your site-subtitle in Hexo `_config.yml` (e.g. subtitle: Subtitle) +index_with_subtitle: false + +# Automatically add external URL with Base64 encrypt & decrypt. +exturl: false +# If true, an icon will be attached to each external URL +exturl_icon: true + +# Google Webmaster tools verification. +# See: https://developers.google.com/search +google_site_verification: + +# Bing Webmaster tools verification. +# See: https://www.bing.com/webmasters +bing_site_verification: + +# Yandex Webmaster tools verification. +# See: https://webmaster.yandex.ru +yandex_site_verification: + +# Baidu Webmaster tools verification. +# See: https://ziyuan.baidu.com/site +baidu_site_verification: + + +# --------------------------------------------------------------- +# Tags Settings +# See: https://theme-next.js.org/docs/tag-plugins/ +# --------------------------------------------------------------- + +# Note tag (bootstrap callout) +note: + # Note tag style values: + # - simple bootstrap callout old alert style. Default. + # - modern bootstrap callout new (v2-v3) alert style. + # - flat flat callout style with background, like on Mozilla or StackOverflow. + # - disabled disable all CSS styles import of note tag. + style: simple + icons: false + # Offset lighter of background in % for modern and flat styles (modern: -12 | 12; flat: -18 | 6). + # Offset also applied to label tag variables. This option can work with disabled note tag. + light_bg_offset: 0 + +# Tabs tag +tabs: + # Make the nav bar of tabs with long content stick to the top. + sticky: false + transition: + tabs: false + labels: true + +# PDF tag +# NexT will try to load pdf files natively, if failed, pdf.js will be used. +# So, you have to install the dependency of pdf.js if you want to use pdf tag and make it available to all browsers. +# Dependencies: https://github.com/next-theme/theme-next-pdf +pdf: + enable: true + # Default height + height: 500px + +# Mermaid tag +mermaid: + enable: true + # Available themes: default | dark | forest | neutral + theme: + light: default + dark: dark + + +# --------------------------------------------------------------- +# Third Party Plugins & Services Settings +# See: https://theme-next.js.org/docs/third-party-services/ +# More plugins: https://github.com/next-theme/awesome-next +# --------------------------------------------------------------- + +# --------------------------------------------------------------- +# Math Formulas Render Support +# See: https://theme-next.js.org/docs/third-party-services/math-equations +# Warning: Please install / uninstall the relevant renderer according to the documentation. +# Server-side plugin: https://github.com/next-theme/hexo-filter-mathjax +# --------------------------------------------------------------- + +math: + # Default (false) will load mathjax / katex script on demand. + # That is it only render those page which has `mathjax: true` in front-matter. + # If you set it to true, it will load mathjax / katex script EVERY PAGE. + every_page: false + + mathjax: + enable: true + # Available values: none | ams | all + tags: none + + katex: + enable: false + # See: https://github.com/KaTeX/KaTeX/tree/master/contrib/copy-tex + copy_tex: false + + +# --------------------------------------------------------------- +# External Libraries +# See: https://theme-next.js.org/docs/third-party-services/external-libraries +# --------------------------------------------------------------- + +# Easily enable fast Ajax navigation on your website. +# For more information: https://github.com/next-theme/pjax +pjax: false + +# FancyBox is a tool that offers a nice and elegant way to add zooming functionality for images. +# For more information: https://fancyapps.com/fancybox/ +fancybox: false + +# Medium Zoom is a JavaScript library for zooming images like Medium. +# Warning: Do not enable both `fancybox` and `mediumzoom`. +# For more information: https://medium-zoom.francoischalifour.com +mediumzoom: false + +# Vanilla JavaScript plugin for lazyloading images. +# For more information: https://apoorv.pro/lozad.js/demo/ +lazyload: false + +# Automatically insert whitespace between CJK and half-width characters. +# For more information: https://github.com/vinta/pangu.js +# Server-side plugin: https://github.com/next-theme/hexo-pangu +pangu: false + +# Prefetch links based on what is in the user's viewport. +# For more information: https://getquick.link +# Front-matter variable (nonsupport home archive). +quicklink: + enable: false + + # Home page and archive page can be controlled through home and archive options below. + # This configuration item is independent of `enable`. + home: false + archive: false + + # Default (true) will initialize quicklink after the load event fires. + delay: true + # Custom a time in milliseconds by which the browser must execute prefetching. + timeout: 3000 + # Default (true) will attempt to use the fetch() API if supported (rather than link[rel=prefetch]). + priority: true + + +# --------------------------------------------------------------- +# Animation Settings +# --------------------------------------------------------------- + +# Use Animate.css to animate everything. +# For more information: https://animate.style +motion: + enable: true + async: false + transition: + # All available transition variants: https://theme-next.js.org/animate/ + menu_item: fadeInDown + post_block: fadeIn + post_header: fadeInDown + post_body: fadeInDown + coll_header: fadeInLeft + # Only for Pisces | Gemini. + sidebar: fadeInUp + +# Progress bar in the top during page loading. +# For more information: https://github.com/CodeByZach/pace +pace: + enable: false + # All available colors: + # black | blue | green | orange | pink | purple | red | silver | white | yellow + color: blue + # All available themes: + # big-counter | bounce | barber-shop | center-atom | center-circle | center-radar | center-simple + # corner-indicator | fill-left | flat-top | flash | loading-bar | mac-osx | material | minimal + theme: minimal + +# Generate a ribbon in your website with HTML5 canvas. +# For more information: https://github.com/hustcc/ribbon.js +canvas_ribbon: + enable: false + size: 300 # The width of the ribbon + alpha: 0.6 # The transparency of the ribbon + zIndex: -1 # The display level of the ribbon + + +# --------------------------------------------------------------- +# Comments Settings +# See: https://theme-next.js.org/docs/third-party-services/comments +# --------------------------------------------------------------- + +# Multiple Comment System Support +comments: + # Available values: tabs | buttons + style: tabs + # Choose a comment system to be displayed by default. + # Available values: disqus | disqusjs | changyan | livere | gitalk | utterances + active: + # Setting `true` means remembering the comment system selected by the visitor. + storage: true + # Lazyload all comment systems. + lazyload: false + # Modify texts or order for any naves, here are some examples. + nav: + #disqus: + # text: Load Disqus + # order: -1 + #gitalk: + # order: -2 + +# Disqus +# For more information: https://disqus.com +disqus: + enable: false + shortname: + count: true + +# DisqusJS +# For more information: https://disqusjs.skk.moe +disqusjs: + enable: false + # API Endpoint of Disqus API (https://disqus.com/api/docs/). + # Leave api empty if you are able to connect to Disqus API. Otherwise you need a reverse proxy for it. + # For example: + # api: https://disqus.skk.moe/disqus/ + api: + apikey: # Register new application from https://disqus.com/api/applications/ + shortname: # See: https://disqus.com/admin/settings/general/ + +# Changyan +# For more information: https://changyan.kuaizhan.com +changyan: + enable: false + appid: + appkey: + # Show comments count + count: true + +# LiveRe comments system +# You can get your uid from https://livere.com/insight/myCode (General web site) +livere_uid: # + +# Gitalk +# For more information: https://gitalk.github.io +gitalk: + enable: false + github_id: # GitHub repo owner + repo: # Repository name to store issues + client_id: # GitHub Application Client ID + client_secret: # GitHub Application Client Secret + admin_user: # GitHub repo owner and collaborators, only these guys can initialize gitHub issues + distraction_free_mode: true # Facebook-like distraction free mode + # When the official proxy is not available, you can change it to your own proxy address + proxy: https://cors-anywhere.azm.workers.dev/https://github.com/login/oauth/access_token # This is official proxy address + # Gitalk's display language depends on user's browser or system environment + # If you want everyone visiting your site to see a uniform language, you can set a force language value + # Available values: en | es-ES | fr | ru | zh-CN | zh-TW + language: + +# Utterances +# For more information: https://utteranc.es +utterances: + enable: false + repo: user-name/repo-name # Github repository owner and name + # Available values: pathname | url | title | og:title + issue_term: pathname + # Available values: github-light | github-dark | preferred-color-scheme | github-dark-orange | icy-dark | dark-blue | photon-dark | boxy-light + theme: github-light + +# Isso +# For more information: https://isso-comments.de +isso: # + +# [MODIFIED] +# Giscus +# For more information: https://giscus.app/ +giscus: + enable: true + repo: LeverImmy/leverimmy.github.io + repo_id: R_kgDOHq9iIQ + category: Announcements + category_id: DIC_kwDOHq9iIc4CgMEM + mapping: pathname + strict: 1 + reactions_enabled: 1 + emit_metadata: 0 + input_position: top + theme: preferred_color_scheme + lang: zh-CN + loading: + +# --------------------------------------------------------------- +# Post Widgets & Content Sharing Services +# See: https://theme-next.js.org/docs/third-party-services/post-widgets +# --------------------------------------------------------------- + +# AddThis Share. See: https://www.addthis.com +# Go to https://www.addthis.com/dashboard to customize your tools. +add_this_id: + + +# --------------------------------------------------------------- +# Statistics and Analytics +# See: https://theme-next.js.org/docs/third-party-services/statistics-and-analytics +# --------------------------------------------------------------- + +# Google Analytics +# See: https://analytics.google.com +google_analytics: + tracking_id: # + # By default, NexT will load an external gtag.js script on your site. + # If you only need the pageview feature, set the following option to true to get a better performance. + only_pageview: false + +# Baidu Analytics +# See: https://tongji.baidu.com +baidu_analytics: # + +# Growingio Analytics +# See: https://www.growingio.com +growingio_analytics: # + +# Cloudflare Web Analytics +# See: https://www.cloudflare.com/web-analytics/ +cloudflare_analytics: + +# Microsoft Clarity Analytics +# See: https://clarity.microsoft.com/ +clarity_analytics: # + +# Matomo Analytics +# See: https://matomo.org/ +matomo: + enable: false + server_url: # https://www.example.com/ + site_id: # + +# Umami Analytics +# See: https://umami.is/ +umami: + enable: false + script_url: # https://umami.example.com/script.js + website_id: # + +# Plausible Analytics +# See: https://plausible.io/ +plausible: + enable: false + script_url: # https://plausible.io/js/script.js + site_domain: # www.example.com + +# Show number of visitors of each article. +# You can visit https://www.leancloud.cn to get AppID and AppKey. +leancloud_visitors: + enable: false + app_id: # + app_key: # + # Required for apps from CN region + server_url: # + # Dependencies: https://github.com/theme-next/hexo-leancloud-counter-security + # If you don't care about security in leancloud counter and just want to use it directly + # (without hexo-leancloud-counter-security plugin), set `security` to `false`. + security: true + +# Another tool to show number of visitors to each article. +# Visit https://console.firebase.google.com/u/0/ to get apiKey and projectId. +# Visit https://firebase.google.com/docs/firestore/ to get more information about firestore. +firestore: + enable: false + collection: articles # Required, a string collection name to access firestore database + apiKey: # Required + projectId: # Required + +# Show Views / Visitors of the website / page with busuanzi. +# For more information: http://ibruce.info/2015/04/04/busuanzi/ +busuanzi_count: + enable: true + total_visitors: true + total_visitors_icon: fa fa-user + total_views: true + total_views_icon: fa fa-eye + post_views: true + post_views_icon: fa fa-eye + + +# --------------------------------------------------------------- +# Search Services +# See: https://theme-next.js.org/docs/third-party-services/search-services +# --------------------------------------------------------------- + +# Algolia Search +# For more information: https://www.algolia.com +algolia_search: + enable: false + hits: + per_page: 10 + +# Local Search +# Dependencies: https://github.com/next-theme/hexo-generator-searchdb +local_search: + enable: true + # If auto, trigger search by changing input. + # If manual, trigger search by pressing enter key or search button. + trigger: auto + # Show top n results per article, show all results by setting to -1 + top_n_per_article: 1 + # Unescape html strings to the readable one. + unescape: false + # Preload the search data when the page loads. + preload: false + + +# --------------------------------------------------------------- +# Chat Services +# See: https://theme-next.js.org/docs/third-party-services/chat-services +# --------------------------------------------------------------- + +# A button to open designated chat widget in sidebar. +# Firstly, you need to enable and configure the chat service. +chat: + enable: false + icon: fa fa-comment # Icon name in Font Awesome, set false to disable icon. + +# Chatra is a functional, easy to use piece of chat software for websites. +# For more information: https://chatra.com +# Dashboard: https://app.chatra.io/settings/general +chatra: + enable: false + async: true + id: # Visit Dashboard to get your ChatraID + #embed: # Unfinished experimental feature for developers. See: https://chatra.com/help/api/#injectto + +# Tidio is a powerful, all-in-one customer service tool. +# For more information: https://www.tidio.com +# Dashboard: https://www.tidio.com/panel/dashboard +tidio: + enable: false + key: # Public Key, get it from dashboard. See: https://www.tidio.com/panel/settings/developer + +# Gitter is a chat and networking platform. +# For more information: https://gitter.im +gitter: + enable: false + room: + + +# --------------------------------------------------------------- +# CDN Settings +# See: https://theme-next.js.org/docs/advanced-settings/vendors +# --------------------------------------------------------------- + +vendors: + # The CDN provider of NexT internal scripts. + # Available values: local | jsdelivr | unpkg | cdnjs | custom + # Warning: If you are using the latest master branch of NexT, please set `internal: local` + internal: local + # The default CDN provider of third-party plugins. + # Available values: local | jsdelivr | unpkg | cdnjs | custom + # Dependencies for `plugins: local`: https://github.com/next-theme/plugins + plugins: cdnjs + # Custom CDN URL + # For example: + # custom_cdn_url: https://cdn.jsdelivr.net/npm/${npm_name}@${version}/${minified} + # custom_cdn_url: https://cdnjs.cloudflare.com/ajax/libs/${cdnjs_name}/${version}/${cdnjs_file} + custom_cdn_url: + +# Assets +# Accelerate delivery of static files using a CDN +# The js option is only valid when vendors.internal is local. +css: css +js: js +images: images diff --git a/themes/next/_vendors.yml b/themes/next/_vendors.yml new file mode 100644 index 0000000..c4bb099 --- /dev/null +++ b/themes/next/_vendors.yml @@ -0,0 +1,174 @@ +# This file is automatically generated +# See https://github.com/next-theme/plugins + +anime: + name: animejs + version: 3.2.1 + file: lib/anime.min.js + integrity: sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY= +fontawesome: + name: '@fortawesome/fontawesome-free' + version: 6.2.1 + file: css/all.min.css + alias: font-awesome + integrity: sha256-Z1K5uhUaJXA7Ll0XrZ/0JhX4lAtZFpT6jkKrEDT0drU= +prism: + name: prismjs + version: 1.29.0 + file: components/prism-core.min.js + alias: prism + integrity: sha256-4mJNT2bMXxcc1GCJaxBmMPdmah5ji0Ldnd79DKd1hoM= +prism_autoloader: + name: prismjs + version: 1.29.0 + file: plugins/autoloader/prism-autoloader.min.js + alias: prism + integrity: sha256-AjM0J5XIbiB590BrznLEgZGLnOQWrt62s3BEq65Q/I0= +prism_line_numbers: + name: prismjs + version: 1.29.0 + file: plugins/line-numbers/prism-line-numbers.min.js + alias: prism + integrity: sha256-9cmf7tcLdXpKsPi/2AWE93PbZpTp4M4tqzFk+lWomjU= +mathjax: + name: mathjax + version: 3.2.2 + file: es5/tex-mml-chtml.js + integrity: sha256-MASABpB4tYktI2Oitl4t+78w/lyA+D7b/s9GEP0JOGI= +katex: + name: katex + version: 0.16.4 + file: dist/katex.min.css + alias: KaTeX + integrity: sha256-gMRN4/6qeELzO1wbFa8qQLU8kfuF2dnAPiUoI0ATjx8= +copy_tex_js: + name: katex + version: 0.16.4 + file: dist/contrib/copy-tex.min.js + alias: KaTeX + integrity: sha256-Us54+rSGDSTvIhKKUs4kygE2ipA0RXpWWh0/zLqw3bs= +pjax: + name: '@next-theme/pjax' + version: 0.6.0 + file: pjax.min.js + alias: next-theme-pjax + integrity: sha256-vxLn1tSKWD4dqbMRyv940UYw4sXgMtYcK6reefzZrao= +jquery: + name: jquery + version: 3.6.3 + file: dist/jquery.min.js + integrity: sha256-pvPw+upLPUjgMXY0G+8O0xUf+/Im1MZjXxxgOcBQBXU= +fancybox_js: + name: '@fancyapps/fancybox' + version: 3.5.7 + file: dist/jquery.fancybox.min.js + alias: fancybox + integrity: sha256-yt2kYMy0w8AbtF89WXb2P1rfjcP/HTHLT7097U8Y5b8= +fancybox_css: + name: '@fancyapps/fancybox' + version: 3.5.7 + file: dist/jquery.fancybox.min.css + alias: fancybox + integrity: sha256-Vzbj7sDDS/woiFS3uNKo8eIuni59rjyNGtXfstRzStA= +mediumzoom: + name: medium-zoom + version: 1.0.8 + file: dist/medium-zoom.min.js + integrity: sha256-7PhEpEWEW0XXQ0k6kQrPKwuoIomz8R8IYyuU1Qew4P8= +lazyload: + name: lozad + version: 1.16.0 + file: dist/lozad.min.js + alias: lozad.js + integrity: sha256-mOFREFhqmHeQbXpK2lp4nA3qooVgACfh88fpJftLBbc= +pangu: + name: pangu + version: 4.0.7 + file: dist/browser/pangu.min.js + integrity: sha256-j+yj56cdEY2CwkVtGyz18fNybFGpMGJ8JxG3GSyO2+I= +quicklink: + name: quicklink + version: 2.3.0 + file: dist/quicklink.umd.js + integrity: sha256-yvJQOINiH9fWemHn0vCA5lsHWJaHs6/ZmO+1Ft04SvM= +disqusjs_js: + name: disqusjs + version: 3.0.2 + file: dist/browser/disqusjs.es2015.umd.min.js + integrity: sha256-okP99ZQKVpIy7+NogAMpGlIQzJa9XKXhIJcFgdju5bU= +disqusjs_css: + name: disqusjs + version: 3.0.2 + file: dist/browser/styles/disqusjs.css + integrity: sha256-71XarXwNr1Td27HmZI9zjY+rMzRdush6/glo6VFXp7o= +gitalk_js: + name: gitalk + version: 1.8.0 + file: dist/gitalk.min.js + integrity: sha256-MVK9MGD/XJaGyIghSVrONSnoXoGh3IFxLw0zfvzpxR4= +gitalk_css: + name: gitalk + version: 1.8.0 + file: dist/gitalk.css + integrity: sha256-AJnUHL7dBv6PGaeyPQJcgQPDjt/Hn/PvYZde1iqfp8U= +firebase_app: + name: firebase + version: 9.15.0 + file: firebase-app-compat.js + integrity: sha256-A8uo1+X48MvWPwgPlvCnYuAImCUflgEhnkcrIB/o0h8= +firebase_firestore: + name: firebase + version: 9.15.0 + file: firebase-firestore-compat.js + integrity: sha256-2vTXB2VWavgiIk/TK93CjOsIcPlVR5Rd4qq74a8UGU0= +algolia_search: + name: algoliasearch + version: 4.14.3 + file: dist/algoliasearch-lite.umd.js + integrity: sha256-dyJcbGuYfdzNfifkHxYVd/rzeR6SLLcDFYEidcybldM= +instant_search: + name: instantsearch.js + version: 4.49.2 + file: dist/instantsearch.production.min.js + integrity: sha256-Nu8yqoXoRZEVYyZf4/eY1V4FsenbiCw85RY3gWjN3zQ= +local_search: + name: hexo-generator-searchdb + version: 1.4.1 + file: dist/search.js + integrity: sha256-1kfA5uHPf65M5cphT2dvymhkuyHPQp5A53EGZOnOLmc= +pdfobject: + name: pdfobject + version: 2.2.8 + file: pdfobject.min.js + integrity: sha256-tu9j5pBilBQrWSDePOOajCUdz6hWsid/lBNzK4KgEPM= +mermaid: + name: mermaid + version: 9.3.0 + file: dist/mermaid.min.js + integrity: sha256-QdTG1YTLLTwD3b95jLqFxpQX9uYuJMNAtVZgwKX4oYU= +animate_css: + name: animate.css + version: 3.1.1 + file: animate.min.css + integrity: sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE= +pace_js: + name: pace-js + version: 1.2.4 + file: pace.min.js + alias: pace + integrity: sha256-gqd7YTjg/BtfqWSwsJOvndl0Bxc8gFImLEkXQT8+qj0= +pace_css: + name: pace-js + version: 1.2.4 + dir: themes + alias: pace +canvas_ribbon: + name: ribbon.js + version: 1.0.2 + file: dist/ribbon.min.js + integrity: sha256-UkSSapoJqxvq+8bSCIrAhXO+aOMBRmkK6vxjTstemLs= +creative_commons: + name: '@creativecommons/vocabulary' + version: 2020.11.3 + dir: assets/license_badges + alias: creativecommons-vocabulary diff --git a/themes/next/crowdin.yml b/themes/next/crowdin.yml new file mode 100644 index 0000000..b3b67b8 --- /dev/null +++ b/themes/next/crowdin.yml @@ -0,0 +1,9 @@ +files: + - source: /languages/en.yml + translation: /languages/%two_letters_code%.%file_extension% + languages_mapping: + two_letters_code: + zh-CN: zh-CN + zh-TW: zh-TW + zh-HK: zh-HK + pt-BR: pt-BR diff --git a/themes/next/docs/AGPL3.md b/themes/next/docs/AGPL3.md new file mode 100644 index 0000000..f90c354 --- /dev/null +++ b/themes/next/docs/AGPL3.md @@ -0,0 +1,649 @@ +#
GNU Affero General Public License
+ +

Version 3, 19 November 2007 Copyright © 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 Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + +The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are 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. + +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. + +Developers that use our General Public Licenses protect your rights +with two steps: **(1)** assert copyright on the software, and **(2)** offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + +A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + +The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + +An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + +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 Affero 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. Remote Network Interaction; Use with the GNU General Public License + +Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + +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 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 work with which it is combined will remain governed by version +3 of the GNU General Public License. + +### 14. Revised Versions of this License + +The Free Software Foundation may publish revised and/or new versions of +the GNU Affero 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 Affero 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 Affero 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 Affero 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. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a “Source” link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + +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 AGPL, see +<>. \ No newline at end of file diff --git a/themes/next/docs/AUTHORS.md b/themes/next/docs/AUTHORS.md new file mode 100644 index 0000000..ede8c5b --- /dev/null +++ b/themes/next/docs/AUTHORS.md @@ -0,0 +1,87 @@ +#
«NexT» Authors
+ +NexT theme was initially developed by: + +- **IIssNaN**: [NexT](https://github.com/iissnan/hexo-theme-next) (2014 - 2017) + +With collaborators from initially repository: + +- **Ivan.Nginx**: [DIFF highlight](https://github.com/iissnan/hexo-theme-next/pull/1079), + [HyperComments](https://github.com/iissnan/hexo-theme-next/pull/1155), + [`{% note %}` tag](https://github.com/iissnan/hexo-theme-next/pull/1160), + [`seo` option](https://github.com/iissnan/hexo-theme-next/pull/1311), + [`{% button %}` tag](https://github.com/iissnan/hexo-theme-next/pull/1328), + [VK API](https://github.com/iissnan/hexo-theme-next/pull/1381), + [WordCount plugin support](https://github.com/iissnan/hexo-theme-next/pull/1381), + [Yandex verification option](https://github.com/iissnan/hexo-theme-next/pull/1381), + [`{% exturl %}` tag](https://github.com/iissnan/hexo-theme-next/pull/1438), + [`b2t` option](https://github.com/iissnan/hexo-theme-next/pull/1438), + [`scrollpercent` option](https://github.com/iissnan/hexo-theme-next/pull/1438), + [`save_scroll` option](https://github.com/iissnan/hexo-theme-next/pull/1574), + [Star rating](https://github.com/iissnan/hexo-theme-next/pull/1649), + [`mobile_layout_economy` option](https://github.com/iissnan/hexo-theme-next/pull/1697), + [`{% tabs %}` tag](https://github.com/iissnan/hexo-theme-next/pull/1697), + [`{% label %}` tag](https://github.com/iissnan/hexo-theme-next/pull/1697), + [**`Gemini`** scheme](https://github.com/iissnan/hexo-theme-next/pull/1697), + [Menu & Sidebar icons in 1 line](https://github.com/iissnan/hexo-theme-next/pull/1830), + [Sidebar scrollable](https://github.com/iissnan/hexo-theme-next/pull/1898), + [Responsive favicons](https://github.com/iissnan/hexo-theme-next/pull/1898) + and many other [PR's with fixes and enhancements](https://github.com/iissnan/hexo-theme-next/pulls?utf8=%E2%9C%93&q=is%3Apr%20author%3Aivan-nginx) +- **Acris**: [Many PR's with fixes and updates](https://github.com/iissnan/hexo-theme-next/pulls?utf8=%E2%9C%93&q=is%3Apr%20author%3AAcris) + +And best contributors from initially repository: + +- **Rainy**: [Gentie comments](https://github.com/iissnan/hexo-theme-next/pull/1301), + [Han](https://github.com/iissnan/hexo-theme-next/pull/1598) + and many [PR's with fixes and optimizations](https://github.com/iissnan/hexo-theme-next/pulls?utf8=%E2%9C%93&q=is%3Apr%20author%3Ageekrainy) +- **Jeff**: [Local search](https://github.com/iissnan/hexo-theme-next/pull/694) + and many [PR's with fixes and improvements](https://github.com/iissnan/hexo-theme-next/pulls?utf8=%E2%9C%93&q=is%3Apr%20author%3Aflashlab) +- **Haocen**: [Footer enhancements](https://github.com/iissnan/hexo-theme-next/pull/1886) + and some other [PR's with improvements](https://github.com/iissnan/hexo-theme-next/pulls?utf8=%E2%9C%93&q=is%3Apr%20author%3AHaocen) +- **uchuhimo**: [Greatest enhancements for local search](https://github.com/iissnan/hexo-theme-next/pulls?utf8=%E2%9C%93&q=is%3Apr%20author%3Auchuhimo) +- **Kei**: [Change static file setting to support subdirectory](https://github.com/iissnan/hexo-theme-next/pull/4) +- **Jolyon**: [Swiftype](https://github.com/iissnan/hexo-theme-next/pull/84) +- **xirong**: [404 page](https://github.com/iissnan/hexo-theme-next/pull/126) +- **PinkyJie**: [Fix Swiftype](https://github.com/iissnan/hexo-theme-next/pull/132) +- **Tim Kuijsten**: [Split javascript into separate files](https://github.com/iissnan/hexo-theme-next/pull/152) +- **iamwent**: [Friendly links](https://github.com/iissnan/hexo-theme-next/pull/250) +- **arao lin**: [Option to lazyload images](https://github.com/iissnan/hexo-theme-next/pull/269) +- **Konstantin Pavlov**: [Microdata, opengraph and other semantic features](https://github.com/iissnan/hexo-theme-next/pull/276) +- **Gary**: [FastClick](https://github.com/iissnan/hexo-theme-next/pull/324) +- **Octavian**: [Baidu site vertification](https://github.com/iissnan/hexo-theme-next/pull/367) +- **Henry Chang**: [Facebook SDK](https://github.com/iissnan/hexo-theme-next/pull/410) +- **XiaMo**: [LeanCloud visitors](https://github.com/iissnan/hexo-theme-next/pull/439) +- **iblogc**: [Fix UA in Duoshuo](https://github.com/iissnan/hexo-theme-next/pull/489) +- **Vincent**: [Automatic headline ID's](https://github.com/iissnan/hexo-theme-next/pull/588) +- **cissoid**: [Tencent analytics](https://github.com/iissnan/hexo-theme-next/pull/603) +- **CosmoX**: [AddThis](https://github.com/iissnan/hexo-theme-next/pull/660) +- **Jason Guo**: [Reward for post](https://github.com/iissnan/hexo-theme-next/pull/687) +- **Jerry Bendy**: [CNZZ counter](https://github.com/iissnan/hexo-theme-next/pull/712) +- **Hui Wang**: [Wechat subscriber](https://github.com/iissnan/hexo-theme-next/pull/788) +- **PoonChiTim**: [Busuanzi counter](https://github.com/iissnan/hexo-theme-next/pull/809) +- **hydai**: [Facebook comments](https://github.com/iissnan/hexo-theme-next/pull/925) +- **OAwan**: [`canonical` option](https://github.com/iissnan/hexo-theme-next/pull/931) +- **Jim Zenn**: [Google Calendar](https://github.com/iissnan/hexo-theme-next/pull/1167) +- **Abner Chou**: [Disqus improvements](https://github.com/iissnan/hexo-theme-next/pull/1173) +- **Igor Fesenko**: [Application Insights](https://github.com/iissnan/hexo-theme-next/pull/1257) +- **jinfang**: [Youyan comments](https://github.com/iissnan/hexo-theme-next/pull/1324) +- **AlynxZhou**: [`canvas_nest` option](https://github.com/iissnan/hexo-theme-next/pull/1327) +- **aleon**: [Tencent MTA](https://github.com/iissnan/hexo-theme-next/pull/1408) +- **asmoker**: [LiveRe comments](https://github.com/iissnan/hexo-theme-next/pull/1415) +- **Jacksgong**: [Copyright on posts](https://github.com/iissnan/hexo-theme-next/pull/1497) +- **zhaiqianfeng**: [Changyan comments](https://github.com/iissnan/hexo-theme-next/pull/1514) +- **zproo**: [`canvas_ribbon` option](https://github.com/iissnan/hexo-theme-next/pull/1565) +- **jjandxa**: [`three_waves`](https://github.com/iissnan/hexo-theme-next/pull/1534), + [`canvas_lines` and `canvas_sphere`](https://github.com/iissnan/hexo-theme-next/pull/1595) options +- **shenzekun**: [Load bar at the top](https://github.com/iissnan/hexo-theme-next/pull/1689) +- **elkan1788**: [Upgrade jiathis share](https://github.com/iissnan/hexo-theme-next/pull/1796) +- **xCss**: [Valine comment system support](https://github.com/iissnan/hexo-theme-next/pull/1811) +- **Julian Xhokaxhiu**: [`override` option](https://github.com/iissnan/hexo-theme-next/pull/1861) +- **LEAFERx**: [NeedMoreShare2](https://github.com/iissnan/hexo-theme-next/pull/1913) +- **aimingoo & LEAFERx**: [Gitment supported with Mint](https://github.com/iissnan/hexo-theme-next/pull/1919) +- **LeviDing**: [Fix the bug of Gitment](https://github.com/iissnan/hexo-theme-next/pull/1944) +- **maple3142**: [Firestore visitor counter](https://github.com/iissnan/hexo-theme-next/pull/1978) + +It lives on as an open source project with many contributors, a self updating list is [here](https://github.com/next-theme/hexo-theme-next/graphs/contributors). + +P.S. If you did some useful pulls/commits in original repository and you are not in the list, let us know and you will be added here. diff --git a/themes/next/docs/LICENSE.txt b/themes/next/docs/LICENSE.txt new file mode 100644 index 0000000..8cc54ac --- /dev/null +++ b/themes/next/docs/LICENSE.txt @@ -0,0 +1,52 @@ + «NexT» – Elegant and powerful theme for Hexo. + + Copyright © 2017 «NexT» (github.com/next-theme/hexo-theme-next). + + Detail attribution information for «NexT» + is contained in the 'docs/AUTHORS.md' file. + + This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License version 3 +as published by the Free Software Foundation with the addition of the +following permission added to Section 15 as permitted in Section 7(a): +FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY «NEXT», +«NEXT» DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. + + 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 Affero General Public License for more details. +You should have received a copy of the GNU Affero General Public License +along with this program; if not, see: https://www.gnu.org/licenses/agpl.txt + + In accordance with Section 7(b) of the GNU Affero General Public License: + + a) It is not necessary to specify copyright in each source file of + this program because GitHub fully save commits of all modified files + with their authors and provides to see for this changes publicly. + + b) For any part of the covered work in which the copyright not specified, + will mean this part owned by «NexT» in accord with terms in this file. + +* c) A covered work must retain «NexT» official website link + (https://theme-next.js.org) in footer section of every website created, + modified or manipulated by using «NexT». + «NexT» theme configuration must be: + ``` + footer: + theme: + enable: true + ``` + Collaborators, best contributors and all authors specified in the + 'docs/AUTHORS.md' file of «NexT» repository under the + 'https://github.com/next-theme' organization can ignore theme info link + requirements. + + Anyone can be released from the requirements of the license by purchasing +a commercial license. Buying such a license is mandatory as soon as you +develop commercial activities involving the «NexT» software without +disclosing the source code of your own applications. +These activities include: + 1. Access to private repository with various premium features. + 2. Priority support for resolve all possible issues with «NexT». + 3. Priority support for implement all possible features to «NexT». diff --git a/themes/next/docs/ru/README.md b/themes/next/docs/ru/README.md new file mode 100644 index 0000000..f559ce8 --- /dev/null +++ b/themes/next/docs/ru/README.md @@ -0,0 +1,181 @@ +
+ Язык: + 🇺🇸 + 🇨🇳 + 🇷🇺 +
+ + + + + NexT preview + + +NexT logo + +# NexT + +> «NexT» — элегантная высококачественная тема под [Hexo](https://hexo.io). Сделана с нуля, с любовью. + +[![NPM version](https://img.shields.io/npm/v/hexo-theme-next?color=red&logo=npm&style=flat-square)](https://www.npmjs.com/package/hexo-theme-next) +[![Required Hexo version](https://img.shields.io/badge/hexo-%3E=5.3.0-blue?style=flat-square&logo=hexo)](https://hexo.io) +[![License](https://img.shields.io/badge/license-%20AGPL-orange?style=flat-square&logo=gnu)](https://github.com/next-theme/hexo-theme-next/blob/master/LICENSE.md) +[![Build Status](https://img.shields.io/github/actions/workflow/status/next-theme/hexo-theme-next/linter.yml?branch=master&label=test&logo=github&style=flat-square)](https://github.com/next-theme/hexo-theme-next/actions?query=workflow%3ALinter) +[![Build Status](https://img.shields.io/github/actions/workflow/status/next-theme/hexo-theme-next/tester.yml?branch=master&logo=github&style=flat-square)](https://github.com/next-theme/hexo-theme-next/actions?query=workflow%3ATester) +[![Coverage Status](https://img.shields.io/coveralls/github/next-theme/hexo-theme-next?logo=coveralls&style=flat-square)](https://coveralls.io/github/next-theme/hexo-theme-next) + +## Демо + +

+ 💟 Muse | 🔯 Mist | ♓️ Pisces | ♊️ Gemini +
+
+ Больше примеров «NexT» здесь. +

+ +## Установка + +If you're using Hexo 5.0 or later, the simplest way to install is through npm: + +```sh +$ cd hexo-site +$ npm install hexo-theme-next +``` + +Or you can clone the entire repository: + +```sh +$ cd hexo-site +$ git clone https://github.com/next-theme/hexo-theme-next themes/next +``` + +See [detailed installation instructions][docs-installation-url] if you want any other variant. + +After the installation, open Hexo config file and set `theme` variable to `next`. + +```yml +theme: next +``` + +## Configuration + +It is not recommended to directly modify any files in the NexT theme. Because this may cause errors (e.g. merge conflicts), and the modified files may be discarded when upgrading the theme. + +At present, NexT encourages users to use the [Alternate Theme Config][docs-configuration-url] to configure NexT. And it's easy to customize the layout or style of NexT using [Custom Files][docs-custom-files-url]. + +## Плагины + +Plugins extend and expand the functionality of NexT. There are two types of plugins: core plugins and third-party plugins. The core plugins are required by the basic functions of NexT. Third-party plugins provide a large number of optional features. + +Configuring these plugins is very easy. Например, Вы хотите использовать `pjax` для своего сайта. Открываем конфиг NexT'а и находим: + +```yml +# Easily enable fast Ajax navigation on your website. +# For more information: https://github.com/next-theme/pjax +pjax: true +``` + +### Configure CDN + +Third-party plugins are loaded from [CDNJS](https://cdnjs.com) CDN by default. We also provide other optional CDNs, including the famous [UNPKG](https://unpkg.com) and [jsDelivr](https://www.jsdelivr.com). + +For example, if you want to use `unpkg` instead of `cdnjs` as the default CDN provider, you need to edit the following settings in NexT config file: + +```yml +vendors: + # ... + # Some contents... + # ... + plugins: unpkg +``` + +## Обновление + +NexT выпускает новые версии каждый месяц. Please read the [release notes][docs-release-url] before updating the theme. You can update NexT by the following command. + +Install the latest version through npm: + +```sh +$ cd hexo-site +$ npm install hexo-theme-next@latest +``` + +Or update to the latest master branch: + +```sh +$ cd themes/next +$ git pull +``` + +**Если нужно обновиться с версии v5.x / v7.x на последней версиями, читаем [здесь][docs-upgrade-url].** + +## Обратная связь + +* Посетите [Awesome NexT][awesome-next-url] список. +* Вступить в наши [GitHub discussions][discussions-url] / [Gitter][gitter-url] чаты. +* [Добавить или улучшить перевод][i18n-url] за несколько секунд. +* Сообщить об ошибке в разделе [GitHub Issues][issues-bug-url]. +* Запросить новую возможность на [GitHub][issues-feat-url]. +* Голосовать за [популярные запросы возможностей][feat-req-vote-url]. + +## Contributing + +We welcome you to join the development of NexT. Please see [contributing document][contributing-document-url]. 🤗 + +Also, we welcome Issue or PR to our [official-plugins][official-plugins-url]. + +## Содействие + +[![Contributors][contributors-image]][contributors-url] + +## Благодарности + +«NexT» send special thanks to these great services that sponsor our core infrastructure: + + + +> GitHub allows us to host the Git repository and run the test suite. + + + + + + Netlify Logo + + + +> Netlify allows us to distribute the documentation. + + + +> Crowdin allows us to translate conveniently the documentation. + + + + + + CDNJS Logo + + + +> Thanks CDNJS for providing public CDN service. + +[docs-installation-url]: https://theme-next.js.org/docs/getting-started/installation.html +[docs-configuration-url]: https://theme-next.js.org/docs/getting-started/configuration.html +[docs-custom-files-url]: https://theme-next.js.org/docs/advanced-settings/custom-files.html +[docs-release-url]: https://github.com/next-theme/hexo-theme-next/releases +[docs-upgrade-url]: https://theme-next.js.org/docs/getting-started/upgrade.html + +[awesome-next-url]: https://github.com/next-theme/awesome-next +[discussions-url]: https://github.com/next-theme/hexo-theme-next/discussions +[gitter-url]: https://gitter.im/hexo-next +[i18n-url]: https://crowdin.com/project/hexo-theme-next + +[issues-bug-url]: https://github.com/next-theme/hexo-theme-next/issues/new?assignees=&labels=Bug&template=bug-report.md +[issues-feat-url]: https://github.com/next-theme/hexo-theme-next/issues/new?assignees=&labels=Feature+Request&template=feature-request.md +[feat-req-vote-url]: https://github.com/next-theme/hexo-theme-next/issues?q=is%3Aopen+is%3Aissue+label%3A%22Feature+Request%22 + +[contributing-document-url]: https://github.com/next-theme/hexo-theme-next/blob/master/.github/CONTRIBUTING.md +[official-plugins-url]: https://github.com/next-theme +[contributors-image]: https://raw.githubusercontent.com/next-theme/contributors/master/contributors.svg +[contributors-url]: https://github.com/next-theme/hexo-theme-next/blob/master/docs/AUTHORS.md diff --git a/themes/next/docs/zh-CN/CODE_OF_CONDUCT.md b/themes/next/docs/zh-CN/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..a385d6c --- /dev/null +++ b/themes/next/docs/zh-CN/CODE_OF_CONDUCT.md @@ -0,0 +1,95 @@ +
+ 语言: + :us: + :cn: + :ru: +
+ +NexT logo + +# NexT + +[NexT](https://theme-next.js.org) 是一个优雅而强大的 [Hexo](https://hexo.io/)主题。在这里,您可以构建一个托管在 [GitHub Pages](https://pages.github.com/) 上的静态博客,分享您的生活,并与新朋友进行交流。 + +参与者公约用来约束在 [NexT](https://github.com/next-theme/hexo-theme-next) 社区中代码更新、问题交流、请求合并等行为。我们期望所有用户相互尊重,礼貌待人。任何违反这些规则的人都将不会被审核,并会在发现后立即被阻止和驱逐。 + +## 目录 + +- [我们的保证](#我们的保证) +- [我们的责任](#我们的责任) +- [我们的标准](#我们的标准) +- [使用范围](#使用范围) +- [强制执行](#强制执行) +- [联系项目维护者](#联系项目维护者) +- [来源](#来源) + +## 我们的保证 + +作为此项目的贡献者和维护者,我们承诺尊重所有做出贡献的用户,这些贡献包括了报告问题、发布功能请求、更新文档、提交合并请求以及其他活动。 + +为了促进一个开放透明且友好的环境,我们作为贡献者和维护者保证:无论年龄、种族、民族、性别认同和表达(方式)、体型、身体健全与否、经验水平、国籍、个人表现、宗教或性别取向,参与者在我们项目和社区中都免于骚扰。 + +## 我们的责任 + +项目维护者有责任为「可接受的行为」标准做出诠释,有权利及责任去删除、编辑、拒绝与本行为标准有所违背的评论(comments)、提交(commits)、代码、wiki 编辑、问题(issues)和其他贡献,以及项目维护者可暂时或永久性的禁止任何他们认为有不适当、威胁、冒犯、有害行为的贡献者。 + +## 我们的标准 + +作为 GitHub 上的一个项目,本项目受到 [GitHub 社区准则](https://help.github.com/articles/github-community-guidelines/)的约束。 此外,作为 npm 托管的项目,[npm 公司的行为准则](https://www.npmjs.com/policies/conduct)也涵盖了本项目。 + +有助于创造正面环境的行为包括但不限于: + +* 使用友好和包容性语言 +* 尊重不同的观点和经历 +* 耐心地接受建设性批评 +* 关注对社区最有利的事情 +* 友善对待其他社区成员 + +身为参与者不能接受的行为包括但不限于: + +* 使用与性有关的言语或是图像,以及不受欢迎的性骚扰 +* 捣乱/煽动/造谣的行为或进行侮辱/贬损的评论,人身攻击及政治攻击 +* 公开或私下的骚扰 +* 未经许可地发布他人的个人资料,例如住址或是电子地址 +* 其他可以被合理地认定为不恰当或者违反职业操守的行为 + +## 使用范围 + +当一个人代表该项目或是其社区时,本行为标准适用于其项目社区和公共社区。 + +根据某人在本社区范围以外发生的违规情况,项目维护者可以认为其不受欢迎,并采取适当措施来保证所有成员的安全性和舒适性。 + +## 强制执行 + +如果您看到违反行为准则的行为,请按以下步骤操作: + +1. 让这个人知道他所做的并不合适,并要求他停止或编辑他们的提交信息。该人应立即停止行为并纠正问题。 +2. 如果该人没有纠正其行为,或者您不方便与其沟通,请[联系项目维护者](#联系项目维护者)。上报时,请尽可能多的提供详细信息,链接,截图,上下文或可用于更好地理解和解决情况的其他信息。 +3. 收到上报信息后,项目维护者会查看问题,并采取进一步的措施。 + +一旦项目维护者参与其中,他们将遵循以下一系列步骤,并尽力保护项目成员的利益。任何维护团队认为有必要且适合的所有投诉都将进行审查及调查,并做出相对应的回应。项目小组有对事件回报者有保密的义务。具体执行的方针近一步细节可能会单独公布。 + +以下是项目维护者根据需要采取的进一步执法步骤: + +1. 再次要求停止违规行为。 +2. 如果违规者还是没有回应,将会受到正式的警告,并收到项目维护者的移除或修改消息。同时,相关的问题或合并请求将会被锁定。 +3. 如果警告后违规行为继续出现,违规者将会被禁言 24 小时。 +4. 如果禁言后违规行为继续出现,违规者将会被处罚长期(6-12个月)禁言。 + +除此之外,项目维护者可以根据需要删除任何违规的消息,图片,贡献等。如果违规行为被认为是对社区成员的严重或直接威胁,包括任何置社区成员于风险的威胁、身体或言语攻击,项目维护者有充分权利自行决定跳过上述任何步骤。 + +没有切实地遵守或是执行本行为标准的项目维护人员,可能会因项目领导人或是其他成员的决定,暂时或是永久地取消其参与资格。 + +## 联系项目维护者 + +您可以通过以下方式与维护人员联系: + +* 讨论: + * [GitHub Discussions](https://github.com/next-theme/hexo-theme-next/discussions) + +* 即时通信: + * [Gitter](https://gitter.im/hexo-next) + +## 来源 + +本行为标准改编自[Contributor Covenant](https://www.contributor-covenant.org/) 和 [WeAllJS Code of Conduct](https://wealljs.org/code-of-conduct)。 diff --git a/themes/next/docs/zh-CN/CONTRIBUTING.md b/themes/next/docs/zh-CN/CONTRIBUTING.md new file mode 100644 index 0000000..1641e68 --- /dev/null +++ b/themes/next/docs/zh-CN/CONTRIBUTING.md @@ -0,0 +1,181 @@ +
+ 语言: + :us: + :cn: + :ru: +
+ +NexT logo + +# NexT + +首先,非常感谢大家抽出宝贵时间来让我们的 NexT 主题越变越好。在这里,我们介绍一下 [NexT 主题及其子模块](https://github.com/next-theme) 的开源贡献指南。不过,我们希望大家不要局限于此,更欢迎大家随时进行补充。 + +## 目录 + +[如何为 NexT 做贡献](#如何为-next-做贡献) + + * [你需要了解的](#你需要了解的) + * [阅读文档](#阅读文档) + * [快速调试指南](#快速调试指南) + * [反馈 Bug](#反馈-bug) + * [提交漏洞](#提交漏洞) + * [提交功能需求](#提交功能需求) + * [提交合并请求](#提交合并请求) + * [发布版本](#发布版本) + +[规范](#规范) + + * [行为规范](#行为规范) + * [编码规范](#编码规范) + * [标签规范](#标签规范) + * [提交信息规范](#提交信息规范) + +## 如何为 NexT 做贡献 + +### 你需要了解的 + +#### 阅读文档 + +如果你在使用过程中遇到了问题,你可以查阅 [FAQs](https://theme-next.js.org/docs/faqs) 或者 [NexT 帮助文档](https://theme-next.js.org/docs/troubleshooting)。 + +另外,你也可以通过 [这里](https://github.com/next-theme/hexo-theme-next/search?q=&type=Issues&utf8=%E2%9C%93) 进行大致检索,有些问题已经得到解答,你可以自行解决。对于没有解决的 Issue,你也可以继续提问。 + +#### 快速调试指南 + +在 GitHub 上提交 Issue 前,请先查看我们的 [快速调试指南](https://theme-next.js.org/docs/troubleshooting.html#Quick-Debug-Instructions) 来 debug。 + +如果你在使用过程中发现了 Bug,请再次确认 Bug 在 [最新发布版本](https://github.com/next-theme/hexo-theme-next/releases/latest) 中是否重现。如果 Bug 重现,欢迎你到我们的 [主题仓库](https://github.com/next-theme/hexo-theme-next) 中 [反馈 Bug](#reporting-bugs) 或者 [提交功能需求](#提交功能需求),也更期待您 [提交合并请求](#提交合并请求)。 + +### 反馈 Bug + +反馈 Bug 前,请再次确认您已经查看了 [你需要了解的](#你需要了解的) 内容,避免提交重复的 Issue。创建 Issue 时,请认真遵守如下指南,这样我们才能更好地理解问题,重现问题和解决问题。 + +* 在标题中清晰准确地描述你的问题。 +* 按照 [模板](../../.github/ISSUE_TEMPLATE.md) 尽可能的详细填写相关信息。 +* 一步步详细你是如何重现 Bug 的,做了什么,使用了哪些功能等等。如果你需要展示代码段,请使用 [Markdown 代码块](https://help.github.com/articles/creating-and-highlighting-code-blocks/) 或 [Github 预览链接](https://help.github.com/articles/creating-a-permanent-link-to-a-code-snippet/) 或 [Gist 链接](https://gist.github.com/)。 +* 提供 Bug 的样例,如图像文件、在线演示网址等等。 +* 详细描述通过上述重现过程出现的问题。 +* 详细描述你期待的结果。 + +#### 提交漏洞 + +如果你发现安全问题,请以负责任的方式行事,即不要在公共 Issue 中提交而是直接向我们反馈,这样我们就可以在漏洞被利用之前对其进行修复。请将相关信息发送到 security@theme-next.com(可接受 PGP 加密邮件)。 + +我们很乐意对任何提交漏洞的人予以特别感谢以便我们修复它。如果你想保持匿名性或使用笔名替代,请告诉我们。我们将充分尊重你的意愿。 + +### 提交功能需求 + +提交功能需求前,请再次确认您已经查看了 [你需要了解的](#你需要了解的) 内容,避免提交重复的 Issue。确定相关仓库后,创建 Issue 并按照 [模板](../../.github/ISSUE_TEMPLATE.md) 尽可能的详细填写相关信息。 + +请认真遵守如下指南,这样我们才能更好地理解和开发功能需求:pencil:: + +* 在标题中清晰准确地描述你的功能需求。 +* 详细描述目前所具有的功能和你所期待的功能,并解释为什么需要该功能。 +* 提供功能需求的样例,如图像文件、在线演示网址等等。 + +### 提交合并请求 + +提交合并请求前,请再次确认您已经查看了 [你需要了解的](#你需要了解的) 内容,避免提交重复的合并请求。确定相关仓库后,创建合并请求。更多详细操作过程可以查看 [帮助文档](https://help.github.com/articles/creating-a-pull-request/)。 + +请认真遵守如下指南,这样我们才能更好地理解你的合并请求: + +* 创建合并请求时,请遵守 [编码规范](#编码规范) 和 [提交信息规范](#提交信息规范)。 +* 在标题中清晰准确地描述你的合并请求,不要加入 Issue 编号。 +* 按照 [模板](../../.github/PULL_REQUEST_TEMPLATE.md) 尽可能的详细填写相关信息。 +* 合并请求需要在所有主题样式中测试通过,并提供所表现功能的样例,如图像文件、在线演示网址等等。 + +### 发布版本 + +版本发布是将项目发布给用户的一种很好的方式。 + +1. 进入 GitHub 项目主页,点击 **Releases** 和 **Draft a new release**。 +2. 输入你需要发布的版本号。版本控制是基于 [Git tags](https://git-scm.com/book/en/Git-Basics-Tagging) 工作的,建议按照 [About Major and Minor NexT versions](https://github.com/theme-next/hexo-theme-next/issues/187) 确定版本号。 +3. 确定你需要发布的分支。除非发布测试版本,通常情况下选择 `master` 分支。 +4. 输入发布版本的标题和说明。 + - 标题为版本号。 + - 内容根据 [Release Drafter](https://github.com/release-drafter/release-drafter) 的模版填写。 + - 使用被动语态,省略主语。 + - 所有的变化都需要记录在版本说明中。对于没有使用 PR 的更改,需要添加相应的 commit 编号。如果使用了 PR 进行合并修改,则直接添加相应的 PR 编号即可。 +5. 如果您希望随版本一起发布二进制文件(如编译的程序),请在上传二进制文件对话框中手动拖放或选择文件。 +6. 如果版本不稳定,请选择 **This is a pre-release**,以通知用户它尚未完全准备好。如果您准备公布您的版本,请点击 **Publish release**。否则,请单击 **Save draft** 以稍后处理。 + +## 规范 + +### 行为规范 + +为了保证本项目的顺利运作,所有参与人都需要遵守 [行为规范](CODE_OF_CONDUCT.md)。 + +### 编码规范 + +我们使用 ESLint 和 Stylint 来识别和报告 JavaScript 和 Stylus 中的模式,目的是使代码更加一致并避免错误。编码时应遵循这些规范。 + +### 标签规范 + +为了方便维护人员和用户能够快速找到他们想要查看的问题,我们使用「标签」功能对 Pull requests 和 Issues 进行分类。 + +如果您不确定某个标签的含义,或者不知道将哪些标签应用于 PR 或 issue,千万别错过这个。 + +Issue 的标签: + +- 类型 + - `Bug`: 检测到需要进行确认的 Bug + - `Feature Request`: 提出了新功能请求的 Issue + - `Question`: 提出疑问的 Issue + - `Meta`: 表明使用条款变更的 Issue + - `Support`: 被标记为支持请求的 Issue + - `Polls`: 发起投票的 Issue +- 结果 + - `Duplicate`: 重复提及的 Issue + - `Hexo`: 与 Hexo 相关的 Issue + - `Hexo Plugin`: 与 Hexo 插件相关的 Issue + - `Browser`: 与浏览器相关的 Issue + - `Invalid`: 无法复现的 Issue + - `Expected Behavior`: 与预期行为相符的 Issue + - `Need More Info`: 需要更多信息的 Issue + - `Solved`: 已经解决的 Issue + - `To Do`: 待解决的 Issue + - `Stale`: 由于长期无人回应被封存的 Issue + +Pull Request 的标签: + +- `Breaking Change`: 产生重大变动的 Pull Request +- `Bug Fix`: 修复相关 Bug 的 Pull Request +- `New Feature`: 添加了新功能的 Pull Request +- `Feature`: 为现有功能提供选项或加成的 Pull Request +- `i18n`: 更新了翻译的 Pull Request +- `Dependencies`: 更新了依赖包的 Pull Request +- `Actions`: 更新了 GitHub Actions 的 Pull Request +- `Skip Release`: 无需在 Release Note 中展现的 Pull Request + +两者兼有: + +- `Roadmap`: 与 NexT 主题发展相关的 Issue 或者 Pull Request +- `Help Wanted`: 需要帮助的 Issue 或者 Pull Request +- `Improvement`: 需要改进的 Issue 或者改进了 NexT 主题的 Pull Request +- `Layout`: 与模版引擎相关的 Issue 或者 Pull Request +- `CSS`: 与 NexT 主题 CSS 文件相关的 Issue 或者 Pull Request +- `Icons & Fonts`: 与 NexT 主题图标和字体相关的 Issue 或者 Pull Request +- `PJAX`: 与 PJAX 相关的 Issue 或者 Pull Request +- `3rd Party Plugin`: 与第三方插件和服务相关的 Issue 或者 Pull Request +- `Docs`: 与文档说明相关的 Issue 或者 Pull Request +- `Configurations`: 与 NexT 主题设置相关的 Issue 或者 Pull Request + +### 提交信息规范 + +我们对项目的 git 提交信息格式进行统一格式约定,每条提交信息由 `type`+`subject` 组成,这将提升项目日志的可读性。 + +- `type` 用于表述此次提交信息的意义,首写字母大写,包括但不局限于如下类型: + * `Build`:基础构建系统或依赖库的变化 + * `Ci`:CI 构建系统及其脚本变化 + * `Docs`:文档内容变化 + * `Feat`:新功能 + * `Fix`:Bug 修复 + * `Perf`:性能优化 + * `Refactor`:重构(即不是新增功能,也不是修改 Bug 的代码变动) + * `Style`:格式(不影响代码运行的变动) + * `Revert`:代码回滚 + * `Release`:版本发布 +- `subject` 用于简要描述修改变更的内容,如 `Update code highlighting in README.md`。 + * 句尾不要使用符号。 + * 使用现在时、祈使句语气。 diff --git a/themes/next/docs/zh-CN/README.md b/themes/next/docs/zh-CN/README.md new file mode 100644 index 0000000..1695c5e --- /dev/null +++ b/themes/next/docs/zh-CN/README.md @@ -0,0 +1,181 @@ +
+ 语言: + 🇺🇸 + 🇨🇳 + 🇷🇺 +
+ + + + + NexT preview + + +NexT logo + +# NexT + +> «NexT» 是一款风格优雅的高质量 [Hexo](https://hexo.io) 主题,自点点滴滴中用爱雕琢而成。 + +[![NPM version](https://img.shields.io/npm/v/hexo-theme-next?color=red&logo=npm&style=flat-square)](https://www.npmjs.com/package/hexo-theme-next) +[![Required Hexo version](https://img.shields.io/badge/hexo-%3E=5.3.0-blue?style=flat-square&logo=hexo)](https://hexo.io) +[![License](https://img.shields.io/badge/license-%20AGPL-orange?style=flat-square&logo=gnu)](https://github.com/next-theme/hexo-theme-next/blob/master/LICENSE.md) +[![Build Status](https://img.shields.io/github/actions/workflow/status/next-theme/hexo-theme-next/linter.yml?branch=master&label=test&logo=github&style=flat-square)](https://github.com/next-theme/hexo-theme-next/actions?query=workflow%3ALinter) +[![Build Status](https://img.shields.io/github/actions/workflow/status/next-theme/hexo-theme-next/tester.yml?branch=master&logo=github&style=flat-square)](https://github.com/next-theme/hexo-theme-next/actions?query=workflow%3ATester) +[![Coverage Status](https://img.shields.io/coveralls/github/next-theme/hexo-theme-next?logo=coveralls&style=flat-square)](https://coveralls.io/github/next-theme/hexo-theme-next) + +## 即时预览 + +

+ 💟 Muse | 🔯 Mist | ♓️ Pisces | ♊️ Gemini +
+
+ 更多 «NexT» 的例子参见这里。 +

+ +## 安装 + +如果你在使用 Hexo 5.0 或更新版本,最简单的安装方式是通过 npm: + +```sh +$ cd hexo-site +$ npm install hexo-theme-next +``` + +你也可以直接克隆整个仓库: + +```sh +$ cd hexo-site +$ git clone https://github.com/next-theme/hexo-theme-next themes/next +``` + +此外,如果你想要使用其他方式,请参见[详细安装步骤][docs-installation-url]。 + +安装完成后,在 Hexo 配置文件中将 `theme` 设置为 `next`。 + +```yml +theme: next +``` + +## 配置 + +我们不推荐直接修改 NexT 主题的文件。因为这可能导致错误(例如 git merge 冲突),并且在升级主题时修改的文件可能丢失。 + +目前 NexT 鼓励用户使用 [Alternate Theme Config][docs-configuration-url] 进行配置。并且可以轻松地通过 [Custom Files][docs-custom-files-url] 自定义主题的布局和样式。 + +## 插件 + +插件丰富和拓展了 NexT 的功能。这些插件分为两种:核心插件和第三方插件。核心插件被 NexT 的基础功能所依赖。第三方插件提供了大量的可选功能。 + +配置这些插件非常简单。例如,你想要在你的站点中使用 `pjax` 插件,请进入 NexT 配置文件,启用 `pjax` 配置项: + +```yml +# Easily enable fast Ajax navigation on your website. +# For more information: https://github.com/next-theme/pjax +pjax: true +``` + +### 设置 CDN + +第三方插件默认通过 [CDNJS](https://cdnjs.com) CDN 服务加载。我们也提供了其它的 CDN 服务供选择,包括著名的 [UNPKG](https://unpkg.com) 和 [jsDelivr](https://www.jsdelivr.com)。 + +例如,你想要使用 `unpkg` 代替 `cdnjs` 作为默认的 CDN 提供商,你需要在 NexT 配置文件中进行如下设置: + +```yml +vendors: + # ... + # Some contents... + # ... + plugins: unpkg +``` + +## 更新 + +NexT 每个月都会发布新版本。请在更新前阅读[更新说明][docs-release-url]。你可以通过如下命令更新 NexT。 + +通过 npm 安装最新版本: + +```sh +$ cd hexo-site +$ npm install hexo-theme-next@latest +``` + +或者通过 git 更新到最新的 master 分支: + +```sh +$ cd themes/next +$ git pull +``` + +**如果你想要从 v5.x / v7.x 更新到最新版本,阅读[这篇文档][docs-upgrade-url]。** + +## 反馈 + +* 浏览 [Awesome NexT][awesome-next-url] 列表,与其它用户分享插件和教程。 +* 加入我们的 [GitHub discussions][discussions-url] / [Gitter][gitter-url] 聊天。 +* 请花几秒钟来[添加或修正翻译][i18n-url]。 +* 在 [GitHub Issues][issues-bug-url] 报告Bug。 +* 在 [GitHub][issues-feat-url] 请求新的功能。 +* 为 [受欢迎的 Feature request][feat-req-vote-url] 投票。 + +## 贡献你的代码 + +我们欢迎你加入 NexT 的开发,贡献出你的一份力量。请看[开源贡献指南][contributing-document-url]。 🤗 + +你也可以随时向我们的[官方插件][official-plugins-url]提交 Issue 或 Pull Request。 + +## 贡献者 + +[![Contributors][contributors-image]][contributors-url] + +## 鸣谢 + +«NexT» 特别感谢这些支持我们核心基础设施的优质服务: + + + +> GitHub 容许我们托管 Git 仓库及运行测试。 + + + + + + Netlify Logo + + + +> Netlify 容许我们发布文档。 + + + +> Crowdin 容许我们方便地翻译文档。 + + + + + + CDNJS Logo + + + +> 感谢 CDNJS 提供的 CDN 服务。 + +[docs-installation-url]: https://theme-next.js.org/docs/getting-started/installation.html +[docs-configuration-url]: https://theme-next.js.org/docs/getting-started/configuration.html +[docs-custom-files-url]: https://theme-next.js.org/docs/advanced-settings/custom-files.html +[docs-release-url]: https://github.com/next-theme/hexo-theme-next/releases +[docs-upgrade-url]: https://theme-next.js.org/docs/getting-started/upgrade.html + +[awesome-next-url]: https://github.com/next-theme/awesome-next +[discussions-url]: https://github.com/next-theme/hexo-theme-next/discussions +[gitter-url]: https://gitter.im/hexo-next +[i18n-url]: https://crowdin.com/project/hexo-theme-next + +[issues-bug-url]: https://github.com/next-theme/hexo-theme-next/issues/new?assignees=&labels=Bug&template=bug-report.md +[issues-feat-url]: https://github.com/next-theme/hexo-theme-next/issues/new?assignees=&labels=Feature+Request&template=feature-request.md +[feat-req-vote-url]: https://github.com/next-theme/hexo-theme-next/issues?q=is%3Aopen+is%3Aissue+label%3A%22Feature+Request%22 + +[contributing-document-url]: https://github.com/next-theme/hexo-theme-next/blob/master/docs/zh-CN/CONTRIBUTING.md +[official-plugins-url]: https://github.com/next-theme +[contributors-image]: https://raw.githubusercontent.com/next-theme/contributors/master/contributors.svg +[contributors-url]: https://github.com/next-theme/hexo-theme-next/blob/master/docs/AUTHORS.md diff --git a/themes/next/languages/README.md b/themes/next/languages/README.md new file mode 100644 index 0000000..cd78b3a --- /dev/null +++ b/themes/next/languages/README.md @@ -0,0 +1,39 @@ +# Internationalization (i18n) + +[![Crowdin](https://badges.crowdin.net/hexo-theme-next/localized.svg)](https://crowdin.com/project/hexo-theme-next) + +You can use internationalization to present your site in different languages. The default language is set by modifying the `language` setting in Hexo `_config.yml`. You can also set multiple languages and modify the order of default languages. + +```yml +language: en +``` + +```yml +language: + - zh-CN + - en +``` + +## Override Default Translations + +If you would like to customize the default translation, you do not need to modify the translation files in the `languages` directory. You can override all translations using [Data Files](https://hexo.io/docs/data-files). + +1. Creat a `languages.yml` in `source/_data`. +2. Insert following codes: (be careful about the two-space indent) + + ```yml + # language + zh-CN: + # items + post: + copyright: + # the translation you perfer + author: 本文博主 + en: + menu: + schedule: Calendar + ``` + +## Improve Translations + +The files in the `language` directory are automatically generated, you do not need to modify them directly. Please submit translations via [Crowdin](https://crowdin.com/project/hexo-theme-next) if you would like to add or improve translation for NexT theme. diff --git a/themes/next/languages/ar.yml b/themes/next/languages/ar.yml new file mode 100644 index 0000000..b7091dc --- /dev/null +++ b/themes/next/languages/ar.yml @@ -0,0 +1,102 @@ +--- +name: عربي +title: + archive: الأرشيف + category: تصنيف + tag: وسم + schedule: التقويم +menu: + home: Home + archives: الأرشيفات + categories: التصنيفات + tags: الوسوم + about: معلومات + search: بحث + schedule: التقويم + sitemap: خريطة الموقع + commonweal: Commonweal 404 +sidebar: + overview: عام + toc: المحتويات + links: Links +post: + posted: نُشر في + edited: عُدل في + created: أُنشأ + modified: عُدل + edit: تحرير هذا المقال + in: في + read_more: تابع القراءة + untitled: بدون عنوان + sticky: مثبت + views: مشاهدات + related_posts: مقالات مشابهة + copyright: + author: مؤلف المقال + link: رابط المقال + post_author: Written by + post_link: This article originally appeared on + license_title: حقوق الملكية + license_content: "حميع المقالات في هذه المدوّنة منشورة تحت رخصة %s إلا عند التنويه بخلافه." +footer: + powered: "تطبيق الموقع %s" + total_views: إجمالي المشاهدات + total_visitors: إجمالي الزوار +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: لا وسوم + one: وسمٌ واحدٌ + other: "%d وسماً بالمُجمل" + categories: + zero: لا تصنيفات + one: تصنيفٌ واحد + other: "%d تصنيفات بالمُجمل" + archive_posts: + zero: لا مقالات. + one: مقالٌ واحد. + other: "%d مقالاً بالمُجمل." +state: + posts: المقالات + tags: الوسوم + categories: التصنيفات +search: + placeholder: بحث... + empty: "We didn't find any results for the search: %s" + hits_time: "%s results found in %s ms" + hits: "%s results found" +cheers: + um: هِم.. + ok: حسناً + nice: جميل + good: جيد + great: عظيم + excellent: ممتاز +keep_on: واصل الكتابة. +symbol: + comma: "، " + period: ". " + colon: ": " +reward: + donate: تبرّع + wechatpay: WeChat Pay + alipay: Alipay + paypal: PayPal + bitcoin: Bitcoin + comment: Buy me a coffee +follow_me: + welcome: مرحباً بك حيثُ أنشر أيضاً +accessibility: + nav_toggle: تشغيل شريط التصفح + prev_page: الصفحة السابقة + next_page: الصفحة التالية + back_to_top: Back to top + select_lang: Select language +symbols_count_time: + count: عدد الحروف في المقال + count_total: مُجمل عدد الحروف + time: زمن القراءة + time_total: مُجمل زمن القراءة + time_minutes: دقائق. diff --git a/themes/next/languages/bn.yml b/themes/next/languages/bn.yml new file mode 100644 index 0000000..c5f12cc --- /dev/null +++ b/themes/next/languages/bn.yml @@ -0,0 +1,102 @@ +--- +name: বাংলা +title: + archive: আর্কাইভ + category: ক্যাটাগরি + tag: ট্যাগ + schedule: কর্ম পরিকল্পনা +menu: + home: হোম পেজ + archives: আর্কাইভ এর তালিকা + categories: ক্যাটাগরি এর তালিকা + tags: ট্যাগ এর তালিকা + about: সম্পর্কে + search: সার্চ + schedule: কর্ম পরিকল্পনা + sitemap: Sitemap + commonweal: Commonweal 404 +sidebar: + overview: সারাংশ + toc: সূচীপত্র + links: Links +post: + posted: প্রকাশিত হয়েছে + edited: সম্পাদিত হয়েছে + created: তৈরি করা হয়েছে + modified: পরিমার্জন করা হয়েছে + edit: পোস্টটি সম্পাদনা করুন + in: শ্রেনী + read_more: আরো পড়ুন + untitled: শিরোনামহীন + sticky: স্থির + views: ভিউ + related_posts: সম্পর্কিত পোস্ট + copyright: + author: লিখিকা + link: পোস্ট লিঙ্ক + post_author: রচনা করেছেন + post_link: এই আর্টিকেলটি প্রথমে প্রকাশিত হয়েছে + license_title: কপিরাইট নোটিস + license_content: "এই ব্লগের সমস্ত আর্টিকেল %s এর অধীনে লাইসেন্সপ্রাপ্ত যদি না ব্যতিক্রম উল্লেখ করা হয়।" +footer: + powered: "%s এর সাহায্যে চলছে" + total_views: মোট দর্শক + total_visitors: মোট দর্শক +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: কোনও ট্যাগ নেই + one: একটি ট্যাগ আছে + other: "মোট %d টি ট্যাগ" + categories: + zero: কোন ক্যাটাগরি নেই + one: একটি ক্যাটাগরি আছে + other: "মোট %d টি ক্যাটাগরি" + archive_posts: + zero: কোনও পোস্ট নেই. + one: ১টি পোস্ট। + other: "মোট %d টি পোস্ট।" +state: + posts: পোস্ট এর তালিকা + tags: ট্যাগ এর তালিকা + categories: ক্যাটাগরি এর তালিকা +search: + placeholder: সার্চ করা হচ্ছে... + empty: "আমরা উক্ত অনুসন্ধানের জন্য কোন ফলাফল খুঁজে পাইনি: %s" + hits_time: "%s টি ফলাফল %s মিলিসেকেন্ড এ পাওয়া গেছে" + hits: "%s টি ফলাফল পাওয়া গেছে" +cheers: + um: ইয়ে... মানে.. + ok: ঠিক আছে + nice: বেশ + good: ভালো + great: অসাধারন + excellent: চমৎকার +keep_on: পোস্ট চালিয়ে যাও। +symbol: + comma: ", " + period: "। " + colon: "ঃ " +reward: + donate: দান করুন + wechatpay: উইচ্যাট পে + alipay: আলি পে + paypal: PayPal + bitcoin: বিটকয়েন + comment: Buy me a coffee +follow_me: + welcome: আমার অন্যান্য প্রকাশনা চ্যানেলে আপনাকে স্বাগতম +accessibility: + nav_toggle: নেভিগেশন বারের দৃশ্যমানতা টগল করুন + prev_page: পূর্ববর্তী পৃষ্ঠা + next_page: পূর্ববর্তী পৃষ্ঠা + back_to_top: উপরে ফিরে যান + select_lang: ভাষা নির্বাচন করুন +symbols_count_time: + count: আর্টিকালে অক্ষর এর পরিমাণ + count_total: আর্টিকালে অক্ষর এর মোট পরিমাণ + time: পড়াতে লাগবে + time_total: মোট পড়াতে লাগবে + time_minutes: মিনিট। diff --git a/themes/next/languages/de.yml b/themes/next/languages/de.yml new file mode 100644 index 0000000..9744bad --- /dev/null +++ b/themes/next/languages/de.yml @@ -0,0 +1,102 @@ +--- +name: Deutsch +title: + archive: Archiv + category: Kategorie + tag: Schlagwort + schedule: Zeitplan +menu: + home: Startseite + archives: Archiv + categories: Kategorien + tags: Schlagwörter + about: Über + search: Suche + schedule: Zeitplan + sitemap: Sitemap + commonweal: Commonweal 404 +sidebar: + overview: Übersicht + toc: Inhaltsverzeichnis + links: Links +post: + posted: Veröffentlicht am + edited: Bearbeitet am + created: Erstellt + modified: Geändert am + edit: Diesen Beitrag bearbeiten + in: in + read_more: Weiterlesen + untitled: Unbenannt + sticky: Angepinnt + views: Aufrufe + related_posts: Ähnliche Beiträge + copyright: + author: Beitragsautor + link: Beitragslink + post_author: Written by + post_link: This article originally appeared on + license_title: Urheberrechtshinweis + license_content: "Alle Artikel in diesem Blog sind unter %s lizenziert, außer es wird anders angegeben." +footer: + powered: "Erstellt mit %s" + total_views: Alle Aufrufe + total_visitors: Alle Besucher +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: Keine Schlagworte + one: Insgesamt ein Schlagwort + other: "Insgesamt %d Schlagwörter" + categories: + zero: Keine Kategorien + one: Insgesamt eine Kategorie + other: "Insgesamt %d Kategorien" + archive_posts: + zero: Keine Artikel vorhanden. + one: Ein Artikel. + other: "Insgesamt %d Artikel." +state: + posts: Artikel + tags: schlagwörter + categories: Kategorien +search: + placeholder: Suche... + empty: "We didn't find any results for the search: %s" + hits_time: "%s results found in %s ms" + hits: "%s results found" +cheers: + um: Öhm.. + ok: OK + nice: Schön + good: Gut + great: Wunderbar + excellent: Exzellent +keep_on: Bleib dran. +symbol: + comma: ". " + period: ", " + colon: ": " +reward: + donate: Spenden + wechatpay: WeChat Bezahlung + alipay: Alipay + paypal: PayPal + bitcoin: Bitcoin + comment: Buy me a coffee +follow_me: + welcome: Willkommen zu meinen anderen Veröffentlichen Kanälen +accessibility: + nav_toggle: Navigationsleiste an/ausschalten + prev_page: Vorherige Seite + next_page: Nächste Seite + back_to_top: Back to top + select_lang: Select language +symbols_count_time: + count: Symbole im Artikel gezählt + count_total: Insgesamt gezählte Symbole + time: Lesezeit + time_total: Insgesamte Lesezeit + time_minutes: minuten. diff --git a/themes/next/languages/default.yml b/themes/next/languages/default.yml new file mode 100644 index 0000000..7fcfc3b --- /dev/null +++ b/themes/next/languages/default.yml @@ -0,0 +1 @@ +en.yml \ No newline at end of file diff --git a/themes/next/languages/en.yml b/themes/next/languages/en.yml new file mode 100644 index 0000000..67f6cad --- /dev/null +++ b/themes/next/languages/en.yml @@ -0,0 +1,119 @@ +name: English + +title: + archive: Archive + category: Category + tag: Tag + schedule: Schedule + +menu: + home: Home + archives: Archives + categories: Categories + tags: Tags + about: About + search: Search + schedule: Schedule + sitemap: Sitemap + commonweal: Commonweal 404 + +sidebar: + overview: Overview + toc: Table of Contents + links: Links + +post: + posted: Posted on + edited: Edited on + created: Created + modified: Modified + edit: Edit this post + in: In + read_more: Read more + untitled: Untitled + sticky: Sticky + views: Views + related_posts: Related Posts + copyright: + author: Post author + link: Post link + post_author: Written by + post_link: This article originally appeared on + license_title: Copyright Notice + license_content: "All articles in this blog are licensed under %s unless stating additionally." + +footer: + powered: "Powered by %s" + total_views: Total Views + total_visitors: Total Visitors + +widget: + github: Follow me on GitHub + chat: Chat + +counter: + tag_cloud: + zero: No tags + one: 1 tag in total + other: "%d tags in total" + + categories: + zero: No categories + one: 1 category in total + other: "%d categories in total" + + archive_posts: + zero: No posts. + one: 1 post. + other: "%d posts in total." + +state: + posts: posts + tags: tags + categories: categories + +search: + placeholder: Searching... + empty: "We didn't find any results for the search: %s" + hits_time: "%s results found in %s ms" + hits: "%s results found" + +cheers: + um: Um.. + ok: OK + nice: Nice + good: Good + great: Great + excellent: Excellent + +keep_on: Keep on posting. + +symbol: + comma: ", " + period: ". " + colon: ": " + +reward: + donate: Donate + wechatpay: WeChat Pay + alipay: Alipay + paypal: PayPal + bitcoin: Bitcoin + comment: Buy me a coffee + +follow_me: + welcome: Welcome to my other publishing channels + +accessibility: + nav_toggle: Toggle navigation bar + prev_page: Previous page + next_page: Next page + back_to_top: Back to top + select_lang: Select language + +symbols_count_time: + count: Word count in article + count_total: Word count total + time: Reading time + time_total: Reading time total + time_minutes: mins. diff --git a/themes/next/languages/es.yml b/themes/next/languages/es.yml new file mode 100644 index 0000000..7b7dfff --- /dev/null +++ b/themes/next/languages/es.yml @@ -0,0 +1,102 @@ +--- +name: Español +title: + archive: Archivo + category: Categoría + tag: Etiqueta + schedule: Calendario +menu: + home: Inicio + archives: Archivo + categories: Categorías + tags: Etiquetas + about: Sobre mi + search: Buscar + schedule: Calendario + sitemap: Mapa del sitio + commonweal: Commonweal 404 +sidebar: + overview: Inicio + toc: Tabla de contenidos + links: Links +post: + posted: Publicado el + edited: Editado el + created: Creado por + modified: Modificado por + edit: Editar esta entrada + in: En + read_more: Leer más + untitled: Sin título + sticky: Destacados + views: Visitas + related_posts: Entradas relacionadas + copyright: + author: Autor de la entrada + link: Enlace a la entrada + post_author: Escrito por + post_link: Este artículo apareció originalmente en + license_title: Copyright + license_content: "Todos los artículos de este blog están licenciados bajo %s a no ser que se especifique una licencia adicional." +footer: + powered: "Creado mediante %s" + total_views: Visitas totales + total_visitors: Visitantes totales +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: Sin etiquetas + one: 1 etiqueta en total + other: "%d etiquetas en total" + categories: + zero: Sin categorías + one: 1 categoría en total + other: "%d categorías en total" + archive_posts: + zero: Sin entradas. + one: 1 entrada. + other: "%d entradas en total." +state: + posts: entradas + tags: etiquetas + categories: categorías +search: + placeholder: Buscando... + empty: "No hemos encontrado ningún resultado para la búsqueda: %s" + hits_time: "%s resultados encontrados en %s ms" + hits: "%s resultados encontrados" +cheers: + um: Um.. + ok: Bueno + nice: Guai + good: Bien + great: Genial + excellent: Excelente +keep_on: Sigue posteando. +symbol: + comma: ", " + period: ". " + colon: ": " +reward: + donate: Donar + wechatpay: WeChat Pay + alipay: Alipay + paypal: PayPal + bitcoin: Bitcoin + comment: Buy me a coffee +follow_me: + welcome: Bienvenido a mis otros canales +accessibility: + nav_toggle: Cambiar a barra de navegación + prev_page: Página anterior + next_page: Página siguiente + back_to_top: Volver al principio + select_lang: Seleccione el idioma +symbols_count_time: + count: Cantidad de caracteres en el articulo + count_total: Cantidad total de caracteres + time: Tiempo de lectura + time_total: Tiempo total de lectura + time_minutes: minutos. diff --git a/themes/next/languages/fa.yml b/themes/next/languages/fa.yml new file mode 100644 index 0000000..3d1856b --- /dev/null +++ b/themes/next/languages/fa.yml @@ -0,0 +1,102 @@ +--- +name: فارسی +title: + archive: بایگانی + category: دسته بندی + tag: برچسب + schedule: زمان بندی +menu: + home: صفحه اصلی + archives: بایگانی + categories: دسته بندی ها + tags: برچسب ها + about: درباره + search: جستجو + schedule: زمان بندی + sitemap: نقشه سایت + commonweal: Commonweal 404 +sidebar: + overview: نمای کلی + toc: فهرست مطالب + links: Links +post: + posted: نوشته شده در + edited: ویرایش شده در + created: ایجاد شده + modified: تغییر یافته + edit: ویرایش این پست + in: در + read_more: ادامه مطلب + untitled: بدون عنوان + sticky: چسبنده + views: بازدیدها + related_posts: پست های مرتبط + copyright: + author: نویسنده پست + link: لینک پست + post_author: Written by + post_link: This article originally appeared on + license_title: مقررات کپی رایت + license_content: "همه مقالات در این وبلاگ تحت %s مجاز می باشند مگر اینکه به طور اضافی بیان شوند." +footer: + powered: "قدرت گرفته از %s" + total_views: مجموع بازدیدها + total_visitors: تعداد بازدید کنندگان +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: بدون برچسب + one: 1 برچسب در مجموع + other: "%d برچسب در مجموع" + categories: + zero: بدون دسته بندی + one: 1 دسته بندی در مجموع + other: "%d دسته بندی در مجموع" + archive_posts: + zero: بدون پست. + one: 1 پست. + other: "%d برچسب در مجموع." +state: + posts: پست ها + tags: برجسب ها + categories: دسته بندی ها +search: + placeholder: جستجو... + empty: "We didn't find any results for the search: %s" + hits_time: "%s results found in %s ms" + hits: "%s results found" +cheers: + um: ام... + ok: باشه + nice: زیبا + good: خوب + great: عالی + excellent: بسیار عالی +keep_on: به پست دادن ادامه دهید. +symbol: + comma: ", " + period: ". " + colon: ": " +reward: + donate: کمک مالی + wechatpay: پرداخت WeChat + alipay: AliPay + paypal: PayPal + bitcoin: بیت کوین + comment: Buy me a coffee +follow_me: + welcome: Welcome to my other publishing channels +accessibility: + nav_toggle: تغییر ناوبری + prev_page: صفحه قبلی + next_page: صفحه بعدی + back_to_top: Back to top + select_lang: Select language +symbols_count_time: + count: تعداد نمادها در مقاله + count_total: تعداد کل نمادها + time: زمان خواندن + time_total: کل زمان خواندن + time_minutes: دقیقه. diff --git a/themes/next/languages/fr.yml b/themes/next/languages/fr.yml new file mode 100644 index 0000000..e7c1d1b --- /dev/null +++ b/themes/next/languages/fr.yml @@ -0,0 +1,102 @@ +--- +name: Français +title: + archive: Archive + category: Catégorie + tag: Mots clés + schedule: Plannifier +menu: + home: Accueil + archives: Archives + categories: Catégories + tags: Mots clés + about: À propos + search: Recherche + schedule: Plannifier + sitemap: Sitemap + commonweal: Commonweal 404 +sidebar: + overview: Aperçu + toc: Table Des Matières + links: Links +post: + posted: Posté le + edited: Édité le + created: Article créé le + modified: Mis à jour le + edit: Éditer cet article + in: dans + read_more: Lire la suite + untitled: Sans titre + sticky: Épingler + views: Vues + related_posts: Articles similaires + copyright: + author: Auteur de l'article + link: Lien de l'article + post_author: Written by + post_link: This article originally appeared on + license_title: Droit d'auteur + license_content: "Tous les articles de ce blog sont sous licence %s, sauf mention contraire." +footer: + powered: "Propulsé par %s" + total_views: Vues totales + total_visitors: Total visiteurs +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: Aucun tag + one: 1 tag au total + other: "%d tags au total" + categories: + zero: Aucune categorie + one: 1 catégorie au total + other: "%d catégories au total" + archive_posts: + zero: Aucun article. + one: 1 article. + other: "%d articles au total." +state: + posts: articles + tags: mots clé + categories: catégories +search: + placeholder: Recherche... + empty: "We didn't find any results for the search: %s" + hits_time: "%s results found in %s ms" + hits: "%s results found" +cheers: + um: Um.. + ok: OK + nice: Jolie + good: Bien + great: Super + excellent: Excellent +keep_on: Continue comme ça. +symbol: + comma: ", " + period: ". " + colon: ": " +reward: + donate: Donner + wechatpay: WeChat Pay + alipay: Alipay + paypal: PayPal + bitcoin: Bitcoin + comment: Buy me a coffee +follow_me: + welcome: Welcome to my other publishing channels +accessibility: + nav_toggle: Basculer la barre de navigation + prev_page: Page précédente + next_page: Page suivante + back_to_top: Back to top + select_lang: Select language +symbols_count_time: + count: Caractères dans l'article + count_total: Caractères total + time: Temps de lecture + time_total: Temps total de lecture + time_minutes: mins. diff --git a/themes/next/languages/id.yml b/themes/next/languages/id.yml new file mode 100644 index 0000000..5921a3d --- /dev/null +++ b/themes/next/languages/id.yml @@ -0,0 +1,102 @@ +--- +name: Bahasa Indonesia +title: + archive: Arsip + category: Kategori + tag: Tag + schedule: Schedule +menu: + home: Beranda + archives: Arsip + categories: Kategori + tags: Tags + about: Tentang + search: Pencarian + schedule: Schedule + sitemap: Sitemap + commonweal: Commonweal 404 +sidebar: + overview: Ikhtisar + toc: Daftar Isi + links: Links +post: + posted: Diposting di + edited: Edited on + created: Post created + modified: Updated at + edit: Edit this post + in: Di + read_more: Baca lebih + untitled: Tidak ada title + sticky: Sticky + views: Views + related_posts: Related Posts + copyright: + author: Post author + link: Post link + post_author: Written by + post_link: This article originally appeared on + license_title: Copyright Notice + license_content: "All articles in this blog are licensed under %s unless stating additionally." +footer: + powered: "Powered by %s" + total_views: Total Views + total_visitors: Total Visitors +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: Tidak ada tags + one: 1 total tag + other: "%d total tags" + categories: + zero: Tidak ada kategori + one: 1 total categori + other: "%d total kategori" + archive_posts: + zero: Tidak ada posting. + one: 1 posting. + other: "%d total posting." +state: + posts: posting + tags: tags + categories: kategori +search: + placeholder: Searching... + empty: "We didn't find any results for the search: %s" + hits_time: "%s results found in %s ms" + hits: "%s results found" +cheers: + um: Um.. + ok: OK + nice: Bagus + good: Bagus + great: Besar + excellent: Baik +keep_on: Terus Posting. +symbol: + comma: ", " + period: ". " + colon: ": " +reward: + donate: Donate + wechatpay: WeChat Pay + alipay: Alipay + paypal: PayPal + bitcoin: Bitcoin + comment: Buy me a coffee +follow_me: + welcome: Welcome to my other publishing channels +accessibility: + nav_toggle: Toggle navigation bar + prev_page: Halaman sebelumnya + next_page: Halaman selanjutnya + back_to_top: Back to top + select_lang: Select language +symbols_count_time: + count: Symbols count in article + count_total: Symbols count total + time: Reading time + time_total: Reading time total + time_minutes: mins. diff --git a/themes/next/languages/it.yml b/themes/next/languages/it.yml new file mode 100644 index 0000000..7d7b81a --- /dev/null +++ b/themes/next/languages/it.yml @@ -0,0 +1,102 @@ +--- +name: Italiano +title: + archive: Archivio + category: Categoria + tag: Tag + schedule: Programma +menu: + home: Home + archives: Archivi + categories: Categorie + tags: Tags + about: Informazioni su + search: Cerca + schedule: Programma + sitemap: Sitemap + commonweal: Commonweal 404 +sidebar: + overview: Panoramica + toc: Indice + links: Links +post: + posted: Scritto il + edited: Edited on + created: Post creato + modified: Post modificato + edit: Edit this post + in: In + read_more: Leggi di più + untitled: Senza titolo + sticky: Sticky + views: Views + related_posts: Related Posts + copyright: + author: Autore + link: Link + post_author: Written by + post_link: This article originally appeared on + license_title: Copyright + license_content: "Tutti gli articoli in questo sito sono sotto licenza %s salvo disposizione contraria." +footer: + powered: "Powered by %s" + total_views: Total Views + total_visitors: Total Visitors +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: Nessun tag + one: 1 tag in totale + other: "%d tags in totale." + categories: + zero: Nessuna categoria + one: 1 categoria in totale + other: "%d categorie in totale." + archive_posts: + zero: Nessun post. + one: 1 post. + other: "%d posts in totale." +state: + posts: posts + tags: tags + categories: categorie +search: + placeholder: Cerca... + empty: "We didn't find any results for the search: %s" + hits_time: "%s results found in %s ms" + hits: "%s results found" +cheers: + um: Mh.. + ok: OK + nice: Bello + good: Buono + great: Ottimo + excellent: Eccellente +keep_on: Continua così. +symbol: + comma: ", " + period: ". " + colon: ": " +reward: + donate: Dona + wechatpay: WeChat Pay + alipay: Alipay + paypal: PayPal + bitcoin: Bitcoin + comment: Buy me a coffee +follow_me: + welcome: Welcome to my other publishing channels +accessibility: + nav_toggle: Toggle navigation bar + prev_page: Pagina precedente + next_page: Pagina successiva + back_to_top: Back to top + select_lang: Select language +symbols_count_time: + count: Symbols count in article + count_total: Symbols count total + time: Reading time + time_total: Reading time total + time_minutes: mins. diff --git a/themes/next/languages/ja.yml b/themes/next/languages/ja.yml new file mode 100644 index 0000000..10c3292 --- /dev/null +++ b/themes/next/languages/ja.yml @@ -0,0 +1,102 @@ +--- +name: 日本語 +title: + archive: アーカイブ + category: カテゴリ + tag: タグ + schedule: スケジュール +menu: + home: ホーム + archives: アーカイブ + categories: カテゴリ + tags: タグ + about: プロフィール + search: 検索 + schedule: スケジュール + sitemap: サイトマップ + commonweal: 公益 404 +sidebar: + overview: 概要 + toc: 見出し + links: Links +post: + posted: 投稿日 + edited: 編集日 + created: 作成日 + modified: 修正日 + edit: この記事を編集する + in: カテゴリ + read_more: 続きを読む + untitled: 無題 + sticky: 固定 + views: 閲覧数 + related_posts: 関連記事 + copyright: + author: 著者 + link: 記事へのリンク + post_author: 作者 + post_link: 元の記事 + license_title: 著作権表示 + license_content: "このブログ内のすべての記事は、特別な記載がない限り %s の下のライセンスで保護されています。" +footer: + powered: "Powered by %s" + total_views: 閲覧合計数 + total_visitors: 合計閲覧者数 +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: タグなし + one: 全 1 タグ + other: "全 %d タグ" + categories: + zero: カテゴリなし + one: 全 1 カテゴリ + other: "全 %d カテゴリ" + archive_posts: + zero: ポストなし + one: 全 1 ポスト + other: "全 %d ポスト" +state: + posts: ポスト + tags: タグ + categories: カテゴリ +search: + placeholder: 検索… + empty: "検索結果が見つかりませんでした: %s" + hits_time: "%s の結果が %s ms で見つかりました" + hits: "%s 件の結果が見つかりました" +cheers: + um: うーん + ok: はい + nice: まあまあ + good: いいね + great: すごい + excellent: 最高 +keep_on: もっと書こう! +symbol: + comma: "、" + period: "。" + colon: ":" +reward: + donate: 寄付 + wechatpay: WeChat 支払う + alipay: Alipay + paypal: PayPal + bitcoin: ビットコイン + comment: Buy me a coffee +follow_me: + welcome: 他の公開チャンネルへようこそ +accessibility: + nav_toggle: ナビゲーションバーの切り替え + prev_page: 前のページ + next_page: 次のページ + back_to_top: Back to top + select_lang: Select language +symbols_count_time: + count: 単語数 + count_total: 単語の総数 + time: 読書の時間 + time_total: 読書の合計時間 + time_minutes: 分 diff --git a/themes/next/languages/ko.yml b/themes/next/languages/ko.yml new file mode 100644 index 0000000..53010ae --- /dev/null +++ b/themes/next/languages/ko.yml @@ -0,0 +1,102 @@ +--- +name: 한국어 +title: + archive: 아카이브 + category: 카테고리 + tag: 태그 + schedule: Schedule +menu: + home: 홈 + archives: 아카이브 + categories: 카테고리 + tags: 태그 + about: 정보 + search: 검색 + schedule: Schedule + sitemap: Sitemap + commonweal: Commonweal 404 +sidebar: + overview: 흝어보기 + toc: 목차 + links: Links +post: + posted: 작성일 + edited: Edited on + created: Post created + modified: Updated at + edit: Edit this post + in: In + read_more: 더 읽어보기 + untitled: 제목 없음 + sticky: 고정 + views: Views + related_posts: Related Posts + copyright: + author: 포스트 작성자 + link: Post link + post_author: Written by + post_link: This article originally appeared on + license_title: Copyright Notice + license_content: "All articles in this blog are licensed under %s unless stating additionally." +footer: + powered: "Powered by %s" + total_views: Total Views + total_visitors: Total Visitors +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: 태그 없음 + one: 1개의 태그 + other: "총 %d개의 태그" + categories: + zero: 카테고리 없음 + one: 1개의 카테고리 + other: "총 %d개의 카테고리" + archive_posts: + zero: 포스트 없음 + one: 1개의 포스트 + other: "총 %d개의 포스트" +state: + posts: 포스트 + tags: 태그 + categories: 카테고리 +search: + placeholder: Searching... + empty: "We didn't find any results for the search: %s" + hits_time: "%s results found in %s ms" + hits: "%s results found" +cheers: + um: 음.. + ok: 동의해요 + nice: 잘했어요 + good: 좋아요 + great: 훌륭해요 + excellent: 완벽해요 +keep_on: 포스트를 마저 작성하세요 +symbol: + comma: ", " + period: ". " + colon: ": " +reward: + donate: 도네이션 + wechatpay: WeChat Pay + alipay: Alipay + paypal: PayPal + bitcoin: 비트코인 + comment: Buy me a coffee +follow_me: + welcome: Welcome to my other publishing channels +accessibility: + nav_toggle: Toggle navigation bar + prev_page: 이전 페이지 + next_page: 다음 페이지 + back_to_top: Back to top + select_lang: Select language +symbols_count_time: + count: Symbols count in article + count_total: Symbols count total + time: Reading time + time_total: Reading time total + time_minutes: mins. diff --git a/themes/next/languages/nl.yml b/themes/next/languages/nl.yml new file mode 100644 index 0000000..617ee0a --- /dev/null +++ b/themes/next/languages/nl.yml @@ -0,0 +1,102 @@ +--- +name: Niederländisch +title: + archive: Archief + category: Categorie + tag: Label + schedule: Rooster +menu: + home: Home + archives: Archieven + categories: Categorieën + tags: Labels + about: Over + search: Zoeken + schedule: Rooster + sitemap: Sitemap + commonweal: Gezond verstand 404 +sidebar: + overview: Overzicht + toc: Inhoudsopgave + links: Links +post: + posted: Geplaatst op + edited: Edited on + created: Post aangemaakt + modified: Post aangepast + edit: Edit this post + in: In + read_more: Lees meer + untitled: Naamloos + sticky: Sticky + views: Views + related_posts: Related Posts + copyright: + author: Post auteur + link: Post link + post_author: Written by + post_link: This article originally appeared on + license_title: Copyright melding + license_content: "Alle artikelen op deze blog zijn gelicenseerd onder %s, mits niet anders aangegeven." +footer: + powered: "Mede mogelijk gemaakt door %s" + total_views: Total Views + total_visitors: Total Visitors +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: Geen labels + one: 1 label in totaal + other: "%d labels in totaal" + categories: + zero: Geen categorieën + one: 1 categorie in totaal + other: "%d categorieën in totaal" + archive_posts: + zero: Geen posts. + one: 1 post. + other: "%d posts in totaal." +state: + posts: posts + tags: labels + categories: categorieën +search: + placeholder: Zoeken... + empty: "We didn't find any results for the search: %s" + hits_time: "%s results found in %s ms" + hits: "%s results found" +cheers: + um: Um.. + ok: Oké + nice: Leuk + good: Goed + great: Geweldig + excellent: Uitstekend +keep_on: Blijf posten. +symbol: + comma: ", " + period: ". " + colon: ": " +reward: + donate: Doneer + wechatpay: WeChat Pay + alipay: Alipay + paypal: PayPal + bitcoin: Bitcoin + comment: Buy me a coffee +follow_me: + welcome: Welcome to my other publishing channels +accessibility: + nav_toggle: Toggle navigation bar + prev_page: Vorige pagina + next_page: Volgende pagina + back_to_top: Back to top + select_lang: Select language +symbols_count_time: + count: Symbols count in article + count_total: Symbols count total + time: Reading time + time_total: Reading time total + time_minutes: mins. diff --git a/themes/next/languages/pt-BR.yml b/themes/next/languages/pt-BR.yml new file mode 100644 index 0000000..f041f7b --- /dev/null +++ b/themes/next/languages/pt-BR.yml @@ -0,0 +1,102 @@ +--- +name: Português +title: + archive: Arquivo + category: Categoria + tag: Etiqueta + schedule: Programação +menu: + home: Home + archives: Arquivos + categories: Categorias + tags: Etiquetas + about: Sobre + search: Pesquisar + schedule: Programação + sitemap: Mapa do site + commonweal: Commonweal 404 +sidebar: + overview: Visão geral + toc: Índice + links: Links +post: + posted: Postado em + edited: Editado em + created: Criado em + modified: Modificado em + edit: Editar publicação + in: Em + read_more: Leia mais + untitled: Sem título + sticky: Fixo + views: Visualizações + related_posts: Publicações Relacionadas + copyright: + author: Autor da publicação + link: Link da publicação + post_author: Escrito por + post_link: Este artigo foi originalmente publicado em + license_title: Nota de Direitos Autorais + license_content: "Todos os artigos deste blog são licenciados sob %s, a menos que seja indicado o contrário." +footer: + powered: "Feito com %s" + total_views: Visualizações Totais + total_visitors: Total de visitantes +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: Sem etiquetas + one: 1 etiqueta no total de + other: "%d etiquetas no total de" + categories: + zero: Sem categoria + one: 1 categoria no total de + other: "%d categoria no total de" + archive_posts: + zero: Sem publicações. + one: 1 publicação. + other: "%d publicações no total." +state: + posts: publicações + tags: etiquetas + categories: categorias +search: + placeholder: Pesquisando... + empty: "Não encontramos nenhum resultado para a pesquisa: %s" + hits_time: "%s resultados encontrados em %s ms" + hits: "%s resultados encontrados" +cheers: + um: Uhmmmm... + ok: OK + nice: Bom + good: Muito Bom + great: Ótimo + excellent: Excelente +keep_on: Continue publicando. +symbol: + comma: ", " + period: ". " + colon: ": " +reward: + donate: Doar + wechatpay: WeChat Pay + alipay: Alipay + paypal: PayPal + bitcoin: Bitcoin + comment: Buy me a coffee +follow_me: + welcome: Bem-vindo aos meus outros canais de publicação +accessibility: + nav_toggle: Alternar barra de navegação + prev_page: Página anterior + next_page: Próxima página + back_to_top: Back to top + select_lang: Select language +symbols_count_time: + count: Contagem total de caracteres no artigo + count_total: Contagem total de caracteres + time: Tempo de leitura + time_total: Tempo total de leitura + time_minutes: mins. diff --git a/themes/next/languages/pt.yml b/themes/next/languages/pt.yml new file mode 100644 index 0000000..0880ca4 --- /dev/null +++ b/themes/next/languages/pt.yml @@ -0,0 +1,102 @@ +--- +name: Português +title: + archive: Arquivo + category: Categoria + tag: Tag + schedule: Schedule +menu: + home: Home + archives: Arquivos + categories: Categorias + tags: Tags + about: Sobre + search: Pesquisa + schedule: Schedule + sitemap: Sitemap + commonweal: Commonweal 404 +sidebar: + overview: Visão Geral + toc: Tabela de Conteúdo + links: Links +post: + posted: Postado em + edited: Edited on + created: Post created + modified: Updated at + edit: Edit this post + in: Em + read_more: Ler mais + untitled: Sem título + sticky: Sticky + views: Views + related_posts: Related Posts + copyright: + author: Post author + link: Post link + post_author: Written by + post_link: This article originally appeared on + license_title: Copyright Notice + license_content: "All articles in this blog are licensed under %s unless stating additionally." +footer: + powered: "Desenvolvido com amor com %s" + total_views: Total Views + total_visitors: Total Visitors +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: Sem tags + one: 1 tag no total + other: "%d tags no total" + categories: + zero: Sem categorias + one: 1 categoria no total + other: "%d categorias no total" + archive_posts: + zero: Sem publicações. + one: 1 post. + other: "%d publicações no total." +state: + posts: publicações + tags: tags + categories: categorias +search: + placeholder: Searching... + empty: "We didn't find any results for the search: %s" + hits_time: "%s results found in %s ms" + hits: "%s results found" +cheers: + um: Um.. + ok: OK + nice: Legal + good: Bom + great: Grandioso + excellent: Excelente +keep_on: Mantenha-se publicando! +symbol: + comma: ", " + period: ". " + colon: ": " +reward: + donate: Donate + wechatpay: WeChat Pay + alipay: Alipay + paypal: PayPal + bitcoin: Bitcoin + comment: Buy me a coffee +follow_me: + welcome: Welcome to my other publishing channels +accessibility: + nav_toggle: Toggle navigation bar + prev_page: Página anterior + next_page: Página seguinte + back_to_top: Back to top + select_lang: Select language +symbols_count_time: + count: Symbols count in article + count_total: Symbols count total + time: Reading time + time_total: Reading time total + time_minutes: mins. diff --git a/themes/next/languages/ru.yml b/themes/next/languages/ru.yml new file mode 100644 index 0000000..d20973d --- /dev/null +++ b/themes/next/languages/ru.yml @@ -0,0 +1,102 @@ +--- +name: Английский +title: + archive: Архив + category: Категория + tag: Тэг + schedule: Календарь +menu: + home: Главная + archives: Архив + categories: Категории + tags: Тэги + about: О сайте + search: Поиск + schedule: Планировщик + sitemap: Карта сайта + commonweal: Страница 404 +sidebar: + overview: Обзор + toc: Содержание + links: Links +post: + posted: Размещено + edited: Изменено + created: Создано + modified: Изменено + edit: Редактировать запись + in: В категории + read_more: Далее... + untitled: Безимянный + sticky: Ссылка + views: Просмотров + related_posts: Похожие записи + copyright: + author: Автор записи + link: Ссылка на запись + post_author: Авторы + post_link: Оригинал этой статьи был написан + license_title: Информация об авторских правах + license_content: "Все записи на этом сайте защищены лицензией %s, если не указано дополнительно." +footer: + powered: "Генератор — %s" + total_views: Всего просмотров + total_visitors: Всего посетителей +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: Нет тэгов. + one: 1 тэг. + other: "%d тэгов всего." + categories: + zero: Нет категорий. + one: 1 категория. + other: "%d категорий всего." + archive_posts: + zero: Нет записей. + one: 1 запись. + other: "%d записей всего." +state: + posts: Архив + tags: Тэги + categories: Категории +search: + placeholder: Поиск... + empty: "По запросу ничего не найдено: %s" + hits_time: "%s результатов найдено за %s мс" + hits: "%s результатов найдено" +cheers: + um: Эм.. + ok: ОК + nice: Неплохо + good: Хорошо + great: Замечательно + excellent: Великолепно +keep_on: Продолжаю писать. +symbol: + comma: ", " + period: ". " + colon: ": " +reward: + donate: Донат + wechatpay: WeChat Pay + alipay: Alipay + paypal: PayPal + bitcoin: Биткоин + comment: Buy me a coffee +follow_me: + welcome: Добро пожаловать на другие мои издательские каналы +accessibility: + nav_toggle: Показать/скрыть меню + prev_page: Предыдущая страница + next_page: Следующая страница + back_to_top: В начало + select_lang: Выберите язык +symbols_count_time: + count: Кол-во символов в статье + count_total: Общее кол-во символов + time: Время чтения + time_total: Общее время чтения + time_minutes: мин. diff --git a/themes/next/languages/si.yml b/themes/next/languages/si.yml new file mode 100644 index 0000000..41e77d1 --- /dev/null +++ b/themes/next/languages/si.yml @@ -0,0 +1,102 @@ +--- +name: සිංහල +title: + archive: සංරක්ෂිතය + category: ප්‍රවර්ගය + tag: ටැගය + schedule: කාලසටහන +menu: + home: මුල + archives: සංරක්ෂිත + categories: ප්‍රවර්ග + tags: ටැග + about: පිළිබඳව + search: සොයන්න + schedule: කාලසටහන + sitemap: අඩවි සිතියම + commonweal: සමස්ත ප්‍රජාව 404 +sidebar: + overview: සමස්ත දැක්ම + toc: පටුන + links: Links +post: + posted: පළ කළේ + edited: සංස්කරණය කළේ + created: හැදුවා + modified: සංස්කරණය කළා + edit: ලිපිය සංස්කරණය + in: තුළ + read_more: තව කියවන්න + untitled: නිර්නාමික + sticky: ඇලෙන + views: දර්ශන වාර + related_posts: ආශ්‍රිත ලිපි + copyright: + author: කර්තෘ + link: සබැඳිය + post_author: ලියන ලද්දේ + post_link: මේ ලිපිය මුළින්ම පළ වූයේ + license_title: හිමිකම් ප්‍රකාශය + license_content: "මෙහි සියලු ලිපි, අමතර සඳහනක් නොමැති තැන් වලදී, %s බලපත්‍රය යටතේ පවතී." +footer: + powered: "%s විසින් බල ගැන්වේ" + total_views: සියලු දර්ශන වාර + total_visitors: සියලු අමුත්තන් +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: ටැග නැත + one: 1 ටැගයක් ඇත + other: "ටැග %dක් ඇත" + categories: + zero: ප්‍රවර්ග නැත + one: 1 ප්‍රවර්ගයක් ඇත + other: "ප්‍රවර්ග %dක් ඇත" + archive_posts: + zero: ලිපි නැත. + one: 1 ලිපියක්. + other: "ලිපි %dක් ඇත." +state: + posts: ලිපි + tags: ටැග + categories: ප්‍රවර්ග +search: + placeholder: සොයමින්... + empty: "%s ගැන සෙවීමෙන් ප්‍රතිඵල හමු නොවුණි" + hits_time: "ප්‍රතිඵල %s සඳහා %s ms ගතවිය" + hits: "ප්‍රතිඵල %s හමු විය" +cheers: + um: ඇත්ත වශයෙන්ම.. + ok: හරි + nice: කදිමයි + good: හොඳයි + great: නියමයි + excellent: විශිෂ්ටයි +keep_on: දිගටම පළ කරන්න. +symbol: + comma: ", " + period: ". " + colon: ": " +reward: + donate: පරිත්‍යාග කරන්න + wechatpay: වීචැට් පේ + alipay: අලිපේ + paypal: පේපෑල් + bitcoin: බිට්කොයින් + comment: Buy me a coffee +follow_me: + welcome: මගේ වෙනත් පළකිරීම් මාධ්‍ය වෙත සාදරයෙන් පිළිගනිමි +accessibility: + nav_toggle: යාත්‍රණය මාරු කිරීම + prev_page: පෙර පිටුව + next_page: පසු පිටුව + back_to_top: Back to top + select_lang: Select language +symbols_count_time: + count: ලිපියේ සංකේත ගණන + count_total: මුළු සංකේත ගණන + time: කියවුම් කාලය + time_total: මුළු කියවුම් කාලය + time_minutes: විනාඩි. diff --git a/themes/next/languages/th.yml b/themes/next/languages/th.yml new file mode 100644 index 0000000..8c60232 --- /dev/null +++ b/themes/next/languages/th.yml @@ -0,0 +1,102 @@ +--- +name: ประเทศไทย +title: + archive: คลังเก็บเอกสารสำคัญ + category: หมวดหมู่ + tag: แท็ก + schedule: กำหนดการ +menu: + home: บ้าน + archives: หอจดหมายเหตุ + categories: หมวดหมู่ + tags: แท็ก + about: เกี่ยวกับ + search: ค้นหา + schedule: กำหนดการ + sitemap: แผนผังเว็บไซต์ + commonweal: เครือจักรภพ404 +sidebar: + overview: ภาพรวม + toc: สารบัญ + links: Links +post: + posted: โพสต์เมื่อ + edited: แก้ไขเมื่อ + created: สร้าง + modified: ดัดแปลง + edit: แก้ไขโพสต์นี้ + in: ใน + read_more: อ่านเพิ่มเติม + untitled: ไม่มีชื่อ + sticky: เหนียว + views: มุมมอง + related_posts: กระทู้ที่เกี่ยวข้อง + copyright: + author: ผู้เขียนโพสต์ + link: โพสต์ลิงค์ + post_author: เขียนโดย + post_link: บทความนี้เดิมปรากฏบน + license_title: ประกาศเกี่ยวกับลิขสิทธิ์ + license_content: "บทความทั้งหมดในบล็อกนี้ได้รับอนุญาตภายใต้ %s เว้นแต่จะระบุไว้เพิ่มเติม" +footer: + powered: "ขับเคลื่อนโดย %s" + total_views: ยอดดูทั้งหมด + total_visitors: ผู้เข้าชมทั้งหมด +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: ไม่มีแท็ก + one: ทั้งหมด 1 แท็ก + other: "รวม %d แท็ก" + categories: + zero: ไม่มีหมวดหมู่ + one: ทั้งหมด 1 หมวดหมู่ + other: "ทั้งหมด %d หมวดหมู่" + archive_posts: + zero: ไม่มีโพสต์ + one: 1 โพสต์ + other: "ทั้งหมด %d โพสต์" +state: + posts: posts + tags: tags + categories: categories +search: + placeholder: กำลังค้นหา... + empty: "เราไม่พบผลลัพธ์ใด ๆ สำหรับการค้นหา: %s" + hits_time: "พบผลลัพธ์ %s ใน %s ms" + hits: "พบผลลัพธ์ %s" +cheers: + um: Um.. + ok: OK + nice: Nice + good: Good + great: Great + excellent: Excellent +keep_on: โพสต์ต่อไป. +symbol: + comma: ", " + period: ". " + colon: ": " +reward: + donate: Donate + wechatpay: WeChat Pay + alipay: Alipay + paypal: PayPal + bitcoin: Bitcoin + comment: Buy me a coffee +follow_me: + welcome: ยินดีต้อนรับสู่ช่องทางการเผยแพร่อื่นๆ ของฉัน +accessibility: + nav_toggle: สลับแถบนำทาง + prev_page: หน้าก่อน + next_page: หน้าต่อไป + back_to_top: กลับไปด้านบน + select_lang: เลือกภาษา +symbols_count_time: + count: สัญลักษณ์นับในบทความ + count_total: สัญลักษณ์นับรวม + time: เวลาอ่านหนังสือ + time_total: เวลาในการอ่านทั้งหมด + time_minutes: นาที diff --git a/themes/next/languages/tk.yml b/themes/next/languages/tk.yml new file mode 100644 index 0000000..1af4f85 --- /dev/null +++ b/themes/next/languages/tk.yml @@ -0,0 +1,102 @@ +--- +name: Türkmençe +title: + archive: Arhiw + category: Bölüm + tag: Teg + schedule: Kalendar +menu: + home: Baş sahypa + archives: Arhiw + categories: Bölümler + tags: Tegler + about: Saýt hakynda + search: Gözleg + schedule: Kalendar + sitemap: Saýtyň kartasy + commonweal: 404 sahypa +sidebar: + overview: Syn + toc: Mazmuny + links: Links +post: + posted: Goýuldy + edited: Üýtgedildi + created: Döredildi + modified: Üýtgedildi + edit: Redaktirle + in: bölümde + read_more: Dowamyny oka + untitled: Atlandyrylmadyk + sticky: Salgylanma + views: Görüldi + related_posts: Meňzeş makalalar + copyright: + author: Makalanyň awtory + link: Makala salgylanma + post_author: Written by + post_link: This article originally appeared on + license_title: Awtorlyk hukugy hakynda maglumat + license_content: "Eger-de goşmaça maglumat berilmedik bolsa, bu saýtdaky ähli maglumatlar %s lisenziýa bilen goragly." +footer: + powered: "Генератор — %s" + total_views: Görülme sany + total_visitors: Girilen sany +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: Teg ýok. + one: 1 teg. + other: "%d teg bar." + categories: + zero: Bölüm ýok. + one: 1 bölüm. + other: "%d bölüm bar." + archive_posts: + zero: Makala tapylmady. + one: 1 makala. + other: "%d makala bar." +state: + posts: Makalalar + tags: Tegler + categories: Bölümler +search: + placeholder: Gözleg... + empty: "We didn't find any results for the search: %s" + hits_time: "%s results found in %s ms" + hits: "%s results found" +cheers: + um: Hmm.. + ok: OK + nice: Erbet däl + good: Gowy + great: Bet + excellent: Örän gowy +keep_on: Ýazmagy dowam et. +symbol: + comma: ", " + period: ". " + colon: ": " +reward: + donate: Donat + wechatpay: WeChat Pay + alipay: Alipay + paypal: PayPal + bitcoin: Bitcoin + comment: Buy me a coffee +follow_me: + welcome: Meniň başga paýlaşma platformalarym +accessibility: + nav_toggle: Görkez/Gizle + prev_page: Öňki sahypa + next_page: Indiki sahypa + back_to_top: Back to top + select_lang: Select language +symbols_count_time: + count: Makalada symbollaryň mukdary + count_total: Symbollaryň umumy sany + time: Okalma wagty + time_total: Jemi okalma wagty + time_minutes: min. diff --git a/themes/next/languages/tr.yml b/themes/next/languages/tr.yml new file mode 100644 index 0000000..27a928b --- /dev/null +++ b/themes/next/languages/tr.yml @@ -0,0 +1,102 @@ +--- +name: Türk +title: + archive: Arşiv + category: Kategori + tag: Etiket + schedule: Program +menu: + home: Ana Sayfa + archives: Arşivler + categories: Kategoriler + tags: Etiketler + about: Hakkımda + search: Ara + schedule: Program + sitemap: Site Haritası + commonweal: Hata 404 +sidebar: + overview: Genel Bakış + toc: İçindekiler + links: Links +post: + posted: Yayınlandı + edited: Düzenlendi + created: Oluşturuldu + modified: Değiştirildi + edit: Bu gönderiyi düzenle + in: İçinde + read_more: Daha fazla oku + untitled: Başlıksız + sticky: Sabit + views: Görünümler + related_posts: İlgili Gönderiler + copyright: + author: Gönderiyi yazan + link: Gönderi bağlantısı + post_author: Written by + post_link: This article originally appeared on + license_title: Telif Hakkı Bildirimi + license_content: "Bu blogdaki tüm makaleler aksi belirtilmediği sürece %s altında lisanslıdır." +footer: + powered: "%s tarafından desteklenmektedir" + total_views: Toplam görüntülenme + total_visitors: Toplam Ziyaretçi +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: Etiket yok + one: Toplam 1 etiket + other: "Toplamda %d etiket" + categories: + zero: Kategori yok + one: Toplamda 1 kategori + other: "Toplamda %d kategori" + archive_posts: + zero: Gönderi yok. + one: 1 gönderi. + other: "Toplamda %d gönderi." +state: + posts: gönderiler + tags: etiketler + categories: kategoriler +search: + placeholder: Aranıyor... + empty: "We didn't find any results for the search: %s" + hits_time: "%s results found in %s ms" + hits: "%s results found" +cheers: + um: Um.. + ok: Tamam + nice: Güzel + good: İyi + great: Müthiş + excellent: Mükemmel +keep_on: Gönderiye devam. +symbol: + comma: ", " + period: ". " + colon: ": " +reward: + donate: Bağış + wechatpay: WeChat Pay + alipay: Alipay + paypal: PayPal + bitcoin: Bitcoin + comment: Buy me a coffee +follow_me: + welcome: Diğer yayıncılık kanallarıma hoşgeldiniz +accessibility: + nav_toggle: Gezinti çubuğunu değiştir + prev_page: Önceki sayfa + next_page: Sonraki sayfa + back_to_top: Back to top + select_lang: Select language +symbols_count_time: + count: Makalede sayılan semboller + count_total: Sayılan toplam semboller + time: Okuma Süresi + time_total: Toplamda Okuma Süresi + time_minutes: dk. diff --git a/themes/next/languages/uk.yml b/themes/next/languages/uk.yml new file mode 100644 index 0000000..887b5a0 --- /dev/null +++ b/themes/next/languages/uk.yml @@ -0,0 +1,102 @@ +--- +name: Український +title: + archive: Архів + category: Категорія + tag: Тег + schedule: Календар +menu: + home: Головна + archives: Архів + categories: Категорії + tags: Теги + about: Про сайт + search: Пошук + schedule: Календар + sitemap: Карта сайту + commonweal: Сторінка 404 +sidebar: + overview: Огляд + toc: Зміст + links: Links +post: + posted: Опубліковано + edited: Змінено + created: Створено + modified: Змінено + edit: Редагувати запис + in: в категорії + read_more: Читати повністю + untitled: Без імені + sticky: Посилання + views: Переглядів + related_posts: Схожі записи + copyright: + author: Автор запису + link: Посилання на запис + post_author: Written by + post_link: This article originally appeared on + license_title: Інформація про авторські права + license_content: "Всі записи на цьому сайті захищені ліцензією %s, якщо не вказано додатково." +footer: + powered: "Генератор — %s" + total_views: Всього переглядів + total_visitors: Всього відвідувачів +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: Немає тегів. + one: 1 тег. + other: "%d тегів всього." + categories: + zero: Немає категорій. + one: 1 категорія. + other: "%d категорій всього." + archive_posts: + zero: Немає записів. + one: 1 запис. + other: "%d записів всього." +state: + posts: Архів + tags: Теги + categories: Категорії +search: + placeholder: Пошук... + empty: "We didn't find any results for the search: %s" + hits_time: "%s results found in %s ms" + hits: "%s results found" +cheers: + um: Ем.. + ok: ОК + nice: Не погано + good: Добре + great: Чудово + excellent: Прекрасно +keep_on: Продовжую писати. +symbol: + comma: ", " + period: ". " + colon: ": " +reward: + donate: Донат + wechatpay: WeChat Pay + alipay: Alipay + paypal: PayPal + bitcoin: Bitcoin + comment: Buy me a coffee +follow_me: + welcome: Мої інші видавничі канали +accessibility: + nav_toggle: Показати/приховати меню + prev_page: Попередня сторінка + next_page: Наступна сторінка + back_to_top: Back to top + select_lang: Select language +symbols_count_time: + count: К-сть символів в статті + count_total: Загальна к-сть символів + time: Час читання + time_total: Загальний час читання + time_minutes: хв. diff --git a/themes/next/languages/vi.yml b/themes/next/languages/vi.yml new file mode 100644 index 0000000..cbb6519 --- /dev/null +++ b/themes/next/languages/vi.yml @@ -0,0 +1,102 @@ +--- +name: Tiếng Việt +title: + archive: Lưu Trữ + category: Phân Loại + tag: Thẻ + schedule: Danh Mục +menu: + home: Trang Chủ + archives: Lưu Trữ + categories: Đầu Mục + tags: Thẻ + about: Giới Thiệu + search: Tìm Kiếm + schedule: Danh Mục + sitemap: Bản đồ trang + commonweal: Commonwealth Act No. 404 +sidebar: + overview: Tổng Quan + toc: Mục Lục + links: Links +post: + posted: Tạo lúc + edited: Chỉnh sửa vào + created: Được tạo + modified: Được thay đổi + edit: Chính sửa bài viết này + in: Trong + read_more: Đọc tiếp + untitled: Không có tiêu đề + sticky: Đính + views: Lượt xem + related_posts: Các bài viết liên quan + copyright: + author: Người viết + link: Liên kết bài viết + post_author: Written by + post_link: This article originally appeared on + license_title: Chú ý bản quyền + license_content: "Tất cả bài viết trong blog này được đăng ký bởi %s trừ khi có thông báo bổ sung." +footer: + powered: "Cung cấp bởi %s" + total_views: Tổng số người xem + total_visitors: Tổng số truy cập +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: Không có thẻ nào + one: có 1 thẻ tất cả + other: "có %d thẻ tất cả" + categories: + zero: Không có trong mục nào + one: có 1 mục tất cả + other: "có %d mục tất cả" + archive_posts: + zero: Không có bài viết. + one: 1 bài viết. + other: "tổng số %d bài viết." +state: + posts: bài viết + tags: thẻ + categories: mục +search: + placeholder: Đang tìm... + empty: "We didn't find any results for the search: %s" + hits_time: "%s results found in %s ms" + hits: "%s results found" +cheers: + um: Um.. + ok: Đồng Ý + nice: Hay + good: Tốt + great: Tuyệt vời + excellent: Tuyệt cú mèo +keep_on: Giữ tiến độ nha. +symbol: + comma: ", " + period: ". " + colon: ": " +reward: + donate: Tài trợ + wechatpay: WeChat Pay + alipay: Alipay + paypal: Paypal + bitcoin: Bitcoin + comment: Buy me a coffee +follow_me: + welcome: Xin chào mừng đến với các kênh khác của tôi +accessibility: + nav_toggle: Thanh điều hướng chuyển đổi + prev_page: Trang trước + next_page: Trang sau + back_to_top: Back to top + select_lang: Select language +symbols_count_time: + count: Số biểu tượng trong bài viết + count_total: Tổng số biểu tượng + time: Thời lượng đọc + time_total: Tổng thời lượng đọc + time_minutes: phút. diff --git a/themes/next/languages/zh-CN.yml b/themes/next/languages/zh-CN.yml new file mode 100644 index 0000000..9c93caa --- /dev/null +++ b/themes/next/languages/zh-CN.yml @@ -0,0 +1,102 @@ +--- +name: 简体中文 +title: + archive: 归档 + category: 分类 + tag: 标签 + schedule: 日程表 +menu: + home: 首页 + archives: 归档 + categories: 分类 + tags: 标签 + about: 关于 + search: 搜索 + schedule: 日程表 + sitemap: 站点地图 + commonweal: 公益 404 +sidebar: + overview: 站点概览 + toc: 文章目录 + links: 链接 +post: + posted: 发表于 + edited: 更新于 + created: 创建时间 + modified: 修改时间 + edit: 编辑 + in: 分类于 + read_more: 阅读全文 + untitled: 未命名 + sticky: 置顶 + views: 阅读次数 + related_posts: 相关文章 + copyright: + author: 本文作者 + link: 本文链接 + post_author: 原作者 + post_link: 原文链接 + license_title: 版权声明 + license_content: "本博客所有文章除特别声明外,均采用 %s 许可协议。转载请注明出处!" +footer: + powered: "由 %s 强力驱动" + total_views: 总访问量 + total_visitors: 总访客量 +widget: + github: Follow me on GitHub + chat: 聊天 +counter: + tag_cloud: + zero: 暂无标签 + one: 目前共计 1 个标签 + other: "目前共计 %d 个标签" + categories: + zero: 暂无分类 + one: 目前共计 1 个分类 + other: "目前共计 %d 个分类" + archive_posts: + zero: 暂无日志。 + one: 目前共计 1 篇日志。 + other: "目前共计 %d 篇日志。" +state: + posts: 日志 + tags: 标签 + categories: 分类 +search: + placeholder: 搜索... + empty: "没有找到任何搜索结果:%s" + hits_time: "找到 %s 个搜索结果(用时 %s 毫秒)" + hits: "找到 %s 个搜索结果" +cheers: + um: 嗯.. + ok: 还行 + nice: 不错 + good: 很好 + great: 非常好 + excellent: 太棒了 +keep_on: 继续努力。 +symbol: + comma: "," + period: "。" + colon: ":" +reward: + donate: 赞赏 + wechatpay: 微信 + alipay: 支付宝 + paypal: PayPal + bitcoin: 比特币 + comment: Buy me a coffee +follow_me: + welcome: 欢迎关注我的其它发布渠道 +accessibility: + nav_toggle: 切换导航栏 + prev_page: 上一页 + next_page: 下一页 + back_to_top: 返回顶部 + select_lang: 选择语言 +symbols_count_time: + count: 本文字数 + count_total: 站点总字数 + time: 阅读时长 + time_total: 站点阅读时长 + time_minutes: 分钟 diff --git a/themes/next/languages/zh-HK.yml b/themes/next/languages/zh-HK.yml new file mode 100644 index 0000000..bc77b3a --- /dev/null +++ b/themes/next/languages/zh-HK.yml @@ -0,0 +1,102 @@ +--- +name: 繁體中文(香港) +title: + archive: 歸檔 + category: 分類 + tag: 標籤 + schedule: 日程表 +menu: + home: 首頁 + archives: 歸檔 + categories: 分類 + tags: 標籤 + about: 關於 + search: 檢索 + schedule: 日程表 + sitemap: 站點地圖 + commonweal: 公益 404 +sidebar: + overview: 本站概覽 + toc: 文章目錄 + links: Links +post: + posted: 發表於 + edited: 更新於 + created: 創建時間 + modified: 修改時間 + edit: 編輯 + in: 分類於 + read_more: 閱讀全文 + untitled: 未命名 + sticky: 置頂 + views: 閱讀次數 + related_posts: 相關文章 + copyright: + author: 博主 + link: 文章連結 + post_author: 已寫入 + post_link: 文章最初發表於 + license_title: 版權聲明 + license_content: "本網誌所有文章除特別聲明外,均採用 %s 許可協議。轉載請註明出處!" +footer: + powered: "由 %s 強力驅動" + total_views: 總瀏覽次數 + total_visitors: 訪客總數 +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: 暫無標籤 + one: 目前共有 1 個標籤 + other: "目前共有 %d 個標籤" + categories: + zero: 暫無分類 + one: 目前共有 1 個分類 + other: "目前共有 %d 個分類" + archive_posts: + zero: 暫無文章。 + one: 目前共有 1 篇文章。 + other: "目前共有 %d 篇文章。" +state: + posts: 文章 + tags: 標籤 + categories: 分類 +search: + placeholder: 搜索... + empty: "我們無法找到任何有關 %s 的搜索結果" + hits_time: "%s 結果在 %s 毫秒找到" + hits: "找到 %s 個結果" +cheers: + um: 嗯.. + ok: 還行 + nice: 好 + good: 很好 + great: 非常好 + excellent: 太棒了 +keep_on: 繼續努力。 +symbol: + comma: "," + period: "。" + colon: ":" +reward: + donate: 讚賞 + wechatpay: 微信支付 + alipay: 支付寶 + paypal: 貝寶 + bitcoin: 比特幣 + comment: Buy me a coffee +follow_me: + welcome: 歡迎關注我的其它發布渠道 +accessibility: + nav_toggle: 切換導航欄 + prev_page: 上一頁 + next_page: 下一頁 + back_to_top: 回到頂部 + select_lang: 選擇語言 +symbols_count_time: + count: 本文字數 + count_total: 站點總字數 + time: 閱讀時長 + time_total: 站點閱讀時長 + time_minutes: 分鍾 diff --git a/themes/next/languages/zh-TW.yml b/themes/next/languages/zh-TW.yml new file mode 100644 index 0000000..16731ef --- /dev/null +++ b/themes/next/languages/zh-TW.yml @@ -0,0 +1,102 @@ +--- +name: 繁體中文 +title: + archive: 歸檔 + category: 分類 + tag: 標籤 + schedule: 時間表 +menu: + home: 首頁 + archives: 歸檔 + categories: 分類 + tags: 標籤 + about: 關於 + search: 搜尋 + schedule: 時間表 + sitemap: 網站地圖 + commonweal: 公益 404 +sidebar: + overview: 本站概要 + toc: 文章目錄 + links: Links +post: + posted: 發表於 + edited: 更新於 + created: 創建時間 + modified: 修改時間 + edit: 編輯 + in: 分類於 + read_more: 閱讀全文 + untitled: 未命名 + sticky: 置頂 + views: 閱讀次數 + related_posts: 相關文章 + copyright: + author: 作者 + link: 文章連結 + post_author: 已寫入 + post_link: 文章最初發表於 + license_title: 版權聲明 + license_content: "本網誌所有文章除特別聲明外,均採用 %s 許可協議。轉載請註明出處!" +footer: + powered: "由 %s 強力驅動" + total_views: 總瀏覽次數 + total_visitors: 訪客總數 +widget: + github: Follow me on GitHub + chat: Chat +counter: + tag_cloud: + zero: 沒有標籤 + one: 目前共有 1 個標籤 + other: "目前共有 %d 個標籤" + categories: + zero: 沒有分類 + one: 目前共有 1 個分類 + other: "目前共有 %d 個分類" + archive_posts: + zero: 沒有文章。 + one: 目前共有 1 篇文章。 + other: "目前共有 %d 篇文章。" +state: + posts: 文章 + tags: 標籤 + categories: 分類 +search: + placeholder: 搜尋... + empty: "我們無法找到任何有關 %s 的搜索結果" + hits_time: "%s 找到 %s 個結果" + hits: "找到 %s 個結果" +cheers: + um: 嗯.. + ok: 還行 + nice: 好 + good: 很好 + great: 非常好 + excellent: 太棒了 +keep_on: 繼續努力。 +symbol: + comma: "," + period: "。" + colon: ":" +reward: + donate: 捐贈 + wechatpay: 微信支付 + alipay: 支付寶 + paypal: 貝寶 + bitcoin: 比特幣 + comment: Buy me a coffee +follow_me: + welcome: 歡迎關注我的其它發布渠道 +accessibility: + nav_toggle: 切換導航欄 + prev_page: 上一頁 + next_page: 下一頁 + back_to_top: 回到頂端 + select_lang: 選擇語言 +symbols_count_time: + count: 文章字數 + count_total: 總字數 + time: 所需閱讀時間 + time_total: 所需總閱讀時間 + time_minutes: 分鐘 diff --git a/themes/next/layout/_layout.njk b/themes/next/layout/_layout.njk new file mode 100644 index 0000000..a73e8d9 --- /dev/null +++ b/themes/next/layout/_layout.njk @@ -0,0 +1,52 @@ + + + + {{ partial('_partials/head/head.njk', {}, {cache: theme.cache.enable}) }} + {%- include '_partials/head/head-unique.njk' -%} + {% block title %}{% endblock %} + {{ partial('_third-party/analytics/index.njk', {}, {cache: theme.cache.enable}) }} + {{- next_inject('head') }} + + + + +
+ +
+
+
+ {%- include '_partials/header/index.njk' -%} +
+ {%- if theme.sidebar.display !== 'remove' %} + {% block sidebar %}{% endblock %} + {%- endif %} +
+ +
+ {%- include '_partials/header/sub-menu.njk' -%} + {% block content %}{% endblock %} + {%- include '_partials/comments.njk' -%} +
+
+ +
+ +
+ + {{ partial('_partials/widgets.njk', {}, {cache: theme.cache.enable}) }} + + {{ partial('_scripts/index.njk', {}, {cache: theme.cache.enable}) }} + {{ partial('_third-party/index.njk', {}, {cache: theme.cache.enable}) }} + {{ partial('_third-party/statistics/index.njk', {}, {cache: theme.cache.enable}) }} + + {%- include '_third-party/math/index.njk' -%} + {%- include '_third-party/quicklink.njk' -%} + + {{- next_inject('bodyEnd') }} + + diff --git a/themes/next/layout/_macro/post-collapse.njk b/themes/next/layout/_macro/post-collapse.njk new file mode 100644 index 0000000..b90a0e2 --- /dev/null +++ b/themes/next/layout/_macro/post-collapse.njk @@ -0,0 +1,41 @@ +{% macro render(posts) %} +{%- set current_year = '1970' %} +{%- for post in posts.toArray() %} + + {%- set year = date(post.date, 'YYYY') %} + + {%- if year !== current_year %} + {%- set current_year = year %} +
+ {{ current_year }} +
+ {%- endif %} + +
+
+ + +
+ {%- if post.link %}{# Link posts #} + {%- set postTitleIcon = '' %} + {%- set postText = post.title or post.link %} + {{ next_url(post.link, postText + postTitleIcon, {class: 'post-title-link post-title-link-external', itemprop: 'url'}) }} + {% else %} + + {%- endif %} +
+ + {{ post_gallery(post.photos) }} +
+
+ +{%- endfor %} +{% endmacro %} diff --git a/themes/next/layout/_macro/post.njk b/themes/next/layout/_macro/post.njk new file mode 100644 index 0000000..0d21e1b --- /dev/null +++ b/themes/next/layout/_macro/post.njk @@ -0,0 +1,159 @@ +{##################} +{### POST BLOCK ###} +{##################} +
+ {# Gallery support #} + {{ post_gallery(post.photos) }} + +
+ + + + + + + + + {%- if post.header !== false %} +
+ <{% if is_index %}h2{% else %}h1{% endif %} class="post-title{% if post.direction and post.direction.toLowerCase() === 'rtl' %} rtl{% endif %}" itemprop="name headline"> + {# Link posts #} + {%- if post.link %} + {%- if post.sticky > 0 %} + + + + {%- endif %} + {%- set postTitleIcon = '' %} + {%- set postText = post.title or post.link %} + {{- next_url(post.link, postText + postTitleIcon, {class: 'post-title-link post-title-link-external', itemprop: 'url'}) }} + {% elif is_index %} + {%- if post.sticky > 0 %} + + + + {%- endif %} + {{- next_url(post.path, post.title or __('post.untitled'), {class: 'post-title-link', itemprop: 'url'}) }} + {%- else %} + {{- post.title }} + {{- post_edit(post.source) }} + {%- endif %} + + + +
+ {%- endif %} + + {#################} + {### POST BODY ###} + {#################} +
+ {%- if is_index %} + {%- if post.description and theme.excerpt_description %} +

{{ post.description }}

+ + {%- if theme.read_more_btn %} +
+ + {{ __('post.read_more') }} » + +
+ {%- endif %} + + {% elif post.excerpt %} + {{ post.excerpt }} + + {%- if theme.read_more_btn %} +
+ + + + {{ __('post.read_more') }} » + +
+ {%- endif %} + + {% else %} + {{ post.content }} + {%- endif %} + {% else %} + {{ post.content }} + {%- endif %} +
+ + {#####################} + {### END POST BODY ###} + {#####################} + +
+ {%- if is_index %} +
+ {% else %} + {{- next_inject('postBodyEnd') }} + + {%- if post.reward_settings.enable %} + {{ partial('_partials/post/post-reward.njk') }} + {%- endif %} + + {%- if theme.creative_commons.license and theme.creative_commons.post and post.copyright !== false %} + {{ partial('_partials/post/post-copyright.njk') }} + {%- endif %} + + {%- if theme.follow_me %} + {{ partial('_partials/post/post-followme.njk', {}, {cache: theme.cache.enable}) }} + {%- endif %} + + {%- if post.tags and post.tags.length %} + {%- set tag_indicate = '' if theme.tag_icon else '#' %} + + {%- endif %} + + {{ partial('_partials/post/post-share.njk', {}, {cache: theme.cache.enable}) }} + + {%- if theme.post_navigation and (post.prev or post.next) %} + {%- set prev = post.prev if theme.post_navigation === 'right' else post.next %} + {%- set next = post.next if theme.post_navigation === 'right' else post.prev %} +
+
+ {%- if prev %} + + {%- endif %} +
+
+ {%- if next %} + + {%- endif %} +
+
+ {%- endif %} + + {%- endif %} +
+
+
+{######################} +{### END POST BLOCK ###} +{######################} diff --git a/themes/next/layout/_macro/sidebar.njk b/themes/next/layout/_macro/sidebar.njk new file mode 100644 index 0000000..1a0b17b --- /dev/null +++ b/themes/next/layout/_macro/sidebar.njk @@ -0,0 +1,77 @@ +{% macro render(display_toc) %} + +{% endmacro %} diff --git a/themes/next/layout/_partials/comments.njk b/themes/next/layout/_partials/comments.njk new file mode 100644 index 0000000..cbe3bc3 --- /dev/null +++ b/themes/next/layout/_partials/comments.njk @@ -0,0 +1,35 @@ +{%- if page.comments %} + {%- if theme.injects.comment.length == 1 %} + {%- set inject_item = theme.injects.comment[0] %} + {{ partial(inject_item.layout, inject_item.locals, inject_item.options) }} + {%- elif theme.injects.comment.length > 1 %} + {%- if theme.comments.style == 'buttons' %} +
+ {%- for inject_item in theme.injects.comment %} + {{ inject_item.locals.button }} + {%- endfor %} +
+ {%- for inject_item in theme.injects.comment %} +
+ {{ partial(inject_item.layout, inject_item.locals, inject_item.options) }} +
+ {%- endfor %} + {{- next_js('comments-buttons.js', { pjax: true }) }} + {%- elif theme.comments.style == 'tabs' %} +
+ +
+ {%- for inject_item in theme.injects.comment %} +
+ {{ partial(inject_item.layout, inject_item.locals, inject_item.options) }} +
+ {%- endfor %} +
+
+ {%- endif %} + {%- endif %} +{%- endif %} diff --git a/themes/next/layout/_partials/footer.njk b/themes/next/layout/_partials/footer.njk new file mode 100644 index 0000000..8b254bc --- /dev/null +++ b/themes/next/layout/_partials/footer.njk @@ -0,0 +1,84 @@ +{%- if theme.footer.beian.enable %} +
+ {{- next_url('https://beian.miit.gov.cn', theme.footer.beian.icp + ' ') }} + {%- if theme.footer.beian.gongan_icon_url %} + + {%- endif %} + {%- if theme.footer.beian.gongan_id and theme.footer.beian.gongan_num %} + {{- next_url('http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=' + theme.footer.beian.gongan_id, theme.footer.beian.gongan_num + ' ') }} + {%- endif %} +
+{%- endif %} + + + +{%- if config.symbols_count_time.total_symbols or config.symbols_count_time.total_time %} +
+ {%- if config.symbols_count_time.total_symbols %} + + {%- endif %} + + {%- if config.symbols_count_time.total_time %} + + {%- endif %} +
+{%- endif %} + +{%- if theme.busuanzi_count.enable %} +
+ {%- if theme.busuanzi_count.total_visitors %} + + {%- endif %} + + {%- if theme.busuanzi_count.total_views %} + + {%- endif %} +
+{%- endif %} + +{%- if theme.footer.powered %} +
+ {%- set next_site = 'https://theme-next.js.org' if theme.scheme === 'Gemini' else 'https://theme-next.js.org/' + theme.scheme | lower + '/' %} + {{- __('footer.powered', next_url('https://hexo.io', 'Hexo') + ' & ' + next_url(next_site, 'NexT.' + theme.scheme)) }} +
+{%- endif %} + +{{- next_inject('footer') }} diff --git a/themes/next/layout/_partials/head/head-unique.njk b/themes/next/layout/_partials/head/head-unique.njk new file mode 100644 index 0000000..e1587dd --- /dev/null +++ b/themes/next/layout/_partials/head/head-unique.njk @@ -0,0 +1,22 @@ +{%- if theme.open_graph.enable %} + {%- if theme.open_graph.options %} + {{ open_graph(theme.open_graph.options) }} + {%- else %} + {{ open_graph() }} + {%- endif %} +{%- endif %} + +{# https://github.com/theme-next/hexo-theme-next/issues/866 #} +{%- set canonical = url | replace(r/index\.html$/, '') %} +{%- if not config.permalink.endsWith('.html') %} + {%- set canonical = canonical | replace(r/\.html$/, '') %} +{%- endif %} + + +{# Exports some front-matter variables to Front-End #} +{# https://hexo.io/docs/variables.html #} +{{ next_data('page', next_config_unique()) }} + +{{ next_data('calendar', + theme.calendar if page.type === 'schedule' else '') +}} diff --git a/themes/next/layout/_partials/head/head.njk b/themes/next/layout/_partials/head/head.njk new file mode 100644 index 0000000..2919621 --- /dev/null +++ b/themes/next/layout/_partials/head/head.njk @@ -0,0 +1,67 @@ + + +{%- if theme.darkmode %} + + +{%- else %} + +{%- endif %} +{%- if config.meta_generator %} + {{- meta_generator() }} +{%- endif %} + +{%- if config.preconnect %} + +{%- endif %} +{{ next_pre() }} + +{%- if theme.favicon.apple_touch_icon %} + +{%- endif %} +{%- if theme.favicon.medium %} + +{%- endif %} +{%- if theme.favicon.small %} + +{%- endif %} +{%- if theme.favicon.safari_pinned_tab %} + +{%- endif %} +{%- if theme.favicon.android_manifest %} + +{%- endif %} + +{%- if theme.google_site_verification %} + +{%- endif %} +{%- if theme.bing_site_verification %} + +{%- endif %} +{%- if theme.yandex_site_verification %} + +{%- endif %} +{%- if theme.baidu_site_verification %} + +{%- endif %} + + + +{{ next_font() }} + +{{ next_vendors('fontawesome') }} + +{%- if theme.motion.enable %} + {{ next_vendors('animate_css') }} +{%- endif %} + +{%- if theme.fancybox %} + {{ next_vendors('fancybox_css') }} +{%- endif %} + +{%- if theme.pace.enable %} + {{ next_vendors('pace_css') }} + {{ next_vendors('pace_js') }} +{%- endif %} + +{{ next_data('main', next_config()) }} +{{- next_js('config.js') }} diff --git a/themes/next/layout/_partials/header/brand.njk b/themes/next/layout/_partials/header/brand.njk new file mode 100644 index 0000000..5f36198 --- /dev/null +++ b/themes/next/layout/_partials/header/brand.njk @@ -0,0 +1,37 @@ +
+ + +
+ {%- if theme.custom_logo and theme.scheme === 'Muse' %} + {{ title }} + {%- endif %} + + + + <{% if is_home() or is_archive() %}h1{% else %}p{% endif %} class="site-title">{{ title }} + + + {%- if subtitle %} +

{{ subtitle }}

+ {%- endif %} + {%- if theme.custom_logo and (theme.scheme === 'Gemini' or theme.scheme === 'Pisces') %} + {{ title }} + {%- endif %} +
+ + +
diff --git a/themes/next/layout/_partials/header/index.njk b/themes/next/layout/_partials/header/index.njk new file mode 100644 index 0000000..6326dd2 --- /dev/null +++ b/themes/next/layout/_partials/header/index.njk @@ -0,0 +1,7 @@ +{{ partial('_partials/header/brand.njk') }} + +{{ partial('_partials/header/menu.njk', {}, {cache: theme.cache.enable}) }} + +{{ partial('_partials/search/index.njk', {}, {cache: theme.cache.enable}) }} + +{{- next_inject('header') }} diff --git a/themes/next/layout/_partials/header/menu-item.njk b/themes/next/layout/_partials/header/menu-item.njk new file mode 100644 index 0000000..d9a21f0 --- /dev/null +++ b/themes/next/layout/_partials/header/menu-item.njk @@ -0,0 +1,28 @@ +{% macro render(node) %} + + {%- set itemURL = node.path %} + + +{% endmacro %} diff --git a/themes/next/layout/_partials/header/menu.njk b/themes/next/layout/_partials/header/menu.njk new file mode 100644 index 0000000..dad8057 --- /dev/null +++ b/themes/next/layout/_partials/header/menu.njk @@ -0,0 +1,19 @@ +{% import 'menu-item.njk' as menu_item with context %} + +{%- if theme.menu or theme.algolia_search.enable or theme.local_search.enable %} + +{%- endif %} diff --git a/themes/next/layout/_partials/header/sub-menu.njk b/themes/next/layout/_partials/header/sub-menu.njk new file mode 100644 index 0000000..0d738d1 --- /dev/null +++ b/themes/next/layout/_partials/header/sub-menu.njk @@ -0,0 +1,12 @@ +{% import '_partials/header/menu-item.njk' as menu_item with context %} + +{%- if theme.menu and is_page() %} + {%- set menus = next_menu(page.path) %} + {%- for menu in menus %} + + {%- endfor %} +{%- endif %} diff --git a/themes/next/layout/_partials/languages.njk b/themes/next/layout/_partials/languages.njk new file mode 100644 index 0000000..5b2140e --- /dev/null +++ b/themes/next/layout/_partials/languages.njk @@ -0,0 +1,16 @@ +{%- if theme.language_switcher and languages.length > 1 %} +
+ + +
+{%- endif %} diff --git a/themes/next/layout/_partials/page/breadcrumb.njk b/themes/next/layout/_partials/page/breadcrumb.njk new file mode 100644 index 0000000..a792c2b --- /dev/null +++ b/themes/next/layout/_partials/page/breadcrumb.njk @@ -0,0 +1,30 @@ +{%- set paths = page.path.split('/') %} +{%- set count = paths.length %} +{%- if count > 2 %} + {%- set link = '/' %} + +{%- endif %} diff --git a/themes/next/layout/_partials/page/categories.njk b/themes/next/layout/_partials/page/categories.njk new file mode 100644 index 0000000..5e0fa04 --- /dev/null +++ b/themes/next/layout/_partials/page/categories.njk @@ -0,0 +1,8 @@ +
+
+ {{ _p('counter.categories', site.categories.length) }} +
+
+ {{ list_categories() }} +
+
diff --git a/themes/next/layout/_partials/page/page-header.njk b/themes/next/layout/_partials/page/page-header.njk new file mode 100644 index 0000000..8e34f34 --- /dev/null +++ b/themes/next/layout/_partials/page/page-header.njk @@ -0,0 +1,15 @@ +
+ +

+ {{- page.title }} + {{- post_edit(page.source) }} +

+ + + +
diff --git a/themes/next/layout/_partials/page/schedule.njk b/themes/next/layout/_partials/page/schedule.njk new file mode 100644 index 0000000..f644f0e --- /dev/null +++ b/themes/next/layout/_partials/page/schedule.njk @@ -0,0 +1,3 @@ +
+
+{{- next_js('schedule.js', { pjax: true }) }} diff --git a/themes/next/layout/_partials/page/tags.njk b/themes/next/layout/_partials/page/tags.njk new file mode 100644 index 0000000..05effd2 --- /dev/null +++ b/themes/next/layout/_partials/page/tags.njk @@ -0,0 +1,16 @@ +
+
+ {{ _p('counter.tag_cloud', site.tags.length) }} +
+
+ {{ tagcloud({ + min_font: theme.tagcloud.min, + max_font: theme.tagcloud.max, + amount : theme.tagcloud.amount, + orderby : theme.tagcloud.orderby, + order : theme.tagcloud.order, + class : 'tag-cloud' + }) + }} +
+
diff --git a/themes/next/layout/_partials/pagination.njk b/themes/next/layout/_partials/pagination.njk new file mode 100644 index 0000000..2c782f0 --- /dev/null +++ b/themes/next/layout/_partials/pagination.njk @@ -0,0 +1,5 @@ +{%- if page.prev or page.next %} + +{%- endif %} diff --git a/themes/next/layout/_partials/post/post-copyright.njk b/themes/next/layout/_partials/post/post-copyright.njk new file mode 100644 index 0000000..19a9221 --- /dev/null +++ b/themes/next/layout/_partials/post/post-copyright.njk @@ -0,0 +1,29 @@ +{%- set ccIcon = '' %} +{%- set ccText = theme.creative_commons.license | upper %} + +
+
    +
  • + {%- if page.author %} + {{ __('post.copyright.post_author') + __('symbol.colon') }} + {{- page.author }} + {%- elif author %} + {{ __('post.copyright.author') + __('symbol.colon') }} + {{- author }} + {%- endif %} +
  • +
  • + {%- if page.post_link %} + {{ __('post.copyright.post_link') + __('symbol.colon') }} + {{ next_url(page.post_link, page.post_link, {title: page.title}) }} + {%- else %} + {{ __('post.copyright.link') + __('symbol.colon') }} + {{ next_url(page.permalink, page.permalink, {title: page.title}) }} + {%- endif %} +
  • +
  • + {{ __('post.copyright.license_title') + __('symbol.colon') }} + {{- __('post.copyright.license_content', next_url(ccURL, ccIcon + ccText)) }} +
  • +
+
diff --git a/themes/next/layout/_partials/post/post-followme.njk b/themes/next/layout/_partials/post/post-followme.njk new file mode 100644 index 0000000..74c4133 --- /dev/null +++ b/themes/next/layout/_partials/post/post-followme.njk @@ -0,0 +1,32 @@ +
+ {{ __('follow_me.welcome') }} + + +
diff --git a/themes/next/layout/_partials/post/post-meta.njk b/themes/next/layout/_partials/post/post-meta.njk new file mode 100644 index 0000000..9ca0dd5 --- /dev/null +++ b/themes/next/layout/_partials/post/post-meta.njk @@ -0,0 +1,107 @@ + diff --git a/themes/next/layout/_partials/post/post-related.njk b/themes/next/layout/_partials/post/post-related.njk new file mode 100644 index 0000000..df35d66 --- /dev/null +++ b/themes/next/layout/_partials/post/post-related.njk @@ -0,0 +1,18 @@ + + diff --git a/themes/next/layout/_partials/post/post-reward.njk b/themes/next/layout/_partials/post/post-reward.njk new file mode 100644 index 0000000..ff3c6cb --- /dev/null +++ b/themes/next/layout/_partials/post/post-reward.njk @@ -0,0 +1,18 @@ +
+
{{ __('reward.comment') }}
+ +
+ + {%- for name, image in theme.reward %} + {%- set builtin = ['wechatpay', 'alipay', 'paypal', 'bitcoin'] %} + {%- set translation = __('reward.' + name) if builtin.includes(name) else name %} +
+ {{ author }} {{ translation }} + {{ translation }} +
+ {%- endfor %} + +
+
diff --git a/themes/next/layout/_partials/post/post-share.njk b/themes/next/layout/_partials/post/post-share.njk new file mode 100644 index 0000000..9ec4d79 --- /dev/null +++ b/themes/next/layout/_partials/post/post-share.njk @@ -0,0 +1,5 @@ +{%- if theme.add_this_id %} + +{%- endif %} diff --git a/themes/next/layout/_partials/search/algolia-search.njk b/themes/next/layout/_partials/search/algolia-search.njk new file mode 100644 index 0000000..564f4d8 --- /dev/null +++ b/themes/next/layout/_partials/search/algolia-search.njk @@ -0,0 +1,14 @@ +
+ + + +
+ + + +
+
+

+
+
+
diff --git a/themes/next/layout/_partials/search/index.njk b/themes/next/layout/_partials/search/index.njk new file mode 100644 index 0000000..3ed8ae3 --- /dev/null +++ b/themes/next/layout/_partials/search/index.njk @@ -0,0 +1,11 @@ +{%- if theme.algolia_search.enable or theme.local_search.enable %} +
+ +
+{%- endif %} diff --git a/themes/next/layout/_partials/search/localsearch.njk b/themes/next/layout/_partials/search/localsearch.njk new file mode 100644 index 0000000..60e2eca --- /dev/null +++ b/themes/next/layout/_partials/search/localsearch.njk @@ -0,0 +1,18 @@ +
+ + + +
+ +
+ + + +
+
+
+ +
+
diff --git a/themes/next/layout/_partials/sidebar/site-overview.njk b/themes/next/layout/_partials/sidebar/site-overview.njk new file mode 100644 index 0000000..10b17b2 --- /dev/null +++ b/themes/next/layout/_partials/sidebar/site-overview.njk @@ -0,0 +1,81 @@ + + +{%- if theme.site_state %} +
+ +
+{%- endif %} + +{%- if theme.chat.enable and (theme.chatra.enable or theme.tidio.enable or theme.gitter.enable) %} + +{%- endif %} + +{%- if theme.social %} + +{%- endif %} + +{%- if theme.creative_commons.license and theme.creative_commons.sidebar %} +
+ {%- set ccImage = 'Creative Commons' %} + {{ next_url(ccURL, ccImage, {class: 'cc-opacity'}) }} +
+{%- endif %} diff --git a/themes/next/layout/_partials/widgets.njk b/themes/next/layout/_partials/widgets.njk new file mode 100644 index 0000000..a610477 --- /dev/null +++ b/themes/next/layout/_partials/widgets.njk @@ -0,0 +1,38 @@ +{# Widgets with fixed position #} + +{%- if theme.sidebar.display !== 'remove' and (theme.scheme === 'Muse' or theme.scheme === 'Mist') %} + + +{%- endif %} + +{%- if theme.back2top.enable and not theme.back2top.sidebar %} +
+ + 0% +
+{%- endif %} + +{%- if theme.reading_progress.enable %} +
+{%- endif %} + +{%- if theme.bookmark.enable %} + +{%- endif %} + +{%- if theme.github_banner.enable %} + {%- set github_URL = theme.github_banner.permalink %} + {%- set github_title = __('widget.github') %} + + {%- set github_image = '' %} + + {{ next_url(github_URL, github_image, {class: 'github-corner', title: github_title, "aria-label": github_title}) }} +{%- endif %} + + diff --git a/themes/next/layout/_scripts/index.njk b/themes/next/layout/_scripts/index.njk new file mode 100644 index 0000000..0a26e9f --- /dev/null +++ b/themes/next/layout/_scripts/index.njk @@ -0,0 +1,20 @@ +{%- include 'vendors.njk' -%} + +{{- next_js('comments.js') }} + +{{- next_js('utils.js') }} +{%- if theme.motion.enable %} + {{- next_js('motion.js') }} +{%- endif %} + +{%- if theme.scheme === 'Muse' or theme.scheme === 'Mist' %} + {{- next_js('schemes/muse.js') }} +{%- endif %} + +{{- next_js('next-boot.js') }} +{%- if theme.bookmark.enable %} + {{- next_js('bookmark.js') }} +{%- endif %} +{%- if theme.pjax %} + {{- next_js('pjax.js') }} +{%- endif %} diff --git a/themes/next/layout/_scripts/vendors.njk b/themes/next/layout/_scripts/vendors.njk new file mode 100644 index 0000000..fcfe57c --- /dev/null +++ b/themes/next/layout/_scripts/vendors.njk @@ -0,0 +1,7 @@ +{%- if theme.canvas_ribbon.enable %} + +{%- endif %} + +{%- for name in js_vendors() %} + {{ next_vendors(name) }} +{%- endfor %} diff --git a/themes/next/layout/_third-party/analytics/baidu-analytics.njk b/themes/next/layout/_third-party/analytics/baidu-analytics.njk new file mode 100644 index 0000000..4113fde --- /dev/null +++ b/themes/next/layout/_third-party/analytics/baidu-analytics.njk @@ -0,0 +1,4 @@ +{%- if theme.baidu_analytics %} + {{ next_js('third-party/analytics/baidu-analytics.js') }} + +{%- endif %} diff --git a/themes/next/layout/_third-party/analytics/cloudflare.njk b/themes/next/layout/_third-party/analytics/cloudflare.njk new file mode 100644 index 0000000..758c14d --- /dev/null +++ b/themes/next/layout/_third-party/analytics/cloudflare.njk @@ -0,0 +1,3 @@ +{%- if theme.cloudflare_analytics %} + +{%- endif %} diff --git a/themes/next/layout/_third-party/analytics/google-analytics.njk b/themes/next/layout/_third-party/analytics/google-analytics.njk new file mode 100644 index 0000000..4a16d00 --- /dev/null +++ b/themes/next/layout/_third-party/analytics/google-analytics.njk @@ -0,0 +1,7 @@ +{%- if theme.google_analytics.tracking_id %} + {%- if not theme.google_analytics.only_pageview %} + + {%- endif %} + {{ next_data('google_analytics', theme.google_analytics) }} + {{ next_js('third-party/analytics/google-analytics.js') }} +{%- endif %} diff --git a/themes/next/layout/_third-party/analytics/growingio.njk b/themes/next/layout/_third-party/analytics/growingio.njk new file mode 100644 index 0000000..58ba767 --- /dev/null +++ b/themes/next/layout/_third-party/analytics/growingio.njk @@ -0,0 +1,5 @@ +{%- if theme.growingio_analytics %} + + {{ next_data('growingio_analytics', theme.growingio_analytics) }} + {{ next_js('third-party/analytics/growingio.js') }} +{%- endif %} diff --git a/themes/next/layout/_third-party/analytics/index.njk b/themes/next/layout/_third-party/analytics/index.njk new file mode 100644 index 0000000..a94dc20 --- /dev/null +++ b/themes/next/layout/_third-party/analytics/index.njk @@ -0,0 +1,8 @@ +{%- include 'google-analytics.njk' -%} +{%- include 'baidu-analytics.njk' -%} +{%- include 'growingio.njk' -%} +{%- include 'cloudflare.njk' -%} +{%- include 'microsoft-clarity.njk' -%} +{%- include 'matomo.njk' -%} +{%- include 'umami.njk' -%} +{%- include 'plausible.njk' -%} diff --git a/themes/next/layout/_third-party/analytics/matomo.njk b/themes/next/layout/_third-party/analytics/matomo.njk new file mode 100644 index 0000000..b547f3f --- /dev/null +++ b/themes/next/layout/_third-party/analytics/matomo.njk @@ -0,0 +1,4 @@ +{%- if theme.matomo.enable %} + {{ next_data('matomo', theme.matomo) }} + {{ next_js('third-party/analytics/matomo.js') }} +{%- endif %} diff --git a/themes/next/layout/_third-party/analytics/microsoft-clarity.njk b/themes/next/layout/_third-party/analytics/microsoft-clarity.njk new file mode 100644 index 0000000..3fecde7 --- /dev/null +++ b/themes/next/layout/_third-party/analytics/microsoft-clarity.njk @@ -0,0 +1,9 @@ +{%- if theme.clarity_analytics %} + +{%- endif %} diff --git a/themes/next/layout/_third-party/analytics/plausible.njk b/themes/next/layout/_third-party/analytics/plausible.njk new file mode 100644 index 0000000..f8802d3 --- /dev/null +++ b/themes/next/layout/_third-party/analytics/plausible.njk @@ -0,0 +1,3 @@ +{%- if theme.plausible.enable %} + +{%- endif %} diff --git a/themes/next/layout/_third-party/analytics/umami.njk b/themes/next/layout/_third-party/analytics/umami.njk new file mode 100644 index 0000000..0dbc6d7 --- /dev/null +++ b/themes/next/layout/_third-party/analytics/umami.njk @@ -0,0 +1,3 @@ +{%- if theme.umami.enable %} + +{%- endif %} diff --git a/themes/next/layout/_third-party/chat/chatra.njk b/themes/next/layout/_third-party/chat/chatra.njk new file mode 100644 index 0000000..e3f6057 --- /dev/null +++ b/themes/next/layout/_third-party/chat/chatra.njk @@ -0,0 +1,3 @@ +{{ next_data('chatra', theme.chatra) }} +{{ next_js('third-party/chat/chatra.js') }} + diff --git a/themes/next/layout/_third-party/chat/gitter.njk b/themes/next/layout/_third-party/chat/gitter.njk new file mode 100644 index 0000000..0749bf7 --- /dev/null +++ b/themes/next/layout/_third-party/chat/gitter.njk @@ -0,0 +1,3 @@ +{{ next_data('gitter', theme.gitter) }} +{{ next_js('third-party/chat/gitter.js') }} + diff --git a/themes/next/layout/_third-party/chat/tidio.njk b/themes/next/layout/_third-party/chat/tidio.njk new file mode 100644 index 0000000..9aae62e --- /dev/null +++ b/themes/next/layout/_third-party/chat/tidio.njk @@ -0,0 +1,2 @@ + +{{ next_js('third-party/chat/tidio.js') }} diff --git a/themes/next/layout/_third-party/comments/changyan.njk b/themes/next/layout/_third-party/comments/changyan.njk new file mode 100644 index 0000000..9e6c1df --- /dev/null +++ b/themes/next/layout/_third-party/comments/changyan.njk @@ -0,0 +1,2 @@ +{{ next_data('changyan', theme.changyan) }} +{{ next_js('third-party/comments/changyan.js') }} diff --git a/themes/next/layout/_third-party/comments/disqus.njk b/themes/next/layout/_third-party/comments/disqus.njk new file mode 100644 index 0000000..c4dd0df --- /dev/null +++ b/themes/next/layout/_third-party/comments/disqus.njk @@ -0,0 +1,6 @@ +{{ next_data('disqus', theme.disqus, { + i18n: { + disqus: __('disqus') + } +}) }} +{{ next_js('third-party/comments/disqus.js') }} diff --git a/themes/next/layout/_third-party/comments/disqusjs.njk b/themes/next/layout/_third-party/comments/disqusjs.njk new file mode 100644 index 0000000..b7c74b8 --- /dev/null +++ b/themes/next/layout/_third-party/comments/disqusjs.njk @@ -0,0 +1,6 @@ +{{ next_vendors('disqusjs_css') }} + +{{ next_data('disqusjs', theme.disqusjs, { + js: theme.vendors.disqusjs_js +}) }} +{{ next_js('third-party/comments/disqusjs.js') }} diff --git a/themes/next/layout/_third-party/comments/giscus.njk b/themes/next/layout/_third-party/comments/giscus.njk new file mode 100644 index 0000000..ef67c0b --- /dev/null +++ b/themes/next/layout/_third-party/comments/giscus.njk @@ -0,0 +1,2 @@ +{{ next_data('giscus', theme.giscus) }} +{{ next_js('third-party/comments/giscus.js') }} diff --git a/themes/next/layout/_third-party/comments/gitalk.njk b/themes/next/layout/_third-party/comments/gitalk.njk new file mode 100644 index 0000000..a5dc0c8 --- /dev/null +++ b/themes/next/layout/_third-party/comments/gitalk.njk @@ -0,0 +1,7 @@ +{{ next_vendors('gitalk_css') }} + +{{ next_data('gitalk', theme.gitalk, { + js: theme.vendors.gitalk_js, + path_md5: gitalk_md5(page.path) +}) }} +{{ next_js('third-party/comments/gitalk.js') }} diff --git a/themes/next/layout/_third-party/comments/isso.njk b/themes/next/layout/_third-party/comments/isso.njk new file mode 100644 index 0000000..fd66292 --- /dev/null +++ b/themes/next/layout/_third-party/comments/isso.njk @@ -0,0 +1,2 @@ +{{ next_data('isso', theme.isso) }} +{{ next_js('third-party/comments/isso.js') }} diff --git a/themes/next/layout/_third-party/comments/livere.njk b/themes/next/layout/_third-party/comments/livere.njk new file mode 100644 index 0000000..b8a7c6f --- /dev/null +++ b/themes/next/layout/_third-party/comments/livere.njk @@ -0,0 +1 @@ +{{ next_js('third-party/comments/livere.js') }} diff --git a/themes/next/layout/_third-party/comments/utterances.njk b/themes/next/layout/_third-party/comments/utterances.njk new file mode 100644 index 0000000..b353527 --- /dev/null +++ b/themes/next/layout/_third-party/comments/utterances.njk @@ -0,0 +1,2 @@ +{{ next_data('utterances', theme.utterances) }} +{{ next_js('third-party/comments/utterances.js') }} diff --git a/themes/next/layout/_third-party/fancybox.njk b/themes/next/layout/_third-party/fancybox.njk new file mode 100644 index 0000000..12906db --- /dev/null +++ b/themes/next/layout/_third-party/fancybox.njk @@ -0,0 +1,3 @@ +{%- if theme.fancybox %} + {{ next_js('third-party/fancybox.js') }} +{%- endif %} diff --git a/themes/next/layout/_third-party/index.njk b/themes/next/layout/_third-party/index.njk new file mode 100644 index 0000000..1ffe9a6 --- /dev/null +++ b/themes/next/layout/_third-party/index.njk @@ -0,0 +1,20 @@ +{%- if theme.algolia_search.enable %} + {%- include 'search/algolia-search.njk' -%} +{%- elif theme.local_search.enable %} + {%- include 'search/localsearch.njk' -%} +{%- endif %} + +{%- if theme.chatra.enable %} + {%- include 'chat/chatra.njk' -%} +{%- elif theme.tidio.enable %} + {%- include 'chat/tidio.njk' -%} +{%- elif theme.gitter.enable %} + {%- include 'chat/gitter.njk' -%} +{%- endif %} + +{%- include 'tags/pdf.njk' -%} +{%- include 'tags/mermaid.njk' -%} + +{%- include 'fancybox.njk' -%} + +{%- include 'pace.njk' -%} diff --git a/themes/next/layout/_third-party/math/index.njk b/themes/next/layout/_third-party/math/index.njk new file mode 100644 index 0000000..39330aa --- /dev/null +++ b/themes/next/layout/_third-party/math/index.njk @@ -0,0 +1,26 @@ +{%- if theme.math.mathjax.enable or theme.math.katex.enable %} + {%- set enable_math = false %} + + {%- set is_index_has_math = false %} + + {# At home, check if there has `mathjax: true` post #} + {%- if is_home() and not theme.math.every_page %} + {%- for post in page.posts.toArray() %} + {%- if post.mathjax and not is_index_has_math %} + {%- set is_index_has_math = true %} + {%- endif %} + {%- endfor %} + {%- endif %} + + {%- if theme.math.every_page or is_index_has_math or page.mathjax %} + {%- set enable_math = true %} + {%- endif %} + + {{ next_data('enableMath', enable_math) }} + + {%- if theme.math.mathjax.enable %} + {%- include '_third-party/math/mathjax.njk' -%} + {% elif theme.math.katex.enable %} + {%- include '_third-party/math/katex.njk' -%} + {%- endif %} +{%- endif %} diff --git a/themes/next/layout/_third-party/math/katex.njk b/themes/next/layout/_third-party/math/katex.njk new file mode 100644 index 0000000..4c9faf6 --- /dev/null +++ b/themes/next/layout/_third-party/math/katex.njk @@ -0,0 +1,7 @@ +{{ next_vendors('katex') }} +{%- if theme.math.katex.copy_tex %} + {{ next_data('katex', { + copy_tex_js: theme.vendors.copy_tex_js + }) }} + {{ next_js('third-party/math/katex.js') }} +{%- endif %} diff --git a/themes/next/layout/_third-party/math/mathjax.njk b/themes/next/layout/_third-party/math/mathjax.njk new file mode 100644 index 0000000..fbe8923 --- /dev/null +++ b/themes/next/layout/_third-party/math/mathjax.njk @@ -0,0 +1,4 @@ +{{ next_data('mathjax', theme.math.mathjax, { + js: theme.vendors.mathjax +}) }} +{{ next_js('third-party/math/mathjax.js') }} diff --git a/themes/next/layout/_third-party/pace.njk b/themes/next/layout/_third-party/pace.njk new file mode 100644 index 0000000..e686eda --- /dev/null +++ b/themes/next/layout/_third-party/pace.njk @@ -0,0 +1,3 @@ +{%- if theme.pace.enable %} + {{ next_js('third-party/pace.js') }} +{%- endif %} diff --git a/themes/next/layout/_third-party/quicklink.njk b/themes/next/layout/_third-party/quicklink.njk new file mode 100644 index 0000000..e481809 --- /dev/null +++ b/themes/next/layout/_third-party/quicklink.njk @@ -0,0 +1,7 @@ +{%- if theme.quicklink.enable %} + {{ next_vendors('quicklink') }} + {{ next_data('quicklink', page.quicklink, { + url: url | replace(r/index\.html$/, '') + }) }} + {{ next_js('third-party/quicklink.js') }} +{%- endif %} diff --git a/themes/next/layout/_third-party/search/algolia-search.njk b/themes/next/layout/_third-party/search/algolia-search.njk new file mode 100644 index 0000000..f580847 --- /dev/null +++ b/themes/next/layout/_third-party/search/algolia-search.njk @@ -0,0 +1,4 @@ +{{ next_vendors('algolia_search') }} +{{ next_vendors('instant_search') }} + +{{- next_js('third-party/search/algolia-search.js') }} diff --git a/themes/next/layout/_third-party/search/localsearch.njk b/themes/next/layout/_third-party/search/localsearch.njk new file mode 100644 index 0000000..b3067e3 --- /dev/null +++ b/themes/next/layout/_third-party/search/localsearch.njk @@ -0,0 +1,2 @@ +{{ next_vendors('local_search') }} +{{ next_js('third-party/search/local-search.js') }} diff --git a/themes/next/layout/_third-party/statistics/busuanzi-counter.njk b/themes/next/layout/_third-party/statistics/busuanzi-counter.njk new file mode 100644 index 0000000..c759a59 --- /dev/null +++ b/themes/next/layout/_third-party/statistics/busuanzi-counter.njk @@ -0,0 +1,3 @@ +{%- if theme.busuanzi_count.enable %} + +{%- endif %} diff --git a/themes/next/layout/_third-party/statistics/firestore.njk b/themes/next/layout/_third-party/statistics/firestore.njk new file mode 100644 index 0000000..353d41c --- /dev/null +++ b/themes/next/layout/_third-party/statistics/firestore.njk @@ -0,0 +1,6 @@ +{%- if theme.firestore.enable %} + {{ next_vendors('firebase_app') }} + {{ next_vendors('firebase_firestore') }} + {{ next_data('firestore', theme.firestore) }} + {{ next_js('third-party/statistics/firestore.js') }} +{%- endif %} diff --git a/themes/next/layout/_third-party/statistics/index.njk b/themes/next/layout/_third-party/statistics/index.njk new file mode 100644 index 0000000..7efe565 --- /dev/null +++ b/themes/next/layout/_third-party/statistics/index.njk @@ -0,0 +1,3 @@ +{%- include 'busuanzi-counter.njk' -%} +{%- include 'firestore.njk' -%} +{%- include 'lean-analytics.njk' -%} diff --git a/themes/next/layout/_third-party/statistics/lean-analytics.njk b/themes/next/layout/_third-party/statistics/lean-analytics.njk new file mode 100644 index 0000000..5af2518 --- /dev/null +++ b/themes/next/layout/_third-party/statistics/lean-analytics.njk @@ -0,0 +1,4 @@ +{%- if theme.leancloud_visitors.enable %} + {{ next_data('leancloud_visitors', theme.leancloud_visitors) }} + {{ next_js('third-party/statistics/lean-analytics.js') }} +{%- endif %} diff --git a/themes/next/layout/_third-party/tags/mermaid.njk b/themes/next/layout/_third-party/tags/mermaid.njk new file mode 100644 index 0000000..143a23f --- /dev/null +++ b/themes/next/layout/_third-party/tags/mermaid.njk @@ -0,0 +1,6 @@ +{%- if theme.mermaid.enable %} + {{ next_data('mermaid', theme.mermaid, { + js: theme.vendors.mermaid + }) }} + {{ next_js('third-party/tags/mermaid.js') }} +{%- endif %} diff --git a/themes/next/layout/_third-party/tags/pdf.njk b/themes/next/layout/_third-party/tags/pdf.njk new file mode 100644 index 0000000..ff24788 --- /dev/null +++ b/themes/next/layout/_third-party/tags/pdf.njk @@ -0,0 +1,7 @@ +{%- if theme.pdf.enable %} + {{ next_data('pdf', { + object_url: theme.vendors.pdfobject, + url: url_for('lib/pdf/web/viewer.html') + }) }} + {{ next_js('third-party/tags/pdf.js') }} +{%- endif %} diff --git a/themes/next/layout/archive.njk b/themes/next/layout/archive.njk new file mode 100644 index 0000000..5fd22b8 --- /dev/null +++ b/themes/next/layout/archive.njk @@ -0,0 +1,48 @@ +{% extends '_layout.njk' %} +{% import '_macro/post-collapse.njk' as post_template with context %} +{% import '_macro/sidebar.njk' as sidebar_template with context %} + +{% block title %}{{ __('title.archive') }} | {{ title }}{% endblock %} + +{% block class %}archive posts-collapse{% endblock %} + +{% block content %} + + {#####################} + {### ARCHIVE BLOCK ###} + {#####################} +
+
+
+ {%- set posts_length = site.posts.length %} + {%- if posts_length > 210 %} + {%- set cheers = 'excellent' %} + {% elif posts_length > 130 %} + {%- set cheers = 'great' %} + {% elif posts_length > 80 %} + {%- set cheers = 'good' %} + {% elif posts_length > 50 %} + {%- set cheers = 'nice' %} + {% elif posts_length > 30 %} + {%- set cheers = 'ok' %} + {% else %} + {%- set cheers = 'um' %} + {%- endif %} + {{ __('cheers.' + cheers) }}! {{ _p('counter.archive_posts', site.posts.length) }} {{ __('keep_on') }} +
+ + {{ post_template.render(page.posts) }} + +
+
+ {#########################} + {### END ARCHIVE BLOCK ###} + {#########################} + + {%- include '_partials/pagination.njk' -%} + +{% endblock %} + +{% block sidebar %} + {{ sidebar_template.render(false) }} +{% endblock %} diff --git a/themes/next/layout/category.njk b/themes/next/layout/category.njk new file mode 100644 index 0000000..74d1367 --- /dev/null +++ b/themes/next/layout/category.njk @@ -0,0 +1,36 @@ +{% extends '_layout.njk' %} +{% import '_macro/post-collapse.njk' as post_template with context %} +{% import '_macro/sidebar.njk' as sidebar_template with context %} + +{% block title %}{{ __('title.category') }}: {{ page.category }} | {{ title }}{% endblock %} + +{% block class %}category posts-collapse{% endblock %} + +{% block content %} + + {######################} + {### CATEGORY BLOCK ###} + {######################} +
+
+
+

+ {{- page.category }} + {{ __('title.category') }} +

+
+ + {{ post_template.render(page.posts) }} +
+
+ {##########################} + {### END CATEGORY BLOCK ###} + {##########################} + + {%- include '_partials/pagination.njk' -%} + +{% endblock %} + +{% block sidebar %} + {{ sidebar_template.render(false) }} +{% endblock %} diff --git a/themes/next/layout/index.njk b/themes/next/layout/index.njk new file mode 100644 index 0000000..37b7c2a --- /dev/null +++ b/themes/next/layout/index.njk @@ -0,0 +1,20 @@ +{% extends '_layout.njk' %} +{% import '_macro/sidebar.njk' as sidebar_template with context %} + +{% block title %}{{ title }}{% if theme.index_with_subtitle and subtitle %} - {{ subtitle }}{% endif %}{% endblock %} + +{% block class %}index posts-expand{% endblock %} + +{% block content %} + + {%- for post in page.posts.toArray() %} + {{ partial('_macro/post.njk', {post: post, is_index: true}) }} + {%- endfor %} + + {%- include '_partials/pagination.njk' -%} + +{% endblock %} + +{% block sidebar %} + {{ sidebar_template.render(false) }} +{% endblock %} diff --git a/themes/next/layout/page.njk b/themes/next/layout/page.njk new file mode 100644 index 0000000..04690ae --- /dev/null +++ b/themes/next/layout/page.njk @@ -0,0 +1,54 @@ +{% extends '_layout.njk' %} +{% import '_macro/sidebar.njk' as sidebar_template with context %} + +{% block title %} + {%- set page_title_suffix = ' | ' + title %} + + {%- if page.type === 'categories' and not page.title %} + {{- __('title.category') + page_title_suffix }} + {%- elif page.type === 'tags' and not page.title %} + {{- __('title.tag') + page_title_suffix }} + {%- elif page.type === 'schedule' and not page.title %} + {{- __('title.schedule') + page_title_suffix }} + {%- else %} + {{- page.title + page_title_suffix }} + {%- endif %} +{% endblock %} + +{% block class %}page posts-expand{% endblock %} + +{% block content %} + + {##################} + {### PAGE BLOCK ###} + {##################} +
+ {%- include '_partials/page/page-header.njk' -%} + {#################} + {### PAGE BODY ###} + {#################} +
+ {%- if page.type === 'tags' %} + {%- include '_partials/page/tags.njk' -%} + {% elif page.type === 'categories' %} + {%- include '_partials/page/categories.njk' -%} + {% elif page.type === 'schedule' %} + {%- include '_partials/page/schedule.njk' -%} + {% else %} + {{ page.content }} + {%- endif %} +
+ {#####################} + {### END PAGE BODY ###} + {#####################} +
+ {%- include '_partials/page/breadcrumb.njk' -%} + {######################} + {### END PAGE BLOCK ###} + {######################} + +{% endblock %} + +{% block sidebar %} + {{ sidebar_template.render(page.toc.enable) }} +{% endblock %} diff --git a/themes/next/layout/post.njk b/themes/next/layout/post.njk new file mode 100644 index 0000000..89b2abb --- /dev/null +++ b/themes/next/layout/post.njk @@ -0,0 +1,16 @@ +{% extends '_layout.njk' %} +{% import '_macro/sidebar.njk' as sidebar_template with context %} + +{% block title %}{{ page.title }} | {{ title }}{% endblock %} + +{% block class %}post posts-expand{% endblock %} + +{% block content %} + + {{ partial('_macro/post.njk', {post: page}) }} + +{% endblock %} + +{% block sidebar %} + {{ sidebar_template.render(page.toc.enable) }} +{% endblock %} diff --git a/themes/next/layout/tag.njk b/themes/next/layout/tag.njk new file mode 100644 index 0000000..7bcc2ad --- /dev/null +++ b/themes/next/layout/tag.njk @@ -0,0 +1,36 @@ +{% extends '_layout.njk' %} +{% import '_macro/post-collapse.njk' as post_template with context %} +{% import '_macro/sidebar.njk' as sidebar_template with context %} + +{% block title %}{{ __('title.tag') }}: {{ page.tag }} | {{ title }}{% endblock %} + +{% block class %}tag posts-collapse{% endblock %} + +{% block content %} + + {#################} + {### TAG BLOCK ###} + {#################} +
+
+
+

+ {{- page.tag }} + {{ __('title.tag') }} +

+
+ + {{ post_template.render(page.posts) }} +
+
+ {#####################} + {### END TAG BLOCK ###} + {#####################} + + {%- include '_partials/pagination.njk' -%} + +{% endblock %} + +{% block sidebar %} + {{ sidebar_template.render(false) }} +{% endblock %} diff --git a/themes/next/package.json b/themes/next/package.json new file mode 100644 index 0000000..7792d9b --- /dev/null +++ b/themes/next/package.json @@ -0,0 +1,46 @@ +{ + "name": "hexo-theme-next", + "version": "8.14.1", + "description": "Elegant and powerful theme for Hexo.", + "main": "package.json", + "files": [ + "docs", + "languages", + "layout", + "scripts", + "source", + "_config.yml", + "_vendors.yml" + ], + "scripts": { + "eslint": "eslint scripts/ source/js test/", + "prepare": "node .githooks/install.js", + "stylint": "stylelint source/css/ --ip source/css/_common/scaffolding/highlight/index.styl", + "test": "mocha test/index.js", + "test-cov": "c8 npm test" + }, + "repository": "next-theme/hexo-theme-next", + "keywords": [ + "hexo", + "theme", + "next" + ], + "author": "NexT (https://theme-next.js.org)", + "license": "AGPL-3.0-or-later", + "bugs": { + "url": "https://github.com/next-theme/hexo-theme-next/issues" + }, + "homepage": "https://theme-next.js.org", + "devDependencies": { + "@next-theme/eslint-config": "0.0.3", + "c8": "7.12.0", + "chai": "4.3.7", + "eslint": "8.31.0", + "hexo": "6.3.0", + "hexo-renderer-marked": "6.0.0", + "js-yaml": "4.1.0", + "mocha": "10.2.0", + "stylelint": "14.16.1", + "stylelint-stylus": "0.17.0" + } +} diff --git a/themes/next/renovate.json b/themes/next/renovate.json new file mode 100644 index 0000000..5e2413d --- /dev/null +++ b/themes/next/renovate.json @@ -0,0 +1,5 @@ +{ + "extends": [ + "config:base" + ] +} diff --git a/themes/next/scripts/events/index.js b/themes/next/scripts/events/index.js new file mode 100644 index 0000000..22a5969 --- /dev/null +++ b/themes/next/scripts/events/index.js @@ -0,0 +1,32 @@ +/* global hexo */ + +'use strict'; + +hexo.extend.filter.register('before_generate', () => { + // Merge config + require('./lib/config')(hexo); + // Set vendors + require('./lib/vendors')(hexo); + // Add filter type `theme_inject` + require('./lib/injects')(hexo); + // Highlight + require('./lib/highlight')(hexo); + // Menu and sub menu + require('./lib/navigation')(hexo); +}, 0); + +hexo.on('ready', () => { + if (!/^(g|s)/.test(hexo.env.cmd) || process.argv.includes('--next-disable-banner')) return; + const { version } = require('../../package.json'); + hexo.log.info(`================================== + ███╗ ██╗███████╗██╗ ██╗████████╗ + ████╗ ██║██╔════╝╚██╗██╔╝╚══██╔══╝ + ██╔██╗ ██║█████╗ ╚███╔╝ ██║ + ██║╚██╗██║██╔══╝ ██╔██╗ ██║ + ██║ ╚████║███████╗██╔╝ ██╗ ██║ + ╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝ ╚═╝ +======================================== +NexT version ${version} +Documentation: https://theme-next.js.org +========================================`); +}); diff --git a/themes/next/scripts/events/lib/config.js b/themes/next/scripts/events/lib/config.js new file mode 100644 index 0000000..f04f158 --- /dev/null +++ b/themes/next/scripts/events/lib/config.js @@ -0,0 +1,44 @@ +'use strict'; + +const { deepMerge } = require('hexo-util'); + +module.exports = hexo => { + const data = hexo.locals.get('data'); + + if (data.next) { + hexo.log.warn('`next.yml` is deprecated. Please upgrade to Hexo 5 or later and use `_config.next.yml` instead.'); + hexo.log.warn('Documentation: https://theme-next.js.org/docs/getting-started/configuration.html'); + } + + const { cache, language_switcher } = hexo.theme.config; + const warning = function(...args) { + hexo.log.warn(`Since ${args[0]} is turned on, the ${args[1]} is disabled to avoid potential hazards.`); + }; + + if (cache && cache.enable && language_switcher) { + warning('language_switcher', 'caching'); + cache.enable = false; + } + if (cache && cache.enable && hexo.config.relative_link) { + warning('caching', '`relative_link` option in Hexo `_config.yml`'); + hexo.config.relative_link = false; + } + + // Custom languages support. Introduced in NexT v6.3.0. + if (data.languages) { + const { language } = hexo.config; + const { i18n } = hexo.theme; + + const mergeLang = lang => { + if (data.languages[lang]) i18n.set(lang, deepMerge(i18n.get([lang]), data.languages[lang])); + }; + + if (Array.isArray(language)) { + for (const lang of language) { + mergeLang(lang); + } + } else { + mergeLang(language); + } + } +}; diff --git a/themes/next/scripts/events/lib/highlight.js b/themes/next/scripts/events/lib/highlight.js new file mode 100644 index 0000000..4841ea1 --- /dev/null +++ b/themes/next/scripts/events/lib/highlight.js @@ -0,0 +1,28 @@ +'use strict'; + +const fs = require('fs'); +const { resolve, highlightTheme } = require('./utils'); + +function prismTheme(name) { + let file = resolve('prismjs', `themes/${name}.css`); + if (!fs.existsSync(file)) file = resolve('prism-themes', `themes/${name}.css`); + return file; +} + +module.exports = hexo => { + const { config } = hexo; + const theme = hexo.theme.config; + config.highlight.hljs = false; + config.prismjs = config.prismjs || {}; + theme.highlight = { + enable: config.highlight.enable && !config.prismjs.enable, + light : highlightTheme(theme.codeblock.theme.light), + dark : highlightTheme(theme.codeblock.theme.dark) + }; + theme.prism = { + enable: config.prismjs.enable, + light : prismTheme(theme.codeblock.prism.light), + dark : prismTheme(theme.codeblock.prism.dark), + number: resolve('prismjs', 'plugins/line-numbers/prism-line-numbers.css') + }; +}; diff --git a/themes/next/scripts/events/lib/injects.js b/themes/next/scripts/events/lib/injects.js new file mode 100644 index 0000000..a6c5ada --- /dev/null +++ b/themes/next/scripts/events/lib/injects.js @@ -0,0 +1,85 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const { points } = require('./utils'); +const defaultExtname = '.njk'; + +// Defining stylus types +class StylusInject { + constructor(base_dir) { + this.base_dir = base_dir; + this.files = []; + } + push(file) { + // Get absolute path base on hexo dir + this.files.push(path.resolve(this.base_dir, file)); + } +} + +// Defining view types +class ViewInject { + constructor(base_dir) { + this.base_dir = base_dir; + this.raws = []; + } + raw(name, raw, ...args) { + // Set default extname + if (path.extname(name) === '') { + name += defaultExtname; + } + this.raws.push({ name, raw, args }); + } + file(name, file, ...args) { + // Set default extname from file's extname + if (path.extname(name) === '') { + name += path.extname(file); + } + // Get absolute path base on hexo dir + this.raw(name, fs.readFileSync(path.resolve(this.base_dir, file), 'utf8'), ...args); + } +} + +// Init injects +function initInject(base_dir) { + const injects = {}; + points.styles.forEach(item => { + injects[item] = new StylusInject(base_dir); + }); + points.views.forEach(item => { + injects[item] = new ViewInject(base_dir); + }); + return injects; +} + +module.exports = hexo => { + // Exec theme_inject filter + const injects = initInject(hexo.base_dir); + hexo.execFilterSync('theme_inject', injects); + hexo.theme.config.injects = {}; + + // Inject stylus + points.styles.forEach(type => { + hexo.theme.config.injects[type] = injects[type].files; + }); + + // Inject views + points.views.forEach(type => { + const configs = Object.create(null); + hexo.theme.config.injects[type] = []; + // Add or override view. + injects[type].raws.forEach((injectObj, index) => { + const name = `inject/${type}/${injectObj.name}`; + hexo.theme.setView(name, injectObj.raw); + configs[name] = { + layout : name, + locals : injectObj.args[0], + options: injectObj.args[1], + order : injectObj.args[2] || index + }; + }); + // Views sort. + hexo.theme.config.injects[type] = Object.values(configs) + .sort((x, y) => x.order - y.order); + }); +}; diff --git a/themes/next/scripts/events/lib/navigation.js b/themes/next/scripts/events/lib/navigation.js new file mode 100644 index 0000000..33ac9d7 --- /dev/null +++ b/themes/next/scripts/events/lib/navigation.js @@ -0,0 +1,57 @@ +'use strict'; + +const { join } = require('path').posix; + +class TreeNode { + constructor(parent, path, name, icon) { + if (parent && !path.startsWith('http')) { + path = join(parent.path, path); + } + this.parent = parent; + this.children = []; + this.path = path; + this.name = name; + this.icon = icon; + } + + append(child) { + this.children.push(child); + } +} + +module.exports = hexo => { + const menu_map = new Map(); + const main_menu = []; + hexo.theme.config.menu_map = menu_map; + hexo.theme.config.main_menu = main_menu; + + function parse(menu, parent) { + if (!menu) return; + Object.entries(menu).forEach(([name, value]) => { + if (name.toLowerCase() === 'default') return; + let node; + if (typeof value === 'string') { + const [path, icon] = value.split('||').map(v => v.trim()); + node = new TreeNode(parent, path, name, icon); + } else if (typeof value === 'object') { + if (typeof value.default !== 'string') { + hexo.log.warn('Missing default entry for menu item:', name); + return; + } + const [path, icon] = value.default.split('||').map(v => v.trim()); + node = new TreeNode(parent, path, name, icon); + parse(value, node); + } + if (node) { + menu_map.set(node.path, node); + if (parent) { + parent.append(node); + } else { + main_menu.push(node); + } + } + }); + } + + parse(hexo.theme.config.menu); +}; diff --git a/themes/next/scripts/events/lib/utils.js b/themes/next/scripts/events/lib/utils.js new file mode 100644 index 0000000..f6484ac --- /dev/null +++ b/themes/next/scripts/events/lib/utils.js @@ -0,0 +1,84 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const css = require('css'); + +function resolve(name, file = '') { + let dir; + try { + dir = path.dirname(require.resolve(`${name}/package.json`)); + } catch (error) { + return ''; + } + return `${dir}/${file}`; +} + +function highlightTheme(name) { + const file = resolve('highlight.js', `styles/${name}.css`); + const content = fs.readFileSync(file, 'utf8'); + + let background = ''; + let foreground = ''; + css.parse(content).stylesheet.rules + .filter(rule => rule.type === 'rule' && rule.selectors.some(selector => selector.endsWith('.hljs'))) + .flatMap(rule => rule.declarations) + .forEach(declaration => { + if (declaration.property === 'background' || declaration.property === 'background-color') background = declaration.value; + else if (declaration.property === 'color') foreground = declaration.value; + }); + return { + file, + background, + foreground + }; +} + +function getVendors({ name, alias, version, file, minified, local, custom }) { + // Make it possible to set `cdnjs_name` and `cdnjs_file` in `custom_cdn_url` + const npm_name = name; + const cdnjs_name = alias || name; + const npm_file = file; + const cdnjs_file = minified.replace(/^(dist|lib|source\/js|)\/(browser\/|)/, ''); + const value = { + npm_name, + cdnjs_name, + version, + npm_file, + minified, + cdnjs_file + }; + return { + local, + jsdelivr: `https://cdn.jsdelivr.net/npm/${npm_name}@${version}/${minified}`, + unpkg : `https://unpkg.com/${npm_name}@${version}/${npm_file}`, + cdnjs : `https://cdnjs.cloudflare.com/ajax/libs/${cdnjs_name}/${version}/${cdnjs_file}`, + custom : (custom || '').replace(/\$\{(.+?)\}/g, (match, $1) => value[$1]) + }; +} + +const points = { + views: [ + 'head', + 'header', + 'sidebar', + 'postMeta', + 'postBodyEnd', + 'footer', + 'bodyEnd', + 'comment' + ], + styles: [ + 'variable', + 'mixin', + 'style' + ] +}; + +// Required by theme-next-docs and @next-theme/plugins +module.exports = { + resolve, + highlightTheme, + getVendors, + points +}; diff --git a/themes/next/scripts/events/lib/vendors.js b/themes/next/scripts/events/lib/vendors.js new file mode 100644 index 0000000..0ecb55f --- /dev/null +++ b/themes/next/scripts/events/lib/vendors.js @@ -0,0 +1,55 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const yaml = require('js-yaml'); +const { url_for } = require('hexo-util'); +const { getVendors } = require('./utils'); + +let internal; +try { + internal = require('@next-theme/plugins'); +} catch (error) { +} +const vendorsFile = fs.readFileSync(path.join(__dirname, '../../../_vendors.yml')); +const dependencies = yaml.load(vendorsFile); + +module.exports = hexo => { + const { vendors, creative_commons, pace } = hexo.theme.config; + if (typeof internal === 'function') { + internal(hexo, dependencies); + } + for (const [key, value] of Object.entries(dependencies)) { + // This script will be executed repeatedly when Hexo listens file changes + // But the variable vendors[key] only needs to be modified once + if (vendors[key] && typeof vendors[key] === 'string') { + vendors[key] = { + url: url_for.call(hexo, vendors[key]) + }; + continue; + } + if (key === 'creative_commons') { + value.file = `${value.dir}/${creative_commons.size}/${creative_commons.license.replace(/-/g, '_')}.svg`; + } + if (key === 'pace_css') { + value.file = `${value.dir}/${pace.color}/pace-theme-${pace.theme}.css`; + } + const { name, file } = value; + const links = getVendors({ + ...value, + minified: file, + local : url_for.call(hexo, `lib/${name}/${file}`), + custom : vendors.custom_cdn_url + }); + let { plugins = 'cdnjs' } = vendors; + if (plugins === 'local' && typeof internal === 'undefined') { + hexo.log.warn('Dependencies for `plugins: local` not found. The default CDN provider CDNJS is used instead.'); + hexo.log.warn('Run `npm install @next-theme/plugins` in Hexo site root directory to install the plugin.'); + plugins = 'cdnjs'; + } + vendors[key] = { + url : links[plugins] || links.cdnjs, + integrity: value.integrity + }; + } +}; diff --git a/themes/next/scripts/filters/comment/changyan.js b/themes/next/scripts/filters/comment/changyan.js new file mode 100644 index 0000000..3e74cc2 --- /dev/null +++ b/themes/next/scripts/filters/comment/changyan.js @@ -0,0 +1,35 @@ +/* global hexo */ + +'use strict'; + +const path = require('path'); +const { iconText } = require('./common'); + +// Add comment +hexo.extend.filter.register('theme_inject', injects => { + const config = hexo.theme.config.changyan; + if (!config.enable || !config.appid || !config.appkey) return; + + injects.comment.raw('changyan', '
', {}, {}); + + injects.bodyEnd.file('changyan', path.join(hexo.theme_dir, 'layout/_third-party/comments/changyan.njk')); + +}); + +// Add post_meta +hexo.extend.filter.register('theme_inject', injects => { + const config = hexo.theme.config.changyan; + if (!config.enable || !config.count || !config.appid || !config.appkey) return; + + injects.postMeta.raw('changyan', ` + {% if post.comments %} + + {% endif %} + `, {}, {}); + +}); diff --git a/themes/next/scripts/filters/comment/common.js b/themes/next/scripts/filters/comment/common.js new file mode 100644 index 0000000..816d9bd --- /dev/null +++ b/themes/next/scripts/filters/comment/common.js @@ -0,0 +1,23 @@ +'use strict'; + +function capitalize(input) { + return input.toString().charAt(0).toUpperCase() + input.toString().substring(1); +} + +module.exports = { + iconText(icon, key, defaultValue) { + if (!defaultValue) { + defaultValue = capitalize(key); + } + return ` + + {%- set post_meta_comment = __('post.comments.${key}') %} + {%- if post_meta_comment == 'post.comments.${key}' %} + {%- set post_meta_comment = '${defaultValue}' %} + {%- endif %} + + `; + } +}; diff --git a/themes/next/scripts/filters/comment/default-config.js b/themes/next/scripts/filters/comment/default-config.js new file mode 100644 index 0000000..ae958bb --- /dev/null +++ b/themes/next/scripts/filters/comment/default-config.js @@ -0,0 +1,34 @@ +/* global hexo */ + +'use strict'; + +const path = require('path'); + +hexo.extend.filter.register('theme_inject', injects => { + injects.comment.raws.forEach(element => { + // Set default button content + const injectName = path.basename(element.name, path.extname(element.name)); + element.args[0] = Object.assign({ + configKey: injectName, + class : injectName, + button : injectName + }, element.args[0]); + // Get locals and config + const locals = element.args[0]; + const config = hexo.theme.config.comments; + // Set activeClass + if (config.active === locals.configKey) { + config.activeClass = locals.class; + } + // Set custom button content + if (config.nav) { + const nav = config.nav[locals.configKey] || {}; + if (nav.order) { + element.args[2] = nav.order; + } + if (nav.text) { + locals.button = nav.text; + } + } + }); +}, 99999); diff --git a/themes/next/scripts/filters/comment/disqus.js b/themes/next/scripts/filters/comment/disqus.js new file mode 100644 index 0000000..f7dda7a --- /dev/null +++ b/themes/next/scripts/filters/comment/disqus.js @@ -0,0 +1,39 @@ +/* global hexo */ + +'use strict'; + +const path = require('path'); +const { iconText } = require('./common'); + +// Add comment +hexo.extend.filter.register('theme_inject', injects => { + const config = hexo.theme.config.disqus; + if (!config.enable || !config.shortname) return; + + injects.comment.raw('disqus', ` +
+ +
+ `, {}, { cache: true }); + + injects.bodyEnd.file('disqus', path.join(hexo.theme_dir, 'layout/_third-party/comments/disqus.njk')); + +}); + +// Add post_meta +hexo.extend.filter.register('theme_inject', injects => { + const config = hexo.theme.config.disqus; + if (!config.enable || !config.shortname || !config.count) return; + + injects.postMeta.raw('disqus', ` + {% if post.comments %} + + {% endif %} + `, {}, {}); + +}); diff --git a/themes/next/scripts/filters/comment/disqusjs.js b/themes/next/scripts/filters/comment/disqusjs.js new file mode 100644 index 0000000..5673fc9 --- /dev/null +++ b/themes/next/scripts/filters/comment/disqusjs.js @@ -0,0 +1,20 @@ +/* global hexo */ + +'use strict'; + +const path = require('path'); + +// Add comment +hexo.extend.filter.register('theme_inject', injects => { + const config = hexo.theme.config.disqusjs; + if (!config.enable || !config.shortname || !config.apikey) return; + + injects.comment.raw('disqusjs', ` +
+ +
+ `, {}, { cache: true }); + + injects.bodyEnd.file('disqusjs', path.join(hexo.theme_dir, 'layout/_third-party/comments/disqusjs.njk')); + +}); diff --git a/themes/next/scripts/filters/comment/giscus.js b/themes/next/scripts/filters/comment/giscus.js new file mode 100644 index 0000000..5247d83 --- /dev/null +++ b/themes/next/scripts/filters/comment/giscus.js @@ -0,0 +1,17 @@ +/* global hexo */ + +'use strict'; + +const path = require('path'); + +// Add comment +hexo.extend.filter.register('theme_inject', injects => { + const config = hexo.theme.config.giscus; + // TODO: Add more attributes. + if (!config.enable) return; + + injects.comment.raw('giscus', '
', {}, { cache: true }); + + injects.bodyEnd.file('giscus', path.join(hexo.theme_dir, 'layout/_third-party/comments/giscus.njk')); + +}); diff --git a/themes/next/scripts/filters/comment/gitalk.js b/themes/next/scripts/filters/comment/gitalk.js new file mode 100644 index 0000000..2d2e253 --- /dev/null +++ b/themes/next/scripts/filters/comment/gitalk.js @@ -0,0 +1,16 @@ +/* global hexo */ + +'use strict'; + +const path = require('path'); + +// Add comment +hexo.extend.filter.register('theme_inject', injects => { + const theme = hexo.theme.config; + if (!theme.gitalk.enable) return; + + injects.comment.raw('gitalk', '
', {}, { cache: true }); + + injects.bodyEnd.file('gitalk', path.join(hexo.theme_dir, 'layout/_third-party/comments/gitalk.njk')); + +}); diff --git a/themes/next/scripts/filters/comment/isso.js b/themes/next/scripts/filters/comment/isso.js new file mode 100644 index 0000000..e80ee72 --- /dev/null +++ b/themes/next/scripts/filters/comment/isso.js @@ -0,0 +1,16 @@ +/* global hexo */ + +'use strict'; + +const path = require('path'); + +// Add comment +hexo.extend.filter.register('theme_inject', injects => { + const theme = hexo.theme.config; + if (!theme.isso) return; + + injects.comment.raw('isso', '
', {}, { cache: true }); + + injects.bodyEnd.file('isso', path.join(hexo.theme_dir, 'layout/_third-party/comments/isso.njk')); + +}); diff --git a/themes/next/scripts/filters/comment/livere.js b/themes/next/scripts/filters/comment/livere.js new file mode 100644 index 0000000..0f190c5 --- /dev/null +++ b/themes/next/scripts/filters/comment/livere.js @@ -0,0 +1,16 @@ +/* global hexo */ + +'use strict'; + +const path = require('path'); + +// Add comment +hexo.extend.filter.register('theme_inject', injects => { + const theme = hexo.theme.config; + if (!theme.livere_uid) return; + + injects.comment.raw('livere', '
', {}, { cache: true }); + + injects.bodyEnd.file('livere', path.join(hexo.theme_dir, 'layout/_third-party/comments/livere.njk')); + +}); diff --git a/themes/next/scripts/filters/comment/utterances.js b/themes/next/scripts/filters/comment/utterances.js new file mode 100644 index 0000000..6feebce --- /dev/null +++ b/themes/next/scripts/filters/comment/utterances.js @@ -0,0 +1,21 @@ +/* global hexo */ + +'use strict'; + +const path = require('path'); + +// Add comment +hexo.extend.filter.register('theme_inject', injects => { + const config = hexo.theme.config.utterances; + if (!config.enable) return; + + if (!config.repo) { + hexo.log.warn('utterances.repo can\'t be null.'); + return; + } + + injects.comment.raw('utterances', '
', {}, { cache: true }); + + injects.bodyEnd.file('utterances', path.join(hexo.theme_dir, 'layout/_third-party/comments/utterances.njk')); + +}); diff --git a/themes/next/scripts/filters/default-injects.js b/themes/next/scripts/filters/default-injects.js new file mode 100644 index 0000000..172558d --- /dev/null +++ b/themes/next/scripts/filters/default-injects.js @@ -0,0 +1,24 @@ +/* global hexo */ + +'use strict'; + +const { points } = require('../events/lib/utils'); + +hexo.extend.filter.register('theme_inject', injects => { + const filePath = hexo.theme.config.custom_file_path; + + if (!filePath) return; + + points.views.forEach(key => { + if (filePath[key]) { + injects[key].file('custom', filePath[key]); + } + }); + + points.styles.forEach(key => { + if (filePath[key]) { + injects[key].push(filePath[key]); + } + }); + +}, 99); diff --git a/themes/next/scripts/filters/locals.js b/themes/next/scripts/filters/locals.js new file mode 100644 index 0000000..b81f6ad --- /dev/null +++ b/themes/next/scripts/filters/locals.js @@ -0,0 +1,37 @@ +/* global hexo */ + +'use strict'; + +const keys = ['toc', 'reward_settings', 'quicklink']; + +hexo.extend.filter.register('template_locals', locals => { + const { config } = hexo; + const { __, theme, page } = locals; + const { i18n } = hexo.theme; + // Hexo & NexT version + locals.next_version = require('../../package.json').version; + // Language & Config + locals.title = __('title') !== 'title' ? __('title') : config.title; + locals.subtitle = __('subtitle') !== 'subtitle' ? __('subtitle') : config.subtitle; + locals.author = __('author') !== 'author' ? __('author') : config.author; + locals.description = __('description') !== 'description' ? __('description') : config.description; + locals.languages = [...i18n.languages]; + locals.languages.splice(locals.languages.indexOf('default'), 1); + // See https://github.com/hexojs/hexo/pull/4614 + page.lang = page.lang || page.language; + // Creative Commons + locals.ccURL = 'https://creativecommons.org/' + (theme.creative_commons.license === 'cc-zero' ? 'publicdomain/zero/1.0/' : 'licenses/' + theme.creative_commons.license + '/4.0/') + (theme.creative_commons.language || ''); + // PJAX + locals.pjax = theme.pjax ? ' data-pjax' : ''; + // Front-matter + keys.forEach(key => { + page[key] = { ...theme[key], ...page[key] }; + }); + // Set home or archive quicklink + if (page.__index) { + page.quicklink.enable = theme.quicklink.home; + } + if (page.archive) { + page.quicklink.enable = theme.quicklink.archive; + } +}); diff --git a/themes/next/scripts/filters/minify.js b/themes/next/scripts/filters/minify.js new file mode 100644 index 0000000..ceef2f7 --- /dev/null +++ b/themes/next/scripts/filters/minify.js @@ -0,0 +1,158 @@ +/* global hexo */ + +'use strict'; + +const internalScripts = []; + +hexo.theme.addProcessor('js/*', file => { + internalScripts.push(file.params[0]); +}); + +hexo.extend.filter.register('after_generate', () => { + const theme = hexo.theme.config; + if (!theme.minify) return; + + if (theme.vendors.internal !== 'local') { + // Remove all internal scripts + internalScripts.forEach(path => { + hexo.route.remove(path); + }); + return; + } + + if (!hexo.locals.get('pages').some(page => page.type === 'schedule')) { + hexo.route.remove('js/schedule.js'); + } + + if (!theme.bookmark.enable) { + hexo.route.remove('js/bookmark.js'); + } + + if (!theme.motion.enable) { + hexo.route.remove('js/motion.js'); + } + + if (!theme.pjax) { + hexo.route.remove('js/pjax.js'); + } + + if (theme.comments.style !== 'buttons') { + hexo.route.remove('js/comments-buttons.js'); + } + + if (theme.scheme === 'Pisces' || theme.scheme === 'Gemini') { + hexo.route.remove('js/schemes/muse.js'); + } + + // Third Party Scripts + // Analytics + if (!theme.baidu_analytics) { + hexo.route.remove('js/third-party/analytics/baidu-analytics.js'); + } + + if (!theme.google_analytics.tracking_id) { + hexo.route.remove('js/third-party/analytics/google-analytics.js'); + } + + if (!theme.growingio_analytics) { + hexo.route.remove('js/third-party/analytics/growingio.js'); + } + + // Chat + if (!theme.chatra.enable) { + hexo.route.remove('js/third-party/chat/chatra.js'); + } + + if (!theme.tidio.enable) { + hexo.route.remove('js/third-party/chat/tidio.js'); + } + + if (!theme.gitter.enable) { + hexo.route.remove('js/third-party/chat/gitter.js'); + } + + // Comments + if (!theme.changyan.enable || !theme.changyan.appid || !theme.changyan.appkey) { + hexo.route.remove('js/third-party/comments/changyan.js'); + } + + if (!theme.disqus.enable || !theme.disqus.shortname) { + hexo.route.remove('js/third-party/comments/disqus.js'); + } + + if (!theme.disqusjs.enable || !theme.disqusjs.shortname || !theme.disqusjs.apikey) { + hexo.route.remove('js/third-party/comments/disqusjs.js'); + } + + if (!theme.gitalk.enable) { + hexo.route.remove('js/third-party/comments/gitalk.js'); + } + + if (!theme.isso) { + hexo.route.remove('js/third-party/comments/isso.js'); + } + + if (!theme.livere_uid) { + hexo.route.remove('js/third-party/comments/livere.js'); + } + + if (!theme.utterances.enable || !theme.utterances.repo) { + hexo.route.remove('js/third-party/comments/utterances.js'); + } + + // MODIFIED + // TODO: Add more attributes. + if (!theme.giscus.enable) { + hexo.route.remove('js/third-party/comments/giscus.js'); + } + + // Math + if (!theme.math.katex.enable || !theme.math.katex.copy_tex) { + hexo.route.remove('js/third-party/math/katex.js'); + } + + if (!theme.math.mathjax.enable) { + hexo.route.remove('js/third-party/math/mathjax.js'); + } + + // Search + if (!theme.algolia_search.enable) { + hexo.route.remove('js/third-party/search/algolia-search.js'); + hexo.route.remove('images/logo-algolia-nebula-blue-full.svg'); + } + + if (!theme.local_search.enable) { + hexo.route.remove('js/third-party/search/local-search.js'); + } + + // Statistics + if (!theme.firestore.enable) { + hexo.route.remove('js/third-party/statistics/firestore.js'); + } + + if (!theme.leancloud_visitors.enable) { + hexo.route.remove('js/third-party/statistics/lean-analytics.js'); + } + + // Tags + if (!theme.mermaid.enable) { + hexo.route.remove('js/third-party/tags/mermaid.js'); + } + + if (!theme.pdf.enable) { + hexo.route.remove('js/third-party/tags/pdf.js'); + } + + // Others + if (!theme.fancybox) { + hexo.route.remove('js/third-party/fancybox.js'); + } + + if (!theme.pace.enable) { + hexo.route.remove('js/third-party/pace.js'); + } + + if (!theme.quicklink.enable) { + hexo.route.remove('js/third-party/quicklink.js'); + } +}); diff --git a/themes/next/scripts/filters/post.js b/themes/next/scripts/filters/post.js new file mode 100644 index 0000000..00162d0 --- /dev/null +++ b/themes/next/scripts/filters/post.js @@ -0,0 +1,36 @@ +/* global hexo */ + +'use strict'; + +const { parse } = require('url'); +const { unescapeHTML } = require('hexo-util'); + +hexo.extend.filter.register('after_post_render', data => { + const { config } = hexo; + const theme = hexo.theme.config; + if (!theme.exturl && !theme.lazyload) return; + if (theme.lazyload) { + data.content = data.content.replace(/(]*)\ssrc=/ig, '$1 data-src='); + } + if (theme.exturl) { + const siteHost = parse(config.url).hostname || config.url; + // External URL icon + const exturlIcon = theme.exturl_icon ? '' : ''; + data.content = data.content.replace(/]*\shref="([^"]+)"[^>]*>([^<]+)<\/a>/ig, (match, href, html) => { + // Exit if the href attribute doesn't exist. + if (!href) return match; + + // Exit if the url has same host with `config.url`, which means it's an internal link. + const link = parse(href); + if (!link.protocol || link.hostname === siteHost) return match; + + // Return encrypted URL with title. + const title = match.match(/title="([^"]+)"/); + const encoded = Buffer.from(unescapeHTML(href)).toString('base64'); + if (title) return `${html}${exturlIcon}`; + + return `${html}${exturlIcon}`; + }); + } + +}, 0); diff --git a/themes/next/scripts/helpers/engine.js b/themes/next/scripts/helpers/engine.js new file mode 100644 index 0000000..9b8fbd6 --- /dev/null +++ b/themes/next/scripts/helpers/engine.js @@ -0,0 +1,115 @@ +/* global hexo */ + +'use strict'; + +const crypto = require('crypto'); +const { parse } = require('url'); +const nextFont = require('./font'); +const nextUrl = require('./next-url'); +const { getVendors } = require('../events/lib/utils'); + +hexo.extend.helper.register('next_font', nextFont); +hexo.extend.helper.register('next_url', nextUrl); + +hexo.extend.helper.register('next_inject', function(point) { + return this.theme.injects[point] + .map(item => this.partial(item.layout, item.locals, item.options)) + .join(''); +}); + +hexo.extend.helper.register('next_js', function(file, { + pjax = false, + module = false +} = {}) { + const { next_version } = this; + const { internal, custom_cdn_url } = this.theme.vendors; + const links = getVendors({ + name : 'hexo-theme-next', + version : next_version, + file : 'source/js/' + file, + minified: 'source/js/' + file.replace(/\.js$/, '.min.js'), + local : this.url_for(`${this.theme.js}/${file}`), + custom : custom_cdn_url + }); + const src = links[internal] || links.local; + return ``; +}); + +hexo.extend.helper.register('next_vendors', function(name) { + const { url, integrity } = this.theme.vendors[name]; + const type = url.endsWith('css') ? 'css' : 'js'; + if (type === 'css') { + if (integrity) return ``; + return ``; + } + if (integrity) return ``; + return ``; +}); + +hexo.extend.helper.register('next_data', function(name, ...data) { + const json = data.length === 1 ? data[0] : Object.assign({}, ...data); + return ``; +}); + +hexo.extend.helper.register('next_pre', function() { + if (!this.theme.preconnect) return ''; + const { enable, host } = this.theme.font; + const { internal, plugins, custom_cdn_url } = this.theme.vendors; + const links = { + local : this.theme.js && parse(this.theme.js).hostname ? parse(this.theme.js).protocol + '//' + parse(this.theme.js).hostname : '', + jsdelivr: 'https://cdn.jsdelivr.net', + unpkg : 'https://unpkg.com', + cdnjs : 'https://cdnjs.cloudflare.com', + custom : custom_cdn_url && parse(custom_cdn_url).hostname ? parse(custom_cdn_url).protocol + '//' + parse(custom_cdn_url).hostname : '' + }; + const h = enable ? host || 'https://fonts.googleapis.com' : ''; + const i = links[internal]; + const p = links[plugins]; + return [...new Set([h, i, p].filter(origin => origin))].map( + origin => `` + ).join('\n'); +}); + +hexo.extend.helper.register('post_gallery', function(photos) { + if (!photos || !photos.length) return ''; + const content = photos.map(photo => ` +
+ +
`).join(''); + return `
+ ${content} +
`; +}); + +hexo.extend.helper.register('post_edit', function(src) { + const { post_edit } = this.theme; + if (!post_edit.enable) return ''; + return this.next_url(post_edit.url + src, '', { + class: 'post-edit-link', + title: this.__('post.edit') + }); +}); + +hexo.extend.helper.register('gitalk_md5', function(path) { + const str = this.url_for(path); + return crypto.createHash('md5').update(str).digest('hex'); +}); + +/** + * Get page path given a certain language tag + */ +hexo.extend.helper.register('i18n_path', function(language) { + const { path, lang } = this.page; + const base = path.startsWith(lang) ? path.slice(lang.length + 1) : path; + return this.url_for(`${this.languages.indexOf(language) === 0 ? '' : '/' + language}/${base}`); +}); + +/** + * Get the language name + */ +hexo.extend.helper.register('language_name', function(language) { + const name = hexo.theme.i18n.__(language)('name'); + return name === 'name' ? language : name; +}); diff --git a/themes/next/scripts/helpers/font.js b/themes/next/scripts/helpers/font.js new file mode 100644 index 0000000..d3cb649 --- /dev/null +++ b/themes/next/scripts/helpers/font.js @@ -0,0 +1,25 @@ +'use strict'; + +// https://developers.google.com/fonts/docs/getting_started +module.exports = function() { + const config = this.theme.font; + + if (!config || !config.enable) return ''; + + const fontStyles = ':300,300italic,400,400italic,700,700italic'; + const fontHost = config.host || 'https://fonts.googleapis.com'; + + // Get a font list from config + let fontFamilies = []; + ['global', 'title', 'headings', 'posts', 'codes'].forEach(item => { + if (config[item] && config[item].family && config[item].external) { + fontFamilies = fontFamilies.concat(config[item].family.split(',')); + } + }); + + fontFamilies = fontFamilies.map(name => name.trim().replace(/\s/g, '+') + fontStyles); + fontFamilies = [...new Set(fontFamilies)].join('%7C'); + + // Merge extra parameters to the final processed font string + return fontFamilies ? `` : ''; +}; diff --git a/themes/next/scripts/helpers/navigation.js b/themes/next/scripts/helpers/navigation.js new file mode 100644 index 0000000..095aa1a --- /dev/null +++ b/themes/next/scripts/helpers/navigation.js @@ -0,0 +1,19 @@ +/* global hexo */ + +'use strict'; + +hexo.extend.helper.register('next_menu', function(path) { + path = ('/' + path).replace(/index\.html$/, ''); + const { menu_map } = this.theme; + if (!menu_map.has(path)) return; + let node = menu_map.get(path); + const menus = []; + if (node.children.length) { + menus.unshift(node.children); + } + while (node.parent) { + menus.unshift(node.parent.children); + node = node.parent; + } + return menus; +}); diff --git a/themes/next/scripts/helpers/next-config.js b/themes/next/scripts/helpers/next-config.js new file mode 100644 index 0000000..fca6ef5 --- /dev/null +++ b/themes/next/scripts/helpers/next-config.js @@ -0,0 +1,64 @@ +/* global hexo */ + +'use strict'; + +const { parse } = require('url'); + +/** + * Export theme config + */ +hexo.extend.helper.register('next_config', function() { + const { config, theme, url_for, __ } = this; + const exportConfig = { + hostname : parse(config.url).hostname || config.url, + root : config.root, + images : url_for(theme.images), + scheme : theme.scheme, + darkmode : theme.darkmode, + version : this.next_version, + exturl : theme.exturl, + sidebar : theme.sidebar, + copycode : theme.codeblock.copy_button, + bookmark : theme.bookmark, + mediumzoom: theme.mediumzoom, + lazyload : theme.lazyload, + pangu : theme.pangu, + comments : theme.comments, + stickytabs: theme.tabs.sticky, + motion : theme.motion, + prism : config.prismjs.enable && !config.prismjs.preprocess, + i18n : { + placeholder: __('search.placeholder'), + empty : __('search.empty', '${query}'), + hits_time : __('search.hits_time', '${hits}', '${time}'), + hits : __('search.hits', '${hits}') + } + }; + if (config.algolia && theme.algolia_search && theme.algolia_search.enable) { + exportConfig.algolia = { + appID : config.algolia.applicationID || config.algolia.appId, + apiKey : config.algolia.apiKey, + indexName: config.algolia.indexName, + hits : theme.algolia_search.hits + }; + } + if (config.search && theme.local_search && theme.local_search.enable) { + exportConfig.path = url_for(config.search.path); + exportConfig.localsearch = theme.local_search; + } + return exportConfig; +}); + +hexo.extend.helper.register('next_config_unique', function() { + const { page, is_home, is_post } = this; + return { + sidebar : page.sidebar || '', + isHome : is_home(), + isPost : is_post(), + lang : page.lang, + comments : page.comments || '', + permalink: page.permalink || '', + path : page.path || '', + title : page.title || '' + }; +}); diff --git a/themes/next/scripts/helpers/next-paginator.js b/themes/next/scripts/helpers/next-paginator.js new file mode 100644 index 0000000..5825a3f --- /dev/null +++ b/themes/next/scripts/helpers/next-paginator.js @@ -0,0 +1,18 @@ +/* global hexo */ + +'use strict'; + +hexo.extend.helper.register('next_paginator', function() { + const prev = this.__('accessibility.prev_page'); + const next = this.__('accessibility.next_page'); + let paginator = this.paginator({ + prev_text: '', + next_text: '', + mid_size : 1, + escape : false + }); + paginator = paginator + .replace('rel="prev"', `rel="prev" title="${prev}" aria-label="${prev}"`) + .replace('rel="next"', `rel="next" title="${next}" aria-label="${next}"`); + return paginator; +}); diff --git a/themes/next/scripts/helpers/next-url.js b/themes/next/scripts/helpers/next-url.js new file mode 100644 index 0000000..c04510a --- /dev/null +++ b/themes/next/scripts/helpers/next-url.js @@ -0,0 +1,54 @@ +'use strict'; + +const { htmlTag } = require('hexo-util'); +const { parse } = require('url'); + +module.exports = function(path, text, options = {}) { + const { config, theme } = this; + const data = parse(path); + const siteHost = parse(config.url).hostname || config.url; + + let exturl = ''; + let tag = 'a'; + let attrs = { href: this.url_for(path) }; + + // If `exturl` enabled, set spanned links only on external links. + if (theme.exturl && data.protocol && data.hostname !== siteHost) { + tag = 'span'; + exturl = 'exturl'; + const encoded = Buffer.from(path).toString('base64'); + attrs = { + class : exturl, + 'data-url': encoded + }; + } + + for (const key in options) { + + /** + * If option have `class` attribute, add it to + * 'exturl' class if `exturl` option enabled. + */ + if (exturl !== '' && key === 'class') { + attrs[key] += ' ' + options[key]; + } else { + attrs[key] = options[key]; + } + } + + // If it's external link, rewrite attributes. + if (data.protocol && data.hostname !== siteHost) { + attrs.external = null; + + if (!theme.exturl) { + // Only for simple link need to rewrite/add attributes. + attrs.rel = attrs.rel || 'noopener'; + attrs.target = '_blank'; + } else { + // Remove rel attributes for `exturl` in main menu. + attrs.rel = null; + } + } + + return htmlTag(tag, attrs, decodeURI(text), false); +}; diff --git a/themes/next/scripts/helpers/next-vendors.js b/themes/next/scripts/helpers/next-vendors.js new file mode 100644 index 0000000..4ff9f7a --- /dev/null +++ b/themes/next/scripts/helpers/next-vendors.js @@ -0,0 +1,30 @@ +/* global hexo */ + +'use strict'; + +hexo.extend.helper.register('js_vendors', function() { + const { config, theme } = this; + const vendors = ['anime']; + if (config.prismjs.enable && !config.prismjs.preprocess) { + vendors.push('prism', 'prism_autoloader'); + if (config.prismjs.line_number) { + vendors.push('prism_line_numbers'); + } + } + if (theme.pjax) { + vendors.push('pjax'); + } + if (theme.fancybox) { + vendors.push('jquery', 'fancybox_js'); + } + if (theme.mediumzoom) { + vendors.push('mediumzoom'); + } + if (theme.lazyload) { + vendors.push('lazyload'); + } + if (theme.pangu) { + vendors.push('pangu'); + } + return vendors; +}); diff --git a/themes/next/scripts/tags/button.js b/themes/next/scripts/tags/button.js new file mode 100644 index 0000000..724674d --- /dev/null +++ b/themes/next/scripts/tags/button.js @@ -0,0 +1,23 @@ +/** + * button.js | https://theme-next.js.org/docs/tag-plugins/button + */ + +'use strict'; + +module.exports = ctx => function(args) { + args = args.join(' ').split(','); + const url = args[0]; + const text = (args[1] || '').trim(); + let icon = (args[2] || '').trim(); + const title = (args[3] || '').trim(); + + if (!url) { + ctx.log.warn('URL can NOT be empty.'); + } + if (icon.length > 0) { + if (!icon.startsWith('fa')) icon = 'fa fa-' + icon; + icon = ``; + } + + return ` 0 ? ` title="${title}"` : ''}>${icon}${text}`; +}; diff --git a/themes/next/scripts/tags/caniuse.js b/themes/next/scripts/tags/caniuse.js new file mode 100644 index 0000000..ba30292 --- /dev/null +++ b/themes/next/scripts/tags/caniuse.js @@ -0,0 +1,16 @@ +/** + * caniuse.js | https://theme-next.js.org/docs/tag-plugins/caniuse + */ + +'use strict'; + +module.exports = ctx => function(args) { + const [feature, periods = 'current'] = args.join('').split('@'); + + if (!feature) { + ctx.log.warn('Caniuse feature can NOT be empty.'); + return ''; + } + + return ``; +}; diff --git a/themes/next/scripts/tags/center-quote.js b/themes/next/scripts/tags/center-quote.js new file mode 100644 index 0000000..a6cdc12 --- /dev/null +++ b/themes/next/scripts/tags/center-quote.js @@ -0,0 +1,11 @@ +/** + * center-quote.js | https://theme-next.js.org/docs/tag-plugins/ + */ + +'use strict'; + +module.exports = ctx => function(args, content) { + return `
+${ctx.render.renderSync({ text: content, engine: 'markdown' })} +
`; +}; diff --git a/themes/next/scripts/tags/group-pictures.js b/themes/next/scripts/tags/group-pictures.js new file mode 100644 index 0000000..7dc9314 --- /dev/null +++ b/themes/next/scripts/tags/group-pictures.js @@ -0,0 +1,132 @@ +/** + * group-pictures.js | https://theme-next.js.org/docs/tag-plugins/group-pictures + */ + +'use strict'; + +const LAYOUTS = { + 2: { + 1: [1, 1], + 2: [2] + }, + 3: { + 1: [1, 2], + 2: [2, 1], + 3: [3] + }, + 4: { + 1: [1, 2, 1], + 2: [1, 3], + 3: [2, 2], + 4: [3, 1] + }, + 5: { + 1: [1, 2, 2], + 2: [2, 1, 2], + 3: [2, 3], + 4: [3, 2] + }, + 6: { + 1: [1, 2, 3], + 2: [1, 3, 2], + 3: [2, 1, 3], + 4: [2, 2, 2], + 5: [3, 3] + }, + 7: { + 1: [1, 2, 2, 2], + 2: [1, 3, 3], + 3: [2, 2, 3], + 4: [2, 3, 2], + 5: [3, 2, 2] + }, + 8: { + 1: [1, 2, 2, 3], + 2: [1, 2, 3, 2], + 3: [1, 3, 2, 2], + 4: [2, 2, 2, 2], + 5: [2, 3, 3], + 6: [3, 2, 3], + 7: [3, 3, 2] + }, + 9: { + 1: [1, 2, 3, 3], + 2: [1, 3, 2, 3], + 3: [2, 2, 2, 3], + 4: [2, 2, 3, 2], + 5: [2, 3, 2, 2], + 6: [3, 2, 2, 2], + 7: [3, 3, 3] + }, + 10: { + 1: [1, 3, 3, 3], + 2: [2, 2, 3, 3], + 3: [2, 3, 2, 3], + 4: [2, 3, 3, 2], + 5: [3, 2, 2, 3], + 6: [3, 2, 3, 2], + 7: [3, 3, 2, 2] + } +}; + +function groupBy(group, data) { + const r = []; + for (const count of group) { + r.push(data.slice(0, count)); + data = data.slice(count); + } + return r; +} + +const templates = { + + dispatch: function(pictures, group, layout) { + const rule = LAYOUTS[group] ? LAYOUTS[group][layout] : null; + return rule ? this.getHTML(groupBy(rule, pictures)) : this.defaults(pictures); + }, + + /** + * Defaults Layout + * + * □ □ □ + * □ □ □ + * ... + * + * @param pictures + */ + defaults: function(pictures) { + const ROW_SIZE = 3; + const rows = pictures.length / ROW_SIZE; + const pictureArr = []; + + for (let i = 0; i < rows; i++) { + pictureArr.push(pictures.slice(i * ROW_SIZE, (i + 1) * ROW_SIZE)); + } + + return this.getHTML(pictureArr); + }, + + getHTML: function(rows) { + return rows.map(row => { + return `
${this.getColumnHTML(row)}
`; + }).join(''); + }, + + getColumnHTML: function(pictures) { + return pictures.map(picture => { + return `
${picture}
`; + }).join(''); + } +}; + +module.exports = ctx => function(args, content) { + args = args[0].split('-'); + const group = parseInt(args[0], 10); + const layout = parseInt(args[1], 10); + + content = ctx.render.renderSync({ text: content, engine: 'markdown' }); + + const pictures = content.match(/(]*>((?!<\/a)(.|\n))+<\/a>)|(]+>)/g); + + return `
${templates.dispatch(pictures, group, layout)}
`; +}; diff --git a/themes/next/scripts/tags/index.js b/themes/next/scripts/tags/index.js new file mode 100644 index 0000000..089c436 --- /dev/null +++ b/themes/next/scripts/tags/index.js @@ -0,0 +1,55 @@ +/* global hexo */ + +'use strict'; + +const postButton = require('./button')(hexo); + +hexo.extend.tag.register('button', postButton); +hexo.extend.tag.register('btn', postButton); + +const caniUse = require('./caniuse')(hexo); + +hexo.extend.tag.register('caniuse', caniUse); +hexo.extend.tag.register('can', caniUse); + +const centerQuote = require('./center-quote')(hexo); + +hexo.extend.tag.register('centerquote', centerQuote, true); +hexo.extend.tag.register('cq', centerQuote, true); + +const groupPicture = require('./group-pictures')(hexo); + +hexo.extend.tag.register('grouppicture', groupPicture, true); +hexo.extend.tag.register('gp', groupPicture, true); + +const postLabel = require('./label')(hexo); + +hexo.extend.tag.register('label', postLabel); + +const linkGrid = require('./link-grid'); + +hexo.extend.tag.register('linkgrid', linkGrid, true); +hexo.extend.tag.register('lg', linkGrid, true); + +const mermaid = require('./mermaid'); + +hexo.extend.tag.register('mermaid', mermaid, true); + +const postNote = require('./note')(hexo); + +hexo.extend.tag.register('note', postNote, true); +hexo.extend.tag.register('subnote', postNote, true); + +const pdf = require('./pdf')(hexo); + +hexo.extend.tag.register('pdf', pdf); + +const postTabs = require('./tabs')(hexo); + +hexo.extend.tag.register('tabs', postTabs, true); +hexo.extend.tag.register('subtabs', postTabs, true); +hexo.extend.tag.register('subsubtabs', postTabs, true); + +const postVideo = require('./video'); + +hexo.extend.tag.register('video', postVideo); diff --git a/themes/next/scripts/tags/label.js b/themes/next/scripts/tags/label.js new file mode 100644 index 0000000..3041afd --- /dev/null +++ b/themes/next/scripts/tags/label.js @@ -0,0 +1,13 @@ +/** + * label.js | https://theme-next.js.org/docs/tag-plugins/label + */ + +'use strict'; + +module.exports = ctx => function(args) { + const [classes = 'default', text = ''] = args.join(' ').split('@'); + + if (!text) ctx.log.warn('Label text must be defined!'); + + return `${text}`; +}; diff --git a/themes/next/scripts/tags/link-grid.js b/themes/next/scripts/tags/link-grid.js new file mode 100644 index 0000000..eed4755 --- /dev/null +++ b/themes/next/scripts/tags/link-grid.js @@ -0,0 +1,20 @@ +/** + * link-grid.js | https://theme-next.js.org/docs/tag-plugins/link-grid + */ + +'use strict'; + +module.exports = function([image = '/images/avatar.gif', delimiter = '|', comment = '%'], content) { + const links = content.split('\n').filter(line => line.trim() !== '').map(line => { + const item = line.split(delimiter).map(arg => arg.trim()); + if (item[0][0] === comment) return ''; + const imageSource = item[3] || image; + const hasExtension = /\.[^/]+$/.test(imageSource); + return ``; + }); + return ``; +}; diff --git a/themes/next/scripts/tags/mermaid.js b/themes/next/scripts/tags/mermaid.js new file mode 100644 index 0000000..090a1a9 --- /dev/null +++ b/themes/next/scripts/tags/mermaid.js @@ -0,0 +1,14 @@ +/** + * mermaid.js | https://theme-next.js.org/docs/tag-plugins/mermaid + */ + +'use strict'; + +const { escapeHTML } = require('hexo-util'); + +module.exports = function(args, content) { + return `
+${args.join(' ')}
+${escapeHTML(content)}
+
`; +}; diff --git a/themes/next/scripts/tags/note.js b/themes/next/scripts/tags/note.js new file mode 100644 index 0000000..344121c --- /dev/null +++ b/themes/next/scripts/tags/note.js @@ -0,0 +1,25 @@ +/** + * note.js | https://theme-next.js.org/docs/tag-plugins/note + */ + +'use strict'; + +module.exports = ctx => function(args, content) { + const keywords = ['default', 'primary', 'info', 'success', 'warning', 'danger', 'no-icon']; + const className = []; + for (let i = 0; i < 2; i++) { + if (keywords.includes(args[0])) { + className.push(args.shift()); + } else { + break; + } + } + + content = ctx.render.renderSync({ text: content, engine: 'markdown' }); + if (args.length === 0) { + return `
${content}
`; + } + return `
${ctx.render.renderSync({ text: args.join(' '), engine: 'markdown' })} +${content} +
`; +}; diff --git a/themes/next/scripts/tags/pdf.js b/themes/next/scripts/tags/pdf.js new file mode 100644 index 0000000..5195473 --- /dev/null +++ b/themes/next/scripts/tags/pdf.js @@ -0,0 +1,10 @@ +/** + * pdf.js | https://theme-next.js.org/docs/tag-plugins/pdf + */ + +'use strict'; + +module.exports = ctx => function(args) { + const theme = ctx.theme.config; + return `
`; +}; diff --git a/themes/next/scripts/tags/tabs.js b/themes/next/scripts/tags/tabs.js new file mode 100644 index 0000000..5e3265d --- /dev/null +++ b/themes/next/scripts/tags/tabs.js @@ -0,0 +1,47 @@ +/** + * tabs.js | https://theme-next.js.org/docs/tag-plugins/tabs + */ + +'use strict'; + +module.exports = ctx => function(args, content = '') { + const tabBlock = /\n([\w\W\s\S]*?)/g; + + args = args.join(' ').split(','); + const tabName = args[0]; + const tabActive = Number(args[1]) || 0; + + let tabId = 0; + let tabNav = ''; + let tabContent = ''; + + if (!tabName) ctx.log.warn('Tabs block must have unique name!'); + const matches = content.matchAll(tabBlock); + + for (const match of matches) { + let [caption = '', icon = ''] = match[1].split('@'); + let postContent = match[2]; + + postContent = ctx.render.renderSync({ text: postContent, engine: 'markdown' }).trim(); + + const abbr = tabName + ' ' + ++tabId; + const href = abbr.toLowerCase().split(' ').join('-'); + + icon = icon.trim(); + if (icon.length > 0) { + if (!icon.startsWith('fa')) icon = 'fa fa-' + icon; + icon = ``; + } + + caption = icon + caption.trim(); + + const isActive = (tabActive > 0 && tabActive === tabId) || (tabActive === 0 && tabId === 1) ? ' active' : ''; + tabNav += `
  • ${caption || abbr}
  • `; + tabContent += `
    ${postContent}
    `; + } + + tabNav = ``; + tabContent = `
    ${tabContent}
    `; + + return `
    ${tabNav + tabContent}
    `; +}; diff --git a/themes/next/scripts/tags/video.js b/themes/next/scripts/tags/video.js new file mode 100644 index 0000000..4d0171c --- /dev/null +++ b/themes/next/scripts/tags/video.js @@ -0,0 +1,9 @@ +/** + * video.js | https://theme-next.js.org/docs/tag-plugins/ + */ + +'use strict'; + +module.exports = function(args) { + return ``; +}; diff --git a/themes/next/source/css/_colors.styl b/themes/next/source/css/_colors.styl new file mode 100644 index 0000000..9f7c194 --- /dev/null +++ b/themes/next/source/css/_colors.styl @@ -0,0 +1,75 @@ +:root { + --body-bg-color: $body-bg-color; + --content-bg-color: $content-bg-color; + --card-bg-color: $card-bg-color; + --text-color: $text-color; + --blockquote-color: $blockquote-color; + --link-color: $link-color; + --link-hover-color: $link-hover-color; + --brand-color: $brand-color; + --brand-hover-color: $brand-hover-color; + --table-row-odd-bg-color: $table-row-odd-bg-color; + --table-row-hover-bg-color: $table-row-hover-bg-color; + --menu-item-bg-color: $menu-item-bg-color; + --theme-color: $theme-color; + + --btn-default-bg: $btn-default-bg; + --btn-default-color: $btn-default-color; + --btn-default-border-color: $btn-default-border-color; + --btn-default-hover-bg: $btn-default-hover-bg; + --btn-default-hover-color: $btn-default-hover-color; + --btn-default-hover-border-color: $btn-default-hover-border-color; + + --highlight-background: $highlight-background; + --highlight-foreground: $highlight-foreground; + --highlight-gutter-background: $highlight-gutter-background; + --highlight-gutter-foreground: $highlight-gutter-foreground; + + color-scheme: light; +} + +if (hexo-config('darkmode')) { + @media (prefers-color-scheme: dark) { + :root { + --body-bg-color: $body-bg-color-dark; + --content-bg-color: $content-bg-color-dark; + --card-bg-color: $card-bg-color-dark; + --text-color: $text-color-dark; + --blockquote-color: $blockquote-color-dark; + --link-color: $link-color-dark; + --link-hover-color: $link-hover-color-dark; + --brand-color: $brand-color-dark; + --brand-hover-color: $brand-hover-color-dark; + --table-row-odd-bg-color: $table-row-odd-bg-color-dark; + --table-row-hover-bg-color: $table-row-hover-bg-color-dark; + --menu-item-bg-color: $menu-item-bg-color-dark; + --theme-color: $theme-color-dark; + + --btn-default-bg: $btn-default-bg-dark; + --btn-default-color: $btn-default-color-dark; + --btn-default-border-color: $btn-default-border-color-dark; + --btn-default-hover-bg: $btn-default-hover-bg-dark; + --btn-default-hover-color: $btn-default-hover-color-dark; + --btn-default-hover-border-color: $btn-default-hover-border-color-dark; + + --highlight-background: $highlight-background-dark; + --highlight-foreground: $highlight-foreground-dark; + --highlight-gutter-background: $highlight-gutter-background-dark; + --highlight-gutter-foreground: $highlight-gutter-foreground-dark; + + color-scheme: dark; + } + + img { + opacity: .75; + + &:hover { + opacity: .9; + } + } + + iframe { + color-scheme: light; + } + } +} diff --git a/themes/next/source/css/_common/components/back-to-top.styl b/themes/next/source/css/_common/components/back-to-top.styl new file mode 100644 index 0000000..0290c3d --- /dev/null +++ b/themes/next/source/css/_common/components/back-to-top.styl @@ -0,0 +1,49 @@ +if (hexo-config('back2top.enable')) { + .back-to-top { + font-size: $b2t-font-size; + + span { + margin-right: 8px; + if (not hexo-config('back2top.scrollpercent')) { + display: none; + } + } + + .fa { + text-align: center; + width: $sidebar-toggle-size; + } + + if (hexo-config('back2top.sidebar')) { + margin: 20px - $sidebar-offset -10px -20px; + // FIXME: opacity override by motion + opacity: 0; + transition: opacity $transition-ease; + + &.back-to-top-on { + cursor: pointer; + opacity: $b2t-opacity; + + &:hover { + opacity: $b2t-opacity-hover; + } + } + } else { + align-items: center; + bottom: $b2t-position-bottom; + color: $b2t-color; + display: flex; + height: $sidebar-toggle-size; + transition: bottom $transition-ease; + sidebar-toggle(); + + &:hover { + color: $sidebar-highlight; + } + + &.back-to-top-on { + bottom: $b2t-position-bottom-on; + } + } + } +} diff --git a/themes/next/source/css/_common/components/index.styl b/themes/next/source/css/_common/components/index.styl new file mode 100644 index 0000000..7a55e8b --- /dev/null +++ b/themes/next/source/css/_common/components/index.styl @@ -0,0 +1,6 @@ +@import 'back-to-top'; +@import 'reading-progress'; + +@import 'post'; +@import 'pages'; +@import 'third-party'; diff --git a/themes/next/source/css/_common/components/pages/breadcrumb.styl b/themes/next/source/css/_common/components/pages/breadcrumb.styl new file mode 100644 index 0000000..1d8b99e --- /dev/null +++ b/themes/next/source/css/_common/components/pages/breadcrumb.styl @@ -0,0 +1,21 @@ +ul.breadcrumb { + font-size: $font-size-smallest; + list-style: none; + margin: 1em 0; + padding: 0 2em; + text-align: center; + + li { + display: inline; + } + + li:not(:first-child)::before { + content: '/\00a0'; + font-weight: normal; + padding: .5em; + } + + li:last-child { + font-weight: bold; + } +} diff --git a/themes/next/source/css/_common/components/pages/categories.styl b/themes/next/source/css/_common/components/pages/categories.styl new file mode 100644 index 0000000..2c89b61 --- /dev/null +++ b/themes/next/source/css/_common/components/pages/categories.styl @@ -0,0 +1,35 @@ +.category-all-page { + .category-all-title { + text-align: center; + } + + .category-all { + margin-top: 20px; + } + + .category-list { + list-style: none; + margin: 0; + padding: 0; + } + + .category-list-item { + margin: 5px 10px; + } + + .category-list-count { + color: $grey; + + &::before { + content: ' ('; + } + + &::after { + content: ') '; + } + } + + .category-list-child { + padding-left: 10px; + } +} diff --git a/themes/next/source/css/_common/components/pages/index.styl b/themes/next/source/css/_common/components/pages/index.styl new file mode 100644 index 0000000..e177216 --- /dev/null +++ b/themes/next/source/css/_common/components/pages/index.styl @@ -0,0 +1,5 @@ +// Page specific styles +@import 'categories'; +@import 'schedule'; +@import 'breadcrumb'; +@import 'tag-cloud'; diff --git a/themes/next/source/css/_common/components/pages/schedule.styl b/themes/next/source/css/_common/components/pages/schedule.styl new file mode 100644 index 0000000..d3c7166 --- /dev/null +++ b/themes/next/source/css/_common/components/pages/schedule.styl @@ -0,0 +1,102 @@ +@keyframes dot-flash { + from { + opacity: 1; + transform: scale(1); + } + + to { + opacity: 0; + transform: scale(.8); + } +} + +.event-list { + hr { + background: $black-deep; + margin: 20px 0 45px; + + &::after { + background: $black-deep; + color: white; + content: 'NOW'; + display: inline-block; + font-weight: bold; + padding: 0 5px; + } + } + + .event { + --event-background: $black-deep; + --event-foreground: $grey; + --event-title: white; + background: var(--event-background); + padding: 15px; + + .event-summary { + border-bottom: 0; + color: var(--event-title); + margin: 0; + padding: 0 0 0 35px; + position: relative; + + &::before { + animation: dot-flash 1s alternate infinite ease-in-out; + background: var(--event-title); + left: 0; + margin-top: -6px; + position: absolute; + top: 50%; + round-icon(12px); + } + } + + &:nth-of-type(odd) .event-summary::before { + animation-delay: .5s; + } + + &:not(:last-child) { + margin-bottom: 20px; + } + + .event-relative-time { + color: var(--event-foreground); + display: inline-block; + font-size: 12px; + font-weight: normal; + padding-left: 12px; + } + + .event-details { + color: var(--event-foreground); + display: block; + line-height: 18px; + padding: 6px 0 6px 35px; + + &::before { + color: var(--event-foreground); + display: inline-block; + margin-right: 9px; + width: 14px; + font-family-icons(); + } + + &.event-location::before { + content: '\f041'; + } + + &.event-duration::before { + content: '\f017'; + } + + &.event-description::before { + content: '\f024'; + } + } + } + + .event-past { + --event-background: $whitesmoke; + --event-foreground: $grey-dark; + --event-title: $black-deep; + } +} diff --git a/themes/next/source/css/_common/components/pages/tag-cloud.styl b/themes/next/source/css/_common/components/pages/tag-cloud.styl new file mode 100644 index 0000000..97fd511 --- /dev/null +++ b/themes/next/source/css/_common/components/pages/tag-cloud.styl @@ -0,0 +1,28 @@ +.tag-cloud { + text-align: center; + + a { + display: inline-block; + margin: 10px; + } +} + +for $tag-cloud in (0 .. 10) { + $tag-cloud-color = mix($tag-cloud-end, $tag-cloud-start, $tag-cloud * 10); + .tag-cloud-{$tag-cloud} { + border-bottom-color: $tag-cloud-color; + color: $tag-cloud-color; + } +} + +if (hexo-config('darkmode')) { + @media (prefers-color-scheme: dark) { + for $tag-cloud in (0 .. 10) { + $tag-cloud-color = mix($tag-cloud-end-dark, $tag-cloud-start-dark, $tag-cloud * 10); + .tag-cloud-{$tag-cloud} { + border-bottom-color: $tag-cloud-color; + color: $tag-cloud-color; + } + } + } +} diff --git a/themes/next/source/css/_common/components/post/index.styl b/themes/next/source/css/_common/components/post/index.styl new file mode 100644 index 0000000..f7c130b --- /dev/null +++ b/themes/next/source/css/_common/components/post/index.styl @@ -0,0 +1,53 @@ +.rtl { + &.post-body { + p, a, h1, h2, h3, h4, h5, h6, li, ul, ol { + direction: rtl; + font-family: UKIJ Ekran; + } + } + + &.post-title { + font-family: UKIJ Ekran; + } +} + +.post-button { + margin-top: 40px; + text-align: $scheme-text-align; +} + +.use-motion { + if (hexo-config('motion.transition.post_block')) { + .post-block, .pagination, .comments { + visibility: hidden; + } + } + + if (hexo-config('motion.transition.post_header')) { + .post-header { + visibility: hidden; + } + } + + if (hexo-config('motion.transition.post_body')) { + .post-body { + visibility: hidden; + } + } + + if (hexo-config('motion.transition.coll_header')) { + .collection-header { + visibility: hidden; + } + } +} + +@import 'post-collapse'; +@import 'post-body'; +@import 'post-gallery'; +@import 'post-header'; +@import 'post-nav'; +@import 'post-footer'; +@import 'post-widgets'; +@import 'post-reward'; +@import 'post-followme'; diff --git a/themes/next/source/css/_common/components/post/post-body.styl b/themes/next/source/css/_common/components/post/post-body.styl new file mode 100644 index 0000000..6df053b --- /dev/null +++ b/themes/next/source/css/_common/components/post/post-body.styl @@ -0,0 +1,79 @@ +.post-body { + font-family: $font-family-posts; + word-wrap(); + + +desktop-large() { + font-size: $font-size-large; + } + + +desktop() { + text-align: unquote(hexo-config('text_align.desktop')); + } + + +tablet-mobile() { + text-align: unquote(hexo-config('text_align.mobile')); + } + + h1, h2, h3, h4, h5, h6 { + // Supported plugins: hexo-renderer-markdown-it hexo-renderer-marked + .header-anchor, .headerlink { + border-bottom-style: none; + color: inherit; + float: right; + font-size: $font-size-small; + margin-left: 10px; + opacity: 0; + + &::before { + font-family-icons('\f0c1'); + } + } + + &:hover { + .header-anchor, .headerlink { + opacity: .5; + + &:hover { + opacity: 1; + } + } + } + } + + .exturl .fa { + font-size: $font-size-small; + margin-left: 4px; + } + + // For fancybox and pandoc + .image-caption, img + figcaption, .fancybox + figcaption { + color: $grey-dark; + font-size: $font-size-small; + font-weight: bold; + line-height: 1; + margin: -15px auto 15px; + text-align: center; + } + + iframe, img, video, embed { + margin-bottom: 20px; + } + + .video-container { + height: 0; + margin-bottom: 20px; + overflow: hidden; + padding-top: 75%; + position: relative; + width: 100%; + + iframe, object, embed { + height: 100%; + left: 0; + margin: 0; + position: absolute; + top: 0; + width: 100%; + } + } +} diff --git a/themes/next/source/css/_common/components/post/post-collapse.styl b/themes/next/source/css/_common/components/post/post-collapse.styl new file mode 100644 index 0000000..293eee5 --- /dev/null +++ b/themes/next/source/css/_common/components/post/post-collapse.styl @@ -0,0 +1,109 @@ +.posts-collapse .post-content { + margin-bottom: $posts-collapse-margin; + margin-left: $posts-collapse-margin; + position: relative; + + +mobile() { + margin-left: $posts-collapse-margin-mobile; + margin-right: $posts-collapse-margin-mobile; + } + + .collection-title { + font-size: $font-size-large; + position: relative; + + &::before { + background: $grey-dark; + border: 1px solid white; + margin-left: -6px; + margin-top: -4px; + position: absolute; + top: 50%; + round-icon(10px); + } + } + + .collection-year { + font-size: $font-size-largest; + font-weight: bold; + margin: 60px 0; + position: relative; + + &::before { + background: $grey; + margin-left: -4px; + margin-top: -4px; + position: absolute; + top: 50%; + round-icon(8px); + } + } + + .collection-header { + display: block; + margin-left: 20px; + + small { + color: $grey; + margin-left: 5px; + } + } + + .post-header { + border-bottom: 1px dashed $grey-light; + // 2px is equal to half the width of .posts-collapse::before + margin: 30px 2px 0; + padding-left: 15px; + position: relative; + transition: border $transition-ease; + + &::before { + background: $grey; + border: 1px solid white; + left: -6px; + position: absolute; + top: $font-size-smallest; + transition: background $transition-ease; + round-icon(6px); + } + + &:hover { + border-bottom-color: $grey-dim; + + &::before { + background: $black-deep; + } + } + } + + .post-meta-container { + display: inline; + font-size: $font-size-smallest; + margin-right: 10px; + } + + .post-title { + display: inline; + + a { + border-bottom: 0; + color: var(--link-color); + } + + .fa-external-link-alt { + font-size: $font-size-small; + margin-left: 5px; + } + } + + &::before { + background: $whitesmoke; + content: ' '; + height: 100%; + margin-left: -2px; + position: absolute; + // To do: 1.25em is inaccurate when .collection-title has line breaks on mobile + top: 1.25em; + width: 4px; + } +} diff --git a/themes/next/source/css/_common/components/post/post-followme.styl b/themes/next/source/css/_common/components/post/post-followme.styl new file mode 100644 index 0000000..84c0895 --- /dev/null +++ b/themes/next/source/css/_common/components/post/post-followme.styl @@ -0,0 +1,56 @@ +if (hexo-config('follow_me')) { + .followme { + color: $grey; + padding: 1em 1.5em; + text-align: center; + post-card(); + + .social-list { + flex-wrap(); + + .social-item { + margin: .5em 2em; + position: relative; + + +tablet-mobile() { + margin: .5em .75em; + } + } + + .social-link { + border: 0; + // Make the hit area continious + display: block; + + .icon { + font-size: 1.75em; + } + + .label { + display: block; + font-size: 14px; + } + + &:hover + .social-item-img { + display: block; + } + } + + span.social-link { + color: var(--link-color); + + &:hover { + color: var(--link-hover-color); + } + } + + .social-item-img { + display: none; + left: 50%; + max-width: $post-reward-img-width; + position: absolute; + transform: translate(-50%, 20px); + } + } + } +} diff --git a/themes/next/source/css/_common/components/post/post-footer.styl b/themes/next/source/css/_common/components/post/post-footer.styl new file mode 100644 index 0000000..42e780d --- /dev/null +++ b/themes/next/source/css/_common/components/post/post-footer.styl @@ -0,0 +1,53 @@ +// Flexbox layout makes it possible to reorder the child +// elements of .post-footer through the `order` CSS property +// Fix issue #16 +// To do: use `gap` instead of `margin` +// See https://caniuse.com/flexbox-gap +.post-footer { + flex-column(); +} + +.post-eof { + background: $grey-light; + height: 1px; + margin: $post-eof-margin-top auto $post-eof-margin-bottom; + width: 8%; + + .post-block:last-of-type & { + display: none; + } +} + +if (hexo-config('creative_commons.post')) { + .post-copyright ul { + list-style: none; + overflow: hidden; + padding: .5em 1em; + position: relative; + post-card(); + + &::after { + content: '\f25e'; + font-family: 'Font Awesome 6 Brands'; + font-size: 200px; + opacity: .1; + position: absolute; + right: -50px; + top: -150px; + } + } +} + +.post-tags { + margin-top: 40px; + text-align: $scheme-text-align; + + a { + display: inline-block; + font-size: $font-size-smaller; + + &:not(:last-child) { + margin-right: 10px; + } + } +} diff --git a/themes/next/source/css/_common/components/post/post-gallery.styl b/themes/next/source/css/_common/components/post/post-gallery.styl new file mode 100644 index 0000000..06f837c --- /dev/null +++ b/themes/next/source/css/_common/components/post/post-gallery.styl @@ -0,0 +1,33 @@ +.post-gallery { + display: flex; + min-height: 200px; + + .post-gallery-image { + flex: 1; + + &:not(:first-child) { + clip-path: polygon(40px 0, 100% 0, 100% 100%, 0 100%); + margin-left: -20px; + } + + &:not(:last-child) { + margin-right: -20px; + } + + img { + height: 100%; + object-fit: cover; + // Override darkmode image opacity. + opacity: 1; + width: 100%; + } + } +} + +.posts-expand .post-gallery { + margin-bottom: 60px; +} + +.posts-collapse .post-gallery { + margin: 15px 0; +} diff --git a/themes/next/source/css/_common/components/post/post-header.styl b/themes/next/source/css/_common/components/post/post-header.styl new file mode 100644 index 0000000..da8279e --- /dev/null +++ b/themes/next/source/css/_common/components/post/post-header.styl @@ -0,0 +1,120 @@ +.posts-expand .post-header { + font-size: $font-size-large; + margin-bottom: 60px; + text-align: center; +} + +.posts-expand .post-title { + font-size: $font-size-largest; + font-weight: normal; + margin: initial; + word-wrap(); + + if (hexo-config('post_edit.enable')) { + .post-edit-link { + border-bottom: 0; + color: $grey; + float: right; + font-size: $font-size-larger; + margin-left: -1.2em; + transition: color $transition-ease-in; + + +mobile-small() { + margin-left: initial; + } + + &:hover { + color: $sidebar-highlight; + } + } + } +} + +.posts-expand .post-title-link { + border-bottom: 0; + color: var(--link-color); + display: inline-block; + position: relative; + + &::before { + background: var(--link-color); + bottom: 0; + content: ''; + height: 2px; + // Fix issue #75 + left: 0; + position: absolute; + transform: scaleX(0); + transition: transform $transition-ease; + width: 100%; + } + + &:hover::before { + transform: scaleX(1); + } + + .fa-external-link-alt { + font-size: $font-size-small; + margin-left: 5px; + } +} + +.post-sticky-flag { + display: inline-block; + // Fix issue #80 #140 + margin-right: 8px; + transform: rotate(30deg); +} + +.posts-expand .post-meta-container { + color: $grey-dark; + font-family: $font-family-posts; + font-size: $font-size-smallest; + margin-top: 3px; + + .post-description { + font-size: $font-size-small; + margin-top: 2px; + } + + time { + border-bottom: 1px dashed $grey-dark; + } +} + +// Flexbox layout makes it possible to reorder the child +// elements of .post-meta through the `order` CSS property +.post-meta { + flex-wrap(); +} + +// .post-meta-item exists in .post-meta and footer +:not(.post-meta-break) + .post-meta-item::before { + content: '|'; + margin: 0 .5em; +} + +.post-meta-item-icon { + margin-right: 3px; +} + +.post-meta-item-text { + if (not hexo-config('post_meta.item_text')) { + display: none; + } + + +tablet-mobile() { + display: none; + } +} + +.post-meta-break { + flex-basis: 100%; + height: 0; +} + +if (hexo-config('busuanzi_count.enable') and hexo-config('busuanzi_count.post_views')) { + #busuanzi_container_page_pv { + display: none; + } +} diff --git a/themes/next/source/css/_common/components/post/post-nav.styl b/themes/next/source/css/_common/components/post/post-nav.styl new file mode 100644 index 0000000..dd9638f --- /dev/null +++ b/themes/next/source/css/_common/components/post/post-nav.styl @@ -0,0 +1,41 @@ +.post-nav { + border-top: 1px solid $gainsboro; + display: flex; + gap: 30px; + justify-content: space-between; + margin-top: 1em; + padding: 10px 5px 0; +} + +.post-nav-item { + flex: 1; + + a { + border-bottom: 0; + display: block; + font-size: $font-size-small; + line-height: 1.6; + + &:active { + top: 2px; + } + } + + .fa { + font-size: $font-size-smallest; + } + + &:first-child { + .fa { + margin-right: 5px; + } + } + + &:last-child { + text-align: right; + + .fa { + margin-left: 5px; + } + } +} diff --git a/themes/next/source/css/_common/components/post/post-reward.styl b/themes/next/source/css/_common/components/post/post-reward.styl new file mode 100644 index 0000000..6400cde --- /dev/null +++ b/themes/next/source/css/_common/components/post/post-reward.styl @@ -0,0 +1,56 @@ +.reward-container { + margin: $post-card-margin; + padding: 1em 0; + text-align: center; + + button { + button($sidebar-highlight); + border: 2px solid $sidebar-highlight; + border-radius: 2px; + outline: 0; + transition: all $transition-ease; + vertical-align: text-top; + } +} + +.post-reward { + display: none; + padding-top: 20px; + + &.active { + display: block; + } + + div { + display: inline-block; + + span { + display: block; + } + + if (hexo-config('reward_settings.animation')) { + &:hover span { + animation: next-roll .1s infinite linear; + // The animation may affect :hover of img in dark mode + pointer-events: none; + } + } + } + + img { + display: inline-block; + margin: .8em 2em 0; + max-width: 100%; + width: $post-reward-img-width; + } +} + +@keyframes next-roll { + from { + transform: rotateZ(30deg); + } + + to { + transform: rotateZ(-30deg); + } +} diff --git a/themes/next/source/css/_common/components/post/post-widgets.styl b/themes/next/source/css/_common/components/post/post-widgets.styl new file mode 100644 index 0000000..100a1a6 --- /dev/null +++ b/themes/next/source/css/_common/components/post/post-widgets.styl @@ -0,0 +1,7 @@ +.social-like { + border-top: 1px solid $gainsboro; + font-size: $font-size-small; + margin-top: 1em; + padding-top: 1em; + text-align: center; +} diff --git a/themes/next/source/css/_common/components/reading-progress.styl b/themes/next/source/css/_common/components/reading-progress.styl new file mode 100644 index 0000000..6353406 --- /dev/null +++ b/themes/next/source/css/_common/components/reading-progress.styl @@ -0,0 +1,27 @@ +if (hexo-config('reading_progress.enable')) { + .reading-progress-bar { + --progress: 0; + background: convert(hexo-config('reading_progress.color')); + height: convert(hexo-config('reading_progress.height')); + position: fixed; + z-index: $zindex-5; + + if (hexo-config('reading_progress.reversed')) { + width: calc(100% - var(--progress)); + } else { + width: var(--progress); + } + + if (hexo-config('reading_progress.start_at') == 'right') { + right: 0; + } else { + left: 0; + } + + if (hexo-config('reading_progress.position') == 'bottom') { + bottom: 0; + } else { + top: 0; + } + } +} diff --git a/themes/next/source/css/_common/components/third-party/disqusjs.styl b/themes/next/source/css/_common/components/third-party/disqusjs.styl new file mode 100644 index 0000000..b3af1c0 --- /dev/null +++ b/themes/next/source/css/_common/components/third-party/disqusjs.styl @@ -0,0 +1,39 @@ +if (hexo-config('disqusjs.enable') and hexo-config('darkmode')) { + @media (prefers-color-scheme:dark) { + html #dsqjs a { + color: var(--link-color); + } + + html #dsqjs a:focus,html #dsqjs a:hover { + color: var(--link-hover-color); + } + + html #dsqjs .dsqjs-nav,html #dsqjs footer { + border-color: var(--card-bg-color); + } + + html #dsqjs .dsqjs-load-more,html #dsqjs .dsqjs-load-more:hover,html #dsqjs .dsqjs-nav-tab,html #dsqjs .dsqjs-no-comment,html #dsqjs .dsqjs-post-content { + color: var(--text-color); + } + + html #dsqjs .dsqjs-order-label { + background-color: #3e4b5e; + } + + html #dsqjs .dsqjs-order-radio:checked+.dsqjs-order-label { + background-color: var(--content-bg-color); + } + + html #dsqjs .dsqjs-tab-active>span:after { + background-color: #2e9fff!important; + } + + html #dsqjs .dsqjs-footer,html #dsqjs .dsqjs-meta { + color: var(--text-color); + } + + html #dsqjs .dsqjs-post-body blockquote { + border-color: var(--content-bg-color); + } + } +} diff --git a/themes/next/source/css/_common/components/third-party/giscus.styl b/themes/next/source/css/_common/components/third-party/giscus.styl new file mode 100644 index 0000000..8778136 --- /dev/null +++ b/themes/next/source/css/_common/components/third-party/giscus.styl @@ -0,0 +1,5 @@ +if (hexo-config('giscus.enable')) { + .giscus { + max-width: unset; + } +} diff --git a/themes/next/source/css/_common/components/third-party/gitalk.styl b/themes/next/source/css/_common/components/third-party/gitalk.styl new file mode 100644 index 0000000..9d682c9 --- /dev/null +++ b/themes/next/source/css/_common/components/third-party/gitalk.styl @@ -0,0 +1,17 @@ +if (hexo-config('gitalk.enable')) { + .gt-header a, .gt-comments a, .gt-popup a { + border-bottom: 0; + } + + .gt-container .gt-popup .gt-action.is--active::before { + top: .7em; + } + + if (hexo-config('darkmode')) { + @media (prefers-color-scheme: dark) { + .gt-container .gt-header-textarea { + background-color: var(--card-bg-color) !important; + } + } + } +} diff --git a/themes/next/source/css/_common/components/third-party/gitter.styl b/themes/next/source/css/_common/components/third-party/gitter.styl new file mode 100644 index 0000000..bd9a84c --- /dev/null +++ b/themes/next/source/css/_common/components/third-party/gitter.styl @@ -0,0 +1,7 @@ +if (hexo-config('gitter.enable')) { + .gitter-open-chat-button { + $alignment = sidebar-toggle-alignment(false); + {$alignment[0]}: auto !important; + {$alignment[1]}: 10px !important; + } +} diff --git a/themes/next/source/css/_common/components/third-party/index.styl b/themes/next/source/css/_common/components/third-party/index.styl new file mode 100644 index 0000000..85b8bef --- /dev/null +++ b/themes/next/source/css/_common/components/third-party/index.styl @@ -0,0 +1,18 @@ +@import 'disqusjs'; +@import 'gitalk'; +@import 'utterances'; +@import 'search'; +@import 'math'; +@import 'gitter'; +@import 'giscus'; + +.use-motion .animated { + // Fix issue #48 #55 + animation-fill-mode: none; + // Fix issue #46 .animated in .sidebar + visibility: inherit; +} + +.use-motion .sidebar .animated { + animation-fill-mode: both; +} diff --git a/themes/next/source/css/_common/components/third-party/math.styl b/themes/next/source/css/_common/components/third-party/math.styl new file mode 100644 index 0000000..a95c930 --- /dev/null +++ b/themes/next/source/css/_common/components/third-party/math.styl @@ -0,0 +1,9 @@ +if (hexo-config('math.mathjax.enable')) { + mjx-container[jax='CHTML'][display='true'], .has-jax { + overflow: auto hidden; + } + + mjx-container[display='true'] + br { + display: none; + } +} diff --git a/themes/next/source/css/_common/components/third-party/search.styl b/themes/next/source/css/_common/components/third-party/search.styl new file mode 100644 index 0000000..21f1196 --- /dev/null +++ b/themes/next/source/css/_common/components/third-party/search.styl @@ -0,0 +1,179 @@ +if (hexo-config('local_search.enable') or hexo-config('algolia_search.enable')) { + .search-active { + overflow: hidden; + } + + .search-pop-overlay { + background: rgba(0, 0, 0, 0); + display: flex; + height: 100%; + left: 0; + position: fixed; + top: 0; + transition: visibility .4s, background .4s; + visibility: hidden; + width: 100%; + z-index: $zindex-4; + + .search-active & { + background: rgba(0, 0, 0, .3); + visibility: visible; + } + } + + .search-popup { + background: var(--card-bg-color); + border-radius: 5px; + height: 80%; + margin: auto; + transform: scale(0); + transition: transform .4s; + width: 700px; + + .search-active & { + transform: scale(1); + } + + +mobile() { + border-radius: 0; + height: 100%; + width: 100%; + } + + .search-icon, .popup-btn-close { + color: $grey-dark; + font-size: 18px; + padding: 0 10px; + } + + .popup-btn-close { + cursor: pointer; + + &:hover .fa { + color: $black-deep; + } + } + + .search-header { + background: $gainsboro; + if (hexo-config('darkmode')) { + @media (prefers-color-scheme: dark) { + background: $grey-dim; + } + } + border-top-left-radius: 5px; + border-top-right-radius: 5px; + display: flex; + padding: 5px; + } + + input.search-input { + background: transparent; + border: 0; + outline: 0; + width: 100%; + + &::-webkit-search-cancel-button { + display: none; + } + } + + .search-result-container { + height: calc(100% - 55px); + overflow: auto; + padding: 5px 25px; + + hr { + margin: 5px 0 10px; + + &:first-child { + display: none; + } + } + } + + .search-result-list { + margin: 0 5px; + padding: 0; + } + + a.search-result-title { + font-weight: bold; + } + + p.search-result { + border-bottom: 1px dashed $grey-light; + padding: 5px 0; + } + } +} + +if (hexo-config('algolia_search.enable')) { + .search-input-container { + flex-grow: 1; + + form { + padding: 2px; + } + } + + .search-stats { + align-items: center; + display: flex; + justify-content: space-between; + + img { + height: 1em; + margin: 0; + } + } + + .algolia-pagination { + // Override default style of ul + margin: 40px 0; + opacity: 1; + padding: 0; + + .pagination-item { + display: inline-block; + } + + .current .page-number { + @extend $page-number-current; + cursor: default; + } + + .disabled-item { + visibility: hidden; + } + } +} + +if (hexo-config('local_search.enable')) { + .search-popup { + .search-input-container { + flex-grow: 1; + padding: 2px; + } + + .no-result { + display: flex; + } + + .search-result-list { + width: 100%; + } + + .search-result-icon { + color: $grey-light; + margin: auto; + } + } + + mark.search-keyword { + background: transparent; + border-bottom: 1px dashed $red; + color: $red; + font-weight: bold; + } +} diff --git a/themes/next/source/css/_common/components/third-party/utterances.styl b/themes/next/source/css/_common/components/third-party/utterances.styl new file mode 100644 index 0000000..58e606d --- /dev/null +++ b/themes/next/source/css/_common/components/third-party/utterances.styl @@ -0,0 +1,5 @@ +if (hexo-config('utterances.enable')) { + .utterances { + max-width: unset; + } +} diff --git a/themes/next/source/css/_common/outline/footer/index.styl b/themes/next/source/css/_common/outline/footer/index.styl new file mode 100644 index 0000000..6e5d9a9 --- /dev/null +++ b/themes/next/source/css/_common/outline/footer/index.styl @@ -0,0 +1,100 @@ +// Footer Section +// -------------------------------------------------- +.footer { + color: $grey-dark; + font-size: $font-size-small; + padding: 20px 0; + + &.footer-fixed { + bottom: 0; + left: 0; + position: absolute; + right: 0; + } +} + +// Flexbox layout makes it possible to reorder the child +// elements of .footer-inner through the `order` CSS property +.footer-inner { + box-sizing: border-box; + text-align: $scheme-text-align; + flex-column(); + main-container(); +} + +.use-motion { + .footer { + opacity: 0; + } +} + +@keyframes icon-animate { + 0%, 100% { + transform: scale(1); + } + + 10%, 30% { + transform: scale(.9); + } + + 20%, 40%, 60%, 80% { + transform: scale(1.1); + } + + 50%, 70% { + transform: scale(1.1); + } +} + +.languages { + display: inline-block; + font-size: $font-size-large; + position: relative; + + .lang-select-label span { + margin: 0 .5em; + } + + .lang-select { + height: 100%; + left: 0; + opacity: 0; + position: absolute; + top: 0; + width: 100%; + } +} + +.with-love { + color: convert(hexo-config('footer.icon.color')); + display: inline-block; + margin: 0 5px; + + if (hexo-config('footer.icon.animated')) { + animation: icon-animate 1.33s ease-in-out infinite; + } +} + +if (hexo-config('footer.beian.enable') and hexo-config('footer.beian.gongan_icon_url')) { + .beian img { + display: inline-block; + margin: 0 3px; + vertical-align: middle; + } +} + +if (hexo-config('busuanzi_count.enable')) { + .busuanzi-count { + if (hexo-config('busuanzi_count.total_visitors')) { + #busuanzi_container_site_uv { + display: none; + } + } + + if (hexo-config('busuanzi_count.total_views')) { + #busuanzi_container_site_pv { + display: none; + } + } + } +} diff --git a/themes/next/source/css/_common/outline/header/bookmark.styl b/themes/next/source/css/_common/outline/header/bookmark.styl new file mode 100644 index 0000000..5dad674 --- /dev/null +++ b/themes/next/source/css/_common/outline/header/bookmark.styl @@ -0,0 +1,24 @@ +if (hexo-config('bookmark.enable')) { + .book-mark-link { + border-bottom: 0; + position: fixed; + top: -10px; + transition: top .3s; + sidebar-toggle-position(true); + + +tablet-mobile() { + display: none; + } + + &::before { + color: convert(hexo-config('bookmark.color')); + font-size: 32px; + line-height: 1; + font-family-icons('\f02e'); + } + } + + .book-mark-link:hover, .book-mark-link-fixed { + top: -2px; + } +} diff --git a/themes/next/source/css/_common/outline/header/github-banner.styl b/themes/next/source/css/_common/outline/header/github-banner.styl new file mode 100644 index 0000000..409de43 --- /dev/null +++ b/themes/next/source/css/_common/outline/header/github-banner.styl @@ -0,0 +1,59 @@ +if (hexo-config('github_banner.enable')) { + @keyframes octocat-wave { + 0%, 100% { + transform: rotate(0); + } + + 20%, 60% { + transform: rotate(-25deg); + } + + 40%, 80% { + transform: rotate(10deg); + } + } + + .github-corner { + :hover .octo-arm { + animation: octocat-wave 560ms ease-in-out; + } + + svg { + color: white; + fill: var(--theme-color); + position: absolute; + right: 0; + top: 0; + z-index: $zindex-0; + } + + +tablet-mobile() { + if (hexo-config('local_search.enable') or hexo-config('algolia_search.enable')) { + display: none; + } + + svg { + if (($scheme == 'Pisces') or ($scheme == 'Gemini')) { + color: var(--theme-color); + fill: white; + } + } + + .github-corner:hover .octo-arm { + animation: none; + } + + .github-corner .octo-arm { + animation: octocat-wave 560ms ease-in-out; + } + } + + if ($scheme == 'Mist') { + +mobile() { + svg { + top: inherit; + } + } + } + } +} diff --git a/themes/next/source/css/_common/outline/header/index.styl b/themes/next/source/css/_common/outline/header/index.styl new file mode 100644 index 0000000..64990fd --- /dev/null +++ b/themes/next/source/css/_common/outline/header/index.styl @@ -0,0 +1,29 @@ +// Header Section +// -------------------------------------------------- +.headband { + background: $headband-bg; + height: $headband-height; + + +tablet-mobile() { + display: none; + } +} + +.site-brand-container { + display: flex; + flex-shrink: 0; + padding: 0 10px; +} + +.use-motion { + .column, .site-brand-container .toggle { + opacity: 0; + } +} + +@import 'site-meta'; +@import 'site-nav'; +@import 'menu'; + +@import 'bookmark'; +@import 'github-banner'; diff --git a/themes/next/source/css/_common/outline/header/menu.styl b/themes/next/source/css/_common/outline/header/menu.styl new file mode 100644 index 0000000..2d7ef23 --- /dev/null +++ b/themes/next/source/css/_common/outline/header/menu.styl @@ -0,0 +1,58 @@ +// Menu +// -------------------------------------------------- +.menu { + margin: 0; + padding: 1em 0; + text-align: center; +} + +.menu-item { + display: inline-block; + list-style: none; + margin: 0 10px; + + +mobile() { + display: block; + margin-top: 10px; + + &.menu-item-search { + display: none; + } + } + + a { + border-bottom: 0; + display: block; + font-size: $font-size-smaller; + transition: border-color $transition-ease; + + &:hover, &.menu-item-active { + background: var(--menu-item-bg-color); + } + } + + .fa, .fab, .far, .fas { + margin-right: 8px; + } + + .badge { + display: inline-block; + font-weight: bold; + line-height: 1; + margin-left: .35em; + margin-top: .35em; + text-align: center; + white-space: nowrap; + + +mobile() { + float: right; + margin-left: 0; + } + } +} + +if (hexo-config('motion.transition.menu_item')) { + .use-motion .menu-item { + visibility: hidden; + } +} diff --git a/themes/next/source/css/_common/outline/header/site-meta.styl b/themes/next/source/css/_common/outline/header/site-meta.styl new file mode 100644 index 0000000..f168dc7 --- /dev/null +++ b/themes/next/source/css/_common/outline/header/site-meta.styl @@ -0,0 +1,49 @@ +.site-meta { + flex-grow: 1; + text-align: center; + + +mobile() { + text-align: center; + } +} + +.custom-logo-image { + margin-top: 20px; + + +tablet-mobile() { + display: none; + } +} + +.brand { + border-bottom: 0; + color: var(--brand-color); + display: inline-block; + padding: $brand-padding; + + &:hover { + color: var(--brand-hover-color); + } +} + +.site-title { + font-family: $font-family-logo; + font-size: $font-size-title; + font-weight: normal; + line-height: 1.5; + margin: 0; +} + +.site-subtitle { + color: $subtitle-color; + font-size: $font-size-subtitle; + margin: $site-subtitle-margin; +} + +.use-motion { + .site-title, .site-subtitle, .custom-logo-image { + opacity: 0; + position: relative; + top: -10px; + } +} diff --git a/themes/next/source/css/_common/outline/header/site-nav.styl b/themes/next/source/css/_common/outline/header/site-nav.styl new file mode 100644 index 0000000..255ff10 --- /dev/null +++ b/themes/next/source/css/_common/outline/header/site-nav.styl @@ -0,0 +1,24 @@ +.site-nav-toggle, .site-nav-right { + display: none; + + +mobile() { + flex-column(); + } + + .toggle { + color: var(--text-color); + padding: 10px; + width: 22px; + + .toggle-line { + background: var(--text-color); + border-radius: 1px; + } + } +} + +.site-nav { + +mobile() { + site-nav-hide-by-default(); + } +} diff --git a/themes/next/source/css/_common/outline/index.styl b/themes/next/source/css/_common/outline/index.styl new file mode 100644 index 0000000..033a1b3 --- /dev/null +++ b/themes/next/source/css/_common/outline/index.styl @@ -0,0 +1,5 @@ +@import 'header'; +@import 'sidebar'; +@import 'footer'; + +@import 'mobile'; diff --git a/themes/next/source/css/_common/outline/mobile.styl b/themes/next/source/css/_common/outline/mobile.styl new file mode 100644 index 0000000..dab49ac --- /dev/null +++ b/themes/next/source/css/_common/outline/mobile.styl @@ -0,0 +1,85 @@ +/* +// < 767px ++mobile() { + +} +*/ + +if (hexo-config('mobile_layout_economy')) { + +mobile-small() { + // For Pisces & Gemini schemes only wider width (remove main blocks in Gemini). + .main-inner { + padding: initial !important; + } + + // For all schemes wider width. + .posts-expand { + .post-header { + margin-bottom: 10px !important; + } + } + + .post-block { + margin-top: initial !important; + // Inside posts blocks content padding (default 40px). + padding: $content-mobile-padding 18px $content-mobile-padding !important; + } + + .post-body { + // For headers narrow width. + h1, h2, h3, h4, h5, h6 { + margin: 20px 0 8px; + } + + // Rewrite paddings & margins inside tags. + .note, .tabs .tab-content .tab-pane { + h1, h2, h3, h4, h5, h6 { + margin: 0 5px; + } + } + + // For paragraphs narrow width. + > p { + margin: 0 0 10px; + } + + // Rewrite paddings & margins inside tags. + .note > p, .tabs .tab-content .tab-pane > p { + padding: 0 5px; + } + + img, video { + margin-bottom: 10px !important; + } + + .note { + margin-bottom: 10px !important; + padding: 10px !important; + + if (hexo-config('note.icons')) { + &:not(.no-icon) { + padding-left: 35px !important; + } + } + } + + .tabs .tab-content .tab-pane { + padding: 10px 10px 0 !important; + } + } + + .post-eof { + margin: 40px auto 20px !important; + } + + .pagination { + margin-top: 40px; + } + } +} +/* +// < 413px ++mobile-smallest() { + +} +*/ diff --git a/themes/next/source/css/_common/outline/sidebar/index.styl b/themes/next/source/css/_common/outline/sidebar/index.styl new file mode 100644 index 0000000..a9c97b6 --- /dev/null +++ b/themes/next/source/css/_common/outline/sidebar/index.styl @@ -0,0 +1,31 @@ +.sidebar-inner { + color: $grey-dark; + padding: $sidebar-padding 10px; + text-align: center; + flex-column(); +} + +.cc-license { + .cc-opacity { + border-bottom: 0; + opacity: .7; + + &:hover { + opacity: .9; + } + } + + img { + display: inline-block; + } +} + +@import 'sidebar-author'; +@import 'sidebar-author-links'; +@import 'sidebar-button'; +@import 'sidebar-blogroll'; +@import 'sidebar-nav'; +@import 'sidebar-toggle'; +@import 'sidebar-toc'; +@import 'site-state'; +@import 'related-posts'; diff --git a/themes/next/source/css/_common/outline/sidebar/related-posts.styl b/themes/next/source/css/_common/outline/sidebar/related-posts.styl new file mode 100644 index 0000000..a4c457f --- /dev/null +++ b/themes/next/source/css/_common/outline/sidebar/related-posts.styl @@ -0,0 +1,31 @@ +if (hexo-config('related_posts.enable')) { + .sidebar-post-related { + font-size: $font-size-smaller; + padding: $sidebar-padding 0 0 0; + } + + .popular-posts { + margin: 0; + padding: 1em 0; + text-align: left; + + .popular-posts-item { + display: block; + + .popular-posts-link { + border-bottom: 0; + display: block; + padding: 5px 20px; + transition: background .2s ease-in-out; + + &:hover { + background: var(--menu-item-bg-color); + } + } + + .popular-posts-time { + color: $site-state-item-name-color; + } + } + } +} diff --git a/themes/next/source/css/_common/outline/sidebar/sidebar-author-links.styl b/themes/next/source/css/_common/outline/sidebar/sidebar-author-links.styl new file mode 100644 index 0000000..765a2ed --- /dev/null +++ b/themes/next/source/css/_common/outline/sidebar/sidebar-author-links.styl @@ -0,0 +1,11 @@ +.links-of-author { + a { + font-size: $font-size-smaller; + } + + if (not hexo-config('social_icons.icons_only')) { + .fa, .fab, .far, .fas { + margin-right: 2px; + } + } +} diff --git a/themes/next/source/css/_common/outline/sidebar/sidebar-author.styl b/themes/next/source/css/_common/outline/sidebar/sidebar-author.styl new file mode 100644 index 0000000..04a00c1 --- /dev/null +++ b/themes/next/source/css/_common/outline/sidebar/sidebar-author.styl @@ -0,0 +1,29 @@ +.site-author-image { + border: $site-author-image-border-width solid $site-author-image-border-color; + max-width: $site-author-image-width; + padding: 2px; + + if (hexo-config('avatar.rounded')) { + border-radius: 50%; + } + + if (hexo-config('avatar.rotated')) { + transition: transform 1s ease-out; + + &:hover { + transform: rotateZ(360deg); + } + } +} + +.site-author-name { + color: $site-author-name-color; + font-weight: $site-author-name-weight; + margin: $site-author-name-margin; +} + +.site-description { + color: $site-description-color; + font-size: $site-description-font-size; + margin-top: $site-description-margin-top; +} diff --git a/themes/next/source/css/_common/outline/sidebar/sidebar-blogroll.styl b/themes/next/source/css/_common/outline/sidebar/sidebar-blogroll.styl new file mode 100644 index 0000000..1df979b --- /dev/null +++ b/themes/next/source/css/_common/outline/sidebar/sidebar-blogroll.styl @@ -0,0 +1,14 @@ +.links-of-blogroll { + font-size: $font-size-smaller; +} + +.links-of-blogroll-title { + font-size: $font-size-small; + font-weight: 600; +} + +.links-of-blogroll-list { + list-style: none; + margin: 0; + padding: 0; +} diff --git a/themes/next/source/css/_common/outline/sidebar/sidebar-button.styl b/themes/next/source/css/_common/outline/sidebar/sidebar-button.styl new file mode 100644 index 0000000..69eef1f --- /dev/null +++ b/themes/next/source/css/_common/outline/sidebar/sidebar-button.styl @@ -0,0 +1,15 @@ +.sidebar .sidebar-button { + &:not(:first-child) { + margin-top: 15px; + } + + button { + button($orange); + border: 1px solid $orange; + border-radius: 4px; + + .fa, .fab, .far, .fas { + margin-right: 5px; + } + } +} diff --git a/themes/next/source/css/_common/outline/sidebar/sidebar-nav.styl b/themes/next/source/css/_common/outline/sidebar/sidebar-nav.styl new file mode 100644 index 0000000..9f9e0d6 --- /dev/null +++ b/themes/next/source/css/_common/outline/sidebar/sidebar-nav.styl @@ -0,0 +1,58 @@ +// Sidebar Navigation +.sidebar-nav { + display: none; + margin: 0; + padding-bottom: 20px; + padding-left: 0; + + .sidebar-nav-active & { + display: block; + } + + li { + border-bottom: 1px solid transparent; + color: $sidebar-nav-color; + cursor: pointer; + display: inline-block; + font-size: $font-size-small; + + &.sidebar-nav-overview { + margin-left: 10px; + } + + &:hover { + color: $sidebar-nav-hover-color; + } + } +} + +.sidebar-toc-active .sidebar-nav-toc, .sidebar-overview-active .sidebar-nav-overview { + border-bottom-color: $sidebar-highlight; + color: $sidebar-highlight; + + &:hover { + color: $sidebar-highlight; + } +} + +// Need for Sidebar/TOC inner scrolling if content taller then viewport. +.sidebar-panel-container { + flex: 1; + overflow-x: hidden; + overflow-y: auto; +} + +.sidebar-panel { + display: none; +} + +.sidebar-overview-active .site-overview-wrap { + // Flexbox layout makes it possible to reorder the child + // elements of .site-overview-wrap through the `order` CSS property + flex-column(); + gap: 10px; +} + +.sidebar-toc-active .post-toc-wrap { + display: block; +} diff --git a/themes/next/source/css/_common/outline/sidebar/sidebar-toc.styl b/themes/next/source/css/_common/outline/sidebar/sidebar-toc.styl new file mode 100644 index 0000000..c9f957b --- /dev/null +++ b/themes/next/source/css/_common/outline/sidebar/sidebar-toc.styl @@ -0,0 +1,61 @@ +if (hexo-config('toc.enable')) { + .post-toc { + font-size: $font-size-small; + + ol { + list-style: none; + margin: 0; + padding: 0 2px 5px 10px; + text-align: left; + + > ol { + padding-left: 0; + } + + a { + transition: all $transition-ease; + } + } + + .nav-item { + line-height: 1.8; + overflow: hidden; + text-overflow: ellipsis; + + if (not hexo-config('toc.wrap')) { + white-space: nowrap; + } + } + + .nav { + .nav-child { + display: hexo-config('toc.expand_all') ? block : none; + } + + .active > .nav-child { + display: block; + } + + .active-current > .nav-child { + display: block; + + > .nav-item { + display: block; + } + } + + .active > a { + border-bottom-color: $sidebar-highlight; + color: $sidebar-highlight; + } + + .active-current > a { + color: $sidebar-highlight; + + &:hover { + color: $sidebar-highlight; + } + } + } + } +} diff --git a/themes/next/source/css/_common/outline/sidebar/sidebar-toggle.styl b/themes/next/source/css/_common/outline/sidebar/sidebar-toggle.styl new file mode 100644 index 0000000..fc935f5 --- /dev/null +++ b/themes/next/source/css/_common/outline/sidebar/sidebar-toggle.styl @@ -0,0 +1,21 @@ +.sidebar-toggle { + bottom: $b2t-position-bottom-on + $sidebar-toggle-size + 5px; + height: $sidebar-toggle-inner-size; + padding: $sidebar-toggle-padding; + width: $sidebar-toggle-inner-size; + sidebar-toggle(); +} + +.sidebar-toggle:hover .toggle-line { + background: $sidebar-highlight; +} + +@media (any-hover: hover) { + body:not(.sidebar-active) .sidebar-toggle:hover { + toggle-arrow(hexo-config('sidebar.position')); + } +} + +.sidebar-active .sidebar-toggle { + toggle-close(hexo-config('sidebar.position')); +} diff --git a/themes/next/source/css/_common/outline/sidebar/site-state.styl b/themes/next/source/css/_common/outline/sidebar/site-state.styl new file mode 100644 index 0000000..6168280 --- /dev/null +++ b/themes/next/source/css/_common/outline/sidebar/site-state.styl @@ -0,0 +1,28 @@ +if (hexo-config('site_state')) { + .site-state { + flex-wrap(); + line-height: 1.4; + } + + .site-state-item { + // Fix issue #103 + // The click area of the link becomes smaller + padding: 0 15px; + + a { + border-bottom: 0; + display: block; + } + } + + .site-state-item-count { + display: block; + font-size: $site-state-item-count-font-size; + font-weight: 600; + } + + .site-state-item-name { + color: $site-state-item-name-color; + font-size: $site-state-item-name-font-size; + } +} diff --git a/themes/next/source/css/_common/scaffolding/base.styl b/themes/next/source/css/_common/scaffolding/base.styl new file mode 100644 index 0000000..652802c --- /dev/null +++ b/themes/next/source/css/_common/scaffolding/base.styl @@ -0,0 +1,99 @@ +::selection { + background: $selection-bg; + color: $selection-color; +} + +html, body { + height: 100%; +} + +body { + background: var(--body-bg-color); + box-sizing: border-box; + color: var(--text-color); + font-family: $font-family-base; + font-size: $font-size-base; + line-height: $line-height-base; + min-height: 100%; + position: relative; + transition: padding $transition-ease; + + if (hexo-config('body_scrollbar.overlay')) { + overflow-x: hidden; + @supports (overflow-x: clip) { + overflow-x: clip; + } + width: 100vw; + } + + if (hexo-config('body_scrollbar.stable')) { + overflow-y: scroll; + } +} + +h1, h2, h3, h4, h5, h6 { + font-family: $font-family-headings; + font-weight: bold; + line-height: 1.5; + margin: 30px 0 15px; +} + +for $headline in (1 .. 6) { + h{$headline} { + font-size: $font-size-headings-base - $font-size-headings-step * $headline; + } +} + +p { + margin: 0 0 20px; +} + +a { + border-bottom: 1px solid $link-decoration-color; + color: var(--link-color); + // For a:not(:any-link) + cursor: pointer; + outline: 0; + text-decoration: none; + word-wrap(); + + &:hover { + border-bottom-color: var(--link-hover-color); + color: var(--link-hover-color); + } +} + +iframe, img, video, embed { + display: block; + margin-left: auto; + margin-right: auto; + max-width: 100%; +} + +hr { + background-image: repeating-linear-gradient(-45deg, $grey-lighter, $grey-lighter 4px, transparent 4px, transparent 8px); + border: 0; + height: 3px; + margin: 40px 0; +} + +blockquote { + border-left: 4px solid $grey-lighter; + color: var(--blockquote-color); + margin: 0; + padding: 0 15px; + + cite::before { + content: '-'; + padding: 0 5px; + } +} + +dt { + font-weight: bold; +} + +dd { + margin: 0; + padding: 0; +} diff --git a/themes/next/source/css/_common/scaffolding/buttons.styl b/themes/next/source/css/_common/scaffolding/buttons.styl new file mode 100644 index 0000000..7320de0 --- /dev/null +++ b/themes/next/source/css/_common/scaffolding/buttons.styl @@ -0,0 +1,26 @@ +.btn { + background: var(--btn-default-bg); + border: 2px solid var(--btn-default-border-color); + border-radius: $btn-default-radius; + color: var(--btn-default-color); + display: inline-block; + font-size: $font-size-small; + line-height: 2; + padding: 0 20px; + transition: background-color $transition-ease; + + &:hover { + background: var(--btn-default-hover-bg); + border-color: var(--btn-default-hover-border-color); + color: var(--btn-default-hover-color); + } + + + .btn { + margin: 0 0 8px 8px; + } + + .fa-fw { + text-align: left; + width: (18em / 14); + } +} diff --git a/themes/next/source/css/_common/scaffolding/comments.styl b/themes/next/source/css/_common/scaffolding/comments.styl new file mode 100644 index 0000000..9dbfb78 --- /dev/null +++ b/themes/next/source/css/_common/scaffolding/comments.styl @@ -0,0 +1,39 @@ +.comments { + margin-top: 60px; + overflow: hidden; +} + +.comment-button-group { + display: flex; + flex-wrap: wrap-reverse; + justify-content: center; + margin: 1em 0; + + .comment-button { + margin: .1em .2em; + + &.active { + background: var(--btn-default-hover-bg); + border-color: var(--btn-default-hover-border-color); + color: var(--btn-default-hover-color); + } + } +} + +.comment-position { + display: none; + + &.active { + display: block; + } +} + +.tabs-comment { + margin-top: 4em; + padding-top: 0; + + .comments { + margin-top: 0; + padding-top: 0; + } +} diff --git a/themes/next/source/css/_common/scaffolding/highlight/copy-code.styl b/themes/next/source/css/_common/scaffolding/highlight/copy-code.styl new file mode 100644 index 0000000..5cfe171 --- /dev/null +++ b/themes/next/source/css/_common/scaffolding/highlight/copy-code.styl @@ -0,0 +1,61 @@ +.highlight:hover .copy-btn, pre:hover .copy-btn { + opacity: 1; +} + +figure.highlight { + .table-container { + position: relative; + } +} + +.copy-btn { + color: $black-dim; + cursor: pointer; + line-height: 1.6; + opacity: 0; + padding: 2px 6px; + position: absolute; + transition: opacity $transition-ease; + + if (hexo-config('codeblock.copy_button.style') == 'flat') { + background: white; + border: 0; + font-size: $font-size-smaller; + right: 0; + top: 0; + } else if (hexo-config('codeblock.copy_button.style') == 'mac') { + color: var(--highlight-foreground); + font-size: 14px; + right: 0; + top: 2px; + } else { + background-color: $gainsboro; + background-image: linear-gradient(#fcfcfc, $gainsboro); + border: 1px solid #d5d5d5; + border-radius: 3px; + font-size: $font-size-smaller; + right: 4px; + top: 8px; + } +} + +if (hexo-config('codeblock.copy_button.style') == 'mac') { + figure.highlight { + border-radius: 5px; + box-shadow: 0 10px 30px 0 rgba(0, 0, 0, .4); + padding-top: 30px; + + .table-container { + border-radius: 0 0 5px 5px; + } + + &::before { + background: #fc625d; + box-shadow: 20px 0 #fdbc40, 40px 0 #35cd4b; + left: 12px; + margin-top: -20px; + position: absolute; + round-icon(12px); + } + } +} diff --git a/themes/next/source/css/_common/scaffolding/highlight/index.styl b/themes/next/source/css/_common/scaffolding/highlight/index.styl new file mode 100644 index 0000000..f60ba6b --- /dev/null +++ b/themes/next/source/css/_common/scaffolding/highlight/index.styl @@ -0,0 +1,146 @@ +// Use `@require` to fix issue #67 +@require hexo-config('highlight.light.file') if (hexo-config('highlight.enable') && hexo-config('highlight.light.file')); +if (hexo-config('prism.enable')) { + @require hexo-config('prism.light') if (hexo-config('prism.light')); + @require hexo-config('prism.number') if (hexo-config('prism.number')); +} + +if (hexo-config('darkmode')) { + @media (prefers-color-scheme: dark) { + @require hexo-config('highlight.dark.file') if (hexo-config('highlight.enable') && hexo-config('highlight.dark.file')); + @require hexo-config('prism.dark') if (hexo-config('prism.enable') && hexo-config('prism.dark')); + } +} + +@require 'copy-code' if (hexo-config('codeblock.copy_button.enable')); + +// Placeholder: $code-inline $code-block +$code-inline { + background: var(--highlight-background); + color: var(--highlight-foreground); +} + +$code-block { + @extend $code-inline; + line-height: $line-height-code-block; + margin: 0 auto 20px; +} + +$figcaption { + background: var(--highlight-gutter-background); + color: var(--highlight-foreground); + display: flow-root; + font-size: $table-font-size; + line-height: 1.2; + padding: .5em; + + a { + color: var(--highlight-foreground); + float: right; + + &:hover { + border-bottom-color: var(--highlight-foreground); + } + } +} + +pre, code { + font-family: $code-font-family; +} + +code { + @extend $code-inline; + border-radius: 3px; + font-size: $table-font-size; + padding: 2px 4px; + word-wrap(); +} + +kbd { + @extend $code-inline; + border: 2px solid $grey-light; + border-radius: .2em; + box-shadow: .1em .1em .2em rgba(0, 0, 0, .1); + font-family: inherit; + padding: .1em .3em; + white-space: nowrap; +} + +// `highlight.line_number: false` and `highlight.wrap: false` +// in Hexo config generates code.highlight elements +figure.highlight { + @extend $code-block; + // Reduce DOM reflow with wrapTableWithBox + overflow: auto; + position: relative; + + pre { + border: 0; + margin: 0; + padding: 10px 0; + } + + table { + border: 0; + margin: 0; + width: auto; + } + + td { + border: 0; + padding: 0; + } + + figcaption { + @extend $figcaption; + } + + .gutter { + disable-user-select(); + + pre { + background: var(--highlight-gutter-background); + color: var(--highlight-gutter-foreground); + padding-left: 10px; + padding-right: 10px; + text-align: right; + } + } + + .code pre { + padding-left: 10px; + width: 100%; + } + + // See https://github.com/next-theme/hexo-theme-next/discussions/410 + .marked { + background: rgba(0, 0, 0, .3); + } +} + +// See https://github.com/hexojs/hexo-util/pull/229 +pre .caption, pre figcaption { + @extend $figcaption; + margin-bottom: 10px; +} + +.gist table { + width: auto; + + td { + border: 0; + } +} + +pre { + @extend $code-block; + overflow: auto; + padding: 10px; + position: relative; + + code { + background: none; + padding: 0; + text-shadow: none; + } +} diff --git a/themes/next/source/css/_common/scaffolding/index.styl b/themes/next/source/css/_common/scaffolding/index.styl new file mode 100644 index 0000000..3d07e6e --- /dev/null +++ b/themes/next/source/css/_common/scaffolding/index.styl @@ -0,0 +1,12 @@ +// +// Scaffolding +// ================================================== +@import 'normalize'; +@import 'base'; +@import 'tables'; +@import 'buttons'; +@import 'toggles'; +@import 'highlight'; +@import 'tags'; +@import 'pagination'; +@import 'comments'; diff --git a/themes/next/source/css/_common/scaffolding/normalize.styl b/themes/next/source/css/_common/scaffolding/normalize.styl new file mode 100644 index 0000000..836c948 --- /dev/null +++ b/themes/next/source/css/_common/scaffolding/normalize.styl @@ -0,0 +1,289 @@ +/* normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ +/* Document +========================================================================== */ +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ +html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections +========================================================================== */ +/** + * Remove the margin in all browsers. + */ +body { + margin: 0; +} + +/** + * Render the `main` element consistently in IE. + */ +main { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ +h1 { + font-size: 2em; + margin: .67em 0; +} + +/* Grouping content +========================================================================== */ +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics +========================================================================== */ +/** + * Remove the gray background on active links in IE 10. + */ +a { + background: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ +b, strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ +code, kbd, samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ +sub, sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -.25em; +} + +sup { + top: -.5em; +} + +/* Embedded content +========================================================================== */ +/** + * Remove the border on images inside links in IE 10. + */ +img { + border-style: none; +} + +/* Forms +========================================================================== */ +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ +button, input, optgroup, select, textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ +button, input { + /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ +button, select { + /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ +button, [type='button'], [type='reset'], [type='submit'] { + -webkit-appearance: button; +} + +/** + * Remove the inner border and padding in Firefox. + */ +button::-moz-focus-inner, [type='button']::-moz-focus-inner, [type='reset']::-moz-focus-inner, [type='submit']::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ +button:-moz-focusring, [type='button']:-moz-focusring, [type='reset']:-moz-focusring, [type='submit']:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ +fieldset { + padding: .35em .75em .625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ +[type='checkbox'], [type='radio'] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ +[type='number']::-webkit-inner-spin-button, [type='number']::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ +[type='search'] { + outline-offset: -2px; /* 2 */ + -webkit-appearance: textfield; /* 1 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ +[type='search']::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ +::-webkit-file-upload-button { + font: inherit; /* 2 */ + -webkit-appearance: button; /* 1 */ +} + +/* Interactive +========================================================================== */ +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ +summary { + display: list-item; +} + +/* Misc +========================================================================== */ +/** + * Add the correct display in IE 10+. + */ +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ +[hidden] { + display: none; +} diff --git a/themes/next/source/css/_common/scaffolding/pagination.styl b/themes/next/source/css/_common/scaffolding/pagination.styl new file mode 100644 index 0000000..6a28aeb --- /dev/null +++ b/themes/next/source/css/_common/scaffolding/pagination.styl @@ -0,0 +1,55 @@ +$page-number-basic { + display: inline-block; + margin: -1px 10px 0; + padding: 0 10px; + + +mobile() { + margin: 0 5px; + } +} + +$page-number-current { + background: $pagination-active-bg; + border-color: $pagination-active-border; + color: $pagination-active-color; +} + +.pagination { + border-top: 1px solid $pagination-border; + margin: 120px 0 0; + text-align: $scheme-text-align; + + .prev, .next, .page-number { + @extend $page-number-basic; + border-bottom: 0; + border-top: 1px solid $pagination-link-border; + transition: border-color $transition-ease; + + &:hover { + border-top-color: $pagination-link-hover-border; + } + } + + +mobile() { + border-top: 0; + + .prev, .next, .page-number { + border-bottom: 1px solid $pagination-link-border; + border-top: 0; + + &:hover { + border-bottom-color: $pagination-link-hover-border; + } + } + } + + .space { + @extend $page-number-basic; + margin: 0; + padding: 0; + } + + .page-number.current { + @extend $page-number-current; + } +} diff --git a/themes/next/source/css/_common/scaffolding/tables.styl b/themes/next/source/css/_common/scaffolding/tables.styl new file mode 100644 index 0000000..28514d8 --- /dev/null +++ b/themes/next/source/css/_common/scaffolding/tables.styl @@ -0,0 +1,39 @@ +.table-container { + overflow: auto; +} + +table { + border-collapse: collapse; + border-spacing: 0; + font-size: $table-font-size; + margin: 0 0 20px; + width: 100%; +} + +tbody tr { + &:nth-of-type(odd) { + background: var(--table-row-odd-bg-color); + } + + &:hover { + background: var(--table-row-hover-bg-color); + } +} + +caption, th, td { + padding: 8px; +} + +th, td { + border: 1px solid $table-border-color; + border-bottom: 3px solid $table-cell-border-bottom-color; +} + +th { + font-weight: 700; + padding-bottom: 10px; +} + +td { + border-bottom-width: 1px; +} diff --git a/themes/next/source/css/_common/scaffolding/tags/blockquote-center.styl b/themes/next/source/css/_common/scaffolding/tags/blockquote-center.styl new file mode 100644 index 0000000..0349eb3 --- /dev/null +++ b/themes/next/source/css/_common/scaffolding/tags/blockquote-center.styl @@ -0,0 +1,34 @@ +// Blockquote with all children centered. +.blockquote-center { + border-left: 0; + margin: 40px 0; + padding: 0; + position: relative; + text-align: center; + + &::before, &::after { + left: 0; + line-height: 1; + opacity: .6; + position: absolute; + width: 100%; + } + + &::before { + border-top: 1px solid $grey-light; + text-align: left; + top: -20px; + font-family-icons('\f10d'); + } + + &::after { + border-bottom: 1px solid $grey-light; + bottom: -20px; + text-align: right; + font-family-icons('\f10e'); + } + + p, div { + text-align: center; + } +} diff --git a/themes/next/source/css/_common/scaffolding/tags/group-pictures.styl b/themes/next/source/css/_common/scaffolding/tags/group-pictures.styl new file mode 100644 index 0000000..9583d7c --- /dev/null +++ b/themes/next/source/css/_common/scaffolding/tags/group-pictures.styl @@ -0,0 +1,20 @@ +.group-picture { + margin-bottom: 20px; + + .group-picture-row { + display: flex; + gap: 3px; + margin-bottom: 3px; + } + + .group-picture-column { + flex: 1; + + img { + height: 100%; + margin: 0; + object-fit: cover; + width: 100%; + } + } +} diff --git a/themes/next/source/css/_common/scaffolding/tags/index.styl b/themes/next/source/css/_common/scaffolding/tags/index.styl new file mode 100644 index 0000000..aedf0d8 --- /dev/null +++ b/themes/next/source/css/_common/scaffolding/tags/index.styl @@ -0,0 +1,8 @@ +@import 'blockquote-center'; +@import 'group-pictures'; +@import 'label'; +@import 'link-grid'; +@import 'mermaid'; +@import 'note'; +@import 'pdf'; +@import 'tabs'; diff --git a/themes/next/source/css/_common/scaffolding/tags/label.styl b/themes/next/source/css/_common/scaffolding/tags/label.styl new file mode 100644 index 0000000..39fe51b --- /dev/null +++ b/themes/next/source/css/_common/scaffolding/tags/label.styl @@ -0,0 +1,10 @@ +.post-body .label { + color: $text-color; + padding: 0 2px; + + for $type in $note-types { + &.{$type} { + background: $label[$type]; + } + } +} diff --git a/themes/next/source/css/_common/scaffolding/tags/link-grid.styl b/themes/next/source/css/_common/scaffolding/tags/link-grid.styl new file mode 100644 index 0000000..26bd1d9 --- /dev/null +++ b/themes/next/source/css/_common/scaffolding/tags/link-grid.styl @@ -0,0 +1,113 @@ +.post-body .link-grid { + display: grid; + // https://caniuse.com/mdn-css_properties_gap_grid_context + grid-gap: 1.5rem; + gap: 1.5rem; + grid-template-columns: 1fr 1fr; + margin-bottom: 20px; + padding: 1rem; + + +mobile() { + grid-template-columns: 1fr; + } + + .link-grid-container { + border: solid $grey-lighter; + box-shadow: 1rem 1rem .5rem rgba(0, 0, 0, .5); + min-height: 5rem; + // Fix issue #30 + min-width: 0; + padding: .5rem; + position: relative; + transition: background .3s; + + &:hover { + animation: next-shake .5s; + background: var(--card-bg-color); + } + + &:active { + box-shadow: .5rem .5rem .25rem rgba(0, 0, 0, .5); + transform: translate(.2rem, .2rem); + } + + .link-grid-image { + border: 1px solid $grey-lighter; + border-radius: 50%; + box-sizing: border-box; + height: 5rem; + padding: 3px; + position: absolute; + width: 5rem; + } + + p { + margin: 0 1rem 0 6rem; + + &:first-of-type { + font-size: 1.2em; + } + + &:last-of-type { + font-size: .8em; + line-height: 1.3rem; + opacity: .7; + } + } + + a { + border: 0; + height: 100%; + left: 0; + position: absolute; + top: 0; + width: 100%; + } + } +} + +@keyframes next-shake { + 0% { + transform: translate(1pt, 1pt) rotate(0deg); + } + + 10% { + transform: translate(-1pt, -2pt) rotate(-1deg); + } + + 20% { + transform: translate(-3pt, 0pt) rotate(1deg); + } + + 30% { + transform: translate(3pt, 2pt) rotate(0deg); + } + + 40% { + transform: translate(1pt, -1pt) rotate(1deg); + } + + 50% { + transform: translate(-1pt, 2pt) rotate(-1deg); + } + + 60% { + transform: translate(-3pt, 1pt) rotate(0deg); + } + + 70% { + transform: translate(3pt, 1pt) rotate(-1deg); + } + + 80% { + transform: translate(-1pt, -1pt) rotate(1deg); + } + + 90% { + transform: translate(1pt, 2pt) rotate(0deg); + } + + 100% { + transform: translate(1pt, -2pt) rotate(-1deg); + } +} diff --git a/themes/next/source/css/_common/scaffolding/tags/mermaid.styl b/themes/next/source/css/_common/scaffolding/tags/mermaid.styl new file mode 100644 index 0000000..929d884 --- /dev/null +++ b/themes/next/source/css/_common/scaffolding/tags/mermaid.styl @@ -0,0 +1,6 @@ +if (hexo-config('mermaid.enable')) { + .mermaid { + margin-bottom: 20px; + text-align: center; + } +} diff --git a/themes/next/source/css/_common/scaffolding/tags/note.styl b/themes/next/source/css/_common/scaffolding/tags/note.styl new file mode 100644 index 0000000..ed1c1d3 --- /dev/null +++ b/themes/next/source/css/_common/scaffolding/tags/note.styl @@ -0,0 +1,110 @@ +if (hexo-config('note.style') != 'disabled') { + .post-body .note { + $note-icons = hexo-config('note.icons'); + $note-style = hexo-config('note.style'); + + border-radius: $note-border-radius; + margin-bottom: 20px; + padding: 1em; + position: relative; + + if ($note-style == 'simple') { + border: 1px solid $gainsboro; + border-left-width: 5px; + } + + if ($note-style == 'modern') { + background: $whitesmoke; + border: 1px solid transparent; + } + + if ($note-style == 'flat') { + background: lighten($gainsboro, 65%); + border: initial; + border-left: 3px solid $gainsboro; + } + + summary { + cursor: pointer; + outline: 0; + + p { + display: inline; + } + } + + h2, h3, h4, h5, h6 { + border-bottom: initial; + margin: 0; + padding-top: 0; + } + + :first-child { + margin-top: 0; + } + + :last-child { + margin-bottom: 0; + } + + if ($note-icons) { + &:not(.no-icon) { + padding-left: 2.5em; + + &::before { + font-size: 1.5em; + left: .3em; + position: absolute; + top: calc(50% - 1em); + } + } + } + + for $type in $note-types { + &.{$type} { + if ($note-style == 'flat') { + background: $note-bg[$type]; + if (hexo-config('darkmode')) { + @media (prefers-color-scheme: dark) { + background: mix($note-bg[$type], $body-bg-color-dark, 10%); + } + } + } + + if ($note-style == 'modern') { + background: $note-modern-bg[$type]; + border-color: $note-modern-border[$type]; + color: $note-modern-text[$type]; + + a:not(.btn) { + border-bottom-color: $note-modern-text[$type]; + color: $note-modern-text[$type]; + + &:hover { + border-bottom-color: $note-modern-hover[$type]; + color: $note-modern-hover[$type]; + } + } + } + + if ($note-style != 'modern') { + border-left-color: $note-border[$type]; + + h2, h3, h4, h5, h6 { + color: $note-text[$type]; + } + } + + if ($note-icons) { + &:not(.no-icon)::before { + font-family-icons($note-icon[$type]); + + if ($note-style != 'modern') { + color: $note-text[$type]; + } + } + } + } + } + } +} diff --git a/themes/next/source/css/_common/scaffolding/tags/pdf.styl b/themes/next/source/css/_common/scaffolding/tags/pdf.styl new file mode 100644 index 0000000..9c5709a --- /dev/null +++ b/themes/next/source/css/_common/scaffolding/tags/pdf.styl @@ -0,0 +1,8 @@ +if (hexo-config('pdf.enable')) { + .pdfobject-container { + iframe, embed { + height: convert(hexo-config('pdf.height')); + width: 100%; + } + } +} diff --git a/themes/next/source/css/_common/scaffolding/tags/tabs.styl b/themes/next/source/css/_common/scaffolding/tags/tabs.styl new file mode 100644 index 0000000..00affaa --- /dev/null +++ b/themes/next/source/css/_common/scaffolding/tags/tabs.styl @@ -0,0 +1,103 @@ +.post-body .tabs { + margin-bottom: 20px; +} + +.post-body .tabs, .tabs-comment { + padding-top: 10px; + + ul.nav-tabs { + background: (($scheme == 'Muse') or ($scheme == 'Mist')) ? var(--body-bg-color) : var(--content-bg-color); + display: flex; + flex-wrap: wrap; + margin: 0; + padding: 0; + position: -webkit-sticky; + position: sticky; + top: 0; + // Fix issue #398 + z-index: $zindex-0; + + +mobile-smallest() { + display: block; + margin-bottom: 5px; + } + + li.tab { + border-bottom: 1px solid $grey-lighter; + border-left: 1px solid transparent; + border-right: 1px solid transparent; + border-radius: $tbr $tbr 0 0; + border-top: 3px solid transparent; + flex-grow: 1; + list-style-type: none; + + +mobile-smallest() { + border-bottom: 1px solid transparent; + border-left: 3px solid transparent; + border-right: 1px solid transparent; + border-top: 1px solid transparent; + } + + +mobile-smallest() { + border-radius: $tbr; + } + + if (hexo-config('tabs.transition.tabs')) { + transition: all $transition-ease-out; + } + + a { + border-bottom: initial; + display: block; + line-height: 1.8; + padding: .25em .75em; + text-align: center; + + i { + width: (18em / 14); + } + + if (hexo-config('tabs.transition.labels')) { + transition: all $transition-ease-out; + } + } + + &.active { + border-bottom-color: transparent; + border-left-color: $table-border-color; + border-right-color: $table-border-color; + border-top-color: $orange; + + +mobile-smallest() { + border-bottom-color: $table-border-color; + border-left-color: $orange; + border-right-color: $table-border-color; + border-top-color: $table-border-color; + } + + a { + cursor: default; + } + } + } + } + + .tab-content { + border: 1px solid $table-border-color; + border-radius: 0 0 $tbr $tbr; + border-top-color: transparent; + + +mobile-smallest() { + border-radius: $tbr; + border-top-color: $table-border-color; + } + + .tab-pane { + padding: 20px 20px 0; + + &:not(.active) { + display: none; + } + } + } +} diff --git a/themes/next/source/css/_common/scaffolding/toggles.styl b/themes/next/source/css/_common/scaffolding/toggles.styl new file mode 100644 index 0000000..86aab78 --- /dev/null +++ b/themes/next/source/css/_common/scaffolding/toggles.styl @@ -0,0 +1,30 @@ +.toggle { + line-height: 0; + + .toggle-line { + background: white; + display: block; + height: 2px; + left: 0; + position: relative; + top: 0; + transition: all .4s; + width: 100%; + + &:first-child { + margin-top: 1px; + } + + &:not(:first-child) { + margin-top: 4px; + } + } +} + +.toggle.toggle-arrow { + toggle-arrow(hexo-config('sidebar.position')); +} + +.toggle.toggle-close { + toggle-close(hexo-config('sidebar.position')); +} diff --git a/themes/next/source/css/_mixins.styl b/themes/next/source/css/_mixins.styl new file mode 100644 index 0000000..08b15e1 --- /dev/null +++ b/themes/next/source/css/_mixins.styl @@ -0,0 +1,271 @@ +mobile-smallest() { + @media (max-width: 413px) { + {block}; + } +} + +mobile-small() { + @media (max-width: 567px) { + {block}; + } +} + +mobile() { + @media (max-width: 767px) { + {block}; + } +} + +tablet-mobile() { + @media (max-width: 991px) { + {block}; + } +} + +tablet-desktop() { + @media (min-width: 768px) { + {block}; + } +} + +tablet() { + @media (min-width: 768px) and (max-width: 991px) { + {block}; + } +} + +desktop() { + @media (min-width: 992px) { + {block}; + } +} + +desktop-large() { + @media (min-width: 1200px) { + {block}; + } +} + +desktop-largest() { + @media (min-width: 1600px) { + {block}; + } +} + +random-color($min, $max) { + return floor(math(0, 'random') * ($max - $min + 1) + $min); +} + +word-wrap() { + overflow-wrap: break-word; +} + +disable-user-select() { + -moz-user-select: none; + -ms-user-select: none; + -webkit-user-select: none; + user-select: none; +} + +sidebar-inline-links-item() { + margin: 5px 0 0; + + a { + box-sizing: border-box; + display: inline-block; + max-width: 100%; + overflow: hidden; + padding: 0 5px; + text-overflow: ellipsis; + white-space: nowrap; + } +} + +flex-wrap() { + display: flex; + flex-wrap: wrap; + justify-content: center; +} + +flex-column() { + display: flex; + flex-direction: column; + justify-content: center; +} + +post-card() { + background: var(--card-bg-color); + border-left: 3px solid $red; + margin: $post-card-margin; +} + +font-family-icons($icon = '') { + if ($icon) { + content: $icon; + } + font-family: 'Font Awesome 6 Free'; + font-weight: 900; +} + +main-container() { + margin: 0 auto; + width: $content-desktop; + + +mobile() { + width: auto; + } + + +desktop-large() { + width: $content-desktop-large; + } + + +desktop-largest() { + width: $content-desktop-largest; + } +} + +sidebar-toggle-alignment($reverse) { + $condition = hexo-config('sidebar.position') == 'right'; + if (($scheme == 'Muse') or ($scheme == 'Mist')) { + $condition = $condition == $reverse; + } + return $condition ? ('left' 'right') : ('right' 'left'); +} + +sidebar-toggle-position($reverse) { + $alignment = sidebar-toggle-alignment($reverse)[0]; + {$alignment}: $b2t-position-right; + +tablet-mobile() { + {$alignment}: $b2t-position-right-mobile; + } +} + +sidebar-toggle() { + background: $b2t-bg-color; + cursor: pointer; + opacity: $b2t-opacity; + position: fixed; + z-index: $zindex-3; + sidebar-toggle-position(false); + + &:hover { + opacity: $b2t-opacity-hover; + } + + +tablet-mobile() { + opacity: $b2t-opacity-hover; + } +} + +round-icon($diameter) { + border-radius: 50%; + content: ' '; + height: $diameter; + width: $diameter; +} + +toggle-arrow($position) { + if ($position == 'right') { + :first-child { + top: 2px; + transform: rotate(-45deg); + width: 50%; + } + + :last-child { + top: -2px; + transform: rotate(45deg); + width: 50%; + } + } else { + :first-child { + left: 50%; + top: 2px; + transform: rotate(45deg); + width: 50%; + } + + :last-child { + left: 50%; + top: -2px; + transform: rotate(-45deg); + width: 50%; + } + } +} + +toggle-close($position) { + :nth-child(2) { + opacity: 0; + } + + if ($position == 'right') { + :first-child { + top: 6px; + transform: rotate(-45deg); + } + + :last-child { + top: -6px; + transform: rotate(45deg); + } + } else { + :first-child { + top: 6px; + transform: rotate(45deg); + } + + :last-child { + top: -6px; + transform: rotate(-45deg); + } + } +} + +site-nav-hide-by-default() { + --scroll-height: 0; + height: 0; + overflow: hidden; + transition: height $transition-ease; + + body:not(.site-nav-on) & .animated { + animation: none; + } + + body.site-nav-on & { + height: var(--scroll-height); + } +} + +button($color) { + background: transparent; + color: $color; + cursor: pointer; + line-height: 2; + padding: 0 15px; + + &:hover { + background: $color; + color: white; + } +} + +gemini-block() { + background: var(--content-bg-color); + border-radius: $border-radius-inner; + box-shadow: $box-shadow-inner; +} + +gemini-block-not-first() { + border-radius: $border-radius; + box-shadow: $box-shadow; + margin-top: $sidebar-offset; + + +tablet() { + margin-top: $content-tablet-padding; + } + + +mobile() { + margin-top: $content-mobile-padding; + } +} diff --git a/themes/next/source/css/_schemes/Gemini/index.styl b/themes/next/source/css/_schemes/Gemini/index.styl new file mode 100644 index 0000000..6becc40 --- /dev/null +++ b/themes/next/source/css/_schemes/Gemini/index.styl @@ -0,0 +1,124 @@ +@import '../Pisces/_layout'; +@import '../Pisces/_header'; +@import '../Pisces/_menu'; +@import '../Pisces/_sub-menu'; +@import '../Pisces/_sidebar'; + +// ================================================== +// Rewrite _layout.styl +// ================================================== +// Sidebar padding used as main desktop content padding for sidebar padding and post blocks padding too. + +// In `source/css/_variables/Pisces.styl` there are variable for main offset: +// $sidebar-offset = 12px; +// This value alse can be changed in main NexT config as `sidebar: offset: 12` option. + +// In `source/css/_variables/base.styl` there are variables for other resolutions: +// $content-tablet-padding = 10px; +// $content-mobile-padding = 8px; +// P.S. If u want to change this paddings u may set this variables into `custom_file_path.variable` (in theme _config.yml). + +// So, it will 12px in Desktop, 10px in Tablets and 8px in Mobiles for all possible paddings. + +// ================================================== +// Desktop layout styles. +// ================================================== +// Post blocks. +.main-inner { + .sub-menu, .post-block, .tabs-comment, & > .comments, .comment-position .comments, .pagination { + gemini-block(); + } + + .post-block:not(:first-child) { + &:not(:first-child) { + gemini-block-not-first(); + } + } + + .tabs-comment, & > .comments, .comment-position .comments, .pagination { + gemini-block-not-first(); + } +} + +// Post & Comments blocks. +.post-block, .comments { + padding: $content-desktop-padding; +} + +// Post delimiters. +.post-eof { + display: none; +} + +// Pagination. +.pagination { + border-top: initial; + padding: 10px 0; +} + +// ================================================== +// Headers. +// ================================================== +.post-body { + h1, h2 { + border-bottom: 1px solid $body-bg-color; + } + + h3 { + border-bottom: 1px dotted $body-bg-color; + } +} + +// ================================================== +// > 768px & < 991px +// ================================================== ++tablet() { + // Posts in blocks. + .main-inner { + padding: $content-tablet-padding; + } + + .posts-expand { + // Components inside Posts. + .post-button { + margin-top: ($content-tablet-padding * 2); + } + } + + .post-block { + // Inside posts blocks content padding (default 40px). + padding: ($content-tablet-padding * 2); + } + + .comments { + padding: $content-tablet-padding ($content-tablet-padding * 2); + // padding: initial; + // padding-top: $content-tablet-padding; + } +} + +// ================================================== +// < 767px +// ================================================== ++mobile() { + // Posts in blocks. + .main-inner { + padding: $content-mobile-padding; + } + + .posts-expand { + // Components inside Posts. + .post-button { + margin: $sidebar-offset 0; + } + } + + .post-block { + // Inside posts blocks content padding (default 40px). + padding: $sidebar-offset; + } + + .comments { + padding: 10px $sidebar-offset; + } +} diff --git a/themes/next/source/css/_schemes/Mist/_header.styl b/themes/next/source/css/_schemes/Mist/_header.styl new file mode 100644 index 0000000..a376820 --- /dev/null +++ b/themes/next/source/css/_schemes/Mist/_header.styl @@ -0,0 +1,58 @@ +// Header +// -------------------------------------------------- +.column { + background: var(--content-bg-color); +} + +.header { + align-items: center; + display: flex; + padding: 20px 0; + + +mobile() { + display: block; + padding: 10px 0; + } +} + +.site-meta { + line-height: normal; + + .brand { + +mobile() { + display: block; + } + } + + .site-title { + font-weight: bolder; + } +} + +.logo-line { + background: var(--brand-color); + display: block; + height: 2px; + margin: 0 auto; + width: 75%; + + +mobile() { + display: none; + } +} + +.use-motion { + .logo-line:first-of-type { + transform: scaleX(0); + transform-origin: left; + } + + .logo-line:last-of-type { + transform: scaleX(0); + transform-origin: right; + } +} + +.site-subtitle { + display: none; +} diff --git a/themes/next/source/css/_schemes/Mist/_layout.styl b/themes/next/source/css/_schemes/Mist/_layout.styl new file mode 100644 index 0000000..2b8fb2d --- /dev/null +++ b/themes/next/source/css/_schemes/Mist/_layout.styl @@ -0,0 +1,39 @@ +// Tags +// -------------------------------------------------- +hr { + height: 2px; + margin: 20px 0; +} + +// Components +// -------------------------------------------------- +.btn { + padding: 0 10px; +} + +.headband { + display: none; +} + +// Pagination +// -------------------------------------------------- +.pagination { + +mobile() { + margin: 80px 0 0; + text-align: center; + } +} + +// Footer +// -------------------------------------------------- +.footer { + background: var(--content-bg-color); + color: var(--text-color); + padding: 10px 0; +} + +.footer-inner { + +mobile() { + text-align: center; + } +} diff --git a/themes/next/source/css/_schemes/Mist/_menu.styl b/themes/next/source/css/_schemes/Mist/_menu.styl new file mode 100644 index 0000000..15cc0c4 --- /dev/null +++ b/themes/next/source/css/_schemes/Mist/_menu.styl @@ -0,0 +1,45 @@ +// Menu +// -------------------------------------------------- +.site-nav { + flex-grow: 1; + + +mobile() { + padding: 0 10px 0; + } +} + +.main-menu { + +mobile() { + padding-top: 10px; + } +} + +.menu { + padding: 0; + + .menu-item { + margin: 0; + + +mobile() { + margin-top: 5px; + } + + a { + border-radius: 2px; + padding: 0 10px; + transition-property: background; + + +mobile() { + text-align: left; + } + } + + .badge { + background: white; + border-radius: 10px; + color: $black-light; + padding: 1px 4px; + text-shadow: 1px 1px 0 rgba(0, 0, 0, .1); + } + } +} diff --git a/themes/next/source/css/_schemes/Mist/_posts-expand.styl b/themes/next/source/css/_schemes/Mist/_posts-expand.styl new file mode 100644 index 0000000..37bda81 --- /dev/null +++ b/themes/next/source/css/_schemes/Mist/_posts-expand.styl @@ -0,0 +1,69 @@ +// Post Expand +// -------------------------------------------------- +.posts-expand { + &.index { + .post-header { + text-align: $scheme-text-align; + + +mobile() { + text-align: center; + } + } + + .post-meta-container { + margin-top: 5px; + } + + .post-meta { + justify-content: flex-start; + + +mobile() { + justify-content: center; + } + } + } + + .post-eof { + display: none; + } + + .post-block:not(:first-of-type) { + margin-top: 120px; + } + + .post-header { + margin-bottom: 20px; + } + + .post-tags { + a { + background: var(--content-bg-color); + border-bottom: 0; + padding: 1px 5px; + + &:hover { + background: var(--menu-item-bg-color); + } + } + } + + .post-nav { + margin-top: 40px; + } +} + +.post-button { + margin-top: 20px; + + .btn { + background: none; + border: 0; + border-bottom: 2px solid var(--btn-default-border-color); + padding: 0; + transition-property: border; + + &:hover { + border-bottom-color: var(--btn-default-hover-border-color); + } + } +} diff --git a/themes/next/source/css/_schemes/Mist/index.styl b/themes/next/source/css/_schemes/Mist/index.styl new file mode 100644 index 0000000..a358dfa --- /dev/null +++ b/themes/next/source/css/_schemes/Mist/index.styl @@ -0,0 +1,10 @@ +// +// Mist scheme +// ================================================== +@import '_layout'; +@import '_header'; +@import '_menu'; +@import '_posts-expand'; +@import '../Muse/_layout'; +@import '../Muse/_sidebar'; +@import '../Muse/_sub-menu'; diff --git a/themes/next/source/css/_schemes/Muse/_header.styl b/themes/next/source/css/_schemes/Muse/_header.styl new file mode 100644 index 0000000..bdabfd0 --- /dev/null +++ b/themes/next/source/css/_schemes/Muse/_header.styl @@ -0,0 +1,18 @@ +.custom-logo-image { + background: white; + margin: 0 auto 10px; + max-width: 150px; + padding: 5px; +} + +.brand { + background: var(--btn-default-bg); +} + +.header { + padding-top: 100px; + + +mobile() { + padding-top: 50px; + } +} diff --git a/themes/next/source/css/_schemes/Muse/_layout.styl b/themes/next/source/css/_schemes/Muse/_layout.styl new file mode 100644 index 0000000..2fbc8d5 --- /dev/null +++ b/themes/next/source/css/_schemes/Muse/_layout.styl @@ -0,0 +1,23 @@ +.header { + main-container(); +} + +.main-inner { + main-container(); + padding-bottom: $content-padding-bottom; + + +mobile() { + padding-left: 20px; + padding-right: 20px; + } +} + +// Page - Container +// -------------------------------------------------- +.post-block:first-of-type { + padding-top: $posts-first-padding; + + +mobile() { + padding-top: $posts-first-padding-mobile; + } +} diff --git a/themes/next/source/css/_schemes/Muse/_menu.styl b/themes/next/source/css/_schemes/Muse/_menu.styl new file mode 100644 index 0000000..8529e64 --- /dev/null +++ b/themes/next/source/css/_schemes/Muse/_menu.styl @@ -0,0 +1,56 @@ +.site-nav { + +mobile() { + padding-top: 30px; + } +} + +.main-menu { + +mobile() { + border-bottom: 1px solid $grey-lighter; + border-top: 1px solid $grey-lighter; + } +} + +.menu { + +mobile() { + text-align: left; + } +} + +.menu .menu-item { + +mobile() { + margin: 0 10px; + } + + a { + border-bottom: 1px solid transparent; + + +mobile() { + padding: 5px 10px; + } + + &:hover, &.menu-item-active { + background: transparent; + border-bottom: 1px solid var(--link-hover-color); + + +mobile() { + border-bottom: 1px dotted $grey-lighter; + } + } + } + + .fa, .fab, .far, .fas { + +tablet-desktop() { + display: block; + line-height: 2; + margin-right: 0; + width: 100%; + } + } + + .badge { + background: $gainsboro; + color: $black-light; + padding: 1px 4px; + } +} diff --git a/themes/next/source/css/_schemes/Muse/_sidebar.styl b/themes/next/source/css/_schemes/Muse/_sidebar.styl new file mode 100644 index 0000000..22cd2b6 --- /dev/null +++ b/themes/next/source/css/_schemes/Muse/_sidebar.styl @@ -0,0 +1,126 @@ +if (hexo-config('sidebar.position') == 'right') { + .sidebar-active { + // Note: $sidebar-desktop + $content-desktop-large should be less than desktop-large threshold + // Otherwise a horizontal scrollbar will appear + +desktop-large() { + padding-right: $sidebar-desktop; + } + } + + .sidebar { + right: 0 - $sidebar-desktop; + + .sidebar-active & { + right: 0; + } + } +} else { + .sidebar-active { + +desktop-large() { + padding-left: $sidebar-desktop; + } + } + + .sidebar { + left: 0 - $sidebar-desktop; + + .sidebar-active & { + left: 0; + } + } +} + +.sidebar { + background: $black-deep; + bottom: 0; + if (not hexo-config('back2top.sidebar')) { + box-shadow: inset 0 2px 6px black; + } + max-height: 100vh; + overflow-y: auto; + position: fixed; + top: 0; + transition: all $transition-ease-out; + width: $sidebar-desktop; + z-index: $zindex-2; + + a { + border-bottom-color: $black-light; + color: $grey-dark; + + &:hover { + border-bottom-color: $gainsboro; + color: $gainsboro; + } + } +} + +.links-of-author { + &:not(:first-child) { + margin-top: 15px; + } + + a { + border-bottom-color: $black-light; + display: inline-block; + margin-bottom: 10px; + margin-right: 10px; + vertical-align: middle; + + if (hexo-config('social_icons.transition')) { + transition: all $transition-ease; + } + + &::before { + background: rgb(random-color(0, 255) - 50%, random-color(0, 255) - 50%, random-color(0, 255) - 50%); + display: inline-block; + margin-right: 3px; + transform: translateY(-2px); + round-icon(4px); + } + } +} + +.links-of-blogroll-item { + if (hexo-config('links_settings.layout') == 'inline') { + display: inline-block; + } + padding: 2px 10px; + + a { + box-sizing: border-box; + display: inline-block; + max-width: 280px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } +} + +.popular-posts .popular-posts-item .popular-posts-link:hover { + background: none; +} + +.sidebar-dimmer { + background: black; + height: 100%; + left: 0; + opacity: 0; + position: fixed; + top: 0; + transition: visibility .4s, opacity .4s; + visibility: hidden; + width: 100%; + z-index: $zindex-1; + + .sidebar-active & { + opacity: .7; + visibility: visible; + } +} + ++desktop-large() { + .sidebar-dimmer { + display: none; + } +} diff --git a/themes/next/source/css/_schemes/Muse/_sub-menu.styl b/themes/next/source/css/_schemes/Muse/_sub-menu.styl new file mode 100644 index 0000000..4e798a3 --- /dev/null +++ b/themes/next/source/css/_schemes/Muse/_sub-menu.styl @@ -0,0 +1,7 @@ +.sub-menu { + margin: 10px 0; + + .menu-item { + display: inline-block; + } +} diff --git a/themes/next/source/css/_schemes/Muse/index.styl b/themes/next/source/css/_schemes/Muse/index.styl new file mode 100644 index 0000000..5bc7242 --- /dev/null +++ b/themes/next/source/css/_schemes/Muse/index.styl @@ -0,0 +1,5 @@ +@import '_layout'; +@import '_header'; +@import '_menu'; +@import '_sub-menu'; +@import '_sidebar'; diff --git a/themes/next/source/css/_schemes/Pisces/_header.styl b/themes/next/source/css/_schemes/Pisces/_header.styl new file mode 100644 index 0000000..1da9548 --- /dev/null +++ b/themes/next/source/css/_schemes/Pisces/_header.styl @@ -0,0 +1,35 @@ +.column { + width: $sidebar-desktop; + + +tablet-mobile() { + width: auto; + } +} + +.site-brand-container { + background: var(--theme-color); + + .site-nav-on & { + +tablet-mobile() { + box-shadow: 0 0 16px rgba(0, 0, 0, .5); + } + } +} + +.site-meta { + padding: 20px 0; +} + +.site-nav-toggle, .site-nav-right { + +tablet() { + flex-column(); + } + + .toggle { + color: white; + + .toggle-line { + background: white; + } + } +} diff --git a/themes/next/source/css/_schemes/Pisces/_layout.styl b/themes/next/source/css/_schemes/Pisces/_layout.styl new file mode 100644 index 0000000..0d2d730 --- /dev/null +++ b/themes/next/source/css/_schemes/Pisces/_layout.styl @@ -0,0 +1,52 @@ +.header { + background: var(--content-bg-color); + border-radius: $border-radius-inner; + box-shadow: $box-shadow-inner; + + +tablet-mobile() { + border-radius: initial; + } +} + +.main { + // Make sure that .header and .main-inner are the same height + // Required for .sidebar `position: sticky;` + align-items: stretch; + display: flex; + justify-content: space-between; + main-container(); + + if (hexo-config('sidebar.position') == 'right') { + flex-direction: row-reverse; + } + + +tablet-mobile() { + display: block; + width: auto; + } +} + +.main-inner { + border-radius: $border-radius-inner; + box-sizing: border-box; + width: $content-wrap; + + +tablet-mobile() { + border-radius: initial; + width: 100%; + } +} + +.footer-inner { + if (hexo-config('sidebar.position') == 'right') { + padding-right: $sidebar-desktop + $sidebar-offset; + } else { + padding-left: $sidebar-desktop + $sidebar-offset; + } + + +tablet-mobile() { + padding-left: 0; + padding-right: 0; + width: auto; + } +} diff --git a/themes/next/source/css/_schemes/Pisces/_menu.styl b/themes/next/source/css/_schemes/Pisces/_menu.styl new file mode 100644 index 0000000..15d38b5 --- /dev/null +++ b/themes/next/source/css/_schemes/Pisces/_menu.styl @@ -0,0 +1,46 @@ +.site-nav { + +tablet() { + site-nav-hide-by-default(); + } +} + +.menu .menu-item { + display: block; + margin: 0; + + a { + padding: 5px 20px; + position: relative; + text-align: left; + transition-property: background-color; + } + + +tablet-mobile() { + &.menu-item-search { + display: none; + } + } + + .badge { + background: $grey-light; + border-radius: 10px; + color: var(--content-bg-color); + float: right; + padding: 2px 5px; + text-shadow: 1px 1px 0 rgba(0, 0, 0, .1); + } +} + +if (not hexo-config('menu_settings.badges')) { + .main-menu .menu-item-active::after { + background: $grey; + border-radius: 50%; + content: ' '; + height: 6px; + margin-top: -3px; + position: absolute; + right: 15px; + top: 50%; + width: 6px; + } +} diff --git a/themes/next/source/css/_schemes/Pisces/_sidebar.styl b/themes/next/source/css/_schemes/Pisces/_sidebar.styl new file mode 100644 index 0000000..bf0fe4c --- /dev/null +++ b/themes/next/source/css/_schemes/Pisces/_sidebar.styl @@ -0,0 +1,88 @@ +.sidebar { + // https://caniuse.com/css-sticky + position: -webkit-sticky; + position: sticky; + top: $sidebar-offset; + + +tablet-mobile() { + display: none; + } +} + +.sidebar-inner { + background: var(--content-bg-color); + border-radius: $border-radius; + box-shadow: $box-shadow; + box-sizing: border-box; + color: var(--text-color); + margin-top: $sidebar-offset; + max-height: 'calc(100vh - %s)' % unit($sidebar-offset * 2, 'px'); + + if (hexo-config('motion.enable') and hexo-config('motion.transition.sidebar')) { + visibility: hidden; + } +} + +.site-state-item { + padding: 0 10px; +} + +.sidebar .sidebar-button { + border-bottom: 1px dotted $grey-light; + border-top: 1px dotted $grey-light; + + button { + border: 0; + color: $orange; + display: block; + width: 100%; + + &:hover { + background: none; + border: 0; + color: darken($orange, 20%); + } + } +} + +.links-of-author { + flex-wrap(); +} + +.links-of-author-item { + sidebar-inline-links-item(); + + if (not hexo-config('social_icons.icons_only')) { + width: 50%; + } + + a { + border-bottom: 0; + border-radius: 4px; + display: block; + + &:hover { + background: var(--body-bg-color); + } + } +} + +.links-of-blogroll-item { + if (hexo-config('links_settings.layout') == 'inline') { + display: inline-block; + max-width: 100%; + sidebar-inline-links-item(); + } +} + +if (hexo-config('back2top.sidebar')) { + // Only when back2top.sidebar is true, apply the following styles + .back-to-top { + background: var(--body-bg-color); + margin: 8px - $sidebar-offset -10px -18px; + + &.back-to-top-on { + margin-top: 16px; + } + } +} diff --git a/themes/next/source/css/_schemes/Pisces/_sub-menu.styl b/themes/next/source/css/_schemes/Pisces/_sub-menu.styl new file mode 100644 index 0000000..82b21e8 --- /dev/null +++ b/themes/next/source/css/_schemes/Pisces/_sub-menu.styl @@ -0,0 +1,28 @@ +.sub-menu { + margin: 0; + padding: 6px 0; + + .menu-item { + display: inline-block; + + a { + background: transparent; + margin: 5px 10px; + padding: initial; + + &:hover { + background: transparent; + color: $sidebar-highlight; + } + } + } + + .menu-item-active { + border-bottom-color: $sidebar-highlight; + color: $sidebar-highlight; + + &:hover { + border-bottom-color: $sidebar-highlight; + } + } +} diff --git a/themes/next/source/css/_schemes/Pisces/index.styl b/themes/next/source/css/_schemes/Pisces/index.styl new file mode 100644 index 0000000..a2b70ce --- /dev/null +++ b/themes/next/source/css/_schemes/Pisces/index.styl @@ -0,0 +1,30 @@ +@import '_layout'; +@import '_header'; +@import '_menu'; +@import '_sub-menu'; +@import '_sidebar'; + +.main-inner { + background: var(--content-bg-color); + box-shadow: $box-shadow-inner; + padding: $content-desktop-padding; + + +tablet-mobile() { + padding: 20px; + } +} + +// Sub-menu(s). +.sub-menu { + border-bottom: 1px solid $table-border-color; +} + +.post-block:first-of-type { + padding-top: 40px; +} + +.pagination { + +mobile() { + margin-bottom: 10px; + } +} diff --git a/themes/next/source/css/_variables/Gemini.styl b/themes/next/source/css/_variables/Gemini.styl new file mode 100644 index 0000000..a2282a8 --- /dev/null +++ b/themes/next/source/css/_variables/Gemini.styl @@ -0,0 +1,18 @@ +// Variables of Gemini scheme +// ================================================== + +@import 'Pisces'; + +// Settings for some of the most global styles. +// -------------------------------------------------- +$body-bg-color = #eee; + +// Borders. +// -------------------------------------------------- +$box-shadow-inner = 0 2px 2px 0 rgba(0, 0, 0, .12), 0 3px 1px -2px rgba(0, 0, 0, .06), 0 1px 5px 0 rgba(0, 0, 0, .12); +$box-shadow = 0 2px 2px 0 rgba(0, 0, 0, .12), 0 3px 1px -2px rgba(0, 0, 0, .06), 0 1px 5px 0 rgba(0, 0, 0, .12), 0 -1px .5px 0 rgba(0, 0, 0, .09); + +$border-radius-inner = initial; +$border-radius = initial; +// $border-radius-inner = 0 0 3px 3px; +// $border-radius = 3px; diff --git a/themes/next/source/css/_variables/Mist.styl b/themes/next/source/css/_variables/Mist.styl new file mode 100644 index 0000000..fbc8c1c --- /dev/null +++ b/themes/next/source/css/_variables/Mist.styl @@ -0,0 +1,27 @@ +// Variables of Mist scheme +// ================================================== + +@import 'Muse'; + +$scheme-text-align = left; + +$content-padding-bottom = 80px; +$posts-first-padding = 80px; +$posts-first-padding-mobile = 60px; + +$link-decoration-color = $grey-light; +$content-bg-color = $whitesmoke; +$menu-item-bg-color = $grey-lighter; + +$brand-color = $black-deep; +$brand-hover-color = $brand-color; +$brand-padding = 2px 1px; + +$posts-collapse-left = 0; + +$btn-default-bg = transparent; +$btn-default-color = var(--link-color); +$btn-default-hover-bg = transparent; +$btn-default-border-color = var(--link-color); +$btn-default-hover-color = var(--link-hover-color); +$btn-default-hover-border-color = var(--link-hover-color); diff --git a/themes/next/source/css/_variables/Muse.styl b/themes/next/source/css/_variables/Muse.styl new file mode 100644 index 0000000..7ede5ad --- /dev/null +++ b/themes/next/source/css/_variables/Muse.styl @@ -0,0 +1,9 @@ +// Variables of Muse scheme +// ================================================== + +$sidebar-width = hexo-config('sidebar.width') is a 'unit' ? hexo-config('sidebar.width') : 320; +$sidebar-desktop = unit($sidebar-width, 'px'); + +$content-padding-bottom = 60px; +$posts-first-padding = 70px; +$posts-first-padding-mobile = 35px; diff --git a/themes/next/source/css/_variables/Pisces.styl b/themes/next/source/css/_variables/Pisces.styl new file mode 100644 index 0000000..bc9cf73 --- /dev/null +++ b/themes/next/source/css/_variables/Pisces.styl @@ -0,0 +1,69 @@ +// Variables of Pisces scheme +// ================================================== + +// Settings for some of the most global styles. +// -------------------------------------------------- +$body-bg-color = #f5f7f9; + +$sidebar-width = hexo-config('sidebar.width') is a 'unit' ? hexo-config('sidebar.width') : 240; +$sidebar-desktop = unit($sidebar-width, 'px'); +$content-wrap = 'calc(100% - %s)' % unit($sidebar-width + $sidebar-offset, 'px'); + +$content-desktop = 'calc(100% - %s)' % unit($content-desktop-padding / 2, 'px'); +$content-desktop-large = 1160px; +$content-desktop-largest = 73%; + + +// Borders +// -------------------------------------------------- +$box-shadow-inner = initial; +$box-shadow = initial; + +$border-radius-inner = initial; +$border-radius = initial; + + +// Header +// -------------------------------------------------- +$subtitle-color = $grey-lighter; +$brand-padding = 0; +$site-subtitle-margin = 10px 10px 0; + + +// Sidebar +// -------------------------------------------------- +$sidebar-nav-color = var(--text-color); +$sidebar-nav-hover-color = $orange; +$sidebar-highlight = $orange; + +$site-author-image-width = 120px; +$site-author-image-border-width = 1px; +$site-author-image-border-color = $gainsboro; + +$site-author-name-margin = 0; +$site-author-name-color = var(--text-color); +$site-author-name-weight = 600; + +$site-description-font-size = $font-size-smaller; +$site-description-color = $grey-dark; +$site-description-margin-top = 0; + +$site-state-item-count-font-size = $font-size-medium; +$site-state-item-name-font-size = $font-size-smaller; +$site-state-item-name-color = $grey-dark; + + +// Components +// -------------------------------------------------- + +// Button +$btn-default-radius = 2px; +$btn-default-bg = white; +$btn-default-color = $text-color; +$btn-default-border-color = $text-color; +$btn-default-hover-bg = $black-deep; +$btn-default-hover-color = white; + +// Back to top +$b2t-opacity = .6; +$b2t-opacity-hover = .8; diff --git a/themes/next/source/css/_variables/base.styl b/themes/next/source/css/_variables/base.styl new file mode 100644 index 0000000..5294ea8 --- /dev/null +++ b/themes/next/source/css/_variables/base.styl @@ -0,0 +1,397 @@ +// +// Variables +// ================================================== + + +// Color system +// -------------------------------------------------- +$whitesmoke = #f5f5f5; +$gainsboro = #eee; +$grey-lighter = #ddd; +$grey-light = #ccc; +$grey = #bbb; +$grey-dark = #999; +$grey-dim = #666; +$black-light = #555; +$black-dim = #333; +$black-deep = #222; +$red = #ff2a2a; +$blue-bright = #87daff; +$blue = #0684bd; +$blue-deep = #262a30; +$orange = #fc6423; + + +// Transition +// -------------------------------------------------- +$transition-ease = .2s ease-in-out; +$transition-ease-in = .2s ease-in; +$transition-ease-out = .2s ease-out; + + +// Scaffolding +// Settings for some of the most global styles. +// -------------------------------------------------- +// Global text color on +$text-color = $black-light; +$text-color-dark = $grey-light; + +// Global link color. +$link-color = $black-light; +$link-color-dark = $grey-light; +$link-hover-color = $black-deep; +$link-hover-color-dark = $gainsboro; +$link-decoration-color = $grey-dark; + +$blockquote-color = $grey-dim; +$blockquote-color-dark = $grey; + +// Global border color. +$border-color = $grey-light; + +// Background color for +$body-bg-color = white; +$body-bg-color-dark = #282828; +$content-bg-color = white; +$content-bg-color-dark = $black-dim; + +// Selection +$selection-bg = $blue-deep; +$selection-color = $gainsboro; + +// Dark mode color +$card-bg-color = $whitesmoke; +$card-bg-color-dark = $black-light; + +$menu-item-bg-color = $whitesmoke; +$menu-item-bg-color-dark = $black-light; + +$theme-color = convert(hexo-config('theme_color.light')); +$theme-color-dark = convert(hexo-config('theme_color.dark')); + +$scheme-text-align = center; + +// Typography +// Font, line-height, and elements colors. +// -------------------------------------------------- +get_font_family(config) { + $custom-family = hexo-config('font.' + config + '.family'); + return $custom-family is a 'string' ? unquote($custom-family) : null; +} + +// Font families. +$font-family-chinese = 'Noto Serif SC'; + +$font-family-base = $font-family-chinese, sans-serif; +$font-family-base = get_font_family('global'), $font-family-chinese, sans-serif if get_font_family('global'); + +$font-family-logo = $font-family-base; +$font-family-logo = get_font_family('title'), $font-family-base if get_font_family('title'); + +$font-family-headings = $font-family-base; +$font-family-headings = get_font_family('headings'), $font-family-base if get_font_family('headings'); + +$font-family-posts = $font-family-base; +$font-family-posts = get_font_family('posts'), $font-family-base if get_font_family('posts'); + +$font-family-monospace = consolas, Menlo, monospace, $font-family-chinese; +$font-family-monospace = get_font_family('codes'), consolas, Menlo, monospace, $font-family-chinese if get_font_family('codes'); + + +// Font size +//$font-size-base = (hexo-config('font.enable') and hexo-config('font.global.size') is a 'unit') ? unit(hexo-config('font.global.size'), em) : 1em; +//$font-size-smallest = .75em; +//$font-size-smaller = .8125em; +//$font-size-small = .875em; +//$font-size-medium = 1em; +//$font-size-large = 1.125em; +//$font-size-larger = 1.25em; +//$font-size-largest = 1.5em; + +$font-size-base = (hexo-config('font.enable') and hexo-config('font.global.size') is a 'unit') ? unit(hexo-config('font.global.size'), em) : 1em; +$font-size-smallest = .75em; +$font-size-smaller = .8125em; +$font-size-small = .875em; +$font-size-medium = .875em; +$font-size-large = 1em; +$font-size-larger = 1.125em; +$font-size-largest = 1.25em; + + +// Headings font size +$font-size-headings-step = .125em; +$font-size-headings-base = (hexo-config('font.enable') and hexo-config('font.headings.size') is a 'unit') ? unit(hexo-config('font.headings.size'), em) : 1.625em; + + +// Global line height +$line-height-base = 2; +$line-height-code-block = 1.6; // Can't be less than 1.3; + + +// Z-index master list +// -------------------------------------------------- +// Fix issue https://github.com/next-theme/theme-next-docs/issues/54 +$zindex-0 = 5; +$zindex-1 = 10; +$zindex-2 = 20; +$zindex-3 = 30; +$zindex-4 = 40; +$zindex-5 = 50; + + +// Table +// -------------------------------------------------- +$table-border-color = $grey-lighter; +$table-font-size = $font-size-small; +$table-cell-border-bottom-color = $grey-lighter; +$table-row-odd-bg-color = #f9f9f9; +$table-row-odd-bg-color-dark = #282828; +$table-row-hover-bg-color = $whitesmoke; +$table-row-hover-bg-color-dark = #363636; + + +// Code & Code Blocks +// -------------------------------------------------- +$code-font-family = $font-family-monospace; + +$highlight-background = convert(hexo-config('highlight.light.background')); +$highlight-foreground = convert(hexo-config('highlight.light.foreground')); +$highlight-gutter-background = mix($highlight-background, $highlight-foreground, 90%); +$highlight-gutter-foreground = mix($highlight-background, $highlight-foreground, 10%); + +$highlight-background-dark = convert(hexo-config('highlight.dark.background')); +$highlight-foreground-dark = convert(hexo-config('highlight.dark.foreground')); +$highlight-gutter-background-dark = mix($highlight-background-dark, $highlight-foreground-dark, 90%); +$highlight-gutter-foreground-dark = mix($highlight-background-dark, $highlight-foreground-dark, 10%); + + +// Buttons +// -------------------------------------------------- +$btn-default-radius = 0; +$btn-default-bg = $black-deep; +$btn-default-bg-dark = $black-deep; +$btn-default-color = white; +$btn-default-color-dark = $text-color-dark; +$btn-default-border-color = $black-deep; +$btn-default-border-color-dark = $black-light; +$btn-default-hover-bg = white; +$btn-default-hover-bg-dark = $grey-dim; +$btn-default-hover-color = $black-deep; +$btn-default-hover-color-dark = $text-color-dark; +$btn-default-hover-border-color = $black-deep; +$btn-default-hover-border-color-dark = $grey-dim; + + +// Pagination +// -------------------------------------------------- +$pagination-border = $gainsboro; + +$pagination-link-bg = transparent; +$pagination-link-color = $link-color; +$pagination-link-border = $gainsboro; + +$pagination-link-hover-bg = transparent; +$pagination-link-hover-color = $link-color; +$pagination-link-hover-border = var(--link-hover-color); + +$pagination-active-bg = $grey-light; +$pagination-active-color = var(--content-bg-color); +$pagination-active-border = $grey-light; + + +// Layout sizes +// -------------------------------------------------- +$content-desktop = 700px; +$content-desktop-large = 800px; +$content-desktop-largest = 900px; + +$content-desktop-padding = 40px; +$content-tablet-padding = 10px; +$content-mobile-padding = 8px; + + +// Headband +// -------------------------------------------------- +$headband-height = 3px; +$headband-bg = var(--theme-color); + + +// Site Meta +// -------------------------------------------------- +$brand-color = white; +$brand-hover-color = white; +$brand-color-dark = $grey-lighter; +$brand-hover-color-dark = $grey-lighter; +$brand-padding = 0 40px; + +$site-subtitle-margin = 10px 0; + +$font-size-title = (hexo-config('font.enable') and hexo-config('font.title.size') is a 'unit') ? unit(hexo-config('font.title.size'), em) : 1.375em; +$font-size-subtitle = $font-size-smaller; +$subtitle-color = $grey-dark; +$site-subtitle-color = $grey-dark; + + +// Posts Collpase +// -------------------------------------------------- +$posts-collapse-margin = 35px; +$posts-collapse-margin-mobile = 0; + + +// Tag Cloud +// -------------------------------------------------- +$tag-cloud-start = #aaa; +$tag-cloud-end = #111; +$tag-cloud-start-dark = #555; +$tag-cloud-end-dark = #eee; + + +// Sidebar +// Variables for sidebar section elements. +// -------------------------------------------------- + +$sidebar-padding = hexo-config('sidebar.padding') is a 'unit' ? unit(hexo-config('sidebar.padding'), px) : 18px; +$sidebar-offset = hexo-config('sidebar.offset') is a 'unit' ? unit(hexo-config('sidebar.offset'), px) : 12px; +$sidebar-nav-color = $grey-dim; +$sidebar-nav-hover-color = $whitesmoke; +$sidebar-highlight = $blue-bright; + +$site-author-image-width = 96px; +$site-author-image-border-width = 2px; +$site-author-image-border-color = $black-dim; + +$site-author-name-margin = 5px 0 0; +$site-author-name-color = $whitesmoke; +$site-author-name-weight = normal; + +$site-description-font-size = $font-size-medium; +$site-description-color = $grey-dark; +$site-description-margin-top = 5px; + +$site-state-item-count-font-size = $font-size-larger; +$site-state-item-name-font-size = $font-size-small; +$site-state-item-name-color = inherit; + + +// Components +// -------------------------------------------------- +// Back to top +$b2t-opacity = .8; +$b2t-opacity-hover = 1; +$b2t-position-bottom = -100px; +$b2t-position-bottom-on = 30px; +$b2t-position-right = 30px; +$b2t-position-right-mobile = 20px; +$b2t-font-size = 12px; +$b2t-color = white; +$b2t-bg-color = $black-deep; + +$sidebar-toggle-inner-size = 16px; +$sidebar-toggle-padding = 5px; +$sidebar-toggle-size = $sidebar-toggle-inner-size + $sidebar-toggle-padding * 2; + +// .post-expand .post-eof +// In Muse scheme, margin above and below the post separator +$post-eof-margin-top = 80px; // or 160px for more white space; +$post-eof-margin-bottom = 60px; // or 120px for less white space; + +$post-card-margin = 1em 0 0; +$post-reward-img-width = 180px; + + +// Note colors +// -------------------------------------------------- +// Read note light_bg_offset from NexT config and set in '$lbg%' to use it as string variable. +$lbg = hexo-config('note.light_bg_offset') is a 'unit' ? unit(hexo-config('note.light_bg_offset'), '%') : 0; +$note-types = 'default' 'primary' 'info' 'success' 'warning' 'danger'; + +$note-border-radius = 3px; + +$note-border = { + default : #777, + primary : #6f42c1, + info : #428bca, + success : #5cb85c, + warning : #f0ad4e, + danger : #d9534f +}; + +$note-bg = { + default : lighten(spin($note-border.default, 0), 94% + $lbg), + primary : lighten(spin($note-border.primary, 10), 92% + $lbg), + info : lighten(spin($note-border.info, -10), 91% + $lbg), + success : lighten(spin($note-border.success, 10), 90% + $lbg), + warning : lighten(spin($note-border.warning, 10), 88% + $lbg), + danger : lighten(spin($note-border.danger, -10), 92% + $lbg) +}; + +$note-text = { + default : $note-border.default, + primary : $note-border.primary, + info : $note-border.info, + success : $note-border.success, + warning : $note-border.warning, + danger : $note-border.danger +}; + +$note-icon = { + default : '\f0a9', + primary : '\f055', + info : '\f05a', + success : '\f058', + warning : '\f06a', + danger : '\f056' +}; + +$note-modern-border = { + default : #e1e1e1, + primary : #e1c2ff, + info : #b3e5ef, + success : #d0e6be, + warning : #fae4cd, + danger : #ebcdd2 +}; + +$note-modern-bg = { + default : lighten(spin($note-modern-border.default, 10), 60% + ($lbg * 4)), + primary : lighten(spin($note-modern-border.primary, 10), 40% + ($lbg * 4)), + info : lighten(spin($note-modern-border.info, 10), 50% + ($lbg * 4)), + success : lighten(spin($note-modern-border.success, 10), 40% + ($lbg * 4)), + warning : lighten(spin($note-modern-border.warning, 10), 43% + ($lbg * 4)), + danger : lighten(spin($note-modern-border.danger, 10), 35% + ($lbg * 4)) +}; + +$note-modern-text = { + default : $grey-dim, + primary : #6f42c1, + info : #31708f, + success : #3c763d, + warning : #8a6d3b, + danger : #a94442 +}; + +$note-modern-hover = { + default : darken(spin($note-modern-text.default, -10), 32%), + primary : darken(spin($note-modern-text.primary, -10), 22%), + info : darken(spin($note-modern-text.info, -10), 32%), + success : darken(spin($note-modern-text.success, -10), 27%), + warning : darken(spin($note-modern-text.warning, -10), 18%), + danger : darken(spin($note-modern-text.danger, -10), 22%) +}; + + +// Tabs border radius +// -------------------------------------------------- +$tbr = 0; + + +// Label colors +// -------------------------------------------------- +$label = { + default : lighten(spin($note-border.default, 0), 89% + $lbg), + primary : lighten(spin($note-border.primary, 10), 87% + $lbg), + info : lighten(spin($note-border.info, -10), 86% + $lbg), + success : lighten(spin($note-border.success, 10), 85% + $lbg), + warning : lighten(spin($note-border.warning, 10), 83% + $lbg), + danger : lighten(spin($note-border.danger, -10), 87% + $lbg) +}; diff --git a/themes/next/source/css/main.styl b/themes/next/source/css/main.styl new file mode 100644 index 0000000..747ae00 --- /dev/null +++ b/themes/next/source/css/main.styl @@ -0,0 +1,47 @@ +// CSS Style Guide: https://codeguide.co/#css + +// https://stylus-lang.com/docs/keyframes.html +vendors = official; + +$scheme = hexo-config('scheme') ? hexo-config('scheme') : 'Muse'; + + +// Variables Layer +// -------------------------------------------------- +@import '_variables/base'; +@import '_variables/' + $scheme; +for $inject_variable in hexo-config('injects.variable') + @import $inject_variable; + +// Mixins Layer +// -------------------------------------------------- +@import '_mixins'; +for $inject_mixin in hexo-config('injects.mixin') + @import $inject_mixin; + +// Dark mode colors +// -------------------------------------------------- +@import '_colors'; + +// Common Layer +// -------------------------------------------------- + +// Scaffolding +@import '_common/scaffolding'; + +// Layout +@import '_common/outline'; + +// Components +@import '_common/components'; + + +// Schemes Layer +// -------------------------------------------------- +@import '_schemes/' + $scheme; + + +// Custom Layer +// -------------------------------------------------- +for $inject_style in hexo-config('injects.style') + @import $inject_style; diff --git a/themes/next/source/css/noscript.styl b/themes/next/source/css/noscript.styl new file mode 100644 index 0000000..f7f87c8 --- /dev/null +++ b/themes/next/source/css/noscript.styl @@ -0,0 +1,47 @@ +@import '_variables/base'; + +body { margin-top: 2rem; } + +.use-motion .menu-item, +.use-motion .sidebar, +.use-motion .sidebar-inner, +.use-motion .post-block, +.use-motion .pagination, +.use-motion .comments, +.use-motion .post-header, +.use-motion .post-body, +.use-motion .collection-header { + visibility: visible; +} + +.use-motion .column, +.use-motion .site-brand-container .toggle, +.use-motion .footer { opacity: initial; } + +.use-motion .site-title, +.use-motion .site-subtitle, +.use-motion .custom-logo-image { + opacity: initial; + top: initial; +} + +.use-motion .logo-line { + transform: scaleX(1); +} + +.search-pop-overlay, .sidebar-nav { display: none; } +.sidebar-panel { display: block; } + +.noscript-warning { + background-color: lighten($red, 20%); + color: white; + font-family: sans-serif; + font-size: 1rem; + font-weight: bold; + left: 0; + position: fixed; + text-align: center; + top: 0; + width: 100%; + z-index: $zindex-5; +} diff --git a/themes/next/source/images/apple-touch-icon-next.png b/themes/next/source/images/apple-touch-icon-next.png new file mode 100644 index 0000000..86a0d1d Binary files /dev/null and b/themes/next/source/images/apple-touch-icon-next.png differ diff --git a/themes/next/source/images/avatar.png b/themes/next/source/images/avatar.png new file mode 100644 index 0000000..a751d30 Binary files /dev/null and b/themes/next/source/images/avatar.png differ diff --git a/themes/next/source/images/favicon-16x16-next.png b/themes/next/source/images/favicon-16x16-next.png new file mode 100644 index 0000000..de8c5d3 Binary files /dev/null and b/themes/next/source/images/favicon-16x16-next.png differ diff --git a/themes/next/source/images/favicon-32x32-next.png b/themes/next/source/images/favicon-32x32-next.png new file mode 100644 index 0000000..e02f5f4 Binary files /dev/null and b/themes/next/source/images/favicon-32x32-next.png differ diff --git a/themes/next/source/images/favicon.svg b/themes/next/source/images/favicon.svg new file mode 100644 index 0000000..11c42c2 --- /dev/null +++ b/themes/next/source/images/favicon.svg @@ -0,0 +1,5494 @@ + + + + diff --git a/themes/next/source/images/logo-algolia-nebula-blue-full.svg b/themes/next/source/images/logo-algolia-nebula-blue-full.svg new file mode 100644 index 0000000..886c422 --- /dev/null +++ b/themes/next/source/images/logo-algolia-nebula-blue-full.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/themes/next/source/images/logo.svg b/themes/next/source/images/logo.svg new file mode 100644 index 0000000..0929ea4 --- /dev/null +++ b/themes/next/source/images/logo.svg @@ -0,0 +1,16 @@ + + + + + background + + + + + + + Layer 1 + + Clever_Jimmy 的博客 + + \ No newline at end of file diff --git a/themes/next/source/js/bookmark.js b/themes/next/source/js/bookmark.js new file mode 100644 index 0000000..2fc66ab --- /dev/null +++ b/themes/next/source/js/bookmark.js @@ -0,0 +1,56 @@ +/* global CONFIG */ + +document.addEventListener('DOMContentLoaded', () => { + 'use strict'; + + const doSaveScroll = () => { + localStorage.setItem('bookmark' + location.pathname, window.scrollY); + }; + + const scrollToMark = () => { + let top = localStorage.getItem('bookmark' + location.pathname); + top = parseInt(top, 10); + // If the page opens with a specific hash, just jump out + if (!isNaN(top) && location.hash === '') { + // Auto scroll to the position + window.anime({ + targets : document.scrollingElement, + duration : 200, + easing : 'linear', + scrollTop: top + }); + } + }; + // Register everything + const init = function(trigger) { + // Create a link element + const link = document.querySelector('.book-mark-link'); + // Scroll event + window.addEventListener('scroll', () => link.classList.toggle('book-mark-link-fixed', window.scrollY === 0), { passive: true }); + // Register beforeunload event when the trigger is auto + if (trigger === 'auto') { + // Register beforeunload event + window.addEventListener('beforeunload', doSaveScroll); + document.addEventListener('pjax:send', doSaveScroll); + } + // Save the position by clicking the icon + link.addEventListener('click', () => { + doSaveScroll(); + window.anime({ + targets : link, + duration: 200, + easing : 'linear', + top : -30, + complete: () => { + setTimeout(() => { + link.style.top = ''; + }, 400); + } + }); + }); + scrollToMark(); + document.addEventListener('pjax:success', scrollToMark); + }; + + init(CONFIG.bookmark.save); +}); diff --git a/themes/next/source/js/comments-buttons.js b/themes/next/source/js/comments-buttons.js new file mode 100644 index 0000000..150cfa4 --- /dev/null +++ b/themes/next/source/js/comments-buttons.js @@ -0,0 +1,25 @@ +/* global CONFIG */ + +(function() { + const commentButton = document.querySelectorAll('.comment-button'); + commentButton.forEach(element => { + const commentClass = element.classList[2]; + element.addEventListener('click', () => { + commentButton.forEach(active => active.classList.toggle('active', active === element)); + document.querySelectorAll('.comment-position').forEach(active => active.classList.toggle('active', active.classList.contains(commentClass))); + if (CONFIG.comments.storage) { + localStorage.setItem('comments_active', commentClass); + } + }); + }); + let { activeClass } = CONFIG.comments; + if (CONFIG.comments.storage) { + activeClass = localStorage.getItem('comments_active') || activeClass; + } + if (activeClass) { + const activeButton = document.querySelector(`.comment-button.${activeClass}`); + if (activeButton) { + activeButton.click(); + } + } +})(); diff --git a/themes/next/source/js/comments.js b/themes/next/source/js/comments.js new file mode 100644 index 0000000..7644f51 --- /dev/null +++ b/themes/next/source/js/comments.js @@ -0,0 +1,21 @@ +/* global CONFIG */ + +window.addEventListener('tabs:register', () => { + let { activeClass } = CONFIG.comments; + if (CONFIG.comments.storage) { + activeClass = localStorage.getItem('comments_active') || activeClass; + } + if (activeClass) { + const activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`); + if (activeTab) { + activeTab.click(); + } + } +}); +if (CONFIG.comments.storage) { + window.addEventListener('tabs:click', event => { + if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return; + const commentClass = event.target.classList[1]; + localStorage.setItem('comments_active', commentClass); + }); +} diff --git a/themes/next/source/js/config.js b/themes/next/source/js/config.js new file mode 100644 index 0000000..256335d --- /dev/null +++ b/themes/next/source/js/config.js @@ -0,0 +1,66 @@ +if (!window.NexT) window.NexT = {}; + +(function() { + const className = 'next-config'; + + const staticConfig = {}; + let variableConfig = {}; + + const parse = text => JSON.parse(text || '{}'); + + const update = name => { + const targetEle = document.querySelector(`.${className}[data-name="${name}"]`); + if (!targetEle) return; + const parsedConfig = parse(targetEle.text); + if (name === 'main') { + Object.assign(staticConfig, parsedConfig); + } else { + variableConfig[name] = parsedConfig; + } + }; + + update('main'); + + window.CONFIG = new Proxy({}, { + get(overrideConfig, name) { + let existing; + if (name in staticConfig) { + existing = staticConfig[name]; + } else { + if (!(name in variableConfig)) update(name); + existing = variableConfig[name]; + } + + // For unset override and mixable existing + if (!(name in overrideConfig) && typeof existing === 'object') { + // Get ready to mix. + overrideConfig[name] = {}; + } + + if (name in overrideConfig) { + const override = overrideConfig[name]; + + // When mixable + if (typeof override === 'object' && typeof existing === 'object') { + // Mix, proxy changes to the override. + return new Proxy({ ...existing, ...override }, { + set(target, prop, value) { + target[prop] = value; + override[prop] = value; + return true; + } + }); + } + + return override; + } + + // Only when not mixable and override hasn't been set. + return existing; + } + }); + + document.addEventListener('pjax:success', () => { + variableConfig = {}; + }); +})(); diff --git a/themes/next/source/js/motion.js b/themes/next/source/js/motion.js new file mode 100644 index 0000000..95cc06c --- /dev/null +++ b/themes/next/source/js/motion.js @@ -0,0 +1,140 @@ +/* global NexT, CONFIG */ + +NexT.motion = {}; + +NexT.motion.integrator = { + queue: [], + init : function() { + this.queue = []; + return this; + }, + add: function(fn) { + const sequence = fn(); + if (CONFIG.motion.async) this.queue.push(sequence); + else this.queue = this.queue.concat(sequence); + return this; + }, + bootstrap: function() { + if (!CONFIG.motion.async) this.queue = [this.queue]; + this.queue.forEach(sequence => { + const timeline = window.anime.timeline({ + duration: 200, + easing : 'linear' + }); + sequence.forEach(item => { + if (item.deltaT) timeline.add(item, item.deltaT); + else timeline.add(item); + }); + }); + } +}; + +NexT.motion.middleWares = { + header: function() { + const sequence = []; + + function getMistLineSettings(targets) { + sequence.push({ + targets, + scaleX : [0, 1], + duration: 500, + deltaT : '-=200' + }); + } + + function pushToSequence(targets, sequenceQueue = false) { + sequence.push({ + targets, + opacity: 1, + top : 0, + deltaT : sequenceQueue ? '-=200' : '-=0' + }); + } + + pushToSequence('.column'); + CONFIG.scheme === 'Mist' && getMistLineSettings('.logo-line'); + CONFIG.scheme === 'Muse' && pushToSequence('.custom-logo-image'); + pushToSequence('.site-title'); + pushToSequence('.site-brand-container .toggle', true); + pushToSequence('.site-subtitle'); + (CONFIG.scheme === 'Pisces' || CONFIG.scheme === 'Gemini') && pushToSequence('.custom-logo-image'); + + const menuItemTransition = CONFIG.motion.transition.menu_item; + if (menuItemTransition) { + document.querySelectorAll('.menu-item').forEach(targets => { + sequence.push({ + targets, + complete: () => targets.classList.add('animated', menuItemTransition), + deltaT : '-=200' + }); + }); + } + + return sequence; + }, + + subMenu: function() { + const subMenuItem = document.querySelectorAll('.sub-menu .menu-item'); + if (subMenuItem.length > 0) { + subMenuItem.forEach(element => { + element.classList.add('animated'); + }); + } + return []; + }, + + postList: function() { + const sequence = []; + const { post_block, post_header, post_body, coll_header } = CONFIG.motion.transition; + + function animate(animation, elements) { + if (!animation) return; + elements.forEach(targets => { + sequence.push({ + targets, + complete: () => targets.classList.add('animated', animation), + deltaT : '-=100' + }); + }); + } + + document.querySelectorAll('.post-block').forEach(targets => { + sequence.push({ + targets, + complete: () => targets.classList.add('animated', post_block), + deltaT : '-=100' + }); + animate(coll_header, targets.querySelectorAll('.collection-header')); + animate(post_header, targets.querySelectorAll('.post-header')); + animate(post_body, targets.querySelectorAll('.post-body')); + }); + + animate(post_block, document.querySelectorAll('.pagination, .comments')); + + return sequence; + }, + + sidebar: function() { + const sequence = []; + const sidebar = document.querySelectorAll('.sidebar-inner'); + const sidebarTransition = CONFIG.motion.transition.sidebar; + // Only for Pisces | Gemini. + if (sidebarTransition && (CONFIG.scheme === 'Pisces' || CONFIG.scheme === 'Gemini')) { + sidebar.forEach(targets => { + sequence.push({ + targets, + complete: () => targets.classList.add('animated', sidebarTransition), + deltaT : '-=100' + }); + }); + } + return sequence; + }, + + footer: function() { + return [{ + targets: document.querySelector('.footer'), + opacity: 1 + }]; + } +}; diff --git a/themes/next/source/js/next-boot.js b/themes/next/source/js/next-boot.js new file mode 100644 index 0000000..980f751 --- /dev/null +++ b/themes/next/source/js/next-boot.js @@ -0,0 +1,75 @@ +/* global NexT, CONFIG */ + +NexT.boot = {}; + +NexT.boot.registerEvents = function() { + + NexT.utils.registerScrollPercent(); + NexT.utils.registerCanIUseTag(); + + // Mobile top menu bar. + document.querySelector('.site-nav-toggle .toggle').addEventListener('click', event => { + event.currentTarget.classList.toggle('toggle-close'); + const siteNav = document.querySelector('.site-nav'); + if (!siteNav) return; + siteNav.style.setProperty('--scroll-height', siteNav.scrollHeight + 'px'); + document.body.classList.toggle('site-nav-on'); + }); + + document.querySelectorAll('.sidebar-nav li').forEach((element, index) => { + element.addEventListener('click', () => { + NexT.utils.activateSidebarPanel(index); + }); + }); + + window.addEventListener('hashchange', () => { + const tHash = location.hash; + if (tHash !== '' && !tHash.match(/%\S{2}/)) { + const target = document.querySelector(`.tabs ul.nav-tabs li a[href="${tHash}"]`); + target && target.click(); + } + }); +}; + +NexT.boot.refresh = function() { + + /** + * Register JS handlers by condition option. + * Need to add config option in Front-End at 'scripts/helpers/next-config.js' file. + */ + CONFIG.prism && window.Prism.highlightAll(); + CONFIG.mediumzoom && window.mediumZoom('.post-body :not(a) > img, .post-body > img', { + background: 'var(--content-bg-color)' + }); + CONFIG.lazyload && window.lozad('.post-body img').observe(); + CONFIG.pangu && window.pangu.spacingPage(); + + CONFIG.exturl && NexT.utils.registerExtURL(); + NexT.utils.wrapTableWithBox(); + NexT.utils.registerCopyCode(); + NexT.utils.registerTabsTag(); + NexT.utils.registerActiveMenuItem(); + NexT.utils.registerLangSelect(); + NexT.utils.registerSidebarTOC(); + NexT.utils.registerPostReward(); + NexT.utils.registerVideoIframe(); +}; + +NexT.boot.motion = function() { + // Define Motion Sequence & Bootstrap Motion. + if (CONFIG.motion.enable) { + NexT.motion.integrator + .add(NexT.motion.middleWares.header) + .add(NexT.motion.middleWares.postList) + .add(NexT.motion.middleWares.sidebar) + .add(NexT.motion.middleWares.footer) + .bootstrap(); + } + NexT.utils.updateSidebarPosition(); +}; + +document.addEventListener('DOMContentLoaded', () => { + NexT.boot.registerEvents(); + NexT.boot.refresh(); + NexT.boot.motion(); +}); diff --git a/themes/next/source/js/pjax.js b/themes/next/source/js/pjax.js new file mode 100644 index 0000000..14418c2 --- /dev/null +++ b/themes/next/source/js/pjax.js @@ -0,0 +1,36 @@ +/* global NexT, CONFIG, Pjax */ + +const pjax = new Pjax({ + selectors: [ + 'head title', + 'script[type="application/json"]', + '.main-inner', + '.post-toc-wrap', + '.languages', + '.pjax' + ], + analytics: false, + cacheBust: false, + scrollTo : !CONFIG.bookmark.enable +}); + +document.addEventListener('pjax:success', () => { + pjax.executeScripts(document.querySelectorAll('script[data-pjax]')); + NexT.boot.refresh(); + // Define Motion Sequence & Bootstrap Motion. + if (CONFIG.motion.enable) { + NexT.motion.integrator + .init() + .add(NexT.motion.middleWares.subMenu) + .add(NexT.motion.middleWares.postList) + // Add sidebar-post-related transition. + .add(NexT.motion.middleWares.sidebar) + .bootstrap(); + } + if (CONFIG.sidebar.display !== 'remove') { + const hasTOC = document.querySelector('.post-toc'); + document.querySelector('.sidebar-inner').classList.toggle('sidebar-nav-active', hasTOC); + NexT.utils.activateSidebarPanel(hasTOC ? 0 : 1); + NexT.utils.updateSidebarPosition(); + } +}); diff --git a/themes/next/source/js/schedule.js b/themes/next/source/js/schedule.js new file mode 100644 index 0000000..6d54c63 --- /dev/null +++ b/themes/next/source/js/schedule.js @@ -0,0 +1,138 @@ +/* global CONFIG */ + +// https://developers.google.com/calendar/api/v3/reference/events/list +(function() { + // Initialization + const calendar = { + orderBy : 'startTime', + showLocation: false, + offsetMax : 72, + offsetMin : 4, + showDeleted : false, + singleEvents: true, + maxResults : 250 + }; + + // Read config form theme config file + Object.assign(calendar, CONFIG.calendar); + + const now = new Date(); + const timeMax = new Date(); + const timeMin = new Date(); + + timeMax.setHours(now.getHours() + calendar.offsetMax); + timeMin.setHours(now.getHours() - calendar.offsetMin); + + // Build URL + const params = { + key : calendar.api_key, + orderBy : calendar.orderBy, + timeMax : timeMax.toISOString(), + timeMin : timeMin.toISOString(), + showDeleted : calendar.showDeleted, + singleEvents: calendar.singleEvents, + maxResults : calendar.maxResults + }; + + const request_url = new URL(`https://www.googleapis.com/calendar/v3/calendars/${calendar.calendar_id}/events`); + Object.entries(params).forEach(param => request_url.searchParams.append(...param)); + + function getRelativeTime(current, previous) { + const msPerMinute = 60 * 1000; + const msPerHour = msPerMinute * 60; + const msPerDay = msPerHour * 24; + const msPerMonth = msPerDay * 30; + const msPerYear = msPerDay * 365; + + let elapsed = current - previous; + const tense = elapsed > 0 ? ' ago' : ' later'; + + elapsed = Math.abs(elapsed); + + if (elapsed < msPerHour) { + return Math.round(elapsed / msPerMinute) + ' minutes' + tense; + } else if (elapsed < msPerDay) { + return Math.round(elapsed / msPerHour) + ' hours' + tense; + } else if (elapsed < msPerMonth) { + return 'about ' + Math.round(elapsed / msPerDay) + ' days' + tense; + } else if (elapsed < msPerYear) { + return 'about ' + Math.round(elapsed / msPerMonth) + ' months' + tense; + } + + return 'about ' + Math.round(elapsed / msPerYear) + ' years' + tense; + } + + function buildEventDOM(tense, event, start, end) { + const durationFormat = { + weekday: 'short', + hour : '2-digit', + minute : '2-digit' + }; + const relativeTime = tense === 'now' ? 'NOW' : getRelativeTime(now, start); + const duration = start.toLocaleTimeString([], durationFormat) + ' - ' + end.toLocaleTimeString([], durationFormat); + + let location = ''; + if (calendar.showLocation && event.location) { + location = `${event.location}`; + } + let description = ''; + if (event.description) { + description = `${event.description}`; + } + + const eventContent = `
    +

    + ${event.summary} + ${relativeTime} +

    + ${location} + ${duration} + ${description} +
    `; + return eventContent; + } + + function fetchData() { + const eventList = document.querySelector('.event-list'); + if (!eventList) return; + + fetch(request_url.href).then(response => { + return response.json(); + }).then(data => { + if (data.items.length === 0) { + eventList.innerHTML = '
    '; + return; + } + // Clean the event list + eventList.innerHTML = ''; + let prevEnd = 0; // used to decide where to insert an
    + const utc = new Date().getTimezoneOffset() * 60000; + + data.items.forEach(event => { + // Parse data + const start = new Date(event.start.dateTime || (new Date(event.start.date).getTime() + utc)); + const end = new Date(event.end.dateTime || (new Date(event.end.date).getTime() + utc)); + + let tense = 'now'; + if (end < now) { + tense = 'past'; + } else if (start > now) { + tense = 'future'; + } + + if (tense === 'future' && prevEnd < now) { + eventList.insertAdjacentHTML('beforeend', '
    '); + } + + eventList.insertAdjacentHTML('beforeend', buildEventDOM(tense, event, start, end)); + prevEnd = end; + }); + }); + } + + fetchData(); + const fetchDataTimer = setInterval(fetchData, 60000); + document.addEventListener('pjax:send', () => { + clearInterval(fetchDataTimer); + }); +})(); diff --git a/themes/next/source/js/schemes/muse.js b/themes/next/source/js/schemes/muse.js new file mode 100644 index 0000000..6b50b36 --- /dev/null +++ b/themes/next/source/js/schemes/muse.js @@ -0,0 +1,60 @@ +/* global CONFIG */ + +document.addEventListener('DOMContentLoaded', () => { + + const isRight = CONFIG.sidebar.position === 'right'; + + const sidebarToggleMotion = { + mouse: {}, + init : function() { + window.addEventListener('mousedown', this.mousedownHandler.bind(this)); + window.addEventListener('mouseup', this.mouseupHandler.bind(this)); + document.querySelector('.sidebar-dimmer').addEventListener('click', this.clickHandler.bind(this)); + document.querySelector('.sidebar-toggle').addEventListener('click', this.clickHandler.bind(this)); + window.addEventListener('sidebar:show', this.showSidebar); + window.addEventListener('sidebar:hide', this.hideSidebar); + }, + mousedownHandler: function(event) { + this.mouse.X = event.pageX; + this.mouse.Y = event.pageY; + }, + mouseupHandler: function(event) { + const deltaX = event.pageX - this.mouse.X; + const deltaY = event.pageY - this.mouse.Y; + const clickingBlankPart = Math.hypot(deltaX, deltaY) < 20 && event.target.matches('.main'); + // Fancybox has z-index property, but medium-zoom does not, so the sidebar will overlay the zoomed image. + if (clickingBlankPart || event.target.matches('img.medium-zoom-image')) { + this.hideSidebar(); + } + }, + clickHandler: function() { + document.body.classList.contains('sidebar-active') ? this.hideSidebar() : this.showSidebar(); + }, + showSidebar: function() { + document.body.classList.add('sidebar-active'); + const animateAction = isRight ? 'fadeInRight' : 'fadeInLeft'; + document.querySelectorAll('.sidebar .animated').forEach((element, index) => { + element.style.animationDelay = (100 * index) + 'ms'; + element.classList.remove(animateAction); + setTimeout(() => { + // Trigger a DOM reflow + element.classList.add(animateAction); + }); + }); + }, + hideSidebar: function() { + document.body.classList.remove('sidebar-active'); + } + }; + if (CONFIG.sidebar.display !== 'remove') sidebarToggleMotion.init(); + + function updateFooterPosition() { + const footer = document.querySelector('.footer'); + const containerHeight = document.querySelector('.column').offsetHeight + document.querySelector('.main').offsetHeight + footer.offsetHeight; + footer.classList.toggle('footer-fixed', containerHeight <= window.innerHeight); + } + + updateFooterPosition(); + window.addEventListener('resize', updateFooterPosition); + window.addEventListener('scroll', updateFooterPosition, { passive: true }); +}); diff --git a/themes/next/source/js/third-party/analytics/baidu-analytics.js b/themes/next/source/js/third-party/analytics/baidu-analytics.js new file mode 100644 index 0000000..b8a06fe --- /dev/null +++ b/themes/next/source/js/third-party/analytics/baidu-analytics.js @@ -0,0 +1,7 @@ +/* global _hmt */ + +if (!window._hmt) window._hmt = []; + +document.addEventListener('pjax:success', () => { + _hmt.push(['_trackPageview', location.pathname]); +}); diff --git a/themes/next/source/js/third-party/analytics/google-analytics.js b/themes/next/source/js/third-party/analytics/google-analytics.js new file mode 100644 index 0000000..5098ca5 --- /dev/null +++ b/themes/next/source/js/third-party/analytics/google-analytics.js @@ -0,0 +1,35 @@ +/* global CONFIG, dataLayer, gtag */ + +if (!CONFIG.google_analytics.only_pageview) { + if (CONFIG.hostname === location.hostname) { + window.dataLayer = window.dataLayer || []; + window.gtag = function() { + dataLayer.push(arguments); + }; + gtag('js', new Date()); + gtag('config', CONFIG.google_analytics.tracking_id); + + document.addEventListener('pjax:success', () => { + gtag('event', 'page_view', { + page_location: location.href, + page_path : location.pathname, + page_title : document.title + }); + }); + } +} else { + const sendPageView = () => { + if (CONFIG.hostname !== location.hostname) return; + const uid = localStorage.getItem('uid') || (Math.random() + '.' + Math.random()); + localStorage.setItem('uid', uid); + navigator.sendBeacon('https://www.google-analytics.com/collect', new URLSearchParams({ + v : 1, + tid: CONFIG.google_analytics.tracking_id, + cid: uid, + t : 'pageview', + dp : encodeURIComponent(location.pathname) + })); + }; + document.addEventListener('pjax:complete', sendPageView); + sendPageView(); +} diff --git a/themes/next/source/js/third-party/analytics/growingio.js b/themes/next/source/js/third-party/analytics/growingio.js new file mode 100644 index 0000000..bc6ba2f --- /dev/null +++ b/themes/next/source/js/third-party/analytics/growingio.js @@ -0,0 +1,10 @@ +/* global CONFIG, gio */ + +if (!window.gio) { + window.gio = function() { + (window.gio.q = window.gio.q || []).push(arguments); + }; +} + +gio('init', `${CONFIG.growingio_analytics}`, {}); +gio('send'); diff --git a/themes/next/source/js/third-party/analytics/matomo.js b/themes/next/source/js/third-party/analytics/matomo.js new file mode 100644 index 0000000..3c71965 --- /dev/null +++ b/themes/next/source/js/third-party/analytics/matomo.js @@ -0,0 +1,19 @@ +/* global CONFIG */ + +if (CONFIG.matomo.enable) { + window._paq = window._paq || []; + const _paq = window._paq; + + /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ + _paq.push(['trackPageView']); + _paq.push(['enableLinkTracking']); + const u = CONFIG.matomo.server_url; + _paq.push(['setTrackerUrl', u + 'matomo.php']); + _paq.push(['setSiteId', CONFIG.matomo.site_id]); + const d = document; + const g = d.createElement('script'); + const s = d.getElementsByTagName('script')[0]; + g.async = true; + g.src = u + 'matomo.js'; + s.parentNode.insertBefore(g, s); +} diff --git a/themes/next/source/js/third-party/chat/chatra.js b/themes/next/source/js/third-party/chat/chatra.js new file mode 100644 index 0000000..c8fc044 --- /dev/null +++ b/themes/next/source/js/third-party/chat/chatra.js @@ -0,0 +1,19 @@ +/* global CONFIG, Chatra */ + +(function() { + if (CONFIG.chatra.embed) { + window.ChatraSetup = { + mode : 'frame', + injectTo: CONFIG.chatra.embed + }; + } + + window.ChatraID = CONFIG.chatra.id; + + const chatButton = document.querySelector('.sidebar-button button'); + if (chatButton) { + chatButton.addEventListener('click', () => { + Chatra('openChat', true); + }); + } +})(); diff --git a/themes/next/source/js/third-party/chat/gitter.js b/themes/next/source/js/third-party/chat/gitter.js new file mode 100644 index 0000000..7102246 --- /dev/null +++ b/themes/next/source/js/third-party/chat/gitter.js @@ -0,0 +1,5 @@ +/* global CONFIG */ + +((window.gitter = {}).chat = {}).options = { + room: CONFIG.gitter.room +}; diff --git a/themes/next/source/js/third-party/chat/tidio.js b/themes/next/source/js/third-party/chat/tidio.js new file mode 100644 index 0000000..aad8211 --- /dev/null +++ b/themes/next/source/js/third-party/chat/tidio.js @@ -0,0 +1,10 @@ +/* global tidioChatApi */ + +(function() { + const chatButton = document.querySelector('.sidebar-button button'); + if (chatButton) { + chatButton.addEventListener('click', () => { + tidioChatApi.open(); + }); + } +})(); diff --git a/themes/next/source/js/third-party/comments/changyan.js b/themes/next/source/js/third-party/comments/changyan.js new file mode 100644 index 0000000..776c5ee --- /dev/null +++ b/themes/next/source/js/third-party/comments/changyan.js @@ -0,0 +1,39 @@ +/* global NexT, CONFIG */ + +document.addEventListener('page:loaded', () => { + const { appid, appkey } = CONFIG.changyan; + const mainJs = 'https://cy-cdn.kuaizhan.com/upload/changyan.js'; + const countJs = `https://cy-cdn.kuaizhan.com/upload/plugins/plugins.list.count.js?clientId=${appid}`; + + // Get the number of comments + setTimeout(() => { + return NexT.utils.getScript(countJs, { + attributes: { + async: true, + id : 'cy_cmt_num' + } + }); + }, 0); + + // When scroll to comment section + if (CONFIG.page.comments && !CONFIG.page.isHome) { + NexT.utils.loadComments('#SOHUCS') + .then(() => { + return NexT.utils.getScript(mainJs, { + attributes: { + async: true + } + }); + }) + .then(() => { + window.changyan.api.config({ + appid, + conf: appkey + }); + }) + .catch(error => { + // eslint-disable-next-line no-console + console.error('Failed to load Changyan', error); + }); + } +}); diff --git a/themes/next/source/js/third-party/comments/disqus.js b/themes/next/source/js/third-party/comments/disqus.js new file mode 100644 index 0000000..7503fb9 --- /dev/null +++ b/themes/next/source/js/third-party/comments/disqus.js @@ -0,0 +1,41 @@ +/* global NexT, CONFIG, DISQUS */ + +document.addEventListener('page:loaded', () => { + + if (CONFIG.disqus.count) { + if (window.DISQUSWIDGETS) { + window.DISQUSWIDGETS.getCount({ reset: true }); + } else { + // Defer loading until the whole page loading is completed + NexT.utils.getScript(`https://${CONFIG.disqus.shortname}.disqus.com/count.js`, { + attributes: { id: 'dsq-count-scr', defer: true } + }); + } + } + + if (CONFIG.page.comments) { + // `disqus_config` should be a global variable + // See https://help.disqus.com/en/articles/1717084-javascript-configuration-variables + window.disqus_config = function() { + this.page.url = CONFIG.page.permalink; + this.page.identifier = CONFIG.page.path; + this.page.title = CONFIG.page.title; + if (CONFIG.disqus.i18n.disqus !== 'disqus') { + this.language = CONFIG.disqus.i18n.disqus; + } + }; + NexT.utils.loadComments('#disqus_thread').then(() => { + if (window.DISQUS) { + DISQUS.reset({ + reload: true, + config: window.disqus_config + }); + } else { + NexT.utils.getScript(`https://${CONFIG.disqus.shortname}.disqus.com/embed.js`, { + attributes: { dataset: { timestamp: '' + +new Date() } } + }); + } + }); + } + +}); diff --git a/themes/next/source/js/third-party/comments/disqusjs.js b/themes/next/source/js/third-party/comments/disqusjs.js new file mode 100644 index 0000000..f0de11f --- /dev/null +++ b/themes/next/source/js/third-party/comments/disqusjs.js @@ -0,0 +1,23 @@ +/* global NexT, CONFIG, DisqusJS */ + +document.addEventListener('page:loaded', () => { + if (!CONFIG.page.comments) return; + + NexT.utils.loadComments('#disqus_thread') + .then(() => NexT.utils.getScript(CONFIG.disqusjs.js, { condition: window.DisqusJS })) + .then(() => { + window.dsqjs = new DisqusJS({ + api : CONFIG.disqusjs.api || 'https://disqus.com/api/', + apikey : CONFIG.disqusjs.apikey, + shortname : CONFIG.disqusjs.shortname, + url : CONFIG.page.permalink, + identifier: CONFIG.page.path, + title : CONFIG.page.title + }); + window.dsqjs.render(document.querySelector('.disqusjs-container')); + }); +}); + +document.addEventListener('pjax:send', () => { + if (window.dsqjs) window.dsqjs.destroy(); +}); diff --git a/themes/next/source/js/third-party/comments/giscus.js b/themes/next/source/js/third-party/comments/giscus.js new file mode 100644 index 0000000..64958da --- /dev/null +++ b/themes/next/source/js/third-party/comments/giscus.js @@ -0,0 +1,26 @@ +/* global NexT, CONFIG */ + +document.addEventListener('page:loaded', () => { + if (!CONFIG.page.comments) return; + + NexT.utils.loadComments('.giscus-container') + .then(() => NexT.utils.getScript('https://giscus.app/client.js', { + attributes: { + async : true, + crossOrigin : 'anonymous', + 'data-repo' : CONFIG.giscus.repo, + 'data-repo-id' : CONFIG.giscus.repo_id, + 'data-category' : CONFIG.giscus.category, + 'data-category-id' : CONFIG.giscus.category_id, + 'data-mapping' : CONFIG.giscus.mapping, + 'data-strict' : CONFIG.giscus.strict, + 'data-reactions-enabled': CONFIG.giscus.reactions_enabled, + 'data-emit-metadata' : CONFIG.giscus.emit_metadata, + 'data-input-position' : CONFIG.giscus.input_position, + 'data-theme' : CONFIG.giscus.theme, + 'data-lang' : CONFIG.giscus.lang, + 'data-loading' : CONFIG.giscus.loading, + }, + parentNode: document.querySelector('.giscus-container') + })); +}); diff --git a/themes/next/source/js/third-party/comments/gitalk.js b/themes/next/source/js/third-party/comments/gitalk.js new file mode 100644 index 0000000..8a2c815 --- /dev/null +++ b/themes/next/source/js/third-party/comments/gitalk.js @@ -0,0 +1,24 @@ +/* global NexT, CONFIG, Gitalk */ + +document.addEventListener('page:loaded', () => { + if (!CONFIG.page.comments) return; + + NexT.utils.loadComments('.gitalk-container') + .then(() => NexT.utils.getScript(CONFIG.gitalk.js, { + condition: window.Gitalk + })) + .then(() => { + const gitalk = new Gitalk({ + clientID : CONFIG.gitalk.client_id, + clientSecret : CONFIG.gitalk.client_secret, + repo : CONFIG.gitalk.repo, + owner : CONFIG.gitalk.github_id, + admin : [CONFIG.gitalk.admin_user], + id : CONFIG.gitalk.path_md5, + proxy : CONFIG.gitalk.proxy, + language : CONFIG.gitalk.language || window.navigator.language, + distractionFreeMode: CONFIG.gitalk.distraction_free_mode + }); + gitalk.render(document.querySelector('.gitalk-container')); + }); +}); diff --git a/themes/next/source/js/third-party/comments/isso.js b/themes/next/source/js/third-party/comments/isso.js new file mode 100644 index 0000000..e00a18c --- /dev/null +++ b/themes/next/source/js/third-party/comments/isso.js @@ -0,0 +1,15 @@ +/* global NexT, CONFIG */ + +document.addEventListener('page:loaded', () => { + if (!CONFIG.page.comments) return; + + NexT.utils.loadComments('#isso-thread') + .then(() => NexT.utils.getScript(`${CONFIG.isso}js/embed.min.js`, { + attributes: { + dataset: { + isso: `${CONFIG.isso}` + } + }, + parentNode: document.querySelector('#isso-thread') + })); +}); diff --git a/themes/next/source/js/third-party/comments/livere.js b/themes/next/source/js/third-party/comments/livere.js new file mode 100644 index 0000000..23e3454 --- /dev/null +++ b/themes/next/source/js/third-party/comments/livere.js @@ -0,0 +1,19 @@ +/* global NexT, CONFIG, LivereTower */ + +document.addEventListener('page:loaded', () => { + if (!CONFIG.page.comments) return; + + NexT.utils.loadComments('#lv-container').then(() => { + window.livereOptions = { + refer: CONFIG.page.path.replace(/index\.html$/, '') + }; + + if (typeof LivereTower === 'function') return; + + NexT.utils.getScript('https://cdn-city.livere.com/js/embed.dist.js', { + attributes: { + async: true + } + }); + }); +}); diff --git a/themes/next/source/js/third-party/comments/utterances.js b/themes/next/source/js/third-party/comments/utterances.js new file mode 100644 index 0000000..82cc38f --- /dev/null +++ b/themes/next/source/js/third-party/comments/utterances.js @@ -0,0 +1,17 @@ +/* global NexT, CONFIG */ + +document.addEventListener('page:loaded', () => { + if (!CONFIG.page.comments) return; + + NexT.utils.loadComments('.utterances-container') + .then(() => NexT.utils.getScript('https://utteranc.es/client.js', { + attributes: { + async : true, + crossOrigin : 'anonymous', + 'repo' : CONFIG.utterances.repo, + 'issue-term': CONFIG.utterances.issue_term, + 'theme' : CONFIG.utterances.theme + }, + parentNode: document.querySelector('.utterances-container') + })); +}); diff --git a/themes/next/source/js/third-party/fancybox.js b/themes/next/source/js/third-party/fancybox.js new file mode 100644 index 0000000..560be41 --- /dev/null +++ b/themes/next/source/js/third-party/fancybox.js @@ -0,0 +1,38 @@ +document.addEventListener('page:loaded', () => { + + /** + * Wrap images with fancybox. + */ + document.querySelectorAll('.post-body :not(a) > img, .post-body > img').forEach(element => { + const $image = $(element); + const imageLink = $image.attr('data-src') || $image.attr('src'); + const $imageWrapLink = $image.wrap(``).parent('a'); + if ($image.is('.post-gallery img')) { + $imageWrapLink.attr('data-fancybox', 'gallery').attr('rel', 'gallery'); + } else if ($image.is('.group-picture img')) { + $imageWrapLink.attr('data-fancybox', 'group').attr('rel', 'group'); + } else { + $imageWrapLink.attr('data-fancybox', 'default').attr('rel', 'default'); + } + + const imageTitle = $image.attr('title') || $image.attr('alt'); + if (imageTitle) { + // Do not append image-caption if pandoc has already created a figcaption + if (!$imageWrapLink.next('figcaption').length) { + $imageWrapLink.append(`

    ${imageTitle}

    `); + } + // Make sure img title tag will show correctly in fancybox + $imageWrapLink.attr('title', imageTitle).attr('data-caption', imageTitle); + } + }); + + $.fancybox.defaults.hash = false; + $('.fancybox').fancybox({ + loop : true, + helpers: { + overlay: { + locked: false + } + } + }); +}); diff --git a/themes/next/source/js/third-party/math/katex.js b/themes/next/source/js/third-party/math/katex.js new file mode 100644 index 0000000..476584b --- /dev/null +++ b/themes/next/source/js/third-party/math/katex.js @@ -0,0 +1,7 @@ +/* global NexT, CONFIG */ + +document.addEventListener('page:loaded', () => { + if (!CONFIG.enableMath) return; + + NexT.utils.getScript(CONFIG.katex.copy_tex_js).catch(() => {}); +}); diff --git a/themes/next/source/js/third-party/math/mathjax.js b/themes/next/source/js/third-party/math/mathjax.js new file mode 100644 index 0000000..000991c --- /dev/null +++ b/themes/next/source/js/third-party/math/mathjax.js @@ -0,0 +1,36 @@ +/* global NexT, CONFIG, MathJax */ + +document.addEventListener('page:loaded', () => { + if (!CONFIG.enableMath) return; + + if (typeof MathJax === 'undefined') { + window.MathJax = { + tex: { + inlineMath: { '[+]': [['$', '$']] }, + tags : CONFIG.mathjax.tags + }, + options: { + renderActions: { + insertedScript: [200, () => { + document.querySelectorAll('mjx-container').forEach(node => { + const target = node.parentNode; + if (target.nodeName.toLowerCase() === 'li') { + target.parentNode.classList.add('has-jax'); + } + }); + }, '', false] + } + } + }; + NexT.utils.getScript(CONFIG.mathjax.js, { + attributes: { + defer: true + } + }); + } else { + MathJax.startup.document.state(0); + MathJax.typesetClear(); + MathJax.texReset(); + MathJax.typesetPromise(); + } +}); diff --git a/themes/next/source/js/third-party/pace.js b/themes/next/source/js/third-party/pace.js new file mode 100644 index 0000000..d312d21 --- /dev/null +++ b/themes/next/source/js/third-party/pace.js @@ -0,0 +1,7 @@ +/* global Pace */ + +Pace.options.restartOnPushState = false; + +document.addEventListener('pjax:send', () => { + Pace.restart(); +}); diff --git a/themes/next/source/js/third-party/quicklink.js b/themes/next/source/js/third-party/quicklink.js new file mode 100644 index 0000000..426bc9a --- /dev/null +++ b/themes/next/source/js/third-party/quicklink.js @@ -0,0 +1,37 @@ +/* global CONFIG, quicklink */ + +(function() { + if (typeof CONFIG.quicklink.ignores === 'string') { + const ignoresStr = `[${CONFIG.quicklink.ignores}]`; + CONFIG.quicklink.ignores = JSON.parse(ignoresStr); + } + + let resetFn = null; + + const onRefresh = () => { + if (resetFn) resetFn(); + if (!CONFIG.quicklink.enable) return; + + let ignoresArr = CONFIG.quicklink.ignores || []; + if (!Array.isArray(ignoresArr)) { + ignoresArr = [ignoresArr]; + } + + resetFn = quicklink.listen({ + timeout : CONFIG.quicklink.timeout, + priority: CONFIG.quicklink.priority, + ignores : [ + uri => uri.includes('#'), + uri => uri === CONFIG.quicklink.url, + ...ignoresArr + ] + }); + }; + + if (CONFIG.quicklink.delay) { + window.addEventListener('load', onRefresh); + document.addEventListener('pjax:success', onRefresh); + } else { + document.addEventListener('page:loaded', onRefresh); + } +})(); diff --git a/themes/next/source/js/third-party/search/algolia-search.js b/themes/next/source/js/third-party/search/algolia-search.js new file mode 100644 index 0000000..1b188ac --- /dev/null +++ b/themes/next/source/js/third-party/search/algolia-search.js @@ -0,0 +1,130 @@ +/* global instantsearch, algoliasearch, CONFIG, pjax */ + +document.addEventListener('DOMContentLoaded', () => { + const { indexName, appID, apiKey, hits } = CONFIG.algolia; + + const search = instantsearch({ + indexName, + searchClient : algoliasearch(appID, apiKey), + searchFunction: helper => { + if (document.querySelector('.search-input').value) { + helper.search(); + } + } + }); + + if (typeof pjax === 'object') { + search.on('render', () => { + pjax.refresh(document.querySelector('.algolia-hits')); + }); + } + + // Registering Widgets + search.addWidgets([ + instantsearch.widgets.configure({ + hitsPerPage: hits.per_page || 10 + }), + + instantsearch.widgets.searchBox({ + container : '.search-input-container', + placeholder : CONFIG.i18n.placeholder, + // Hide default icons of algolia search + showReset : false, + showSubmit : false, + showLoadingIndicator: false, + cssClasses : { + input: 'search-input' + } + }), + + instantsearch.widgets.stats({ + container: '.algolia-stats', + templates: { + text: data => { + const stats = CONFIG.i18n.hits_time + .replace('${hits}', data.nbHits) + .replace('${time}', data.processingTimeMS); + return `${stats} + Algolia`; + } + }, + cssClasses: { + text: 'search-stats' + } + }), + + instantsearch.widgets.hits({ + container : '.algolia-hits', + escapeHTML: false, + templates : { + item: data => { + const { title, excerpt, excerptStrip, contentStripTruncate } = data._highlightResult; + let result = `${title.value}`; + const content = excerpt || excerptStrip || contentStripTruncate; + if (content && content.value) { + const div = document.createElement('div'); + div.innerHTML = content.value; + result += `

    ${div.textContent.substring(0, 100)}...

    `; + } + return result; + }, + empty: data => { + return `
    + ${CONFIG.i18n.empty.replace('${query}', data.query)} +
    `; + } + }, + cssClasses: { + list: 'search-result-list' + } + }), + + instantsearch.widgets.pagination({ + container: '.algolia-pagination', + scrollTo : false, + showFirst: false, + showLast : false, + templates: { + first : '', + last : '', + previous: '', + next : '' + }, + cssClasses: { + list : ['pagination', 'algolia-pagination'], + item : 'pagination-item', + link : 'page-number', + selectedItem: 'current', + disabledItem: 'disabled-item' + } + }) + ]); + + search.start(); + + // Handle and trigger popup window + document.querySelectorAll('.popup-trigger').forEach(element => { + element.addEventListener('click', () => { + document.body.classList.add('search-active'); + setTimeout(() => document.querySelector('.search-input').focus(), 500); + }); + }); + + // Monitor main search box + const onPopupClose = () => { + document.body.classList.remove('search-active'); + }; + + document.querySelector('.search-pop-overlay').addEventListener('click', event => { + if (event.target === document.querySelector('.search-pop-overlay')) { + onPopupClose(); + } + }); + document.querySelector('.popup-btn-close').addEventListener('click', onPopupClose); + document.addEventListener('pjax:success', onPopupClose); + window.addEventListener('keyup', event => { + if (event.key === 'Escape') { + onPopupClose(); + } + }); +}); diff --git a/themes/next/source/js/third-party/search/local-search.js b/themes/next/source/js/third-party/search/local-search.js new file mode 100644 index 0000000..79429a9 --- /dev/null +++ b/themes/next/source/js/third-party/search/local-search.js @@ -0,0 +1,99 @@ +/* global CONFIG, pjax, LocalSearch */ + +document.addEventListener('DOMContentLoaded', () => { + if (!CONFIG.path) { + // Search DB path + console.warn('`hexo-generator-searchdb` plugin is not installed!'); + return; + } + const localSearch = new LocalSearch({ + path : CONFIG.path, + top_n_per_article: CONFIG.localsearch.top_n_per_article, + unescape : CONFIG.localsearch.unescape + }); + + const input = document.querySelector('.search-input'); + + const inputEventFunction = () => { + if (!localSearch.isfetched) return; + const searchText = input.value.trim().toLowerCase(); + const keywords = searchText.split(/[-\s]+/); + const container = document.querySelector('.search-result-container'); + let resultItems = []; + if (searchText.length > 0) { + // Perform local searching + resultItems = localSearch.getResultItems(keywords); + } + if (keywords.length === 1 && keywords[0] === '') { + container.classList.add('no-result'); + container.innerHTML = '
    '; + } else if (resultItems.length === 0) { + container.classList.add('no-result'); + container.innerHTML = '
    '; + } else { + resultItems.sort((left, right) => { + if (left.includedCount !== right.includedCount) { + return right.includedCount - left.includedCount; + } else if (left.hitCount !== right.hitCount) { + return right.hitCount - left.hitCount; + } + return right.id - left.id; + }); + const stats = CONFIG.i18n.hits.replace('${hits}', resultItems.length); + + container.classList.remove('no-result'); + container.innerHTML = `
    ${stats}
    +
    +
      ${resultItems.map(result => result.item).join('')}
    `; + if (typeof pjax === 'object') pjax.refresh(container); + } + }; + + localSearch.highlightSearchWords(document.querySelector('.post-body')); + if (CONFIG.localsearch.preload) { + localSearch.fetchData(); + } + + if (CONFIG.localsearch.trigger === 'auto') { + input.addEventListener('input', inputEventFunction); + } else { + document.querySelector('.search-icon').addEventListener('click', inputEventFunction); + input.addEventListener('keypress', event => { + if (event.key === 'Enter') { + inputEventFunction(); + } + }); + } + window.addEventListener('search:loaded', inputEventFunction); + + // Handle and trigger popup window + document.querySelectorAll('.popup-trigger').forEach(element => { + element.addEventListener('click', () => { + document.body.classList.add('search-active'); + // Wait for search-popup animation to complete + setTimeout(() => input.focus(), 500); + if (!localSearch.isfetched) localSearch.fetchData(); + }); + }); + + // Monitor main search box + const onPopupClose = () => { + document.body.classList.remove('search-active'); + }; + + document.querySelector('.search-pop-overlay').addEventListener('click', event => { + if (event.target === document.querySelector('.search-pop-overlay')) { + onPopupClose(); + } + }); + document.querySelector('.popup-btn-close').addEventListener('click', onPopupClose); + document.addEventListener('pjax:success', () => { + localSearch.highlightSearchWords(document.querySelector('.post-body')); + onPopupClose(); + }); + window.addEventListener('keyup', event => { + if (event.key === 'Escape') { + onPopupClose(); + } + }); +}); diff --git a/themes/next/source/js/third-party/statistics/firestore.js b/themes/next/source/js/third-party/statistics/firestore.js new file mode 100644 index 0000000..c7e17c8 --- /dev/null +++ b/themes/next/source/js/third-party/statistics/firestore.js @@ -0,0 +1,60 @@ +/* global CONFIG, firebase */ + +firebase.initializeApp({ + apiKey : CONFIG.firestore.apiKey, + projectId: CONFIG.firestore.projectId +}); + +(function() { + const getCount = (doc, increaseCount) => { + // IncreaseCount will be false when not in article page + return doc.get().then(d => { + // Has no data, initialize count + let count = d.exists ? d.data().count : 0; + // If first view this article + if (increaseCount) { + // Increase count + count++; + doc.set({ + count + }); + } + return count; + }); + }; + + const db = firebase.firestore(); + const articles = db.collection(CONFIG.firestore.collection); + + document.addEventListener('page:loaded', () => { + + if (CONFIG.page.isPost) { + // Fix issue #118 + // https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent + const title = document.querySelector('.post-title').textContent.trim(); + const doc = articles.doc(title); + let increaseCount = CONFIG.hostname === location.hostname; + if (localStorage.getItem(title)) { + increaseCount = false; + } else { + // Mark as visited + localStorage.setItem(title, true); + } + getCount(doc, increaseCount).then(count => { + document.querySelector('.firestore-visitors-count').innerText = count; + }); + } else if (CONFIG.page.isHome) { + const promises = [...document.querySelectorAll('.post-title')].map(element => { + const title = element.textContent.trim(); + const doc = articles.doc(title); + return getCount(doc); + }); + Promise.all(promises).then(counts => { + const metas = document.querySelectorAll('.firestore-visitors-count'); + counts.forEach((val, idx) => { + metas[idx].innerText = val; + }); + }); + } + }); +})(); diff --git a/themes/next/source/js/third-party/statistics/lean-analytics.js b/themes/next/source/js/third-party/statistics/lean-analytics.js new file mode 100644 index 0000000..a2aa944 --- /dev/null +++ b/themes/next/source/js/third-party/statistics/lean-analytics.js @@ -0,0 +1,107 @@ +/* global CONFIG */ +/* eslint-disable no-console */ + +(function() { + const leancloudSelector = url => { + url = encodeURI(url); + return document.getElementById(url).querySelector('.leancloud-visitors-count'); + }; + + const addCount = Counter => { + const visitors = document.querySelector('.leancloud_visitors'); + const url = decodeURI(visitors.id); + const title = visitors.dataset.flagTitle; + + Counter('get', `/classes/Counter?where=${encodeURIComponent(JSON.stringify({ url }))}`) + .then(response => response.json()) + .then(({ results }) => { + if (results.length > 0) { + const counter = results[0]; + leancloudSelector(url).innerText = counter.time + 1; + Counter('put', '/classes/Counter/' + counter.objectId, { + time: { + '__op' : 'Increment', + 'amount': 1 + } + }) + .catch(error => { + console.error('Failed to save visitor count', error); + }); + } else if (CONFIG.leancloud_visitors.security) { + leancloudSelector(url).innerText = 'Counter not initialized! More info at console err msg.'; + console.error('ATTENTION! LeanCloud counter has security bug, see how to solve it here: https://github.com/theme-next/hexo-leancloud-counter-security. \n However, you can still use LeanCloud without security, by setting `security` option to `false`.'); + } else { + Counter('post', '/classes/Counter', { title, url, time: 1 }) + .then(response => response.json()) + .then(() => { + leancloudSelector(url).innerText = 1; + }) + .catch(error => { + console.error('Failed to create', error); + }); + } + }) + .catch(error => { + console.error('LeanCloud Counter Error', error); + }); + }; + + const showTime = Counter => { + const visitors = document.querySelectorAll('.leancloud_visitors'); + const entries = [...visitors].map(element => { + return decodeURI(element.id); + }); + + Counter('get', `/classes/Counter?where=${encodeURIComponent(JSON.stringify({ url: { '$in': entries } }))}`) + .then(response => response.json()) + .then(({ results }) => { + for (const url of entries) { + const target = results.find(item => item.url === url); + leancloudSelector(url).innerText = target ? target.time : 0; + } + }) + .catch(error => { + console.error('LeanCloud Counter Error', error); + }); + }; + + const { app_id, app_key, server_url } = CONFIG.leancloud_visitors; + const fetchData = api_server => { + const Counter = (method, url, data) => { + return fetch(`${api_server}/1.1${url}`, { + method, + headers: { + 'X-LC-Id' : app_id, + 'X-LC-Key' : app_key, + 'Content-Type': 'application/json' + }, + body: JSON.stringify(data) + }); + }; + if (CONFIG.page.isPost) { + if (CONFIG.hostname !== location.hostname) return; + addCount(Counter); + } else if (document.querySelectorAll('.post-title-link').length >= 1) { + showTime(Counter); + } + }; + + let api_server; + if (server_url) { + api_server = server_url; + } else if (app_id.slice(-9) === '-MdYXbMMI') { + api_server = `https://${app_id.slice(0, 8).toLowerCase()}.api.lncldglobal.com`; + } + + document.addEventListener('page:loaded', () => { + if (api_server) { + fetchData(api_server); + } else { + fetch(`https://app-router.leancloud.cn/2/route?appId=${app_id}`) + .then(response => response.json()) + .then(({ api_server }) => { + fetchData(`https://${api_server}`); + }); + } + }); +})(); diff --git a/themes/next/source/js/third-party/tags/mermaid.js b/themes/next/source/js/third-party/tags/mermaid.js new file mode 100644 index 0000000..70a364f --- /dev/null +++ b/themes/next/source/js/third-party/tags/mermaid.js @@ -0,0 +1,32 @@ +/* global NexT, CONFIG, mermaid */ + +document.addEventListener('page:loaded', () => { + const mermaidElements = document.querySelectorAll('.mermaid'); + if (mermaidElements.length) { + NexT.utils.getScript(CONFIG.mermaid.js, { + condition: window.mermaid + }).then(() => { + mermaidElements.forEach(element => { + const newElement = document.createElement('div'); + newElement.innerHTML = element.innerHTML; + newElement.className = element.className; + const parent = element.parentNode; + // Fix issue #347 + // Support mermaid inside backtick code block + if (parent.matches('pre')) { + parent.parentNode.replaceChild(newElement, parent); + } else { + parent.replaceChild(newElement, element); + } + }); + mermaid.initialize({ + theme : CONFIG.darkmode && window.matchMedia('(prefers-color-scheme: dark)').matches ? CONFIG.mermaid.theme.dark : CONFIG.mermaid.theme.light, + logLevel : 4, + flowchart: { curve: 'linear' }, + gantt : { axisFormat: '%m/%d/%Y' }, + sequence : { actorMargin: 50 } + }); + mermaid.init(); + }); + } +}); diff --git a/themes/next/source/js/third-party/tags/pdf.js b/themes/next/source/js/third-party/tags/pdf.js new file mode 100644 index 0000000..645edd3 --- /dev/null +++ b/themes/next/source/js/third-party/tags/pdf.js @@ -0,0 +1,23 @@ +/* global NexT, CONFIG, PDFObject */ + +document.addEventListener('page:loaded', () => { + if (document.querySelectorAll('.pdf-container').length) { + NexT.utils.getScript(CONFIG.pdf.object_url, { + condition: window.PDFObject + }).then(() => { + document.querySelectorAll('.pdf-container').forEach(element => { + PDFObject.embed(element.dataset.target, element, { + pdfOpenParams: { + navpanes : 0, + toolbar : 0, + statusbar: 0, + pagemode : 'thumbs', + view : 'FitH' + }, + PDFJS_URL: CONFIG.pdf.url, + height : element.dataset.height + }); + }); + }); + } +}); diff --git a/themes/next/source/js/utils.js b/themes/next/source/js/utils.js new file mode 100644 index 0000000..c452f79 --- /dev/null +++ b/themes/next/source/js/utils.js @@ -0,0 +1,431 @@ +/* global NexT, CONFIG */ + +HTMLElement.prototype.wrap = function(wrapper) { + this.parentNode.insertBefore(wrapper, this); + this.parentNode.removeChild(this); + wrapper.appendChild(this); +}; + +(function() { + const onPageLoaded = () => document.dispatchEvent( + new Event('page:loaded', { + bubbles: true + }) + ); + + if (document.readyState === 'loading') { + document.addEventListener('readystatechange', onPageLoaded, { once: true }); + } else { + onPageLoaded(); + } + document.addEventListener('pjax:success', onPageLoaded); +})(); + +NexT.utils = { + + registerExtURL: function() { + document.querySelectorAll('span.exturl').forEach(element => { + const link = document.createElement('a'); + // https://stackoverflow.com/questions/30106476/using-javascripts-atob-to-decode-base64-doesnt-properly-decode-utf-8-strings + link.href = decodeURIComponent(atob(element.dataset.url).split('').map(c => { + return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); + }).join('')); + link.rel = 'noopener external nofollow noreferrer'; + link.target = '_blank'; + link.className = element.className; + link.title = element.title; + link.innerHTML = element.innerHTML; + element.parentNode.replaceChild(link, element); + }); + }, + + /** + * One-click copy code support. + */ + registerCopyCode: function() { + let figure = document.querySelectorAll('figure.highlight'); + if (figure.length === 0) figure = document.querySelectorAll('pre:not(.mermaid)'); + figure.forEach(element => { + element.querySelectorAll('.code .line span').forEach(span => { + span.classList.forEach(name => { + span.classList.replace(name, `hljs-${name}`); + }); + }); + if (!CONFIG.copycode.enable) return; + let target = element; + if (CONFIG.copycode.style !== 'mac') target = element.querySelector('.table-container') || element; + target.insertAdjacentHTML('beforeend', '
    '); + const button = element.querySelector('.copy-btn'); + button.addEventListener('click', () => { + const lines = element.querySelector('.code') || element.querySelector('code'); + const code = lines.innerText; + if (navigator.clipboard) { + // https://caniuse.com/mdn-api_clipboard_writetext + navigator.clipboard.writeText(code).then(() => { + button.querySelector('i').className = 'fa fa-check-circle fa-fw'; + }, () => { + button.querySelector('i').className = 'fa fa-times-circle fa-fw'; + }); + } else { + const ta = document.createElement('textarea'); + ta.style.top = window.scrollY + 'px'; // Prevent page scrolling + ta.style.position = 'absolute'; + ta.style.opacity = '0'; + ta.readOnly = true; + ta.value = code; + document.body.append(ta); + ta.select(); + ta.setSelectionRange(0, code.length); + ta.readOnly = false; + const result = document.execCommand('copy'); + button.querySelector('i').className = result ? 'fa fa-check-circle fa-fw' : 'fa fa-times-circle fa-fw'; + ta.blur(); // For iOS + button.blur(); + document.body.removeChild(ta); + } + }); + element.addEventListener('mouseleave', () => { + setTimeout(() => { + button.querySelector('i').className = 'fa fa-copy fa-fw'; + }, 300); + }); + }); + }, + + wrapTableWithBox: function() { + document.querySelectorAll('table').forEach(element => { + const box = document.createElement('div'); + box.className = 'table-container'; + element.wrap(box); + }); + }, + + registerVideoIframe: function() { + document.querySelectorAll('iframe').forEach(element => { + const supported = [ + 'www.youtube.com', + 'player.vimeo.com', + 'player.youku.com', + 'player.bilibili.com', + 'www.tudou.com' + ].some(host => element.src.includes(host)); + if (supported && !element.parentNode.matches('.video-container')) { + const box = document.createElement('div'); + box.className = 'video-container'; + element.wrap(box); + const width = Number(element.width); + const height = Number(element.height); + if (width && height) { + box.style.paddingTop = (height / width * 100) + '%'; + } + } + }); + }, + + registerScrollPercent: function() { + const backToTop = document.querySelector('.back-to-top'); + const readingProgressBar = document.querySelector('.reading-progress-bar'); + // For init back to top in sidebar if page was scrolled after page refresh. + window.addEventListener('scroll', () => { + if (backToTop || readingProgressBar) { + const contentHeight = document.body.scrollHeight - window.innerHeight; + const scrollPercent = contentHeight > 0 ? Math.min(100 * window.scrollY / contentHeight, 100) : 0; + if (backToTop) { + backToTop.classList.toggle('back-to-top-on', Math.round(scrollPercent) >= 5); + backToTop.querySelector('span').innerText = Math.round(scrollPercent) + '%'; + } + if (readingProgressBar) { + readingProgressBar.style.setProperty('--progress', scrollPercent.toFixed(2) + '%'); + } + } + if (!Array.isArray(NexT.utils.sections)) return; + let index = NexT.utils.sections.findIndex(element => { + return element && element.getBoundingClientRect().top > 10; + }); + if (index === -1) { + index = NexT.utils.sections.length - 1; + } else if (index > 0) { + index--; + } + this.activateNavByIndex(index); + }, { passive: true }); + + backToTop && backToTop.addEventListener('click', () => { + window.anime({ + targets : document.scrollingElement, + duration : 500, + easing : 'linear', + scrollTop: 0 + }); + }); + }, + + /** + * Tabs tag listener (without twitter bootstrap). + */ + registerTabsTag: function() { + // Binding `nav-tabs` & `tab-content` by real time permalink changing. + document.querySelectorAll('.tabs ul.nav-tabs .tab').forEach(element => { + element.addEventListener('click', event => { + event.preventDefault(); + // Prevent selected tab to select again. + if (element.classList.contains('active')) return; + const nav = element.parentNode; + // Get the height of `tab-pane` which is activated before, and set it as the height of `tab-content` with extra margin / paddings. + const tabContent = nav.nextElementSibling; + tabContent.style.overflow = 'hidden'; + tabContent.style.transition = 'height 1s'; + // Comment system selection tab does not contain .active class. + const activeTab = tabContent.querySelector('.active') || tabContent.firstElementChild; + // Hight might be `auto`. + const prevHeight = parseInt(window.getComputedStyle(activeTab).height.replace('px', ''), 10) || 0; + const paddingTop = parseInt(window.getComputedStyle(activeTab).paddingTop.replace('px', ''), 10); + const marginBottom = parseInt(window.getComputedStyle(activeTab.firstElementChild).marginBottom.replace('px', ''), 10); + tabContent.style.height = prevHeight + paddingTop + marginBottom + 'px'; + // Add & Remove active class on `nav-tabs` & `tab-content`. + [...nav.children].forEach(target => { + target.classList.toggle('active', target === element); + }); + // https://stackoverflow.com/questions/20306204/using-queryselector-with-ids-that-are-numbers + const tActive = document.getElementById(element.querySelector('a').getAttribute('href').replace('#', '')); + [...tActive.parentNode.children].forEach(target => { + target.classList.toggle('active', target === tActive); + }); + // Trigger event + tActive.dispatchEvent(new Event('tabs:click', { + bubbles: true + })); + // Get the height of `tab-pane` which is activated now. + const hasScrollBar = document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight); + const currHeight = parseInt(window.getComputedStyle(tabContent.querySelector('.active')).height.replace('px', ''), 10); + // Reset the height of `tab-content` and see the animation. + tabContent.style.height = currHeight + paddingTop + marginBottom + 'px'; + // Change the height of `tab-content` may cause scrollbar show / disappear, which may result in the change of the `tab-pane`'s height + setTimeout(() => { + if ((document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight)) !== hasScrollBar) { + tabContent.style.transition = 'height 0.3s linear'; + // After the animation, we need reset the height of `tab-content` again. + const currHeightAfterScrollBarChange = parseInt(window.getComputedStyle(tabContent.querySelector('.active')).height.replace('px', ''), 10); + tabContent.style.height = currHeightAfterScrollBarChange + paddingTop + marginBottom + 'px'; + } + // Remove all the inline styles, and let the height be adaptive again. + setTimeout(() => { + tabContent.style.transition = ''; + tabContent.style.height = ''; + }, 250); + }, 1000); + if (!CONFIG.stickytabs) return; + const offset = nav.parentNode.getBoundingClientRect().top + window.scrollY + 10; + window.anime({ + targets : document.scrollingElement, + duration : 500, + easing : 'linear', + scrollTop: offset + }); + }); + }); + + window.dispatchEvent(new Event('tabs:register')); + }, + + registerCanIUseTag: function() { + // Get responsive height passed from iframe. + window.addEventListener('message', ({ data }) => { + if (typeof data === 'string' && data.includes('ciu_embed')) { + const featureID = data.split(':')[1]; + const height = data.split(':')[2]; + document.querySelector(`iframe[data-feature=${featureID}]`).style.height = parseInt(height, 10) + 5 + 'px'; + } + }, false); + }, + + registerActiveMenuItem: function() { + document.querySelectorAll('.menu-item a[href]').forEach(target => { + const isSamePath = target.pathname === location.pathname || target.pathname === location.pathname.replace('index.html', ''); + const isSubPath = !CONFIG.root.startsWith(target.pathname) && location.pathname.startsWith(target.pathname); + target.classList.toggle('menu-item-active', target.hostname === location.hostname && (isSamePath || isSubPath)); + }); + }, + + registerLangSelect: function() { + const selects = document.querySelectorAll('.lang-select'); + selects.forEach(sel => { + sel.value = CONFIG.page.lang; + sel.addEventListener('change', () => { + const target = sel.options[sel.selectedIndex]; + document.querySelectorAll('.lang-select-label span').forEach(span => { + span.innerText = target.text; + }); + // Disable Pjax to force refresh translation of menu item + window.location.href = target.dataset.href; + }); + }); + }, + + registerSidebarTOC: function() { + this.sections = [...document.querySelectorAll('.post-toc li a.nav-link')].map(element => { + const target = document.getElementById(decodeURI(element.getAttribute('href')).replace('#', '')); + // TOC item animation navigate. + element.addEventListener('click', event => { + event.preventDefault(); + const offset = target.getBoundingClientRect().top + window.scrollY; + window.anime({ + targets : document.scrollingElement, + duration : 500, + easing : 'linear', + scrollTop: offset, + complete : () => { + history.pushState(null, document.title, element.href); + } + }); + }); + return target; + }); + }, + + registerPostReward: function() { + const button = document.querySelector('.reward-container button'); + if (!button) return; + button.addEventListener('click', () => { + document.querySelector('.post-reward').classList.toggle('active'); + }); + }, + + activateNavByIndex: function(index) { + const target = document.querySelectorAll('.post-toc li a.nav-link')[index]; + if (!target || target.classList.contains('active-current')) return; + + document.querySelectorAll('.post-toc .active').forEach(element => { + element.classList.remove('active', 'active-current'); + }); + target.classList.add('active', 'active-current'); + let parent = target.parentNode; + while (!parent.matches('.post-toc')) { + if (parent.matches('li')) parent.classList.add('active'); + parent = parent.parentNode; + } + // Scrolling to center active TOC element if TOC content is taller then viewport. + const tocElement = document.querySelector(CONFIG.scheme === 'Pisces' || CONFIG.scheme === 'Gemini' ? '.sidebar-panel-container' : '.sidebar'); + if (!document.querySelector('.sidebar-toc-active')) return; + window.anime({ + targets : tocElement, + duration : 200, + easing : 'linear', + scrollTop: tocElement.scrollTop - (tocElement.offsetHeight / 2) + target.getBoundingClientRect().top - tocElement.getBoundingClientRect().top + }); + }, + + updateSidebarPosition: function() { + if (window.innerWidth < 1200 || CONFIG.scheme === 'Pisces' || CONFIG.scheme === 'Gemini') return; + // Expand sidebar on post detail page by default, when post has a toc. + const hasTOC = document.querySelector('.post-toc'); + let display = CONFIG.page.sidebar; + if (typeof display !== 'boolean') { + // There's no definition sidebar in the page front-matter. + display = CONFIG.sidebar.display === 'always' || (CONFIG.sidebar.display === 'post' && hasTOC); + } + if (display) { + window.dispatchEvent(new Event('sidebar:show')); + } + }, + + activateSidebarPanel: function(index) { + const duration = 200; + const sidebar = document.querySelector('.sidebar-inner'); + const panel = document.querySelector('.sidebar-panel-container'); + const activeClassName = ['sidebar-toc-active', 'sidebar-overview-active']; + + if (sidebar.classList.contains(activeClassName[index])) return; + + window.anime({ + duration, + targets : panel, + easing : 'linear', + opacity : 0, + translateY: [0, -20], + complete : () => { + // Prevent adding TOC to Overview if Overview was selected when close & open sidebar. + sidebar.classList.replace(activeClassName[1 - index], activeClassName[index]); + window.anime({ + duration, + targets : panel, + easing : 'linear', + opacity : [0, 1], + translateY: [-20, 0] + }); + } + }); + }, + + getScript: function(src, options = {}, legacyCondition) { + if (typeof options === 'function') { + return this.getScript(src, { + condition: legacyCondition + }).then(options); + } + const { + condition = false, + attributes: { + id = '', + async = false, + defer = false, + crossOrigin = '', + dataset = {}, + ...otherAttributes + } = {}, + parentNode = null + } = options; + return new Promise((resolve, reject) => { + if (condition) { + resolve(); + } else { + const script = document.createElement('script'); + + if (id) script.id = id; + if (crossOrigin) script.crossOrigin = crossOrigin; + script.async = async; + script.defer = defer; + Object.assign(script.dataset, dataset); + Object.entries(otherAttributes).forEach(([name, value]) => { + script.setAttribute(name, String(value)); + }); + + script.onload = resolve; + script.onerror = reject; + + if (typeof src === 'object') { + const { url, integrity } = src; + script.src = url; + if (integrity) { + script.integrity = integrity; + script.crossOrigin = 'anonymous'; + } + } else { + script.src = src; + } + (parentNode || document.head).appendChild(script); + } + }); + }, + + loadComments: function(selector, legacyCallback) { + if (legacyCallback) { + return this.loadComments(selector).then(legacyCallback); + } + return new Promise(resolve => { + const element = document.querySelector(selector); + if (!CONFIG.comments.lazyload || !element) { + resolve(); + return; + } + const intersectionObserver = new IntersectionObserver((entries, observer) => { + const entry = entries[0]; + if (!entry.isIntersecting) return; + + resolve(); + observer.disconnect(); + }); + intersectionObserver.observe(element); + }); + } +}; diff --git a/themes/next/test/helpers/font.js b/themes/next/test/helpers/font.js new file mode 100644 index 0000000..18484c8 --- /dev/null +++ b/themes/next/test/helpers/font.js @@ -0,0 +1,86 @@ +'use strict'; + +require('chai').should(); +const Hexo = require('hexo'); +const hexo = new Hexo(); + +const fontStyles = ':300,300italic,400,400italic,700,700italic'; +const fontHost = 'https://fonts.googleapis.com'; + +describe('font', () => { + const nextFont = require('../../scripts/helpers/font').bind(hexo); + + before(() => { + hexo.theme.font = {}; + }); + + it('font disabled', () => { + hexo.theme.font.enable = false; + hexo.theme.font.title = { + family : 'Amatic SC', + external: true + }; + nextFont().should.eql(''); + }); + + it('no external font', () => { + hexo.theme.font.enable = true; + hexo.theme.font.title = { + family : 'Amatic SC', + external: false + }; + nextFont().should.eql(''); + }); + + it('trivial', () => { + hexo.theme.font.enable = true; + hexo.theme.font.title = { + family : 'Amatic SC', + external: true + }; + hexo.theme.font.headings = { + family : 'Palatino', + external: false + }; + nextFont().should.eql(``); + }); + + it('multiple', () => { + hexo.theme.font.enable = true; + hexo.theme.font.title = { + family : 'Amatic SC', + external: true + }; + hexo.theme.font.headings = { + family : 'Palatino', + external: true + }; + nextFont().should.eql(``); + }); + + it('duplicate', () => { + hexo.theme.font.enable = true; + hexo.theme.font.title = { + family : 'Palatino', + external: true + }; + hexo.theme.font.headings = { + family : 'Palatino', + external: true + }; + nextFont().should.eql(``); + }); + + it('fallback font', () => { + hexo.theme.font.enable = true; + hexo.theme.font.title = { + family : 'Roboto Slab, Noto Serif SC', + external: true + }; + hexo.theme.font.headings = { + family : 'Palatino', + external: true + }; + nextFont().should.eql(``); + }); +}); diff --git a/themes/next/test/helpers/index.js b/themes/next/test/helpers/index.js new file mode 100644 index 0000000..fcc7e9f --- /dev/null +++ b/themes/next/test/helpers/index.js @@ -0,0 +1,6 @@ +'use strict'; + +describe('Helpers', () => { + require('./font'); + require('./next-url'); +}); diff --git a/themes/next/test/helpers/next-url.js b/themes/next/test/helpers/next-url.js new file mode 100644 index 0000000..1eb6e09 --- /dev/null +++ b/themes/next/test/helpers/next-url.js @@ -0,0 +1,46 @@ +'use strict'; + +require('chai').should(); +const Hexo = require('hexo'); +const hexo = new Hexo(); + +function btoa(str) { + return Buffer.from(str).toString('base64'); +} + +describe('next-url', () => { + const nextUrl = require('../../scripts/helpers/next-url').bind(hexo); + + before(() => { + hexo.config.url = 'https://example.com'; + hexo.url_for = require('hexo/lib/plugins/helper/url_for').bind(hexo); + }); + + it('text', () => { + nextUrl('/child/', 'Text').should.eql('Text'); + }); + + it('icon', () => { + nextUrl('/child/', '').should.eql(''); + }); + + it('class', () => { + nextUrl('/child/', 'Text', { class: 'theme-link' }).should.eql('Text'); + }); + + it('external', () => { + nextUrl('https://theme-next.js.org', 'Text').should.eql('Text'); + }); + + it('exturl enabled', () => { + hexo.theme.exturl = true; + const encoded = btoa('https://theme-next.js.org'); + nextUrl('https://theme-next.js.org', 'Text').should.eql(`Text`); + }); + + it('class with exturl enabled', () => { + hexo.theme.exturl = true; + const encoded = btoa('https://theme-next.js.org'); + nextUrl('https://theme-next.js.org', 'Text', { class: 'theme-link' }).should.eql(`Text`); + }); +}); diff --git a/themes/next/test/index.js b/themes/next/test/index.js new file mode 100644 index 0000000..d8bd03f --- /dev/null +++ b/themes/next/test/index.js @@ -0,0 +1,7 @@ +'use strict'; + +describe('NexT', () => { + require('./helpers'); + require('./tags'); + require('./validate'); +}); diff --git a/themes/next/test/tags/button.js b/themes/next/test/tags/button.js new file mode 100644 index 0000000..7432198 --- /dev/null +++ b/themes/next/test/tags/button.js @@ -0,0 +1,33 @@ +'use strict'; + +require('chai').should(); +const Hexo = require('hexo'); +const hexo = new Hexo(); + +describe('button', () => { + const postButton = require('../../scripts/tags/button')(hexo); + + it('only url', () => { + postButton(['#']).should.eql(''); + }); + + it('url and text', () => { + postButton('#, Hello world'.split(' ')).should.eql('Hello world'); + }); + + it('url and icon (Font Awesome 4)', () => { + postButton('#,, home fa-5x'.split(' ')).should.eql(''); + }); + + it('url and icon', () => { + postButton('#,, fab fa-fort-awesome fa-5x'.split(' ')).should.eql(''); + }); + + it('url, text and title', () => { + postButton('#, Hello world,, Title'.split(' ')).should.eql('Hello world'); + }); + + it('url, text, icon and title', () => { + postButton('#, Hello world, home, Title'.split(' ')).should.eql('Hello world'); + }); +}); diff --git a/themes/next/test/tags/caniuse.js b/themes/next/test/tags/caniuse.js new file mode 100644 index 0000000..425133e --- /dev/null +++ b/themes/next/test/tags/caniuse.js @@ -0,0 +1,17 @@ +'use strict'; + +require('chai').should(); +const Hexo = require('hexo'); +const hexo = new Hexo(); + +describe('caniuse', () => { + const caniUse = require('../../scripts/tags/caniuse')(hexo); + + it('only feature', () => { + caniUse(['loading-lazy-attr']).should.eql(''); + }); + + it('feature and periods', () => { + caniUse('fetch @ future_3,future_2,future_1'.split(' ')).should.eql(''); + }); +}); diff --git a/themes/next/test/tags/center-quote.js b/themes/next/test/tags/center-quote.js new file mode 100644 index 0000000..f1d1686 --- /dev/null +++ b/themes/next/test/tags/center-quote.js @@ -0,0 +1,21 @@ +'use strict'; + +require('chai').should(); +const Hexo = require('hexo'); +const hexo = new Hexo(); + +const content = 'Test **Bold** *Italic*'; +const result = '

    Test Bold Italic

    '; + +describe('center-quote', () => { + const centerQuote = require('../../scripts/tags/center-quote')(hexo); + + before(() => hexo.init().then(() => hexo.loadPlugin(require.resolve('hexo-renderer-marked')))); + + it('markdown content', () => { + centerQuote([], content).should.eql(`
    +${result} + +
    `); + }); +}); diff --git a/themes/next/test/tags/group-pictures.js b/themes/next/test/tags/group-pictures.js new file mode 100644 index 0000000..95e5417 --- /dev/null +++ b/themes/next/test/tags/group-pictures.js @@ -0,0 +1,63 @@ +'use strict'; + +require('chai').should(); +const Hexo = require('hexo'); +const hexo = new Hexo(); + +const link = '
    '; +const image = '
    '; + +describe('group-pictures', () => { + const groupPicture = require('../../scripts/tags/group-pictures')(hexo); + + before(() => hexo.init().then(() => hexo.loadPlugin(require.resolve('hexo-renderer-marked')))); + + it('layout 3-3', () => { + groupPicture(['3-3'], ` +![](/images/sample.png) +![](/images/sample.png) +![](/images/sample.png)`).should.eql(`
    ${image}${image}${image}
    `); + }); + + it('layout 5-2', () => { + groupPicture(['5-2'], ` +![](/images/sample.png) +![](/images/sample.png) +![](/images/sample.png) +![](/images/sample.png) +![](/images/sample.png)`).should.eql(`
    ${image}${image}
    ${image}
    ${image}${image}
    `); + }); + + it('remove text', () => { + groupPicture(['3-3'], ` +![](/images/sample.png) +Text +![](/images/sample.png) +Text +![](/images/sample.png)`).should.eql(`
    ${image}${image}${image}
    `); + }); + + it('set hyperlinks', () => { + groupPicture(['4-3'], ` +![](/images/sample.png) +[![](/images/sample.png)](https://theme-next.js.org/) +[![](/images/sample.png)](https://theme-next.js.org/) +![](/images/sample.png)`).should.eql(`
    ${image}${link}
    ${link}${image}
    `); + }); + + it('set hyperlinks 2', () => { + groupPicture(['3-3'], ` +![](/images/sample.png) +[![](/images/sample.png)](https://theme-next.js.org/) +![](/images/sample.png)`).should.eql(`
    ${image}${link}${image}
    `); + }); + + it('no layout', () => { + groupPicture(['NaN-NaN'], ` +![](/images/sample.png) +![](/images/sample.png) +![](/images/sample.png) +![](/images/sample.png) +![](/images/sample.png)`).should.eql(`
    ${image}${image}${image}
    ${image}${image}
    `); + }); +}); diff --git a/themes/next/test/tags/index.js b/themes/next/test/tags/index.js new file mode 100644 index 0000000..38bb8fd --- /dev/null +++ b/themes/next/test/tags/index.js @@ -0,0 +1,15 @@ +'use strict'; + +describe('Tags', () => { + require('./button'); + require('./caniuse'); + require('./center-quote'); + require('./group-pictures'); + require('./label'); + require('./link-grid'); + require('./mermaid'); + require('./note'); + require('./pdf'); + require('./tabs'); + require('./video'); +}); diff --git a/themes/next/test/tags/label.js b/themes/next/test/tags/label.js new file mode 100644 index 0000000..d136f1b --- /dev/null +++ b/themes/next/test/tags/label.js @@ -0,0 +1,21 @@ +'use strict'; + +require('chai').should(); +const Hexo = require('hexo'); +const hexo = new Hexo(); + +describe('label', () => { + const postLabel = require('../../scripts/tags/label')(hexo); + + it('only text', () => { + postLabel('@Hello world'.split(' ')).should.eql('Hello world'); + }); + + it('classes and text', () => { + postLabel('primary@Hello world'.split(' ')).should.eql('Hello world'); + }); + + it('classes and text with space', () => { + postLabel('primary @Hello world'.split(' ')).should.eql('Hello world'); + }); +}); diff --git a/themes/next/test/tags/link-grid.js b/themes/next/test/tags/link-grid.js new file mode 100644 index 0000000..f95f323 --- /dev/null +++ b/themes/next/test/tags/link-grid.js @@ -0,0 +1,49 @@ +'use strict'; + +require('chai').should(); + +const result = ``; + +describe('link-grid', () => { + const linkGrid = require('../../scripts/tags/link-grid'); + + it('default', () => { + linkGrid([], ` +Theme NexT | https://theme-next.js.org/ | Stay Simple. Stay NexT. | /images/sample.png +Theme NexT | https://theme-next.js.org/ | Stay Simple. Stay NexT. | /images/sample.png`).should.eql(result); + }); + + it('comment', () => { + linkGrid([], ` +Theme NexT | https://theme-next.js.org/ | Stay Simple. Stay NexT. | /images/sample.png +Theme NexT | https://theme-next.js.org/ | Stay Simple. Stay NexT. | /images/sample.png +% Theme NexT | https://theme-next.js.org/ | Stay Simple. Stay NexT. | /images/sample.png`).should.eql(result); + }); + + it('default image', () => { + linkGrid(['/images/sample.png'], ` +Theme NexT | https://theme-next.js.org/ | Stay Simple. Stay NexT. | +Theme NexT | https://theme-next.js.org/ | Stay Simple. Stay NexT. |`).should.eql(result); + }); + + it('custom delimiter', () => { + linkGrid(['/images/sample.png', ','], ` +Theme NexT , https://theme-next.js.org/ , Stay Simple. Stay NexT. , /images/sample.png +Theme NexT , https://theme-next.js.org/ , Stay Simple. Stay NexT. , /images/sample.png`).should.eql(result); + }); + + it('custom delimiter and comment', () => { + linkGrid(['/images/sample.png', ',', '#'], ` +Theme NexT , https://theme-next.js.org/ , Stay Simple. Stay NexT. , /images/sample.png +Theme NexT , https://theme-next.js.org/ , Stay Simple. Stay NexT. , /images/sample.png +# Theme NexT , https://theme-next.js.org/ , Stay Simple. Stay NexT. , /images/sample.png`).should.eql(result); + }); +}); diff --git a/themes/next/test/tags/mermaid.js b/themes/next/test/tags/mermaid.js new file mode 100644 index 0000000..b870fab --- /dev/null +++ b/themes/next/test/tags/mermaid.js @@ -0,0 +1,21 @@ +'use strict'; + +require('chai').should(); + +const { escapeHTML } = require('hexo-util'); + +const result = `A[Hard] -->|Text| B(Round) +B --> C{Decision} +C -->|One| D[Result 1] +C -->|Two| E[Result 2]`; + +describe('mermaid', () => { + const mermaid = require('../../scripts/tags/mermaid'); + + it('default', () => { + mermaid(['graph', 'TD'], result).should.eql(`
    +graph TD
    +${escapeHTML(result)}
    +
    `); + }); +}); diff --git a/themes/next/test/tags/note.js b/themes/next/test/tags/note.js new file mode 100644 index 0000000..1c44606 --- /dev/null +++ b/themes/next/test/tags/note.js @@ -0,0 +1,63 @@ +'use strict'; + +require('chai').should(); +const Hexo = require('hexo'); +const hexo = new Hexo(); + +const content = 'Test **Bold** *Italic*'; +const result = '

    Test Bold Italic

    '; +const args = 'This is a *summary*'.split(' '); +const summary = '

    This is a summary'; + +describe('note', () => { + const postNote = require('../../scripts/tags/note')(hexo); + + before(() => hexo.init().then(() => hexo.loadPlugin(require.resolve('hexo-renderer-marked')))); + + it('only text', () => { + postNote([], content).should.eql(`

    ${result} +
    `); + }); + + it('classes and text', () => { + postNote(['primary'], content).should.eql(`
    ${result} +
    `); + }); + + it('classes, no-icon and text', () => { + postNote(['primary', 'no-icon'], content).should.eql(`
    ${result} +
    `); + }); + + it('summary and text', () => { + postNote(args, content).should.eql(`
    ${summary}

    +
    +${result} + +`); + }); + + it('classes, summary and text', () => { + postNote(['primary'].concat(args), content).should.eql(`
    ${summary}

    + +${result} + +
    `); + }); + + it('classes, no-icon, summary and text', () => { + postNote(['primary', 'no-icon'].concat(args), content).should.eql(`
    ${summary}

    + +${result} + +
    `); + }); + + it('keywords in summary', () => { + postNote(['It\'s', 'danger'], content).should.eql(`

    It’s danger

    +
    +${result} + +
    `); + }); +}); diff --git a/themes/next/test/tags/pdf.js b/themes/next/test/tags/pdf.js new file mode 100644 index 0000000..76e7c47 --- /dev/null +++ b/themes/next/test/tags/pdf.js @@ -0,0 +1,23 @@ +'use strict'; + +require('chai').should(); +const Hexo = require('hexo'); +const hexo = new Hexo(); + +describe('pdf', () => { + const pdf = require('../../scripts/tags/pdf')(hexo); + + before(() => { + hexo.theme.config.pdf = { + height: '500px' + }; + }); + + it('default', () => { + pdf(['https://example.com/sample.pdf']).should.eql('
    '); + }); + + it('custom height', () => { + pdf(['https://example.com/sample.pdf', '1000px']).should.eql('
    '); + }); +}); diff --git a/themes/next/test/tags/tabs.js b/themes/next/test/tags/tabs.js new file mode 100644 index 0000000..4747362 --- /dev/null +++ b/themes/next/test/tags/tabs.js @@ -0,0 +1,96 @@ +'use strict'; + +require('chai').should(); +const Hexo = require('hexo'); +const hexo = new Hexo(); + +const content = 'Test **Bold** *Italic*'; +const result = '

    Test Bold Italic

    '; +const container = '
    `); + }); + + it('default', () => { + postTabs(['name'], + ` +${content} + + + +${content} +`).should.eql(`${container}
  • name 1
  • name 2
  • ${result}
    ${result}
    `); + }); + + it('selected index', () => { + postTabs('name, 2'.split(' '), + ` +${content} + + + +${content} +`).should.eql(`${container}
  • name 1
  • name 2
  • ${result}
    ${result}
    `); + }); + + it('no tab selected', () => { + postTabs('name, -1'.split(' '), + ` +${content} + + + +${content} +`).should.eql(`${container}
  • name 1
  • name 2
  • ${result}
    ${result}
    `); + }); + + it('label', () => { + postTabs('name'.split(' '), + ` +${content} + + + +${content} +`).should.eql(`${container}
  • Tab 1
  • Tab 2
  • ${result}
    ${result}
    `); + }); + + it('icon (Font Awesome 4)', () => { + postTabs('name'.split(' '), + ` +${content} + + + +${content} +`).should.eql(`${container}
  • ${result}
    ${result}
    `); + }); + + it('icon', () => { + postTabs('name'.split(' '), + ` +${content} + + + +${content} +`).should.eql(`${container}
  • ${result}
    ${result}
    `); + }); + + it('label and icon', () => { + postTabs('name, -1'.split(' '), + ` +${content} + + + +${content} +`).should.eql(`${container}
  • Tab 1
  • Tab 1
  • ${result}
    ${result}
    `); + }); +}); diff --git a/themes/next/test/tags/video.js b/themes/next/test/tags/video.js new file mode 100644 index 0000000..556bc13 --- /dev/null +++ b/themes/next/test/tags/video.js @@ -0,0 +1,15 @@ +'use strict'; + +require('chai').should(); + +describe('video', () => { + const postVideo = require('../../scripts/tags/video'); + + it('default', () => { + postVideo(['https://example.com/sample.mp4']).should.eql(''); + }); + + it('poster', () => { + postVideo(['https://example.com/sample.mp4', 'https://example.com/sample.jpg']).should.eql(''); + }); +}); diff --git a/themes/next/test/validate/index.js b/themes/next/test/validate/index.js new file mode 100644 index 0000000..1bd0b43 --- /dev/null +++ b/themes/next/test/validate/index.js @@ -0,0 +1,35 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const yaml = require('js-yaml'); +const should = require('chai').should(); + +describe('Validate', () => { + it('config', () => { + const themeConfig = fs.readFileSync(path.join(__dirname, '../../_config.yml')); + should.not.throw(() => { + yaml.load(themeConfig); + }); + }); + + it('vendors', () => { + const vendorsFile = fs.readFileSync(path.join(__dirname, '../../_vendors.yml')); + should.not.throw(() => { + yaml.load(vendorsFile); + }); + }); + + it('language', () => { + const languagesPath = path.join(__dirname, '../../languages'); + should.not.throw(() => { + fs.readdirSync(languagesPath).forEach(lang => { + if (!lang.endsWith('.yml')) return; + const languagePath = path.join(languagesPath, lang); + yaml.load(fs.readFileSync(languagePath), { + filename: path.relative(__dirname, languagePath) + }); + }); + }); + }); +});