diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..cdded464 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +charset = utf-8 +# 2 space indentation +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true +# Unix-style newlines with a newline ending every file +end_of_line = lf +insert_final_newline = true diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..262d6bd7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,16 @@ +# Set default behavior to automatically normalize line endings. +* text=auto + +# Force bash scripts to always use LF line endings so that if a repo is accessed +# in Unix via a file share from Windows, the scripts will work. +*.sh text eol=lf + +# Force batch scripts to always use CRLF line endings so that if a repo is accessed +# in Windows via a file share from Linux, the scripts will work. +*.{cmd,[cC][mM][dD]} text eol=crlf +*.{bat,[bB][aA][tT]} text eol=crlf + +# Denote all files that are truly binary and should not be modified. +*.png binary +*.jpg binary +*.ico binary diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..bf8db4d0 --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,73 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at `cotes.chung@gmail.com`. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at + +For answers to common questions about this code of conduct, see + + +[homepage]: https://www.contributor-covenant.org \ No newline at end of file diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 00000000..162cb5f9 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,16 @@ +# How to Contribute + +I want to thank you for sparing time to improve this project! Here are some guidelines for contributing: + +To ensure that the blog design is not confused, this project does not accept suggestions for design changes, such as color scheme, fonts, typography, etc. If your request is about an enhancement, it is recommended to first submit a [`Feature Request`](https://github.com/cotes2020/jekyll-theme-chirpy/issues/new?labels=enhancement&template=feature_request.md) issue to discuss whether your idea fits the project. + +Generally, contribute to the project by: + +1. Fork this project on GitHub and clone it locally. +2. Create a new branch from `master` and give it a descriptive name (e.g., `my-new-feature`, `fix-a-bug`). +3. After completing the development, commit and push to remote. +4. Submit a new pull request. + +--- + +:tada: Your volunteering will make the open-source world more beautiful, thanks again! :tada: diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..89494bc4 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +ko_fi: coteschung +custom: https://cotes.gitee.io/alipay-wechat-donation diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..d86d8729 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,64 @@ +--- +name: Bug Report +about: Create a report to help us improve +--- + + + +## Checklist + + + +- [ ] I have read the [tutorials](https://chirpy.cotes.info/categories/tutorial/) and know the correct effect of the functional design. +- [ ] There are no similar reports on [existing issues](https://github.com/cotes2020/jekyll-theme-chirpy/issues?q=is%3Aissue) (including closed ones). +- [ ] I found the bug on the latest code of the `master` branch. + +## Describe the bug + + + +### To Reproduce + +Steps to reproduce the behavior: + + +### Expected behavior + + + +### Screenshots + + + +### Software + + +- Ruby version: +- Gem version: +- Bundler version: +- Jekyll version: +- Theme version: + +### Desktop + + + +### Smartphone + + + +### Additional context + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..7d866cf7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,35 @@ +--- +name: Feature Request +about: Suggest an idea for this project +labels: enhancement +--- + + + +## Checklist + + +- [ ] I have read the [contributing guidelines](https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/.github/CONTRIBUTING.md). +- [ ] There is no similar request on [existing issues](https://github.com/cotes2020/jekyll-theme-chirpy/issues?q=is%3Aissue) (including closed ones). +- [ ] I have read the [project progress](https://github.com/cotes2020/jekyll-theme-chirpy/projects) and know the current progress of the project. +- [ ] I was in the `master` branch of the latest code. + + +## Is your feature request related to a problem? Please describe + + + + +## Describe the solution you'd like + + + + +## Describe alternatives you've considered + + + + +## Additional context + + diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md new file mode 100644 index 00000000..80f94fd4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.md @@ -0,0 +1,20 @@ +--- +name: Question +about: Ask whatever you want +labels: question +--- + + + +## Checklist + + + +- [ ] I have read the [newlest tutorials](https://chirpy.cotes.info/categories/tutorial/) and know the correct effect of the functional design. +- [ ] There is no similar question on [existing issues](https://github.com/cotes2020/jekyll-theme-chirpy/issues?q=is%3Aissue) (including closed ones). +- [ ] I have tried to find the answer on [Jekyll Forum](https://talk.jekyllrb.com/) and [StackOverflow](https://stackoverflow.com/questions/tagged/jekyll). +- [ ] My question is based on the latest code of the `master` branch. + +## Description + + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..0906ce6f --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,42 @@ +## Description + + + +## Type of change + + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] Documentation update + +## How has this been tested + + + +- [ ] I have run `bash ./tools/deploy.sh --dry-run` (at the root of the project) locally and passed +- [ ] I have tested this feature in the browser + +### Test Configuration + +- Browser type & version: +- Operating system: +- Ruby version: +- Bundler version: +- Jekyll version: + +### Checklist + + +- [ ] I have performed a self-review of my code +- [ ] I have commented on my code, particularly in hard-to-understand areas +- [ ] I have made corresponding changes to the documentation +- [ ] My changes generate no new warnings diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 00000000..019fa16f --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,17 @@ +# Clean up the stale issues + +daysUntilStale: 30 +daysUntilClose: 1 + +exemptLabels: + - in progress + - pending + +staleLabel: stale + +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. + +closeComment: false diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..f2222fca --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,40 @@ +name: 'Continuous Integration' +on: + push: + branches-ignore: + - 'production' + tags-ignore: + - '*' + paths-ignore: + - '.github/**' + - '!.github/workflows/ci.yml' + - '.travis.yml' + - '.gitignore' + - 'docs/**' + - 'README.md' + - 'LICENSE' + pull_request: + paths: + - '**' + +jobs: + ci: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 # for posts's lastmod + + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.7 + bundler-cache: true + + - name: Test Site + run: bash tools/deploy.sh --dry-run diff --git a/.github/workflows/issue-interceptor.yml b/.github/workflows/issue-interceptor.yml new file mode 100644 index 00000000..22bafdca --- /dev/null +++ b/.github/workflows/issue-interceptor.yml @@ -0,0 +1,18 @@ +name: Intercept bad issues + +on: + issues: + types: [opened, edited] + +jobs: + auto_close_issues: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v1 + - name: Auto close issues that did not follow template + uses: lucasbento/auto-close-issues@v1.0.2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + issue-close-message: ":wave: Hi @${issue.user.login},\n\nThis issue is being automatically closed because it does not follow the issue template. Please DO NOT open another similar issue, try to edit the current issue according to the template, then it will be reopened automatically." + closed-issues-label: "🙁 Not following issue template" diff --git a/.github/workflows/pages-deploy.yml.hook b/.github/workflows/pages-deploy.yml.hook new file mode 100644 index 00000000..81a249e2 --- /dev/null +++ b/.github/workflows/pages-deploy.yml.hook @@ -0,0 +1,29 @@ +name: 'Automatic build' +on: + push: + branches: + - master + paths-ignore: + - .gitignore + - README.md + - LICENSE + +jobs: + continuous-delivery: + + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 # for posts's lastmod + + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.7 + bundler-cache: true + + - name: Deploy + run: bash tools/deploy.sh diff --git a/.gitignore b/.gitignore index badbc02f..982a22d7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,18 @@ +# hidden files +.* +!.git* +!.editorconfig +!.nojekyll +!.travis.yml + +# bundler cache _site -.sass-cache +vendor +Gemfile.lock + +# rubygem +*.gem + +# npm dependencies +node_modules +package-lock.json diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/.nojekyll @@ -0,0 +1 @@ + diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..4ad238d7 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,49 @@ +os: linux +dist: bionic + +language: minimal + +branches: + only: + - /^release\/(\d)+(\.(\d)+){1}$/ + +jobs: + include: + - name: Deploy + language: ruby + rvm: 2.7.0 + addons: + apt: + packages: + # required to avoid SSL error (for htmlproofer) + - libcurl4-openssl-dev + cache: + directories: + - $TRAVIS_BUILD_DIR/vendor/bundle + before_install: + # match the Gemfile.lock, travis' bundler is 2.1.2 + - gem install bundler:2.2.4 + - bundle config path 'vendor/bundle' + install: + # overriding to drop the travis `--development` flag + - bundle install --jobs=3 --retry=3 + script: + - eval "$BUILD_CMD" + git: + depth: false # for posts' lastmod + + - name: Flush Starter + script: eval "$FLUSH_STARTER" + +before_script: + - git -C "$HOME" clone "$BUILDER_REPO" --depth=1 -q + +notifications: + email: + recipients: + - secure: "fFLqX7uOzFA8RE2AUFlU1mmxMw+rdV6DnODJ/1Gl+3ecNtrv5LeH3c5a4a5ShQqYTrx9BPfD40VRN7UB+lzOdXiWLI9yDGRPPxGG26/WfrKpdQPZilc8zAOEeDnLAJeGZLsUvgmNb3KCXW6S8NPqqh34CfWcTIzjCARhRgO33wcs8X5wP5cugtNqO5Ew/pUcfWcmiuXNX0GNT6l+nL5A7yN+IO5mRHqSRmlfYd5EHhGMTIL4La+Cd1CNv1m4Dl0Ah2cDeJwi5wLnVbqAgunLhAYmDtxIOCVYMTBrP37UiNe/7QeFelyJfODsmMg1mx3WCykbXydC753WVoAlTg6nNoeeI9fmK+/tuLK+sx/KnYfTVGBXQYq39DyV/2o/IfCzEAKImlzFKGD8R13+ddu4B5UML+cby5KBvhTKIGaC5tKoe39z/31UPpy11/EHMCof2BUOzIgu5Hsv4OSNJlw3oRE31oOPn8xP4e7uWR8bRUhAgzN0Cn0ht+UfpemfGAXrp0M3IXQdc9L4azEFqxRhivMTLK/P6INay7IM+DJ30Ht2dWylGw/sxcRTqyNm3YomJQnXIO4xeqTSLulWr80FFHTys3JEDJYrcKvJmpwLFEAOZtwKsZ6ZShrOIA4LE5fgQtakH3ZLJG9a7jVSlMcNIfaSKgjdDQOe6CoRQL7KouA=" + on_success: never + +env: + global: + - NOKOGIRI_USE_SYSTEM_LIBRARIES=true # speeds up installation of html-proofer diff --git a/Gemfile b/Gemfile new file mode 100644 index 00000000..ffef29a3 --- /dev/null +++ b/Gemfile @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +gemspec + +group :test do + gem "html-proofer", "~> 3.18" +end + +# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem +# and associated library. +install_if -> { RUBY_PLATFORM =~ %r!mingw|mswin|java! } do + gem "tzinfo", "~> 1.2" + gem "tzinfo-data" +end + +# Performance-booster for watching directories on Windows +gem "wdm", "~> 0.1.1", :install_if => Gem.win_platform? + +# Jekyll <= 4.2.0 compatibility with Ruby 3.0 +gem "webrick", "~> 1.7" diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..299d89fd --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019 Cotes Chung + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 00000000..83bf90c3 --- /dev/null +++ b/README.md @@ -0,0 +1,247 @@ +
+ + EN / [中文](https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/docs/README.zh-CN.md) + +
+ +
+ + # Chirpy Jekyll Theme + + A minimal, responsive, and powerful Jekyll theme for presenting professional writing. + + [![Gem Version](https://img.shields.io/gem/v/jekyll-theme-chirpy?color=brightgreen)](https://rubygems.org/gems/jekyll-theme-chirpy) + [![Build Status](https://github.com/cotes2020/jekyll-theme-chirpy/workflows/build/badge.svg?branch=master&event=push)](https://github.com/cotes2020/jekyll-theme-chirpy/actions?query=branch%3Amaster+event%3Apush) + [![Codacy Badge](https://app.codacy.com/project/badge/Grade/4e556876a3c54d5e8f2d2857c4f43894)](https://www.codacy.com/gh/cotes2020/jekyll-theme-chirpy/dashboard?utm_source=github.com&utm_medium=referral&utm_content=cotes2020/jekyll-theme-chirpy&utm_campaign=Badge_Grade) + [![GitHub license](https://img.shields.io/github/license/cotes2020/jekyll-theme-chirpy.svg)](https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/LICENSE) + [![996.icu](https://img.shields.io/badge/link-996.icu-%23FF4D5B.svg)](https://996.icu) + + [**Live Demo →**](https://chirpy.cotes.info) + + [![Devices Mockup](https://cdn.jsdelivr.net/gh/cotes2020/chirpy-images@0a003683c0c3ca549d12c309f9b3e03ea20981e5/commons/devices-mockup.png)](https://chirpy.cotes.info) + +
+ +## Features + +- Localized Layout +- Configurable Theme Mode +- Pinned Posts +- Hierarchical Categories +- Last Modified Date for Posts +- Table of Contents +- Automatically Recommend Related Posts +- Syntax Highlighting +- Mathematical Expressions +- Mermaid Diagram & Flowchart +- Search +- Atom Feeds +- Disqus Comments +- Google Analytics +- GA Pageviews Reporting (Advanced) +- SEO & Performance Optimization + +## Prerequisites + +Follow the instructions in the [Jekyll Docs](https://jekyllrb.com/docs/installation/) to complete the installation of `Ruby`, `RubyGems`, `Jekyll`, and `Bundler`. + +## Installation + +### Creating a New Site + +There are two ways to create a new repository for this theme: + +- [**Using the Chirpy Starter**](#option-1-using-the-chirpy-starter) - Easy to upgrade, isolates irrelevant project files so you can focus on writing. +- [**Forking on GitHub**](#option-2-forking-on-github) - Convenient for custom development, but difficult to upgrade. Unless you are familiar with Jekyll and are determined to tweak or contribute to this project, this approach is not recommended. + +#### Option 1. Using the Chirpy Starter + +Create a new repository from the [**Chirpy Starter**][use-starter] and name it `.github.io`, where `GH_USERNAME` represents your GitHub username. + +#### Option 2. Forking on GitHub + +[Fork **Chirpy**](https://github.com/cotes2020/jekyll-theme-chirpy/fork) on GitHub and rename it to `.github.io`. Please note that the default branch code is in development. If you want the site to be stable, please switch to the [latest tag][latest-tag] and start writing. + +And then execute: + +```console +$ bash tools/init.sh +``` + +> **Note**: If you don't want to deploy your site on GitHub Pages, append option `--no-gh` at the end of the above command. + +The above command will: + +1. Removes some files or directories from your repository: + + - `.travis.yml` + - files under `_posts` + - folder `docs` + +2. If the option `--no-gh` is provided, the directory `.github` will be deleted. Otherwise, set up the GitHub Action workflow by removing the extension `.hook` of `.github/workflows/pages-deploy.yml.hook`, and then remove the other files and directories in the folder `.github`. + +3. Removes item `Gemfile.lock` from `.gitignore`. + +4. Creates a new commit to save the changes automatically. + +### Installing Dependencies + +Before running for the first time, go to the root directory of your site, and install dependencies as follows: + +```console +$ bundle +``` + +## Usage + +### Configuration + +Update the variables of `_config.yml` as needed. Some of them are typical options: + +- `url` +- `avatar` +- `timezone` +- `lang` + +### Customing Stylesheet + +If you need to customize the stylesheet, copy the theme's `assets/css/style.scss` to the same path on your Jekyll site, and then add the custom style at the end of the style file. + +Starting from [`v4.1.0`][chirpy-4.1.0], if you want to overwrite the SASS variables defined in `_sass/addon/variables.scss`, create a new file `_sass/variables-hook.scss` and assign new values to the target variable in it. + +### Running Local Server + +You may want to preview the site contents before publishing, so just run it by: + +```console +$ bundle exec jekyll s +``` + +Or run the site on Docker with the following command: + +```console +$ docker run -it --rm \ + --volume="$PWD:/srv/jekyll" \ + -p 4000:4000 jekyll/jekyll \ + jekyll serve +``` + +After a while, the local service will be published at __. + +### Deployment + +Before the deployment begins, check out the file `_config.yml` and make sure the `url` is configured correctly. Furthermore, if you prefer the [**project site**](https://help.github.com/en/github/working-with-github-pages/about-github-pages#types-of-github-pages-sites) and don't use a custom domain, or you want to visit your website with a base URL on a web server other than **GitHub Pages**, remember to change the `baseurl` to your project name that starts with a slash, e.g, `/project-name`. + +Now you can choose ONE of the following methods to deploy your Jekyll site. + +#### Deploy by Using Github Actions + +For security reasons, GitHub Pages build runs on `safe` mode, which restricts us from using plugins to generate additional page files. Therefore, we can use **GitHub Actions** to build the site, store the built site files on a new branch, and use that branch as the source of the GitHub Pages service. + +Quickly check the files needed for GitHub Actions build: + +- Ensure your Jekyll site has the file `.github/workflows/pages-deploy.yml`. Otherwise, create a new one and fill in the contents of the [sample file][workflow], and the value of the `on.push.branches` should be the same as your repo's default branch name. + +- Ensure your Jekyll site has file `tools/deploy.sh`. Otherwise, copy it from here to your Jekyll site. + +- Furthermore, if you have committed `Gemfile.lock` to the repo, and your runtime system is not Linux, don't forget to update the platform list in the lock file: + + ```console + $ bundle lock --add-platform x86_64-linux + ``` + +After the above steps, rename your repository to `.github.io` on GitHub. + +Now publish your Jekyll site by: + +1. Push any commit to remote to trigger the GitHub Actions workflow. Once the build is complete and successful, a new remote branch named `gh-pages` will appear to store the built site files. + +2. Browse to your repository on GitHub. Select the tab _Settings_, then click _Pages_ in the left navigation bar, and then in the section **Source** of _GitHub Pages_, select the `/(root)` directory of branch `gh-pages` as the [publishing source][pages-src]. Remember to click Save before leaving. + + ![gh-pages-sources](https://cdn.jsdelivr.net/gh/cotes2020/chirpy-images@0a003683c0c3ca549d12c309f9b3e03ea20981e5/posts/20190809/gh-pages-sources.png) + +3. Visit your website at the address indicated by GitHub. + +#### Manually Build and Deploy + +On self-hosted servers, you cannot enjoy the convenience of **GitHub Actions**. Therefore, you should build the site on your local machine and then upload the site files to the server. + +Go to the root of the source project, and build your site as follows: + +```console +$ JEKYLL_ENV=production bundle exec jekyll b +``` + +Or build the site on Docker: + +```console +$ docker run -it --rm \ + --env JEKYLL_ENV=production \ + --volume="$PWD:/srv/jekyll" \ + jekyll/jekyll \ + jekyll build +``` + +Unless you specified the output path, the generated site files will be placed in folder `_site` of the project's root directory. Now you should upload those files to the target server. + +### Upgrading + +It depends on how you use the theme: + +- If you are using the theme gem (there will be `gem "jekyll-theme-chirpy"` in the `Gemfile`), editing the `Gemfile` and update the version number of the theme gem, for example: + + ```diff + - gem "jekyll-theme-chirpy", "~> 3.2", ">= 3.2.1" + + gem "jekyll-theme-chirpy", "~> 3.3", ">= 3.3.0" + ``` + + And then execute the following command: + + ```console + $ bundle update jekyll-theme-chirpy + ``` + + As the version upgrades, the critical files (for details, see the [Startup Template][starter]) and configuration options will change. Please refer to the [Upgrade Guide](https://github.com/cotes2020/jekyll-theme-chirpy/wiki/Upgrade-Guide) to keep your repo's files in sync with the latest version of the theme. + +- If you forked from the source project (there will be `gemspec` in the `Gemfile` of your site), then merge the [latest upstream tags][latest-tag] into your Jekyll site to complete the upgrade. +The merge is likely to conflict with your local modifications. Please be patient and careful to resolve these conflicts. + +## Documentation + +For more details and a better reading experience, please check out the [tutorials on the demo site](https://chirpy.cotes.info/categories/tutorial/). In the meanwhile, a copy of the tutorial is also available on the [Wiki](https://github.com/cotes2020/jekyll-theme-chirpy/wiki). Please note that the tutorials on the demo website or Wiki are based on the latest release, and the features of `master` branch are usually ahead of the documentation. + +## Contributing + +The old saying, "Two heads are better than one." Consequently, welcome to report bugs, improve code quality or submit a new feature. For more information, see [contributing guidelines](.github/CONTRIBUTING.md). + +## Credits + +This theme is mainly built with [Jekyll](https://jekyllrb.com/) ecosystem, [Bootstrap](https://getbootstrap.com/), [Font Awesome](https://fontawesome.com/) and some other wonderful tools (their copyright information can be found in the relevant files). The avatar and favicon design come from [Clipart Max](https://www.clipartmax.com/middle/m2i8b1m2K9Z5m2K9_ant-clipart-childrens-ant-cute/). + +:tada: Thanks to all the volunteers who contributed to this project, their GitHub IDs are on [this list](https://github.com/cotes2020/jekyll-theme-chirpy/graphs/contributors). Also, I won't forget those guys who submitted the issues or unmerged PR because they reported bugs, shared ideas or inspired me to write more readable documentation. + +Last but not least, thank [JetBrains][jb] for providing the open source license. + +## Sponsoring + +If you like this theme or find it helpful, please consider sponsoring me, because it will encourage and help me better maintain the project, I will be very grateful! + +[![Ko-fi](https://img.shields.io/badge/-Buy%20Me%20a%20Coffee-ff5f5f?logo=ko-fi&logoColor=white)](https://ko-fi.com/coteschung) +[![Wechat Pay](https://img.shields.io/badge/-Tip%20Me%20on%20WeChat-brightgreen?logo=wechat&logoColor=white)][cn-donation] +[![Alipay](https://img.shields.io/badge/-Tip%20Me%20on%20Alipay-blue?logo=alipay&logoColor=white)][cn-donation] + +## License + +This work is published under [MIT](https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/LICENSE) License. + +[starter]: https://github.com/cotes2020/chirpy-starter +[use-starter]: https://github.com/cotes2020/chirpy-starter/generate +[workflow]: https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/.github/workflows/pages-deploy.yml.hook +[chirpy-4.1.0]: https://github.com/cotes2020/jekyll-theme-chirpy/releases/tag/v4.1.0 +[pages-src]: https://docs.github.com/en/github/working-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site +[latest-tag]: https://github.com/cotes2020/jekyll-theme-chirpy/tags + + + +[jb]: https://www.jetbrains.com/?from=jekyll-theme-chirpy +[cn-donation]: https://cotes.gitee.io/alipay-wechat-donation/ diff --git a/_config.yml b/_config.yml new file mode 100644 index 00000000..43b0349b --- /dev/null +++ b/_config.yml @@ -0,0 +1,189 @@ +# The Site Configuration + +# Import the theme +theme: jekyll-theme-chirpy + +# Change the following value to '/PROJECT_NAME' ONLY IF your site type is GitHub Pages Project sites +# and doesn't have a custom domain. +baseurl: '' + +# The language of the webpage › http://www.lingoes.net/en/translator/langcode.htm +# If it has the same name as one of the files in folder `_data/locales`, the layout language will also be changed, +# otherwise, the layout language will use the default value of 'en'. +lang: en + +# Change to your timezone › http://www.timezoneconverter.com/cgi-bin/findzone/findzone +timezone: Asia/Tokyo + +# jekyll-seo-tag settings › https://github.com/jekyll/jekyll-seo-tag/blob/master/docs/usage.md +# ↓ -------------------------- + +title: 松松de小屋 # the main title + +tagline: ... # it will display as the sub-title + +description: >- # used by seo meta and the atom feed + A minimal, portfolio, sidebar, + bootstrap Jekyll theme with responsive web design + and focuses on text presentation. + +# fill in the protocol & hostname for your site, e.g., 'https://username.github.io' +url: '' + +github: + username: ssdh233 # change to your github username + +twitter: + username: ssdh233 # change to your twitter username + +social: + # Change to your full name. + # It will be displayed as the default author of the posts and the copyright owner in the Footer + name: ssdh233 + email: songsongdahu233@gmail.com # change to your email address + links: + # The first element serves as the copyright owner's link + - https://twitter.com/ssdh233 # change to your twitter homepage + - https://github.com/ssdh233 # change to your github homepage + # Uncomment below to add more social links + # - https://www.facebook.com/username + # - https://www.linkedin.com/in/username + +google_site_verification: google_meta_tag_verification # change to your verification string + +# ↑ -------------------------- + + +google_analytics: + id: 'UA-89581468-1' # fill in your Google Analytics ID + # Google Analytics pageviews report settings + pv: + proxy_endpoint: # fill in the Google Analytics superProxy endpoint of Google App Engine + cache_path: # the local PV cache data, friendly to visitors from GFW region + +# Prefer color scheme setting. +# +# Note: Keep empty will follow the system prefer color by default, +# and there will be a toggle to switch the theme between dark and light +# on the bottom left of the sidebar. +# +# Available options: +# +# light - Use the light color scheme +# dark - Use the dark color scheme +# +theme_mode: # [light|dark] + +# The CDN endpoint for images. +# Notice that once it is assigned, the CDN url +# will be added to all image (site avatar & posts' images) paths starting with '/' +# +# e.g. 'https://cdn.com' +img_cdn: 'http://localhost:4000/assets' +#img_cdn: 'https://ssdh233.me' + +# the avatar on sidebar, support local or CORS resources +avatar: '/avatar.jpg' + +# boolean type, the global switch for ToC in posts. +toc: true + +disqus: + comments: false # boolean type, the global switch for posts comments. + shortname: '' # Fill with your Disqus shortname. › https://help.disqus.com/en/articles/1717111-what-s-a-shortname + +paginate: 10 + +# ------------ The following options are not recommended to be modified ------------------ + +kramdown: + syntax_highlighter: rouge + syntax_highlighter_opts: # Rouge Options › https://github.com/jneen/rouge#full-options + css_class: highlight + # default_lang: console + span: + line_numbers: false + block: + line_numbers: true + start_line: 1 + +collections: + tabs: + output: true + sort_by: order + + +defaults: + - + scope: + path: '' # An empty string here means all files in the project + type: posts + values: + layout: post + comments: true # Enable comments in posts. + toc: true # Display TOC column in posts. + # DO NOT modify the following parameter unless you are confident enough + # to update the code of all other post links in this project. + permalink: /posts/:title/ + - + scope: + path: _drafts + values: + comments: false + - + scope: + path: '' + type: tabs # see `site.collections` + values: + layout: page + permalink: /:title/ + +sass: + style: compressed + +compress_html: + clippings: all + comments: all + endings: all + profile: false + blanklines: false + ignore: + envs: [development] + +exclude: + - '*.gem' + - '*.gemspec' + - tools + - docs + - README.md + - LICENSE + - gulpfile.js + - node_modules + - package*.json + +jekyll-archives: + enabled: [categories, tags] + layouts: + category: category + tag: tag + permalinks: + tag: /tags/:name/ + category: /categories/:name/ + +projects: + - title: Gitadora Skill Viewer + url: "http://gsv.fun" + github: "https://github.com/ssdh233/gitadora-skill-viewer" + description: ギタドラのスキルデータを保存するウェブサイト。 + - title: ポックラスクリプト + url: "https://twitter.com/ssdh233/status/1327288525473996802" + github: "https://github.com/ssdh233/popn-class" + description: ポップンクラスの一覧を出すブックマークレットスクリプト。 + - title: PMS Database Support + url: "http://ssdh233.me/pms-diff-support/" + github: "https://github.com/ssdh233/pms-diff-support" + description: PMS Databaseの発狂難易度表にクリアレートを追加したもの(ソート可能)。 + - title: Mahjong-Tiles-Converter + url: "http://ssdh233.me/mtc/" + github: "https://github.com/ssdh233/mtc" + description: 麻雀牌を表示するhtmlを自動的に生成する便利なツールです。 diff --git a/_data/contact.yml b/_data/contact.yml new file mode 100644 index 00000000..05da2f21 --- /dev/null +++ b/_data/contact.yml @@ -0,0 +1,30 @@ +# The contact options. + +- + type: github + icon: 'fab fa-github' +- + type: twitter + icon: 'fab fa-twitter' +- + type: email + icon: 'fas fa-envelope' + noblank: true # open link in current tab +- + type: rss + icon: 'fas fa-rss' + noblank: true + +# Uncomment and complete the url below to enable more contact options +# - +# type: mastodon +# icon: 'fab fa-mastodon' # icons powered by +# url: '' # Fill with your mastodon account page +# - +# type: linkedin +# icon: 'fab fa-linkedin' # icons powered by +# url: '' # Fill with your Linkedin homepage +# - +# type: stack-overflow +# icon: 'fab fa-stack-overflow' +# url: '' # Fill with your stackoverflow homepage diff --git a/_data/locales/en.yml b/_data/locales/en.yml new file mode 100644 index 00000000..4f405a6e --- /dev/null +++ b/_data/locales/en.yml @@ -0,0 +1,91 @@ +# The layout text of site + +# ----- Commons label ----- + +layout: + post: Post + category: Category + tag: Tag + +# The tabs of sidebar +tabs: + # format: : + home: Home + categories: Categories + tags: Tags + archives: Archives + about: About + +# the text displayed in the search bar & search results +search: + hint: search + cancel: Cancel + no_results: Oops! No result founds. + +panel: + lastmod: Recent Update + trending_tags: Trending Tags + toc: Contents + +# The liquid date format › http://strftime.net/ +date_format: + tooltip: '%F, %R %z' + post: + long: '%F' + short: '%m-%d' + archive_month: '%m月' + +copyright: + # Shown at the bottom of the post + license: + template: This post is licensed under :LICENSE_NAME by the author. + name: CC BY 4.0 + link: https://creativecommons.org/licenses/by/4.0/ + + # Displayed in the footer + brief: Some rights reserved. + verbose: >- + Except where otherwise noted, the blog posts on this site are licensed + under the Creative Commons Attribution 4.0 International (CC BY 4.0) License by the author. + +meta: Powered by :PLATFORM with :THEME theme. + +not_found: + statment: Sorry, we've misplaced that URL or it's pointing to something that doesn't exist. + hint_template: :HEAD_BAK to try finding it again, or search for it on the :ARCHIVES_PAGE. + head_back: Head back Home + archives_page: Archives page + +# ----- Posts related labels ----- + +post: + written_by: By + posted: Posted + updated: Updated + timeago: + day: days ago + hour: hours ago + minute: minutes ago + just_now: just now + words: words + pageview_measure: views + read_time: + unit: min + prompt: read + relate_posts: Further Reading + share: Share + button: + next: Newer + previous: Older + copy_code: + succeed: Copied! + share_link: + title: Copy link + succeed: Link copied successfully! + # pinned prompt of posts list on homepage + pin_prompt: Pinned + +# categories page +categories: + category_measure: categories + post_measure: posts diff --git a/_data/locales/id-ID.yml b/_data/locales/id-ID.yml new file mode 100644 index 00000000..4693c5e6 --- /dev/null +++ b/_data/locales/id-ID.yml @@ -0,0 +1,91 @@ +# The layout text of site + +# ----- Commons label ----- + +layout: + post: Postingan + category: Kategori + tag: Tagar + +# The tabs of sidebar +tabs: + # format: : + home: Beranda + categories: Kategori + tags: Tagar + archives: Arsip + about: Tentang + +# the text displayed in the search bar & search results +search: + hint: Cari + cancel: Batal + no_results: Ups! Tidak ada hasil yang ditemukan. + +panel: + lastmod: Postingan Terbaru + trending_tags: Tagar Terpopuler + toc: Konten + +# The liquid date format › http://strftime.net/ +date_format: + tooltip: "%a, %e %b, %Y, %l:%M %p" + post: + long: "%e %b, %Y" + short: "%e %b" + archive_month: "%b" + +copyright: + # Shown at the bottom of the post + license: + template: Postingan ini dilisensikan di bawah :LICENSE_NAME oleh penulis. + name: CC BY 4.0 + link: https://creativecommons.org/licenses/by/4.0/ + + # Displayed in the footer + brief: Sebagian konten dilindungi. + verbose: >- + Kecuali jika dinyatakan, Postingan blog di situs ini dilisensikan + di bawah Lisensi Creative Commons Attribution 4.0 International (CC BY 4.0) oleh penulis. + +meta: Didukung oleh :PLATFORM dengan tema :THEME. + +not_found: + statment: Maaf, kami gagal menemukan URL itu atau memang mengarah ke sesuatu yang tidak ada. + hint_template: :HEAD_BAK untuk mencoba mencari kembali, atau cari di :ARCHIVES_PAGE. + head_back: Kembali ke Beranda + archives_page: Halaman Arsip + +# ----- Posts related labels ----- + +post: + written_by: Oleh + posted: Diterbitkan + updated: Diperbarui + timeago: + day: hari yang lalu + hour: jam yang lalu + minute: menit yang lalu + just_now: baru saja + words: kata + pageview_measure: dilihat + read_time: + unit: menit + prompt: baca + relate_posts: Postingan Lainya + share: Bagikan + button: + next: Terbaru + previous: Terlama + copy_code: + succeed: Disalin! + share_link: + title: Salin tautan + succeed: Tautan berhasil disalin! + # pinned prompt of posts list on homepage + pin_prompt: Disematkan + +# categories page +categories: + category_measure: kategori + post_measure: Postingan diff --git a/_data/locales/zh-CN.yml b/_data/locales/zh-CN.yml new file mode 100644 index 00000000..83f2376c --- /dev/null +++ b/_data/locales/zh-CN.yml @@ -0,0 +1,90 @@ +# The layout text of site + +# ----- Commons label ----- + +layout: + post: 文章 + category: 分类 + tag: 标签 + +# The tabs of sidebar +tabs: + # format: : + home: 首页 + categories: 分类 + tags: 标签 + archives: 归档 + about: 关于 + +# the text displayed in the search bar & search results +search: + hint: 搜索 + cancel: 取消 + no_results: 搜索结果为空 + +panel: + lastmod: 最近更新 + trending_tags: 热门标签 + toc: 文章内容 + +# The liquid date format › http://strftime.net/ +date_format: + tooltip: '%F, %R %z' + post: + long: '%F' + short: '%m-%d' + archive_month: '%m月' + +copyright: + # Shown at the bottom of the post + license: + template: 本文由作者按照 :LICENSE_NAME 进行授权 + name: CC BY 4.0 + link: https://creativecommons.org/licenses/by/4.0/ + + # Displayed in the footer + brief: 保留部分权利。 + verbose: >- + 除非另有说明,本网站上的博客文章均由作者按照知识共享署名 4.0 国际 (CC BY 4.0) 许可协议进行授权。 + +meta: 本站由 :PLATFORM 生成,采用 :THEME 主题。 + +not_found: + statment: 抱歉,我们放错了该 URL,或者它指向了不存在的内容。 + hint_template: :HEAD_BAK尝试再次查找它,或在:ARCHIVES_PAGE上搜索它。 + head_back: 返回主页 + archives_page: 归档页面 + +# ----- Posts related labels ----- + +post: + written_by: 作者 + posted: 发表于 + updated: 更新于 + timeago: + day: 天前 + hour: 小时前 + minute: 分钟前 + just_now: 刚刚 + words: 字 + pageview_measure: 次浏览 + read_time: + unit: 分钟 + prompt: 阅读 + relate_posts: 相关文章 + share: 分享 + button: + next: 下一篇 + previous: 上一篇 + copy_code: + succeed: 已复制! + share_link: + title: 分享链接 + succeed: 链接已复制! + # pinned prompt of posts list on homepage + pin_prompt: 顶置 + +# categories page +categories: + category_measure: 个分类 + post_measure: 篇文章 diff --git a/_data/share.yml b/_data/share.yml new file mode 100644 index 00000000..ecd1b0d8 --- /dev/null +++ b/_data/share.yml @@ -0,0 +1,27 @@ +# Sharing options at the bottom of the post. +# Icons from + +platforms: + - + type: Twitter + icon: "fab fa-twitter" + link: "https://twitter.com/intent/tweet?text=TITLE&url=URL" + - + type: Facebook + icon: "fab fa-facebook-square" + link: "https://www.facebook.com/sharer/sharer.php?title=TITLE&u=URL" + - + type: Telegram + icon: "fab fa-telegram" + link: "https://telegram.me/share?text=TITLE&url=URL" + + # Uncomment below if you need to. + # - + # type: Linkedin + # icon: "fab fa-linkedin" + # link: "https://www.linkedin.com/sharing/share-offsite/?url=URL" + # + # - + # type: Weibo + # icon: "fab fa-weibo" + # link: "http://service.weibo.com/share/share.php?title=TITLE&url=URL" diff --git a/_includes/css-selector.html b/_includes/css-selector.html new file mode 100644 index 00000000..39fe288e --- /dev/null +++ b/_includes/css-selector.html @@ -0,0 +1,15 @@ + + + + +{% if site.toc and page.toc %} + +{% endif %} + +{% if page.layout == 'page' or page.layout == 'post' %} + + +{% endif %} diff --git a/_includes/disqus.html b/_includes/disqus.html new file mode 100644 index 00000000..f4897c82 --- /dev/null +++ b/_includes/disqus.html @@ -0,0 +1,58 @@ + + +{% if site.disqus.comments and page.comments %} + +
+

+ Comments powered by Disqus. +

+
+ + + +{% endif %} diff --git a/_includes/favicons.html b/_includes/favicons.html new file mode 100644 index 00000000..201f6d80 --- /dev/null +++ b/_includes/favicons.html @@ -0,0 +1,17 @@ + + +{% capture favicon_path %}{{ '/assets/img/favicons' | relative_url }}{% endcapture %} + + + + + + + + + + + diff --git a/_includes/footer.html b/_includes/footer.html new file mode 100644 index 00000000..29aa129e --- /dev/null +++ b/_includes/footer.html @@ -0,0 +1,37 @@ + + +
+
+ + + + +
+
diff --git a/_includes/google-analytics.html b/_includes/google-analytics.html new file mode 100644 index 00000000..e5e5119e --- /dev/null +++ b/_includes/google-analytics.html @@ -0,0 +1,14 @@ + + + + diff --git a/_includes/head.html b/_includes/head.html new file mode 100644 index 00000000..710d47d8 --- /dev/null +++ b/_includes/head.html @@ -0,0 +1,75 @@ + + + + + + + {% if page.layout == 'home' or page.layout == 'post' %} + + + + + + + + {% if site.google_analytics.pv.proxy_endpoint %} + + {% endif %} + + {% if site.google_analytics.pv.cache_path %} + + {% endif %} + + {% endif %} + + {% seo title=false %} + + + {%- unless page.layout == "home" -%} + {{ page.title | append: " | "}} + {%- endunless -%} + {{ site.title }} + + + {% include favicons.html %} + + + + + + + {% if jekyll.environment == 'production' %} + + + + + + + {% if site.google_analytics.pv.proxy_endpoint %} + {% assign proxy_url = site.google_analytics.pv.proxy_endpoint + | replace: "https://", "" | split: "/" | first | prepend: "https://" %} + + + + {% endif %} + {% endif %} + + + + + + + + + + + + {% include css-selector.html %} + + + + + + diff --git a/_includes/js-selector.html b/_includes/js-selector.html new file mode 100644 index 00000000..219fe96d --- /dev/null +++ b/_includes/js-selector.html @@ -0,0 +1,68 @@ + + + + +{% if page.layout == 'post' %} + {% if site.google_analytics.pv.proxy_endpoint or site.google_analytics.pv.cache_path %} + + + + {% endif %} +{% endif %} + +{% if page.layout == 'post' or page.layout == 'page' %} + + +{% endif %} + +{% if page.layout == 'home' + or page.layout == 'categories' + or page.layout == 'post' + or page.layout == 'page' %} + {% assign type = page.layout %} +{% else %} + {% assign type = "commons" %} +{% endif %} + +{% assign js = type | prepend: '/assets/js/dist/' | append: '.min.js' %} + + +{% if page.math %} + + + + +{% endif %} + + + + + +{% if jekyll.environment == 'production' %} + + + + + {% if site.google_analytics.id %} + {% include google-analytics.html %} + {% endif %} + +{% endif %} diff --git a/_includes/lang.html b/_includes/lang.html new file mode 100644 index 00000000..656f200f --- /dev/null +++ b/_includes/lang.html @@ -0,0 +1,8 @@ +{% comment %} +Detect appearance language and return it through variable "lang" +{% endcomment %} +{% if site.data.locales[site.lang] %} + {% assign lang = site.lang %} +{% else %} + {% assign lang = 'en' %} +{% endif %} diff --git a/_includes/language-alias.html b/_includes/language-alias.html new file mode 100644 index 00000000..abfa7ba9 --- /dev/null +++ b/_includes/language-alias.html @@ -0,0 +1,70 @@ +{% comment %} + + Convert the alias of the syntax language to the official name + + See: + +{% endcomment %} + +{% assign _lang = include.language | default: '' %} + +{% case _lang %} + {% when 'actionscript', 'as', 'as3' %} + {{ 'ActionScript' }} + {% when 'applescript' %} + {{ 'AppleScript' }} + {% when 'brightscript', 'bs', 'brs' %} + {{ 'BrightScript' }} + {% when 'cfscript', 'cfc' %} + {{ 'CFScript' }} + {% when 'coffeescript', 'coffee', 'coffee-script' %} + {{ 'CoffeeScript' }} + {% when 'cs', 'csharp' %} + {{ 'C#' }} + {% when 'erl' %} + {{ 'Erlang' }} + {% when 'graphql' %} + {{ 'GraphQL' }} + {% when 'haskell', 'hs' %} + {{ 'Haskell' }} + {% when 'javascript', 'js' %} + {{ 'JavaScript' }} + {% when 'make', 'mf', 'gnumake', 'bsdmake' %} + {{ 'Makefile' }} + {% when 'md', 'mkd' %} + {{ 'Markdown' }} + {% when 'm' %} + {{ 'Matlab' }} + {% when 'objective_c', 'objc', 'obj-c', 'obj_c', 'objectivec' %} + {{ 'Objective-C' }} + {% when 'perl', 'pl' %} + {{ 'Perl' }} + {% when 'php','php3','php4','php5' %} + {{ 'PHP' }} + {% when 'py' %} + {{ 'Python' }} + {% when 'rb' %} + {{ 'Ruby' }} + {% when 'rs','no_run','ignore','should_panic' %} + {{ 'Rust' }} + {% when 'bash', 'zsh', 'ksh', 'sh' %} + {{ 'Shell' }} + {% when 'st', 'squeak' %} + {{ 'Smalltalk' }} + {% when 'tex'%} + {{ 'TeX' }} + {% when 'latex' %} + {{ 'LaTex' }} + {% when 'ts', 'typescript' %} + {{ 'TypeScript' }} + {% when 'vb', 'visualbasic' %} + {{ 'Visual Basic' }} + {% when 'vue', 'vuejs' %} + {{ 'Vue.js' }} + {% when 'yml' %} + {{ 'YAML' }} + {% when 'css', 'html', 'scss', 'ssh', 'toml', 'xml', 'yaml', 'json' %} + {{ _lang | upcase }} + {% else %} + {{ _lang | capitalize }} +{% endcase %} diff --git a/_includes/mermaid.html b/_includes/mermaid.html new file mode 100644 index 00000000..063d9508 --- /dev/null +++ b/_includes/mermaid.html @@ -0,0 +1,29 @@ + + + + diff --git a/_includes/mode-toggle.html b/_includes/mode-toggle.html new file mode 100644 index 00000000..e2eb2d76 --- /dev/null +++ b/_includes/mode-toggle.html @@ -0,0 +1,135 @@ + + + diff --git a/_includes/no-linenos.html b/_includes/no-linenos.html new file mode 100644 index 00000000..85006933 --- /dev/null +++ b/_includes/no-linenos.html @@ -0,0 +1,10 @@ +{% comment %} + Remove the line number of the code snippet. +{% endcomment %} + +{% assign content = include.content %} + +{% if content contains '
' %}
+  {% assign content = content | replace: '
', '' %}
+{% endif %}
diff --git a/_includes/no-zero-date.html b/_includes/no-zero-date.html
new file mode 100644
index 00000000..5c98b733
--- /dev/null
+++ b/_includes/no-zero-date.html
@@ -0,0 +1,13 @@
+{% comment %}
+  Remove the zero padding from a month/day string
+{% endcomment %}
+
+{% assign ret = include.date_str %}
+{% assign _first_chat = ret | slice: 0 %}
+
+{% if _first_chat == '0' %}
+  {% assign _last_idx = ret.size | minus: 1 %}
+  {% assign ret = ret | slice: 1, _last_idx %}
+{% endif %}
+
+{{ ret | replace: ' 0', ' ' }}
diff --git a/_includes/post-nav.html b/_includes/post-nav.html
new file mode 100644
index 00000000..bb3b52d5
--- /dev/null
+++ b/_includes/post-nav.html
@@ -0,0 +1,30 @@
+
+
+
+ {% if page.previous.url %} + +

{{ page.previous.title }}

+
+ {% else %} + +

-

+
+ {% endif %} + + {% if page.next.url %} + +

{{ page.next.title }}

+
+ {% else %} + +

-

+
+ {% endif %} + +
diff --git a/_includes/post-paginator.html b/_includes/post-paginator.html new file mode 100644 index 00000000..9d9608c6 --- /dev/null +++ b/_includes/post-paginator.html @@ -0,0 +1,88 @@ + + +
    + + {% if paginator.previous_page %} + {% assign prev_url = paginator.previous_page_path | relative_url %} + {% else %} + {% assign prev_url = "#" %} + {% endif %} + +
  • + + + +
  • + + + {% assign left_ellipsis = false %} + {% assign right_ellipsis = false %} + + {% for i in (1..paginator.total_pages) %} + + {% assign pre = paginator.page | minus: 1 %} + {% assign next = paginator.page | plus: 1 %} + {% assign pre_less = pre | minus: 1 %} + {% assign next_more = next | plus: 1 %} + {% assign show = false %} + + {% if paginator.page == 1 %} + {% if i <= 3 or i == paginator.total_pages %} + {% assign show = true %} + {% endif %} + {% elsif paginator.page == paginator.total_pages %} + {% if i == 1 or i >= pre_less %} + {% assign show = true %} + {% endif %} + {% else %} + {% if i == 1 or i == paginator.total_pages%} + {% assign show = true %} + {% elsif i >= pre and i <= next %} + {% assign show = true %} + {% endif %} + {% endif %} + + {% if show %} + +
  • + {{ i }} +
  • + {% else %} + + {% if i < pre and left_ellipsis == false %} +
  • + ... +
  • + {% assign left_ellipsis = true %} + {% elsif i > next and right_ellipsis == false %} +
  • + ... +
  • + {% assign right_ellipsis = true %} + {% endif %} + {% endif %} + + {% endfor %} + + +
  • + {{ paginator.page }} + / {{ paginator.total_pages }} +
  • + + + {% if paginator.next_page_path %} + {% assign next_url = paginator.next_page_path | relative_url %} + {% else %} + {% assign next_url = "#" %} + {% endif %} + +
  • + + + +
  • + +
diff --git a/_includes/post-sharing.html b/_includes/post-sharing.html new file mode 100644 index 00000000..80ad1e9c --- /dev/null +++ b/_includes/post-sharing.html @@ -0,0 +1,26 @@ + + + diff --git a/_includes/read-time.html b/_includes/read-time.html new file mode 100644 index 00000000..fbbc0b28 --- /dev/null +++ b/_includes/read-time.html @@ -0,0 +1,30 @@ + + +{% assign words = include.content | strip_html | number_of_words: "auto" %} + + + +{% assign wpm = 180 %} +{% assign min_time = 1 %} + +{% assign read_time = words | divided_by: wpm %} + +{% unless read_time > 0 %} + {% assign read_time = min_time %} +{% endunless %} + +{% capture read_prompt %} + {{- site.data.locales[lang].post.read_time.prompt -}} +{% endcapture %} + + + + {{- read_time -}}{{" "}}{{- site.data.locales[lang].post.read_time.unit -}} + {%- if include.prompt -%} + {%- assign _prompt_words = read_prompt | number_of_words: 'auto' -%} + {%- unless _prompt_words > 1 -%}{{ " " }}{%- endunless -%}{{ read_prompt }} + {%- endif -%} + diff --git a/_includes/refactor-content.html b/_includes/refactor-content.html new file mode 100644 index 00000000..7e899ff8 --- /dev/null +++ b/_includes/refactor-content.html @@ -0,0 +1,153 @@ + + +{% assign _content = include.content %} + + + +{% if _content contains '' %} + {% assign _content = _content + | replace: '
', '
' + | replace: '
', '' + | replace: '', '' + %} +{% endif %} + + + +{% if _content contains '
' %}
+  {% assign _content = _content
+    | replace: '
', '' + %} +{% endif %} + + + +{% if _content contains '
  • <' %} + {% assign _content = _content + | replace: '"task-list-item"><', '"task-list-item" hide-bullet><' + %} +{% endif %} + + + + +{% if _content contains ' + +{% if _content contains '
    ' %} + {% assign _code_spippets = _content | split: '
    ' %} + {% assign _new_content = '' %} + + {% for _snippet in _code_spippets %} + + {% if forloop.last %} + {% assign _new_content = _new_content | append: _snippet %} + + {% else %} + + {% assign _left = _snippet | split: '><' | last%} + + {% if _left contains 'file="' %} + {% assign _label_text = _left | split: 'file="' | last | split: '"' | first %} + {% assign _label_icon = 'far fa-file-code' %} + {% else %} + {% assign _lang = _left | split: 'language-' | last | split: ' ' | first %} + {% capture _label_text %}{% include language-alias.html language=_lang %}{% endcapture %} + {% assign _label_icon = 'fas fa-code small' %} + {% endif %} + + {% capture _label %} + + {% endcapture %} + + {% assign _new_content = _new_content | append: _snippet + | append: '
    ' + | append: _label + | append: '
    ' + | append: '
    ' + %} + + {% endif %} + + {% endfor %} + + {% assign _content = _new_content %} + +{% endif %} + + + + +{{ _content }} diff --git a/_includes/related-posts.html b/_includes/related-posts.html new file mode 100644 index 00000000..910de537 --- /dev/null +++ b/_includes/related-posts.html @@ -0,0 +1,106 @@ + + + +{% assign TOTAL_SIZE = 3 %} + + +{% assign TAG_SCORE = 1 %} + + +{% assign CATEGORY_SCORE = 0.5 %} + +{% assign SEPARATOR = ":" %} + +{% assign score_list = "" | split: "" %} +{% assign last_index = site.posts.size | minus: 1 %} + +{% for i in (0..last_index) %} + {% assign post = site.posts[i] %} + + {% if post.url == page.url %} + {% continue %} + {% endif %} + + {% assign score = 0 %} + + {% for tag in post.tags %} + {% if page.tags contains tag %} + {% assign score = score | plus: TAG_SCORE %} + {% endif %} + {% endfor %} + + {% for category in post.categories %} + {% if page.categories contains category %} + {% assign score = score | plus: CATEGORY_SCORE %} + {% endif %} + {% endfor %} + + {% if score > 0 %} + {% capture score_item %}{{ score }}{{ SEPARATOR }}{{ i }}{% endcapture %} + {% assign score_list = score_list | push: score_item %} + {% endif %} + +{% endfor %} + + +{% assign index_list = "" | split: "" %} + +{% if score_list.size > 0 %} + {% assign score_list = score_list | sort | reverse %} + {% for entry in score_list limit: TOTAL_SIZE %} + {% assign index = entry | split: SEPARATOR | last %} + {% assign index_list = index_list | push: index %} + {% endfor %} +{% endif %} + + +{% assign less = TOTAL_SIZE | minus: index_list.size %} + +{% if less > 0 %} + + {% for i in (0..last_index) %} + {% assign post = site.posts[i] %} + {% if post.url != page.url %} + {% capture cur_index %}{{ i }}{% endcapture %} + {% unless index_list contains cur_index %} + {% assign index_list = index_list | push: cur_index %} + {% assign less = less | minus: 1 %} + {% if less <= 0 %} + {% break %} + {% endif %} + {% endunless %} + {% endif %} + {% endfor %} + +{% endif %} + + +{% if index_list.size > 0 %} + +{% endif %} diff --git a/_includes/search-loader.html b/_includes/search-loader.html new file mode 100644 index 00000000..d07b63c4 --- /dev/null +++ b/_includes/search-loader.html @@ -0,0 +1,46 @@ + + +{% capture result_elem %} +
    + {title} + +

    {snippet}

    +
    +{% endcapture %} + +{% capture not_found %}

    {{ site.data.locales[lang].search.no_results }}

    {% endcapture %} + + + + diff --git a/_includes/search-results.html b/_includes/search-results.html new file mode 100644 index 00000000..d19e3bd3 --- /dev/null +++ b/_includes/search-results.html @@ -0,0 +1,11 @@ + +
    +
    +
    + {% include trending-tags.html %} +
    +
    +
    +
    diff --git a/_includes/sidebar.html b/_includes/sidebar.html new file mode 100644 index 00000000..5974fced --- /dev/null +++ b/_includes/sidebar.html @@ -0,0 +1,93 @@ + + + diff --git a/_includes/timeago.html b/_includes/timeago.html new file mode 100644 index 00000000..bd0ed8a7 --- /dev/null +++ b/_includes/timeago.html @@ -0,0 +1,26 @@ + + +{% assign tooltip_df = site.data.locales[lang].date_format.tooltip %} +{% assign post_long_df = site.data.locales[lang].date_format.post.long %} +{% assign post_short_df = site.data.locales[lang].date_format.post.short %} + + + + {%- assign this_year = site.time | date: "%Y" -%} + {%- assign post_year = include.date | date: "%Y" -%} + + {%- if post_year == this_year -%} + {{ include.date | date: post_short_df }} + {%- else -%} + {{ include.date | date: post_long_df }} + {%- endif -%} + diff --git a/_includes/toc.html b/_includes/toc.html new file mode 100644 index 00000000..e9da07ef --- /dev/null +++ b/_includes/toc.html @@ -0,0 +1,10 @@ +{% if site.toc and page.toc %} + + +
    +

    + {{- site.data.locales[lang].panel.toc -}} +

    + +
    +{% endif %} diff --git a/_includes/topbar.html b/_includes/topbar.html new file mode 100644 index 00000000..039434d0 --- /dev/null +++ b/_includes/topbar.html @@ -0,0 +1,71 @@ + + +
    +
    + + + {% assign paths = page.url | split: '/' %} + + {% if paths.size == 0 or page.layout == 'home' %} + + {{ site.data.locales[lang].tabs.home | capitalize }} + + {% else %} + + {% for item in paths %} + + {% if forloop.first %} + + + {{ site.data.locales[lang].tabs.home | capitalize }} + + + + {% elsif forloop.last %} + + {% if page.collection == 'tabs' %} + {{ site.data.locales[lang].tabs[item] | default: page.title }} + {% else %} + {{ page.title }} + {% endif %} + + {% elsif page.layout == 'category' or page.layout == 'tag' %} + + + {{ site.data.locales[lang].tabs[item] | default: page.title }} + + + {% endif %} + + {% endfor %} + + {% endif %} + + + + + +
    + {% if page.layout == 'home' %} + {{- site.data.locales[lang].title | default: site.title -}} + {% elsif page.collection == 'tabs' or page.dynamic_title %} + {%- capture tab_key -%}{{ page.url | split: '/' }}{%- endcapture -%} + {{- site.data.locales[lang].tabs[tab_key] | default: page.title -}} + {% else %} + {{- site.data.locales[lang].layout[page.layout] | default: page.layout | capitalize -}} + {% endif %} +
    + + + + + + + + {{ site.data.locales[lang].search.cancel }} +
    + +
    diff --git a/_includes/trending-tags.html b/_includes/trending-tags.html new file mode 100644 index 00000000..a5ff0c08 --- /dev/null +++ b/_includes/trending-tags.html @@ -0,0 +1,50 @@ +{% comment %} + The trending tags list +{% endcomment %} + +{% assign MAX = 10 %} + +{% assign size_list = "" | split: "" %} +{% assign tag_list = "" | split: "" %} + +{% for tag in site.tags %} + {% assign size = tag | last | size %} + {% assign size_list = size_list | push: size %} + + {% assign tag_str = tag | first | append: "::" | append: size %} + {% assign tag_list = tag_list | push: tag_str %} +{% endfor %} + +{% assign size_list = size_list | sort | reverse %} + +{% assign tag_list = tag_list | sort_natural %} + +{% assign trending_tags = "" | split: "" %} + +{% for size in size_list limit: MAX %} + {% for tag_str in tag_list %} + {% assign tag = tag_str | split: "::" %} + {% assign tag_name = tag | first %} + {% assign tag_size = tag | last | plus: 0 %} + {% if tag_size == size %} + {% unless trending_tags contains tag_name %} + {% assign trending_tags = trending_tags | push: tag_name %} + {% break %} + {% endunless %} + {% endif %} + {% endfor %} +{% endfor %} + +{% if trending_tags.size > 0 %} +
    +

    {{- site.data.locales[lang].panel.trending_tags -}}

    +
    + + {% for tag_name in trending_tags %} + {% assign url = tag_name | slugify | url_encode | prepend: "/tags/" | append: "/" %} + + {% endfor %} + +
    +
    +{% endif %} diff --git a/_includes/update-list.html b/_includes/update-list.html new file mode 100644 index 00000000..4f4201bc --- /dev/null +++ b/_includes/update-list.html @@ -0,0 +1,40 @@ +{% comment %} + Get the last 5 posts from lastmod list. +{% endcomment %} + +{% assign MAX_SIZE = 5 %} + +{% assign all_list = "" | split: "" %} + +{% for post in site.posts %} + {% if post.last_modified_at %} + {% capture elem %} + {{- post.last_modified_at | date: "%Y%m%d%H%M%S" -}}::{{- forloop.index0 -}} + {% endcapture %} + {% assign all_list = all_list | push: elem %} + {% endif %} +{% endfor %} + +{% assign all_list = all_list | sort | reverse %} + +{% assign update_list = "" | split: "" %} + +{% for entry in all_list limit:MAX_SIZE %} + {% assign update_list = update_list | push: entry %} +{% endfor %} + +{% if update_list.size > 0 %} + +
    +

    {{- site.data.locales[lang].panel.lastmod -}}

    +
      + {% for item in update_list %} + {% assign index = item | split: "::" | last | plus: 0 %} + {% assign post = site.posts[index] %} + {% assign url = post.url | relative_url %} +
    • {{ post.title }}
    • + {% endfor %} +
    +
    + +{% endif %} diff --git a/_javascript/commons/back-to-top.js b/_javascript/commons/back-to-top.js new file mode 100644 index 00000000..1807332a --- /dev/null +++ b/_javascript/commons/back-to-top.js @@ -0,0 +1,20 @@ +/* +Reference: https://bootsnipp.com/snippets/featured/link-to-top-page +*/ +$(function() { + $(window).scroll(() => { + if ($(this).scrollTop() > 50 && + $("#sidebar-trigger").css("display") === "none") { + $("#back-to-top").fadeIn(); + } else { + $("#back-to-top").fadeOut(); + } + }); + + $("#back-to-top").click(() => { + $("body,html").animate({ + scrollTop: 0 + }, 800); + return false; + }); +}); diff --git a/_javascript/commons/mode-toggle.js b/_javascript/commons/mode-toggle.js new file mode 100644 index 00000000..7d4926e8 --- /dev/null +++ b/_javascript/commons/mode-toggle.js @@ -0,0 +1,10 @@ +/* + * Document-reday functions for '#mode-toggle-wrapper' + */ +$(function() { + $("#mode-toggle-wrapper").keyup((e) => { + if(e.keyCode === 13) { + flipMode(); + } + }); +}); diff --git a/_javascript/commons/search-display.js b/_javascript/commons/search-display.js new file mode 100644 index 00000000..1d0518f7 --- /dev/null +++ b/_javascript/commons/search-display.js @@ -0,0 +1,153 @@ +/* +* This script make #search-result-wrapper switch to unloaded or shown automatically. +*/ + +$(function() { + + const btnSbTrigger = $("#sidebar-trigger"); + const btnSearchTrigger = $("#search-trigger"); + const btnCancel = $("#search-cancel"); + const btnClear = $("#search-cleaner"); + + const main = $("#main"); + const topbarTitle = $("#topbar-title"); + const searchWrapper = $("#search-wrapper"); + const resultWrapper = $("#search-result-wrapper"); + const results = $("#search-results"); + const input = $("#search-input"); + const hints = $("#search-hints"); + + const scrollBlocker = (function () { + let offset = 0; + return { + block() { + offset = window.scrollY; + $("html,body").scrollTop(0); + }, + release() { + $("html,body").scrollTop(offset); + }, + getOffset() { + return offset; + } + }; + }()); + + + /*--- Actions in small screens (Sidebar unloaded) ---*/ + + const mobileSearchBar = (function () { + return { + on() { + btnSbTrigger.addClass("unloaded"); + topbarTitle.addClass("unloaded"); + btnSearchTrigger.addClass("unloaded"); + searchWrapper.addClass("d-flex"); + btnCancel.addClass("loaded"); + }, + off() { + btnCancel.removeClass("loaded"); + searchWrapper.removeClass("d-flex"); + btnSbTrigger.removeClass("unloaded"); + topbarTitle.removeClass("unloaded"); + btnSearchTrigger.removeClass("unloaded"); + } + }; + }()); + + const resultSwitch = (function () { + let visible = false; + + return { + on() { + if (!visible) { + // the block method must be called before $(#main) unloaded. + scrollBlocker.block(); + resultWrapper.removeClass("unloaded"); + main.addClass("unloaded"); + visible = true; + } + }, + off() { + if (visible) { + results.empty(); + if (hints.hasClass("unloaded")) { + hints.removeClass("unloaded"); + } + resultWrapper.addClass("unloaded"); + btnClear.removeClass("visible"); + main.removeClass("unloaded"); + + // now the release method must be called after $(#main) display + scrollBlocker.release(); + + input.val(""); + visible = false; + } + }, + isVisible() { + return visible; + } + }; + + }()); + + + function isMobileView() { + return btnCancel.hasClass("loaded"); + } + + btnSearchTrigger.click(function() { + mobileSearchBar.on(); + resultSwitch.on(); + input.focus(); + }); + + btnCancel.click(function() { + mobileSearchBar.off(); + resultSwitch.off(); + }); + + input.focus(function() { + searchWrapper.addClass("input-focus"); + }); + + input.focusout(function() { + searchWrapper.removeClass("input-focus"); + }); + + input.on("keyup", function(e) { + if (e.keyCode === 8 && input.val() === "") { + if (!isMobileView()) { + resultSwitch.off(); + } else { + hints.removeClass("unloaded"); + } + } else { + if (input.val() !== "") { + resultSwitch.on(); + + if (!btnClear.hasClass("visible")) { + btnClear.addClass("visible"); + } + + if (isMobileView()) { + hints.addClass("unloaded"); + } + } + } + }); + + btnClear.on("click", function() { + input.val(""); + if (isMobileView()) { + hints.removeClass("unloaded"); + results.empty(); + } else { + resultSwitch.off(); + } + input.focus(); + btnClear.removeClass("visible"); + }); + +}); diff --git a/_javascript/commons/sidebar.js b/_javascript/commons/sidebar.js new file mode 100644 index 00000000..014411a1 --- /dev/null +++ b/_javascript/commons/sidebar.js @@ -0,0 +1,30 @@ +/** + * Expand or close the sidebar in mobile screens. + */ + +$(function() { + + const sidebarUtil = (function () { + const ATTR_DISPLAY = "sidebar-display"; + let isExpanded = false; + const body = $("body"); + + return { + toggle() { + if (isExpanded === false) { + body.attr(ATTR_DISPLAY, ""); + } else { + body.removeAttr(ATTR_DISPLAY); + } + + isExpanded = !isExpanded; + } + }; + + }()); + + $("#sidebar-trigger").click(sidebarUtil.toggle); + + $("#mask").click(sidebarUtil.toggle); + +}); diff --git a/_javascript/commons/tooltip-loader.js b/_javascript/commons/tooltip-loader.js new file mode 100644 index 00000000..90c6a98f --- /dev/null +++ b/_javascript/commons/tooltip-loader.js @@ -0,0 +1,6 @@ +/** + * Initial Bootstrap Tooltip. +*/ +$(function () { + $("[data-toggle=\"tooltip\"]").tooltip(); +}); diff --git a/_javascript/commons/topbar-switch.js b/_javascript/commons/topbar-switch.js new file mode 100644 index 00000000..55fbab6d --- /dev/null +++ b/_javascript/commons/topbar-switch.js @@ -0,0 +1,69 @@ +/* + * Hide Header on scroll down + */ + +$(function() { + + const topbarWrapper = $("#topbar-wrapper"); + const toc = $("#toc-wrapper"); + const access = $(".access"); + const searchInput = $("#search-input"); + + let didScroll; + let lastScrollTop = 0; + + const delta = 5; + const topbarHeight = topbarWrapper.outerHeight(); + + function hasScrolled() { + var st = $(this).scrollTop(); + + /* Make sure they scroll more than delta */ + if (Math.abs(lastScrollTop - st) <= delta) { + return; + } + + if (st > lastScrollTop && st > topbarHeight) { + /* Scroll Down */ + topbarWrapper.removeClass("topbar-down").addClass("topbar-up"); + + if (toc.length > 0) { + toc.removeClass("topbar-down"); + } + + if (access.length > 0) { + access.removeClass("topbar-down"); + } + + if (searchInput.is(":focus")) { + searchInput.blur(); /* remove focus */ + } + + } else if (st + $(window).height() < $(document).height()) { + /* Scroll Up */ + topbarWrapper.removeClass("topbar-up").addClass("topbar-down"); + if (toc.length > 0) { + toc.addClass("topbar-down"); + } + if (access.length > 0) { + access.addClass("topbar-down"); + } + } + + lastScrollTop = st; + } + + $(window).scroll(function(event) { + if ($("#topbar-title").is(":hidden")) { /* Not in small screens */ + didScroll = true; + } + }); + + setInterval(function() { + if (didScroll) { + hasScrolled(); + didScroll = false; + } + }, 250); + +}); diff --git a/_javascript/commons/topbar-title.js b/_javascript/commons/topbar-title.js new file mode 100644 index 00000000..6bc78055 --- /dev/null +++ b/_javascript/commons/topbar-title.js @@ -0,0 +1,47 @@ +/* + * Top bar title auto change while scrolling in mobile screens. +*/ + +$(function() { + + const topbarTitle = $("#topbar-title"); + const postTitle = $("div.post>h1"); + + const DEFAULT = topbarTitle.text().trim(); + + let title = (postTitle.length > 0) ? + postTitle.text().trim() : $("h1").text().trim(); + + if ($("#page-category").length || $("#page-tag").length) { + /* The title in Category or Tag page will be " <count_of_posts>" */ + if (/\s/.test(title)) { + title = title.replace(/[0-9]/g, "").trim(); + } + } + + /* Replace topbar title while scroll screens. */ + $(window).scroll(function () { + if ($("#post-list").length /* in Home page */ + || postTitle.is(":hidden") /* is tab pages */ + || topbarTitle.is(":hidden") /* not mobile screens */ + || $("#sidebar.sidebar-expand").length) { /* when the sidebar trigger is clicked */ + return false; + } + + if ($(this).scrollTop() >= 95) { + if (topbarTitle.text() !== title) { + topbarTitle.text(title); + } + } else { + if (topbarTitle.text() !== DEFAULT) { + topbarTitle.text(DEFAULT); + } + } + }); + + /* Click title remove hover effect. */ + topbarTitle.click(function() { + $("body,html").animate({scrollTop: 0}, 800); + }); + +}); diff --git a/_javascript/copyright b/_javascript/copyright new file mode 100644 index 00000000..c9baf3c5 --- /dev/null +++ b/_javascript/copyright @@ -0,0 +1,5 @@ +/*! + * Chirpy v4.3.4 (https://github.com/cotes2020/jekyll-theme-chirpy/) + * © 2019 Cotes Chung + * MIT Licensed + */ diff --git a/_javascript/utils/category-collapse.js b/_javascript/utils/category-collapse.js new file mode 100644 index 00000000..904b4481 --- /dev/null +++ b/_javascript/utils/category-collapse.js @@ -0,0 +1,30 @@ +/* + * Tab 'Categories' expand/close effect. + */ + +$(function() { + const childPrefix = "l_"; + const parentPrefix = "h_"; + const collapse = $(".collapse"); + + /* close up top-category */ + collapse.on("hide.bs.collapse", function () { /* Bootstrap collapse events. */ + const parentId = parentPrefix + $(this).attr("id").substring(childPrefix.length); + if (parentId) { + $(`#${parentId} .far.fa-folder-open`).attr("class", "far fa-folder fa-fw"); + $(`#${parentId} i.fas`).addClass("rotate"); + $(`#${parentId}`).removeClass("hide-border-bottom"); + } + }); + + /* expand the top category */ + collapse.on("show.bs.collapse", function() { + const parentId = parentPrefix + $(this).attr("id").substring(childPrefix.length); + if (parentId) { + $(`#${parentId} .far.fa-folder`).attr("class", "far fa-folder-open fa-fw"); + $(`#${parentId} i.fas`).removeClass("rotate"); + $(`#${parentId}`).addClass("hide-border-bottom"); + } + }); + +}); diff --git a/_javascript/utils/checkbox.js b/_javascript/utils/checkbox.js new file mode 100644 index 00000000..b600d0a7 --- /dev/null +++ b/_javascript/utils/checkbox.js @@ -0,0 +1,12 @@ +/* + * Create a more beautiful checkbox + */ + +$(function() { + /* hide browser default checkbox */ + $("input[type=checkbox]").addClass("unloaded"); + /* create checked checkbox */ + $("input[type=checkbox][checked]").before("<i class=\"fas fa-check-circle checked\"></i>"); + /* create normal checkbox */ + $("input[type=checkbox]:not([checked])").before("<i class=\"far fa-circle\"></i>"); +}); diff --git a/_javascript/utils/clipboard.js b/_javascript/utils/clipboard.js new file mode 100644 index 00000000..9993e091 --- /dev/null +++ b/_javascript/utils/clipboard.js @@ -0,0 +1,131 @@ +/* + * Clipboard functions + * + * Dependencies: + * - popper.js (https://github.com/popperjs/popper-core) + * - clipboard.js (https://github.com/zenorocha/clipboard.js) + */ + +$(function() { + const btnSelector = '.code-header>button'; + const ICON_SUCCESS = 'fas fa-check'; + const ATTR_TIMEOUT = 'timeout'; + const TIMEOUT = 2000; // in milliseconds + + function isLocked(node) { + if ($(node)[0].hasAttribute(ATTR_TIMEOUT)) { + let timeout = $(node).attr(ATTR_TIMEOUT); + if (Number(timeout) > Date.now()) { + return true; + } + } + return false; + } + + function lock(node) { + $(node).attr(ATTR_TIMEOUT, Date.now() + TIMEOUT); + } + + function unlock(node) { + $(node).removeAttr(ATTR_TIMEOUT); + } + + /* --- Copy code block --- */ + + // Initial the clipboard.js object + const clipboard = new ClipboardJS(btnSelector, { + target(trigger) { + let codeBlock = trigger.parentNode.nextElementSibling; + return codeBlock.querySelector('code .rouge-code'); + } + }); + + $(btnSelector).tooltip({ + trigger: 'hover', + placement: 'left' + }); + + function getIcon(btn) { + let iconNode = $(btn).children(); + return iconNode.attr('class'); + } + + const ICON_DEFAULT = getIcon(btnSelector); + + function showTooltip(btn) { + const succeedTitle = $(btn).attr('title-succeed'); + $(btn).attr('data-original-title', succeedTitle).tooltip('show'); + } + + function hideTooltip(btn) { + $(btn).tooltip('hide').removeAttr('data-original-title'); + } + + function setSuccessIcon(btn) { + let btnNode = $(btn); + let iconNode = btnNode.children(); + iconNode.attr('class', ICON_SUCCESS); + } + + function resumeIcon(btn) { + let btnNode = $(btn); + let iconNode = btnNode.children(); + iconNode.attr('class', ICON_DEFAULT); + } + + clipboard.on('success', (e) => { + e.clearSelection(); + + const trigger = e.trigger; + if (isLocked(trigger)) { + return; + } + + setSuccessIcon(trigger); + showTooltip(trigger); + lock(trigger); + + setTimeout(() => { + hideTooltip(trigger); + resumeIcon(trigger); + unlock(trigger); + }, TIMEOUT); + + }); + + /* --- Post link sharing --- */ + + $('#copy-link').click((e) => { + + let target = $(e.target); + + if (isLocked(target)) { + return; + } + + // Copy URL to clipboard + + const url = window.location.href; + const $temp = $("<input>"); + + $("body").append($temp); + $temp.val(url).select(); + document.execCommand("copy"); + $temp.remove(); + + // Switch tooltip title + + const defaultTitle = target.attr('data-original-title'); + const succeedTitle = target.attr('title-succeed'); + + target.attr('data-original-title', succeedTitle).tooltip('show'); + lock(target); + + setTimeout(() => { + target.attr('data-original-title', defaultTitle); + unlock(target); + }, TIMEOUT); + + }); + +}); diff --git a/_javascript/utils/img-extra.js b/_javascript/utils/img-extra.js new file mode 100644 index 00000000..efdb4d42 --- /dev/null +++ b/_javascript/utils/img-extra.js @@ -0,0 +1,47 @@ +/** + Lazy load images (https://github.com/ApoorvSaxena/lozad.js) + and popup when clicked (https://github.com/dimsemenov/Magnific-Popup) +*/ + +$(function() { + + const IMG_SCOPE = '#main > div.row:first-child > div:first-child'; + + if ($(`${IMG_SCOPE} img`).length <= 0 ) { + return; + } + + /* lazy loading */ + + const imgList = document.querySelectorAll(`${IMG_SCOPE} img[data-src]`); + const observer = lozad(imgList); + observer.observe(); + + /* popup */ + + $(`${IMG_SCOPE} p > img[data-src],${IMG_SCOPE} img[data-src].preview-img`).each( + function() { + let nextTag = $(this).next(); + const title = nextTag.prop('tagName') === 'EM' ? nextTag.text() : ''; + const src = $(this).attr('data-src'); // created by lozad.js + + $(this).wrap(`<a href="${src}" title="${title}" class="popup"></a>`); + } + ); + + $('.popup').magnificPopup({ + type: 'image', + closeOnContentClick: true, + showCloseBtn: false, + zoom: { + enabled: true, + duration: 300, + easing: 'ease-in-out' + } + }); + + /* markup the image links */ + + $(`${IMG_SCOPE} a`).has('img').addClass('img-link'); + +}); diff --git a/_javascript/utils/pageviews.js b/_javascript/utils/pageviews.js new file mode 100644 index 00000000..1b715082 --- /dev/null +++ b/_javascript/utils/pageviews.js @@ -0,0 +1,250 @@ +/* + * Count page views form GA or local cache file. + * + * Dependencies: + * - jQuery + * - countUp.js <https://github.com/inorganik/countUp.js> + */ + +const getInitStatus = (function () { + let hasInit = false; + return () => { + let ret = hasInit; + if (!hasInit) { + hasInit = true; + } + return ret; + }; +}()); + +const PvOpts = (function () { + function getContent(selector) { + return $(selector).attr("content"); + } + + function hasContent(selector) { + let content = getContent(selector); + return (typeof content !== "undefined" && content !== false); + } + + return { + getProxyMeta() { + return getContent("meta[name=pv-proxy-endpoint]"); + }, + getLocalMeta() { + return getContent("meta[name=pv-cache-path]"); + }, + hasProxyMeta() { + return hasContent("meta[name=pv-proxy-endpoint]"); + }, + hasLocalMeta() { + return hasContent("meta[name=pv-cache-path]"); + } + }; + +}()); + +const PvStorage = (function () { + const Keys = { + KEY_PV: "pv", + KEY_PV_SRC: "pv_src", + KEY_CREATION: "pv_created_date" + }; + + const Source = { + LOCAL: "same-origin", + PROXY: "cors" + }; + + function get(key) { + return localStorage.getItem(key); + } + + function set(key, val) { + localStorage.setItem(key, val); + } + + function saveCache(pv, src) { + set(Keys.KEY_PV, pv); + set(Keys.KEY_PV_SRC, src); + set(Keys.KEY_CREATION, new Date().toJSON()); + } + + return { + keysCount() { + return Object.keys(Keys).length; + }, + hasCache() { + return (localStorage.getItem(Keys.KEY_PV) !== null); + }, + getCache() { + return JSON.parse(localStorage.getItem(Keys.KEY_PV)); + }, + saveLocalCache(pv) { + saveCache(pv, Source.LOCAL); + }, + saveProxyCache(pv) { + saveCache(pv, Source.PROXY); + }, + isExpired() { + let date = new Date(get(Keys.KEY_CREATION)); + date.setHours(date.getHours() + 1); // per hour + return Date.now() >= date.getTime(); + }, + isFromLocal() { + return get(Keys.KEY_PV_SRC) === Source.LOCAL; + }, + isFromProxy() { + return get(Keys.KEY_PV_SRC) === Source.PROXY; + }, + newerThan(pv) { + return PvStorage.getCache().totalsForAllResults["ga:pageviews"] > pv.totalsForAllResults["ga:pageviews"]; + }, + inspectKeys() { + if (localStorage.length !== PvStorage.keysCount()) { + localStorage.clear(); + return; + } + + for(let i = 0; i < localStorage.length; i++){ + const key = localStorage.key(i); + switch (key) { + case Keys.KEY_PV: + case Keys.KEY_PV_SRC: + case Keys.KEY_CREATION: + break; + default: + localStorage.clear(); + return; + } + } + } + }; +}()); /* PvStorage */ + +function countUp(min, max, destId) { + if (min < max) { + let numAnim = new CountUp(destId, min, max); + if (!numAnim.error) { + numAnim.start(); + } else { + console.error(numAnim.error); + } + } +} + +function countPV(path, rows) { + let count = 0; + + if (typeof rows !== "undefined" ) { + for (let i = 0; i < rows.length; ++i) { + const gaPath = rows[parseInt(i, 10)][0]; + if (gaPath === path) { /* path format see: site.permalink */ + count += parseInt(rows[parseInt(i, 10)][1], 10); + break; + } + } + } + + return count; +} + +function tacklePV(rows, path, elem, hasInit) { + let count = countPV(path, rows); + count = (count === 0 ? 1 : count); + + if (!hasInit) { + elem.text(new Intl.NumberFormat().format(count)); + } else { + const initCount = parseInt(elem.text().replace(/,/g, ""), 10); + if (count > initCount) { + countUp(initCount, count, elem.attr("id")); + } + } +} + +function displayPageviews(data) { + if (typeof data === "undefined") { + return; + } + + let hasInit = getInitStatus(); + const rows = data.rows; /* could be undefined */ + + if ($("#post-list").length > 0) { /* the Home page */ + $(".post-preview").each(function() { + const path = $(this).find("a").attr("href"); + tacklePV(rows, path, $(this).find(".pageviews"), hasInit); + }); + + } else if ($(".post").length > 0) { /* the post */ + const path = window.location.pathname; + tacklePV(rows, path, $("#pv"), hasInit); + } +} + +function fetchProxyPageviews() { + if (PvOpts.hasProxyMeta()) { + $.ajax({ + type: "GET", + url: PvOpts.getProxyMeta(), + dataType: "jsonp", + jsonpCallback: "displayPageviews", + success: (data) => { + PvStorage.saveProxyCache(JSON.stringify(data)); + }, + error: (jqXHR, textStatus, errorThrown) => { + console.log("Failed to load pageviews from proxy server: " + errorThrown); + } + }); + } +} + +function fetchLocalPageviews(hasCache = false) { + return fetch(PvOpts.getLocalMeta()) + .then(response => response.json()) + .then(data => { + if (hasCache) { + // The cache from the proxy will sometimes be more recent than the local one + if (PvStorage.isFromProxy() && PvStorage.newerThan(data)) { + return; + } + } + displayPageviews(data); + PvStorage.saveLocalCache(JSON.stringify(data)); + }); +} + +$(function() { + if ($(".pageviews").length <= 0) { + return; + } + + PvStorage.inspectKeys(); + + if (PvStorage.hasCache()) { + displayPageviews(PvStorage.getCache()); + + if (PvStorage.isExpired()) { + if (PvOpts.hasLocalMeta()) { + fetchLocalPageviews(true).then(fetchProxyPageviews); + } else { + fetchProxyPageviews(); + } + + } else { + if (PvStorage.isFromLocal()) { + fetchProxyPageviews(); + } + } + + } else { // no cached + + if (PvOpts.hasLocalMeta()) { + fetchLocalPageviews().then(fetchProxyPageviews); + } else { + fetchProxyPageviews(); + } + } + +}); diff --git a/_javascript/utils/smooth-scroll.js b/_javascript/utils/smooth-scroll.js new file mode 100644 index 00000000..cb90803d --- /dev/null +++ b/_javascript/utils/smooth-scroll.js @@ -0,0 +1,81 @@ +/* + Safari doesn't support CSS `scroll-behavior: smooth`, + so here is a compatible solution for all browser to smooth scrolling + + See: <https://css-tricks.com/snippets/jquery/smooth-scrolling/> + + Warning: It must be called after all `<a>` tags (e.g., the dynamic TOC) are ready. +*/ + +$(function() { + $("a[href*='#']") + .not("[href='#']") + .not("[href='#0']") + .click(function(event) { + + if (this.pathname.replace(/^\//, "") === location.pathname.replace(/^\//, "")) { + if (location.hostname === this.hostname) { + + const REM = 16; /* 16px */ + + const hash = decodeURI(this.hash); + let isFnRef = RegExp(/^#fnref:/).test(hash); + let isFn = isFnRef? false : RegExp(/^#fn:/).test(hash); + let selector = hash.includes(":") ? hash.replace(/\:/g, "\\:") : hash; + let target = $(selector); + + if (target.length) { + event.preventDefault(); + + if (history.pushState) { /* add hash to URL */ + history.pushState(null, null, hash); + } + + let curOffset = $(this).offset().top; + let destOffset = target.offset().top; + const scrollUp = (destOffset < curOffset); + const topbarHeight = $("#topbar-wrapper").outerHeight(); + + if (scrollUp && isFnRef) { + /* Avoid the top-bar covering `fnref` when scrolling up + because `fnref` has no `%anchor`(see: module.scss) style. */ + destOffset -= (topbarHeight + REM / 2); + } + + $("html,body").animate({ + scrollTop: destOffset + }, 800, () => { + + const $target = $(target); + $target.focus(); + + const SCROLL_MARK = "scroll-focus"; + + /* clean up old scroll mark */ + if ($(`[${SCROLL_MARK}=true]`).length) { + $(`[${SCROLL_MARK}=true]`).attr(SCROLL_MARK, false); + } + + /* Clean :target links */ + if ($(":target").length) { /* element that visited by the URL with hash */ + $(":target").attr(SCROLL_MARK, false); + } + + /* set scroll mark to footnotes */ + if (isFn || isFnRef) { + $target.attr(SCROLL_MARK, true); + } + + if ($target.is(":focus")) { /* Checking if the target was focused */ + return false; + } else { + $target.attr("tabindex", "-1"); /* Adding tabindex for elements not focusable */ + $target.focus(); /* Set focus again */ + } + }); + } + } + } + + }); /* click() */ +}); diff --git a/_javascript/utils/timeago.js b/_javascript/utils/timeago.js new file mode 100644 index 00000000..371231ad --- /dev/null +++ b/_javascript/utils/timeago.js @@ -0,0 +1,77 @@ +/* + * Calculate the Timeago + */ + +$(function() { + const timeagoElem = $(".timeago"); + let tasks = timeagoElem.length; + let intervalId = void 0; + + const dPrompt = $("meta[name=day-prompt]").attr("content"); + const hrPrompt = $("meta[name=hour-prompt]").attr("content"); + const minPrompt = $("meta[name=minute-prompt]").attr("content"); + const justnowPrompt = $("meta[name=justnow-prompt]").attr("content"); + + function timeago(date, initDate) { + let now = new Date(); + let past = new Date(date); + + if (past.getFullYear() !== now.getFullYear() + || past.getMonth() !== now.getMonth()) { + return initDate; + } + + let seconds = Math.floor((now - past) / 1000); + + let day = Math.floor(seconds / 86400); + if (day >= 1) { + return ` ${day} ${dPrompt}`; + } + + let hour = Math.floor(seconds / 3600); + if (hour >= 1) { + return ` ${hour} ${hrPrompt}`; + } + + let minute = Math.floor(seconds / 60); + if (minute >= 1) { + return ` ${minute} ${minPrompt}`; + } + + return justnowPrompt; + } + + function updateTimeago() { + $(".timeago").each(function() { + if ($(this)[0].hasAttribute("date") === false) { + tasks -= 1; + return; + } + + let date = $(this).attr("date"); + let initDate = $(this).text(); + let relativeDate = timeago(date, initDate); + + if (relativeDate === initDate) { + $(this).removeAttr("date"); + } else { + $(this).text(relativeDate); + } + + }); + + if (tasks === 0 && typeof intervalId !== "undefined") { + clearInterval(intervalId); /* stop interval */ + } + return tasks; + } + + if (tasks === 0) { + return; + } + + if (updateTimeago() > 0) { /* run immediately */ + intervalId = setInterval(updateTimeago, 60000); /* run every minute */ + } + +}); diff --git a/_layouts/archives.html b/_layouts/archives.html new file mode 100644 index 00000000..1304354d --- /dev/null +++ b/_layouts/archives.html @@ -0,0 +1,37 @@ +--- +layout: page +# The Archives of posts. +--- + +{% include lang.html %} + +<div id="archives" class="pl-xl-2"> + +{% for post in site.posts %} + {% capture this_year %}{{ post.date | date: "%Y" }}{% endcapture %} + {% capture pre_year %}{{ post.previous.date | date: "%Y" }}{% endcapture %} + {% if forloop.first %} + {% assign last_day = "" %} + {% assign last_month = "" %} + <span class="lead">{{this_year}}</span> + <ul class="list-unstyled"> + {% endif %} + <li> + <div> + {% assign post_short_df = site.data.locales[lang].date_format.post.short %} + <span class="date month small text-muted">{{ post.date | date: post_short_df }}</span> + <span class="date month small text-muted"></span> + <a href="{{ post.url | relative_url }}">{{ post.title }}</a> + </div> + </li> + {% if forloop.last %} + </ul> + {% elsif this_year != pre_year %} + </ul> + <span class="lead">{{pre_year}}</span> + <ul class="list-unstyled"> + {% assign last_day = "" %} + {% assign last_month = "" %} + {% endif %} +{% endfor %} +</div> diff --git a/_layouts/categories.html b/_layouts/categories.html new file mode 100644 index 00000000..4e9ce771 --- /dev/null +++ b/_layouts/categories.html @@ -0,0 +1,99 @@ +--- +layout: page +# All the Categories of posts +--- + +{% include lang.html %} + +{% assign HEAD_PREFIX = "h_" %} +{% assign LIST_PREFIX = "l_" %} + +{% assign group_index = 0 %} + +{% assign sort_categories = site.categories | sort %} + +{% for category in sort_categories %} + {% assign category_name = category | first %} + {% assign posts_of_category = category | last %} + {% assign first_post = posts_of_category | first %} + + {% if category_name == first_post.categories[0] %} + {% assign sub_categories = "" | split: "" %} + + {% for post in posts_of_category %} + {% assign second_category = post.categories[1] %} + {% if second_category %} + {% unless sub_categories contains second_category %} + {% assign sub_categories = sub_categories | push: second_category %} + {% endunless %} + {% endif %} + {% endfor %} + + {% assign sub_categories = sub_categories | sort %} + {% assign sub_categories_size = sub_categories | size %} + + <div class="card categories"> + <!-- top-category --> + <div id="{{ HEAD_PREFIX }}{{ group_index }}" + class="card-header d-flex justify-content-between hide-border-bottom"> + <span> + <i class="far fa-folder{% if sub_categories_size > 0 %}-open{% endif %} fa-fw"></i> + + {% capture _category_url %}/categories/{{ category_name | slugify | url_encode }}/{% endcapture %} + <a href="{{ _category_url | relative_url }}" class="ml-1 mr-2">{{ category_name }}</a> + + <!-- content count --> + {% assign top_posts_size = site.categories[category_name] | size %} + <span class="text-muted small font-weight-light"> + {% if sub_categories_size > 0 %} + {{ sub_categories_size }} + {{ site.data.locales[lang].categories.category_measure }}, + {% endif %} + {{ top_posts_size }} + {{ site.data.locales[lang].categories.post_measure }} + </span> + </span> + + <!-- arrow --> + {% if sub_categories_size > 0%} + <a href="#{{ LIST_PREFIX }}{{ group_index }}" data-toggle="collapse" + aria-expanded="true" aria-label="{{ HEAD_PREFIX }}{{ group_index }}-trigger" + class="category-trigger hide-border-bottom"> + <i class="fas fa-fw fa-angle-down"></i> + </a> + {% else %} + <span data-toggle="collapse" class="category-trigger hide-border-bottom disabled"> + <i class="fas fa-fw fa-angle-right"></i> + </span> + {% endif %} + + </div> <!-- .card-header --> + + <!-- Sub-categories --> + {% if sub_categories_size > 0 %} + <div id="{{ LIST_PREFIX }}{{ group_index }}" class="collapse show" aria-expanded="true"> + <ul class="list-group"> + {% for sub_category in sub_categories %} + <li class="list-group-item"> + <i class="far fa-folder fa-fw"></i> + + {% capture _sub_ctg_url %}/categories/{{ sub_category | slugify | url_encode }}/{% endcapture %} + <a href="{{ _sub_ctg_url | relative_url }}" class="ml-1 mr-2">{{ sub_category }}</a> + + {% assign posts_size = site.categories[sub_category] | size %} + <span class="text-muted small font-weight-light"> + {{ posts_size }} + {{ site.data.locales[lang].categories.post_measure }} + </span> + </li> + {% endfor %} + </ul> + </div> + {% endif %} + + </div> <!-- .card --> + + {% assign group_index = group_index | plus: 1 %} + + {% endif %} +{% endfor %} diff --git a/_layouts/category.html b/_layouts/category.html new file mode 100644 index 00000000..a3660818 --- /dev/null +++ b/_layouts/category.html @@ -0,0 +1,26 @@ +--- +layout: page +# The Category layout +--- + +{% include lang.html %} + +<div id="page-category"> + <h1 class="pl-lg-2"> + <i class="far fa-folder-open fa-fw text-muted"></i> + {{ page.title }} + <span class="lead text-muted pl-2">{{ page.posts | size }}</span> + </h1> + + <ul class="post-content pl-0"> + {% assign post_df = site.data.locales[lang].date_format.post.long %} + + {% for post in page.posts %} + <li class="d-flex justify-content-between pl-md-3 pr-md-3"> + <a href="{{ post.url | relative_url }}">{{ post.title }}</a> + <span class="dash flex-grow-1"></span> + <span class="text-muted small">{{ post.date | date: post_df }}</span> + </li> + {% endfor %} + </ul> +</div> diff --git a/_layouts/compress.html b/_layouts/compress.html new file mode 100644 index 00000000..bb34487d --- /dev/null +++ b/_layouts/compress.html @@ -0,0 +1,10 @@ +--- +# Jekyll layout that compresses HTML +# v3.1.0 +# http://jch.penibelst.de/ +# © 2014–2015 Anatol Broder +# MIT License +--- + +{% capture _LINE_FEED %} +{% endcapture %}{% if site.compress_html.ignore.envs contains jekyll.environment or site.compress_html.ignore.envs == "all" %}{{ content }}{% else %}{% capture _content %}{{ content }}{% endcapture %}{% assign _profile = site.compress_html.profile %}{% if site.compress_html.endings == "all" %}{% assign _endings = "html head body li dt dd optgroup option colgroup caption thead tbody tfoot tr td th" | split: " " %}{% else %}{% assign _endings = site.compress_html.endings %}{% endif %}{% for _element in _endings %}{% capture _end %}</{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _end %}{% endfor %}{% if _profile and _endings %}{% assign _profile_endings = _content | size | plus: 1 %}{% endif %}{% for _element in site.compress_html.startings %}{% capture _start %}<{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _start %}{% endfor %}{% if _profile and site.compress_html.startings %}{% assign _profile_startings = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.comments == "all" %}{% assign _comments = "<!-- -->" | split: " " %}{% else %}{% assign _comments = site.compress_html.comments %}{% endif %}{% if _comments.size == 2 %}{% capture _comment_befores %}.{{ _content }}{% endcapture %}{% assign _comment_befores = _comment_befores | split: _comments.first %}{% for _comment_before in _comment_befores %}{% if forloop.first %}{% continue %}{% endif %}{% capture _comment_outside %}{% if _carry %}{{ _comments.first }}{% endif %}{{ _comment_before }}{% endcapture %}{% capture _comment %}{% unless _carry %}{{ _comments.first }}{% endunless %}{{ _comment_outside | split: _comments.last | first }}{% if _comment_outside contains _comments.last %}{{ _comments.last }}{% assign _carry = false %}{% else %}{% assign _carry = true %}{% endif %}{% endcapture %}{% assign _content = _content | remove_first: _comment %}{% endfor %}{% if _profile %}{% assign _profile_comments = _content | size | plus: 1 %}{% endif %}{% endif %}{% assign _pre_befores = _content | split: "<pre" %}{% assign _content = "" %}{% for _pre_before in _pre_befores %}{% assign _pres = _pre_before | split: "</pre>" %}{% assign _pres_after = "" %}{% if _pres.size != 0 %}{% if site.compress_html.blanklines %}{% assign _lines = _pres.last | split: _LINE_FEED %}{% capture _pres_after %}{% for _line in _lines %}{% assign _trimmed = _line | split: " " | join: " " %}{% if _trimmed != empty or forloop.last %}{% unless forloop.first %}{{ _LINE_FEED }}{% endunless %}{{ _line }}{% endif %}{% endfor %}{% endcapture %}{% else %}{% assign _pres_after = _pres.last | split: " " | join: " " %}{% endif %}{% endif %}{% capture _content %}{{ _content }}{% if _pre_before contains "</pre>" %}<pre{{ _pres.first }}</pre>{% endif %}{% unless _pre_before contains "</pre>" and _pres.size == 1 %}{{ _pres_after }}{% endunless %}{% endcapture %}{% endfor %}{% if _profile %}{% assign _profile_collapse = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.clippings == "all" %}{% assign _clippings = "html head title base link meta style body article section nav aside h1 h2 h3 h4 h5 h6 hgroup header footer address p hr blockquote ol ul li dl dt dd figure figcaption main div table caption colgroup col tbody thead tfoot tr td th" | split: " " %}{% else %}{% assign _clippings = site.compress_html.clippings %}{% endif %}{% for _element in _clippings %}{% assign _edges = " <e;<e; </e>;</e>;</e> ;</e>" | replace: "e", _element | split: ";" %}{% assign _content = _content | replace: _edges[0], _edges[1] | replace: _edges[2], _edges[3] | replace: _edges[4], _edges[5] %}{% endfor %}{% if _profile and _clippings %}{% assign _profile_clippings = _content | size | plus: 1 %}{% endif %}{{ _content }}{% if _profile %} <table id="compress_html_profile_{{ site.time | date: "%Y%m%d" }}" class="compress_html_profile"> <thead> <tr> <td>Step <td>Bytes <tbody> <tr> <td>raw <td>{{ content | size }}{% if _profile_endings %} <tr> <td>endings <td>{{ _profile_endings }}{% endif %}{% if _profile_startings %} <tr> <td>startings <td>{{ _profile_startings }}{% endif %}{% if _profile_comments %} <tr> <td>comments <td>{{ _profile_comments }}{% endif %}{% if _profile_collapse %} <tr> <td>collapse <td>{{ _profile_collapse }}{% endif %}{% if _profile_clippings %} <tr> <td>clippings <td>{{ _profile_clippings }}{% endif %} </table>{% endif %}{% endif %} diff --git a/_layouts/default.html b/_layouts/default.html new file mode 100644 index 00000000..4bcede59 --- /dev/null +++ b/_layouts/default.html @@ -0,0 +1,59 @@ +--- +layout: compress +# Default layout +--- + +<!DOCTYPE html> + +{% include lang.html %} + +{% capture prefer_mode %} + {% if site.theme_mode %} + mode="{{ site.theme_mode }}" + {% endif %} +{% endcapture %} + +<html lang="{{ site.lang }}"{{ prefer_mode }}> + + {% include head.html %} + + {% unless site.theme_mode %} + {% include mode-toggle.html %} + {% endunless %} + + <body data-spy="scroll" data-target="#toc"> + + {% include sidebar.html %} + + {% include topbar.html %} + + <div id="main-wrapper"> + <div id="main"> + + {{ content }} + + {% include footer.html %} + + </div> + + {% include search-results.html %} + + </div> <!-- #main-wrapper --> + + {% if page.mermaid %} + {% include mermaid.html %} + {% endif %} + + <div id="mask"></div> + + <a id="back-to-top" href="#" aria-label="back-to-top" class="btn btn-lg btn-box-shadow" role="button"> + <i class="fas fa-angle-up"></i> + </a> + + {% include search-loader.html %} + + {% include js-selector.html %} + + </body> + +</html> diff --git a/_layouts/home.html b/_layouts/home.html new file mode 100644 index 00000000..279feeda --- /dev/null +++ b/_layouts/home.html @@ -0,0 +1,100 @@ +--- +layout: page +# The Home page layout +--- + +{% include lang.html %} + +{% assign pinned = site.posts | where: "pin", "true" %} +{% assign default = site.posts | where_exp: "item", "item.pin != true" %} + +{% assign posts = "" | split: "" %} + +<!-- Get pinned posts --> + +{% assign offset = paginator.page | minus: 1 | times: paginator.per_page %} +{% assign pinned_num = pinned.size | minus: offset %} + +{% if pinned_num > 0 %} + {% for i in (offset..pinned.size) limit: pinned_num %} + {% assign posts = posts | push: pinned[i] %} + {% endfor %} +{% else %} + {% assign pinned_num = 0 %} +{% endif %} + + +<!-- Get default posts --> + +{% assign default_beg = offset | minus: pinned.size %} + +{% if default_beg < 0 %} + {% assign default_beg = 0 %} +{% endif %} + +{% assign default_num = paginator.posts | size | minus: pinned_num %} +{% assign default_end = default_beg | plus: default_num | minus: 1 %} + +{% if default_num > 0 %} + {% for i in (default_beg..default_end) %} + {% assign posts = posts | push: default[i] %} + {% endfor %} +{% endif %} + +<div id="post-list"> + +{% for post in posts %} + + <div class="post-preview"> + <h1> + <a href="{{ post.url | relative_url }}">{{ post.title }}</a> + </h1> + + <div class="post-content"> + <p> + {% include no-linenos.html content=post.content %} + {{ content | markdownify | strip_html | truncate: 200 }} + </p> + </div> + + <div class="post-meta text-muted d-flex"> + + <div class="mr-auto"> + <!-- posted date --> + <i class="far fa-calendar fa-fw"></i> + {% include timeago.html date=post.date tooltip=true %} + + <!-- time to read --> + <i class="far fa-clock fa-fw"></i> + {% include read-time.html content=post.content %} + + <!-- categories --> + {% if post.categories.size > 0 %} + <i class="far fa-folder-open fa-fw"></i> + <span> + {% for category in post.categories %} + {{ category }} + {%- unless forloop.last -%},{%- endunless -%} + {% endfor %} + </span> + {% endif %} + </div> + + {% if post.pin %} + <div class="pin"> + <i class="fas fa-thumbtack fa-fw"></i> + <span>{{ site.data.locales[lang].post.pin_prompt }}</span> + </div> + {% endif %} + + </div> <!-- .post-meta --> + + </div> <!-- .post-review --> + +{% endfor %} + +</div> <!-- #post-list --> + +{% if paginator.total_pages > 0 %} + {% include post-paginator.html %} +{% endif %} diff --git a/_layouts/page.html b/_layouts/page.html new file mode 100644 index 00000000..77c1d1b8 --- /dev/null +++ b/_layouts/page.html @@ -0,0 +1,54 @@ +--- +layout: default +--- + +{% include lang.html %} + +<div class="row{% unless layout.tail_includes %} alone{% endunless %}"> + + <!-- core --> + <div id="core-wrapper" class="col-12 col-lg-11 col-xl-8"> + <div class="post pl-1 pr-1 pl-sm-2 pr-sm-2 pl-md-4 pr-md-4"> + {% if page.dynamic_title or page.collection == 'tabs' %} + <h1 class="dynamic-title"> + {%- capture tab_key -%}{{ page.url | split: '/' }}{%- endcapture -%} + {{- site.data.locales[lang].tabs[tab_key] | default: page.title -}} + </h1> + <div class="post-content"> + {% include refactor-content.html content=content %} + </div> + {% else %} + {% include refactor-content.html content=content %} + {% endif %} + </div> + </div> <!-- #core-wrapper --> + + <!-- pannel --> + <div id="panel-wrapper" class="col-xl-3 pl-2 text-muted topbar-down"> + + <div class="access"> + {% include update-list.html %} + {% include trending-tags.html %} + </div> + + {% for _include in layout.pannel_includes %} + {% assign _include_path = _include | append: '.html' %} + {% include {{ _include_path }} %} + {% endfor %} + </div> + +</div> + +<!-- tail --> +{% if layout.tail_includes %} +<div class="row"> + <div class="col-12 col-lg-11 col-xl-8"> + <div id="tail-wrapper" class="pl-1 pr-1 pl-sm-2 pr-sm-2 pl-md-4 pr-md-4"> + {% for _include in layout.tail_includes %} + {% assign _include_path = _include | append: '.html' %} + {% include {{ _include_path }} %} + {% endfor %} + </div> + </div> +</div> <!-- .row --> +{% endif %} diff --git a/_layouts/post.html b/_layouts/post.html new file mode 100644 index 00000000..b7c333ad --- /dev/null +++ b/_layouts/post.html @@ -0,0 +1,124 @@ +--- +layout: page +pannel_includes: + - toc +tail_includes: + - related-posts + - post-nav + - disqus +--- + +{% include lang.html %} + +{% if page.image.src %} + {% capture bg %} + {% unless page.image.no_bg %}{{ 'bg' }}{% endunless %} + {% endcapture %} + <img src="{{ page.image.src }}" class="preview-img {{ bg | strip }}" + alt="{{ page.image.alt | default: "Preview Image" }}" + {% if page.image.width %}width="{{ page.image.width }}"{% endif %} + {% if page.image.height %}height="{{ page.image.height }}"{% endif %}> +{% endif %} + +<h1 data-toc-skip>{{ page.title }}</h1> + +<div class="post-meta text-muted"> + + <!-- author --> + <div> + {% capture author_name %}{{ page.author.name | default: site.social.name }}{% endcapture %} + {% assign author_link = nil %} + + {% if page.author.link %} + {% assign author_link = page.author.link %} + {% elsif author_name == site.social.name %} + {% assign author_link = site.social.links[0] %} + {% endif %} + </div> + + <div class="d-flex"> + <div> + <!-- published date --> + <span> + {{ site.data.locales[lang].post.posted }} + {% include timeago.html date=page.date tooltip=true %} + </span> + + <!-- lastmod date --> + {% if page.last_modified_at %} + <span> + {{ site.data.locales[lang].post.updated }} + {% include timeago.html date=page.last_modified_at tooltip=true %} + </span> + {% endif %} + + <!-- read time --> + {% include read-time.html content=content prompt=true %} + + <!-- page views --> + {% if site.google_analytics.pv.proxy_endpoint or site.google_analytics.pv.cache_path %} + <span> + <em id="pv" class="pageviews"> + <i class="fas fa-spinner fa-spin fa-fw"></i> + </em> + {{ site.data.locales[lang].post.pageview_measure }} + </span> + {% endif %} + </div> + + </div> <!-- .d-flex --> + +</div> <!-- .post-meta --> + +<div class="post-content"> + {{ content }} +</div> + +<div class="post-tail-wrapper text-muted"> + + <!-- categories --> + {% if page.categories.size > 0 %} + <div class="post-meta mb-3"> + <i class="far fa-folder-open fa-fw mr-1"></i> + {% for category in page.categories %} + <a href='{{ site.baseurl }}/categories/{{ category | slugify | url_encode }}/'>{{ category }}</a> + {%- unless forloop.last -%}, {%- endunless -%} + {% endfor %} + </div> + {% endif %} + + <!-- tags --> + {% if page.tags.size > 0 %} + <div class="post-tags"> + <i class="fa fa-tags fa-fw mr-1"></i> + {% for tag in page.tags %} + <a href="{{ site.baseurl }}/tags/{{ tag | slugify | url_encode }}/" + class="post-tag no-text-decoration" > + {{- tag -}} + </a> + {% endfor %} + </div> + {% endif %} + + <div class="post-tail-bottom + d-flex justify-content-between align-items-center mt-3 pt-5 pb-2"> + <div class="license-wrapper"> + + {% if site.data.locales[lang].copyright.license.template %} + + {% capture _replacement %} + <a href="{{ site.data.locales[lang].copyright.license.link }}"> + {{ site.data.locales[lang].copyright.license.name }} + </a> + {% endcapture %} + + {{ site.data.locales[lang].copyright.license.template | replace: ':LICENSE_NAME', _replacement }} + + {% endif %} + </div> + + {% include post-sharing.html %} + + </div><!-- .post-tail-bottom --> + +</div><!-- div.post-tail-wrapper --> diff --git a/_layouts/tag.html b/_layouts/tag.html new file mode 100644 index 00000000..30371ef4 --- /dev/null +++ b/_layouts/tag.html @@ -0,0 +1,25 @@ +--- +layout: page +# The layout for Tag page +--- + +{% include lang.html %} + +<div id="page-tag"> + <h1 class="pl-lg-2"> + <i class="fa fa-tag fa-fw text-muted"></i> + {{ page.title }} + <span class="lead text-muted pl-2">{{ page.posts | size }}</span> + </h1> + <ul class="post-content pl-0"> + {% assign post_df = site.data.locales[lang].date_format.post.long %} + + {% for post in page.posts %} + <li class="d-flex justify-content-between pl-md-3 pr-md-3"> + <a href="{{ post.url | relative_url }}">{{ post.title }}</a> + <span class="dash flex-grow-1"></span> + <span class="text-muted small">{{ post.date | date: post_df }}</span> + </li> + {% endfor %} + </ul> +</div> diff --git a/_layouts/tags.html b/_layouts/tags.html new file mode 100644 index 00000000..d0e63d59 --- /dev/null +++ b/_layouts/tags.html @@ -0,0 +1,21 @@ +--- +layout: page +# All the Tags of posts. +--- + +<div id="tags" class="d-flex flex-wrap ml-xl-2 mr-xl-2"> + + {% assign tags = "" | split: "" %} + {% for t in site.tags %} + {% assign tags = tags | push: t[0] %} + {% endfor %} + + {% assign sorted_tags = tags | sort_natural %} + + {% for t in sorted_tags %} + <div> + <a class="tag" href="{{ site.baseurl }}/tags/{{ t | slugify | url_encode }}/">{{ t }}<span class="text-muted">{{ site.tags[t].size }}</span></a> + </div> + {% endfor %} + +</div> diff --git a/_plugins/posts-lastmod-hook.rb b/_plugins/posts-lastmod-hook.rb new file mode 100644 index 00000000..1fd6ecf9 --- /dev/null +++ b/_plugins/posts-lastmod-hook.rb @@ -0,0 +1,14 @@ +#!/usr/bin/env ruby +# +# Check for changed posts + +Jekyll::Hooks.register :posts, :post_init do |post| + + commit_num = `git rev-list --count HEAD "#{ post.path }"` + + if commit_num.to_i > 1 + lastmod_date = `git log -1 --pretty="%ad" --date=iso "#{ post.path }"` + post.data['last_modified_at'] = lastmod_date + end + +end diff --git a/_posts/2016-07-19-china-taiko.md b/_posts/2016-07-19-china-taiko.md new file mode 100644 index 00000000..4ccfc1f9 --- /dev/null +++ b/_posts/2016-07-19-china-taiko.md @@ -0,0 +1,59 @@ +--- +layout: post +title: "中国の太鼓の達人用語" +date: 2016-7-19 +category: blog +tags: [音ゲー] +description: "面白い中国の太鼓の達人用語を紹介しました" +--- +こんにちは、まつまつです。日本語を勉強し始めてからもう二年半ほど経ちましたが、恥ずかしいながら今まで日本語で文章を書いたことはありません。というわけで、何かを書こうと思いまして、このブログを作りました。 + +まず、軽く自己紹介をさせていただきます。日本在住の中国人です。組成割合はゲーマー99%と、学生1%となっています。いろんなジャンルのゲームが好きで、ここで主にゲームの話をしようと考えています。 + +ということで、いきなりですが、今日は太鼓の達人を中心に、自分が面白いと思った中国の音ゲー用語を紹介します。 + +#### **1.ヴァーナス ー 炒菜(chǎo cài)** + +元々「炒菜」という言葉は、野菜を炒めるという意味です。太鼓でヴァーナスする時、利き手で上下に面と縁を叩くの動作は、炒め物をする時、鍋にある野菜をへら、またはお玉で頻繁に返す動作と微妙に似ているので、こういうふうに名付けられました。 + +この言葉から派生して、ヴァーナスでやるという意味を表したい時、直接「炒める」と言うことが多いです。例えば、 + +<pre>裏黒薔薇を3連続ヴァーナスでやって腕が死にそうになった</pre> + +と言いたい時、中国語でいうと + +<pre>裏黒薔薇を3連続炒めて腕が死にそうになった</pre> + +という感じになります。 + +#### **2.複合 ー 鱼蛋(yú dàn)** + +「鱼蛋」とは、中国のつみれのことです。既に分かった方がいると思いますが、太鼓の中で、16分音符が並んでいるところ、とてもつみれ団子の串のように見えます。最初の「鱼蛋」は全ての複合のことを指していたかもしれませんが、私が太鼓を始めた頃、すでに長い複合は「鱼蛋」で、短い複合はそのまま「3連」、「5連」で使い分けられています。 + +#### **3.ゲーセンに行く - 出勤(chū qín)** + +「出勤」という単語日本語にもありますね。日本語でも中国語でも「出勤」の意味が同じです。ただし、中国語での出勤は日本語のように、日常生活によく使われる言葉ではありません。 + +日本も中国も、ガチ勢の音ゲーマーにとって、毎日ゲーセンに通うのは当たり前のことです。というわけで、音ゲーマーの皆さんはゲーセンに行くことを出勤に喩えています。ちょっと自虐的な言い方ですが、近年非常に広く使われています。 + +使用例(とあるLINEグループみたいなところで) +<pre> +A 「今日出勤する人いる?」 +B 「俺休む」 +C 「わたしとXは8時までいるわ」 +A 「じゃ決めた。今すぐ出勤する」 +</pre> +のような会話、毎日各地のローカル音ゲーグループで行われているのでしょうね… + +#### **4.リザルトを晒す - 撒花(sā huā)** + +「撒花」は直接和訳すると、花を撒くという意味になります。中国の古代では、祝いの気持ちを表現したい時、花を撒くという風習があるらしいです。いいリザルト出た時、そのリザルトをSNSサイト、LINEグループみたいなところや巨大掲示版みたいなところにポストする行為は、「撒花」と呼ばれています。 + +使用例 +<pre> +A 「撒花~~」添付ファイル:きたさいたま2000.jpg(内訳 良802 以下略) +B 「人?」(お前は人間じゃないだろう?の略) +</pre> +もっとたくさんあると思いますが…すみません、私の脳みそを絞り尽くした結果はこれだけです。今後何か思いついたら、もしくは何か新しい言葉が出てきたら、また追加するかもしれません。 + +何か不適切な日本語がありましたら、ご指摘いただければ…いや、もしその気がありましたら、ぜひご指摘してください。日本語難しいですね・・・ \ No newline at end of file diff --git a/_posts/2017-01-01-new-year.md b/_posts/2017-01-01-new-year.md new file mode 100644 index 00000000..ff653265 --- /dev/null +++ b/_posts/2017-01-01-new-year.md @@ -0,0 +1,54 @@ +--- +layout: post +title: "明けましておめでとうございます" +date: 2016-12-31 +category: blog +tags: [日記,音ゲー,STG] +description: "謹賀新年" +--- +この記事は2016年12月31日の23時半から書き始めましたけど、多分書き終わる頃もう2017年になりますね。自分は日本語を書くのがまだまだ慣れなくて、進みがとても遅いです。そのせいで修論がなかなか捗らなく、もっと早めに書けばよかったなぁと最近何度も思いました(苦笑)。 + +2016年はカラフルな一年でした。成功したことも、失敗したこともありました。新しい物事もいろいろ触れて、死にかけた(と勝手に思っていただけ)経験もしました。日本に来て二年目に突入し、一年目の頃と比べてだいぶ慣れてきた感じがしますね。でもまだ頑張る余地がたくさんありまして、これからもどんどん進化していきたいと思います٩(`・ω・´)و + +<br /> + +#### 死にかけた経験 + +とりあえず、死にかけた経験を報告します。11月28日(月)の朝10時頃、いつも通りに目が覚めましたが、ちょっとした異常を感じました。10分が経っても意識的な呼吸が止まらなくなってしまい、やはりどこかがおかしいと思いまして、グーグルで調査し始めました。「心筋梗塞」というキーワードに引っかかり、詳しく調べた後、症状がとても似ていると感じました。20分ぐらい経ったら手と足が震え始めて、救急車を呼ぶと決意しました。その後近くの病院に運ばれていろいろ検査を受けましたが、結局症状の原因が解明されず、生理食塩水の点滴を受けただけで症状がなくなりました。 + +翌日は異常感がなく、治ったと勝手に思っていましたが、次の日また同じ症状が出ました。しかし今回から朝に限らず、一日中ずっと息苦しく感じるようになってしまいました。(ただし起きた直後は特にひどく、手の震えなどの症状を伴うこともよくある)それだけでなく、呼吸を意識するせいで就寝が困難になり、寝てもせいぜい二、三時間ですぐ起きてしまい、まともな睡眠が取れない日々が続けていました。その日から近くのクリニックに通い、全面的な検査を受け始めました。だけど前と同じく、原因が分からないままで、毎日死亡の恐怖と戦い続けていました。 + +一人暮らしでなかなか心細くて、それに両親を安心させるためにも、しばらく友人の宿を借りることにしました。状況を打開したのは土曜日の夜、また症状がひどくなって救急車を呼んでいましたが、結局救急車が来る前に落ち着いてきました。その時の救急員からたくさんのアドバイスをいただき、そののうち一つは「過呼吸(hyperventilation)の可能性がある」でした。それがきっかけで僕は過呼吸について調べ始めて、可能性が高いと判断しました。次の週の月曜日、通っていたクリニックから紹介状をいただき、近くにある病院の先生に診てもらいました。先生も過呼吸の可能性が高いと判断し、精神を安定する薬を処方していただきました。その薬でとても効果を感じて、そして息苦しくなった時もなるべく平穏な呼吸を保つようにしたら、症状がだんだん出なくなり、良質な睡眠が取れるようになりました。今日に至ってほぼ完全に治りました。 + +**分かったこと** + +* 友人の大切さ +* 病因が分からないとき、一つのクリニックに拘らずもっと広くアドバイスを受けるべき +* 日本の救急の素晴らしさ(ただし軽い気持ちで救急車を呼んではいけない) +* 本当に死にかけた時、頭で考えてるのは「生きたい」しかない。「サイレントEXまだクリアしてない」なんかどうでもよくなる + +<br /> + +#### 収穫 + +重い話をしてしまいましたが、これから(自分が)楽しい(と思う)話をしたいと思います。自分は実は目標を立てるのがとても好きな人間です。あまり公表はしないので、いつも自分しか見れないところで目標のリストとかを作っています。今年はなんと、全達成しました\(^o^)/ + +一番ギリギリのは、「リナシタ、エンジェリオン、トイコンをクリアし、スコアはできるだけ頑張る」というポップンの目標でした。トイコンはクリアできた日までずっとワケワカ地帯でゲージがからっぽになるパターンでしたが、その日急にワケワカが残られるようになって、二度目の選曲でぎりぎりクリアできました([ボーダー+1](https://twitter.com/ssdh233/status/813351707547607040))。時間的にもゲージ的にもギリギリでしたw + +音ゲーに関して、太鼓も難しくなった十段を成功に奪還し、ギタドラも両赤ネになり、丸く収まりました。ちなみに、今年はPS4で出された初音ミク Project DIVA Future Toneというゲームもやりこんでいました。この作品は前のDIVAシリーズと比べて、(いい方向で)難易度が大幅に上がり、収録曲も非常に豊かで(移植だから新曲ないけど)、音ゲーとしてとてもやりがいのある作品だと思いました。ただし16分の同時押し(基本的に片手で16分をごり押しするしかない)とホールドだけは勘弁してほしいです… + +今年シューティングも久しぶりに再開しました。プレイしたのはデススマイルズと怒首領蜂最大往生、どっちもケーブの作品でした。特にデススマイルズでスコアも狙ってみましたが、クリア狙いとまったく違うゲームになって、シューティングゲームの奥深さを改めて感じました。結局DVDに倣ったばかりで一応3億は超えましたけど、自分の新規性は何もありませんでした。来年時間があればもっと頑張りたいと思います。 + +<br /> + +#### 新しい物事 + +たまたまyoutubeでちょろい(矢作・佐倉のちょっとお時間よろしいですか)の面白いカット集が勧めされて、見たら「これ~~日本語の勉強になれるぞ!~~めちゃ面白いなぁ!」と思ってFlowersで馴染んだ佐倉さんを中心にラジオを聞き始めました。最近特にとしたい(佐倉としたい大西)にハマっていて、毎週定時的に聞くようになっています。ただしこれから放送時間が火曜日の23時半に変更するのがつらいです… + +佐倉さんの影響を受けたというわけではないですけど、百合姫を読み始めました。きっかけはこの前kindle unlimitedでいっぱい百合姫連載の単行本を読んだことと、百合姫が月刊化になったことです。ゆるゆりはもちろん、他の連載や読切もとても面白く感じて、毎月の楽しみが増えました😆 + +<br /> +<br /> +やはり2017年になりました…しかも夜の3時になっちゃって…早く寝ないと😩 + +今年は社会人になりますが、どれだけゲームをやる時間が取れるかが非常に重大な課題です。とりあえず「頑張ります」としか言えないですね…振り返ってみたらこの文章は「僕が小学生の頃で書いた作文感」がすごくしますね。日本語の文章力を上げるために今年はどんどん記事を書いていこうと思っています。新年もよろしくお願いします。 \ No newline at end of file diff --git a/_posts/2017-01-15-game-center.md b/_posts/2017-01-15-game-center.md new file mode 100644 index 00000000..0bbbf580 --- /dev/null +++ b/_posts/2017-01-15-game-center.md @@ -0,0 +1,81 @@ +--- +layout: post +title: "溝の口ゲーセン考察レポート" +date: 2017-01-15 +category: blog +tags: [音ゲー,ゲーセン] +description: "音ゲーを中心に考察してきました" +--- +今日は次の引越し先候補である高津&溝の口辺りのゲーセンを考察しに行きました。久し(三日)ぶりの音ゲーなので調子があまり良くなくて、感想がズレるかもしれませんが、来週また行く予定がありますので、もし何か新しい感想がありましたら加筆します。 + +まずはゲーセンの地図です。 + +![screenshot]({{ site.url }}/assets/2017-01-15-game-center/1.jpeg) + +近いですね。タイトーからゲームイミグランデまで歩行距離はおよそ290メートルで、ゲームイミグランデからラウンドワンまでおよそ450メートルです。駅までの距離も画像の通り、とても近いです。以下は各ゲーセンの詳しい情報です。 + +### **タイトーステーション 溝の口2号店** + +#### ポップンミュージック +* 初期筐体二台(筐体の分類は[ここに参照してください](http://www.atomic--age.net/topics/columns/kindofpopn)) +* 100/120円設定。朝から14時まで?/100円(多分80/100円)のサービスある。 +* 左の筐体 + * 若干誤反応出やすく感じるが、プレイ回数が少ないためまだ確信できない。 + * よく説明できないが落下軌道の色が若干見分けにくい。ル・モンド巣鴨の筐体と似たような感じがする。 +* 右の筐体 + * 右下の部分色がおかしいが、特に影響がない。 + * ボルテ側の反射がひどい +* ~~両方共にテンキーがめちゃ離れてるところに設置されてる~~ + * 店員さんに調整してもらった + +#### 太鼓の達人 +* レッドver.一台。100円/3曲設定。 +* 音量小さめ。特に後ろのギャラリー勢がうるさい時の影響が大きい。 +* メンテは特に問題ないが特良抜けやすい(1P側)。 +* 筐体上の貼り紙によるとマイバチが推奨されない。詳しい事情が分からないが… + +#### ギタドラ +* 白筐体一組。 +* 100/120円設定。 +* ドラム + * 椅子の高さが調整できる。 + * 下手だけど特にメンテ上の異常を感じなかった。 + +#### その他 +* 【営業時間】9:00~23:50 +* ブレイブルーがある。 + + +### **ゲームイミグランデ溝の口店** + +#### 太鼓の達人 +* レッドver.一台。100円/3曲設定。電子マネーで90円 +* ~~軽く真ん中を叩くと反応しない時がある~~ + * 多分錯覚だった。今は特に異常なし(2017年07月) +* 音量超でかい。 +* 録画できる。 + +#### その他 +* 【営業時間】平日10:00~24:00 土日祝9:00~24:00 + +### **ラウンドワン高津店** + +#### ポップンミュージック +* 新筐体三台 +* ずっと100円2クレ +* 右の筐体の過反応がひどく、フルコン狙いにきつい +* 左と真ん中の筐体は特に異常なし + +#### 太鼓の達人 +* レッドver.一台。100円/4曲設定。 +* 1P側の面、真ん中の左よりの上の方の反応が悪い +* 音量が小さめ +* ラウンドワンだし休日には一般人が多いので並ぶ確率が高め。 + +#### ギタドラ +* 黒筐体一組。 +* 100/120円設定。 +* 並んでる人が多かったのでプレイしなかった。 + +#### その他 +* 【営業時間】全日6:00~23:50 \ No newline at end of file diff --git a/_posts/2017-01-23-kac.md b/_posts/2017-01-23-kac.md new file mode 100644 index 00000000..999c454f --- /dev/null +++ b/_posts/2017-01-23-kac.md @@ -0,0 +1,83 @@ +--- +layout: post +title: "KAC 6th ポップン予選ラウンド感想" +date: 2017-01-23 +category: blog +tags: [音ゲー] +description: "頑張りました" +--- +日本に来たのは2014年の7月なので、今回は三回目のKAC参戦でした。一回目はラピストリアの頃、一応KACコースを全部やってみましたけど、まだ対象曲のMetamorphoseでたまに落ちる程度の腕前なので、記憶に残るほどの思い出が特にありません。ただし、決勝ラウンドは現場に見に行きましたが、輪廻の譜面を初めて見た時「これ47くらいかなぁ」っていう動画勢を極める発言をした覚えは確実に記憶に残りました(笑)。~~その後コースモードで何度も落ちました~~ + +二回目はエクラルですね。男々道ありましたね。無理でしたね。その頃のスコア力ではスコアが出やすい低レベルの曲でも98kを出すのが精一杯で、中高難易度の曲のスコアを意識することがほとんどありませんでした。それでも自分なりにそこそこ頑張りましたが、結果が300位か400位くらいでした。 + +今回のKAC 6th、ポップンの予選ラウンドは新作稼働の翌日にスタートしまして、個人的にかなり盛り上がりました。前回の頃と比べてだいぶスコア力が成長しましたし、今回の選曲も**一見**そんなに難しくありませんし、とりあえずランキング(200位以内)に入るぞという意気込みで頑張りました。 + +結果はこちらです。 + +<a href="{{ site.url }}/assets/2017-01-23-kac/1.png"><img src="{{ site.url }}/assets/2017-01-23-kac/1.png" style="width: 60%"/></a> + +結局ランキング200位以内に入らなかったのがちょっと残念でしたが、最初の目標の871kより3000点も超えまして、とても満足しました。 + +ちなみに、毎日の順位の変化を記録して(意識高い)、下のチャートを作りました。 + +![screenshot]({{ site.url }}/assets/2017-01-23-kac/2.png) + +ではこれから曲ごとに感想を述べます。 + +#### Jack in the Box + +BPM250の片手16分トリルと8分縦連が一番印象的でした。曲はノリノリですが、精度を取るためにBPM250の8分をしっかり押さないといけないため、調子が良い時と悪い時の差が今回のKAC曲において一番大きいかもしれません。 + +#### トウキョウ・ドリーム・ポップ + +ソフラン。選曲TOP(23回)。 + +中盤の低速地帯はサドプラを付け外す余裕がほとんどなく、スコア狙いには低速力必須と言ってもいいでしょう。幸い中盤の低速地帯が主に8分で構成されていますので、認識すること自体がそこまで難しいではありません。(光らせられるとは言っていない) + +この曲のスコア狙いでソフランについて新たな発見がありました。ソフラン曲は低速だけではなく、低速から切り替わった直後の高速地帯も光らせにくいです。多分まだソフランに慣れていなく、目線の切り替えが上手く出来ないからだと思います。 + +最初は93kくらいしか出さなかったですが、何度もやっているうちに中盤の低速地帯をだんだん慣れてきたら伸びました。~~その後癖付いてしまって完全に光らせなくなりました~~ + +#### white night story + +98.6k → 98.9k + +お待ちかねのつらら曲!開幕を除けば結構スコアが取りやすい譜面なんですが、開幕が一番むずかしいパターンは辛いです。 + +#### Spangles + +一番無理でした。BPM130の24分メインのハネリズム譜面って無理ですよね…初見のスコアが一番高かったのですが、うさねこ初日で記録されていませんでした。その後頑張って初見に近いスコアまで出したんですが、結局最後まで初見のスコアを超えられませんでした。 + +こういう系の譜面、多分ハイスピを上げて認識しやすくしたら伸びると思うんですが、結局何度もやってもハマりませんでした。地力不足ですね。 + +#### アルレシャ + +98.0k → 98.3k → 98.6k + +98.0k出した時これでいいやと思ったんですけど、KACはそんなに甘くないですね。この曲のスコア推移のおかげで、今までたまたま高いスコアを出した曲、真剣に詰めればもっと伸びるかもしれないと思いました。 + +#### LEAD Gravity (M) + +前半の繰り返し地帯、ミラーかけると16分が右手になって何故か押せなくなります。普通に考えれば右手のほうが強いはずですけど…あと後半の8分地味に黄ばみやすいと感じました(地力不足)。 + +#### 如雨露姫が世界征服 + +予選において一番レベルの高い譜面でした。フルコンしたい + +如雨露姫のキャラ設定よく分かりません(^o^) + +#### Sing a Song Sign + +簡単なところと難しいところ綺麗に分けられる譜面。こういう繰り返し配置一旦意識し始めると押せなくなるんですよね。 + +余談ですが、かおりんのキャラデザイン、ファンタジアの時点から変わっていないですね…~~お金がなくて新しい服が買えないのかなぁ~~ + +#### 霊魂爆砕 -SOUL EXPLOSION- + +ランダムでした。このBPM帯の16分乱打さえ安定できないことを実感しました。地力上げたい。 + +### 最後 + +今回は限界まで頑張ったという感じでした。これ以上伸びることはないだろうと思った曲を伸ばしたことが何度もありました。逆に、もうちょっと伸ばしたいなぁと思った曲を十何回やっても結局伸びなかったこともありました。辛い時もありますが、収穫が非常に多くて良い思い出でした(小並感)。 + +また来年ランキングに入れるように頑張ります。 \ No newline at end of file diff --git a/_posts/2017-03-03-graduation.md b/_posts/2017-03-03-graduation.md new file mode 100644 index 00000000..e52553bc --- /dev/null +++ b/_posts/2017-03-03-graduation.md @@ -0,0 +1,24 @@ +--- +layout: post +title: "卒業" +date: 2017-03-03 +category: blog +tags: [日記] +description: "研究を諦めました" +--- + +今までの人生で何度も学校を卒業したことあるが、大体「時間が経ったら卒業した」という感じだった。小学校から高校までは授業さえ受ければ誰でも卒業できる。大学は一応単位と卒論という条件が追加されたが、僕が通ったところではとてもゆるくて、卒業するために特に頑張ったという覚えがなかった。そのゆるさのおかげで大学四年生の頃どっぷり日本語の勉強ができて、とてもありがたく思っている(笑) + +今回の卒業はひと味が違った。自己評価すると、「一生懸命頑張った」までは行けなかったが、「そこそこ頑張った」くらいでいいかな。日本での修士(Master)は、いくら時間が経っても、それなりの研究成果がなければ卒業ができないことが最初から告げられた。だけど、「それなり」の基準が、今でもよく分からない。その結果、そこそこ頑張った二年だった。 + +<br/> + +そもそも日本の大学院に行くと決めたのは、研究をしたいわけではなかった。僕にとって日本の魅力は主に二つある。一つは、日本の人が日本語をしゃべること。日本語しか対応していない日本製ゲームが多く存在するため、日本語力を身に付ければプレイできるゲームの範囲が広がる。もう一つは、日本でしかプレイできないゲームがあること。日本のゲーセンで稼働されている多くのアーケードゲームは、中国ではプレイできない。日本以外にも稼働されているところも一応あるが、数と種類を考えるとやはり日本に来るのがベストチョイスだ。 + +というわけで、入学した後、ずっと「何をすれば卒業できるんだろ」という悩みを抱え込んでいた。テーマを決めるため、とりあえず先生のアドバイスに従って、ちょっと興味のある分野で論文を探して読んで、そこから何か新しいアイデアを考え出すことにした。ただし、そのアイデアは新しさ(新規性)と嬉しさ(研究の価値?)がなければならない。特に知識のない僕にとって、その二つの特徴を兼備しているアイデアを捻出することはなかなかむずかしい。結局、考え出したアイデアがボコボコされて、振り出しに戻る。このようなプロセスを何度も何度も繰り返して、ようやく自分ができそうな研究テーマを見つけたけど、それと同時に、自分は研究者を向いていないこともだんだん分かってきた。 + +僕から見ると、研究者にとって一番大事なのは、自分の研究成果に嬉しく思う気持ちだ。そういうモチベーションがあるからこそ、大量の時間と情熱を研究に振ることができる。それに、研究は常に新しいことを挑戦するから、"これくらいの時間を払えばこれくらい"の報酬がもらえるという予測が難しい。もちろん仕事も単純に時間をお金に引き換えるものではないと思うけど、研究と比べれば比較的にコントロールしやすい。だからこれからただゲームをプレイし続けたい自分にとっては、できるだけ少ない労働時間で生活を維持できるお金を儲けることが望ましい。今の段階では、仕事という選択が一番いいと判断したので、これから社会の歯車として(ry + +<br/> + +ちなみに、修士課程での研究テーマはソースコード検索関連なものだった。正直なところ、モチベーションのところは今でも少し怪しいと思うけど、これから更に掘り下げても何も得られないから、もうこのままでいいかな。今後どっかに出すかもしれないが、どこにも出さないかもしれない。もうどうでもいい。疲れた。 \ No newline at end of file diff --git a/_posts/2017-03-12-cannot-write.md b/_posts/2017-03-12-cannot-write.md new file mode 100644 index 00000000..2d26bde7 --- /dev/null +++ b/_posts/2017-03-12-cannot-write.md @@ -0,0 +1,64 @@ +--- +layout: post +title: "書けない" +date: 2017-03-12 +category: blog +tags: [語学] +description: "日本語も英語も" +--- + +今日論文の翻訳をやっているとき、ふと気付いた。 + +*英語なんて書けない!!!!!* + +実は日本語も書けない。英語よりはマシだけど、今まで書いた短いブログでも、完成するのに3、4時間くらいかかるから、とても書けるとは言えない。 + +書けないから、書けるようになりたい。というわけで、中国語で<font color="red">なんでそんなに書けるんだよっ!英語で...何回書いたんだよ!?</font>とググってみた。いや、うそです。そんな中国語知らない。とりあえずいろいろ検索してみた。 + +そこで中国有名のQ&Aサイト[知乎(zhihu)](https://ja.wikipedia.org/wiki/知乎)に辿った。[如何有效提高日语写作?](https://www.zhihu.com/question/27907557)(訳:How to effectively improve Japanese writing)というタイトルのスレッドに、こんな回答があった。 + +<pre>写作不是客观题,没有标准答案告诉你什么是对什么是错。</pre> + +訳すと、Writingには絶対的な正解がありません。 + +だからWritingは難しい。麻雀もそうだ。でも麻雀の場合は「ありません」より「分かりません」のほうが多いかも。 + +まあ麻雀のことはどうでもいいとして、そんなことみんなとっくに知っているし、わざわざここに書く必要がない。 + +大切なのは、この文の下に、こういう勉強法が進められた。日本語で要約すると、 + +**(中国語で日本語を勉強する場合)日本語から中国語に翻訳した文章を、日本語に翻訳して、原文と対比する** + +例えば、 + +<pre>我见到了从美国来的布鲁斯。现在它和住在东京都八王子市一座公寓中的千叶小姐(33岁)生活在一起。千叶小姐出生9个月后便得了小儿麻痹症,走不了路,靠轮椅生活,手也有残疾。</pre> + +僕の答え + +<pre>アメリカからのブルースに会った。今彼?は東京都八王子のあるマンションに住んでいる千葉さんと暮らしている。千葉さんは生まれて9ヶ月後なになに症に患ってしまい、歩けなくなった。ずっと車椅子上に生活をしていて、手にも障害がある。</pre> + +原文 + +<pre>米国からきたブルース君にあった。東京都八王子市のアパートで千葉れい子さん(33)と一緒に暮らしている。千葉さんは、生後9ヶ月で小児まひになった。歩けない。車いすの生活だ。手も不自由である。</pre> + +感想 +* ブルースくんは人間ではないことが分かっていたけど、人間以外のものを指示する時どんな代名詞を使えばいいか分からなかった +* 「マンションに住んでいる千葉さんと暮らしている」のところ、おかしいと思ったがやっぱりそうだった +* 「生まれて9ヶ月後」 ...◯◯してから何ヶ月が経って、◯◯になったという表現がずっと苦手だった。要グーグル +* ... + +なんか面白そう!勉強になりそう!と思った。ちなみに、勧められた本の名前は『天声人语』、朝日新聞の同名のコラムから文章を集めて、中国語に翻訳した本だ。(ここの日本語がおかしい) + +この方法の名前は、中国語では**逆向写作法**と回答者が定義したけど、これをキーワードでググると逆ポーランド記法のWikipediaが出るところから見ると、あんまり広がっていないようだ。 + +今後時間があったらこの方法を実践してみようと思っているけど、とりあえず本を東京に届ける方法を考えないと… + +論文の翻訳を続けなくちゃ...やっぱり + +***英語なんて書けないよ!!!!!*** + +<br/> +<br/> +<br/> +<br/> +p.s. 初めてブログっぽい記事を書いてみた \ No newline at end of file diff --git a/_posts/2017-05-12-uzaku-book.md b/_posts/2017-05-12-uzaku-book.md new file mode 100644 index 00000000..460fd30b --- /dev/null +++ b/_posts/2017-05-12-uzaku-book.md @@ -0,0 +1,36 @@ +--- +layout: post +title: "ウザく本一周" +date: 2017-05-12 +category: blog +tags: [天鳳,麻雀] +description: "牌効率UP" +--- + +お久しぶりです。グーグルアナリティクスを見る限りここにはほとんど来客がいないですけど、それでもこれから日記のような文章よりブログを書いていきたいです。 + +最近天鳳というクソゲーをハマっています。ガチでやっています。説明しよう、天鳳という麻雀もどきのラス回避ゲームは、いくら真剣にやっても、他のゲームと違って必ず収穫が出るというわけではありません。去年の11月からちょくちょくやってきましたが、ptが全く上がっていません。実力は上がっているかもしれませんが、それがデータに反映されるまでは分かりません。逆にptが上がっても、それはただ運が良かったかもしれません。だからクソゲーです(^o^) + +こんなクソゲーでも、強くなりたいです。 + +前はラスった牌譜の検討とかしていましたが、そんなに効果がありませんでした。やっぱり今自分に必要なのは、インプットです。**こう打ったら正しいとか、こう打ったらだめとか**、このような知識がほしいです。というわけで、最近麻雀の戦術本を読んだりしています。今日はあの有名なウザく本を一周した感想をここで話します。(ちなみに、ウザく本を知ったきっかけは、天鳳位のしゅかつさんのブロクです) + +まず正答率は、六割くらいでした。どうでもいい二択を含めれば、多分六割強くらいはありました。 + +収穫をまとめます。 + +#### 1.多面張 +前も245667とかもうある程度慣れていますが、何切る問題に出てくるとやはり短時間に解くことが難しいです。344456とか334445とか、一回まとめて整理する必要性を感じました。 + +#### 2.対子手 +チートイの見逃しによる誤答がひどかったです。あれこれ対子五個でしたっけ?とかもあったんですが、打点が少ない場合、三暗刻やチートイにもっと頼ったほうがいいと思いました。 + +#### 3.浮かせ打ち +3対子落としの場合、浮かせ打ちはほとんどしないべきです。一向聴ピーク理論にも繋がります。これは完全に盲点でした。 + +<br /> +以上と比べて、もっとも大きい収穫は、**牌効率は、聴牌までの効率だけではなく、形と打点も含めて考慮するものだ**ということを改めて認識したことです。 + +今回はざっくりなことしか書いてないですが、二周したらもっと具体的なレビューを書こうと思っています。二周は一、二ヶ月後くらい行う予定です。 + +最後に、これからも麻雀のことをブログに書くので、markdownで麻雀牌のフリー素材をここで簡単に使えるようなプラグインを作りたいです。最近いろいろ忙しくて(主に天鳳^_^;)なかなか時間が取れませんが、頑張ります。 \ No newline at end of file diff --git a/_posts/2017-06-18-tenhou-1.md b/_posts/2017-06-18-tenhou-1.md new file mode 100644 index 00000000..7c3d5159 --- /dev/null +++ b/_posts/2017-06-18-tenhou-1.md @@ -0,0 +1,93 @@ +--- +layout: post +title: "牌譜検討 その一" +date: 2017-06-18 +category: blog +tags: [天鳳,麻雀] +description: "六段坂1305/2400" +--- + +先日ようやく六段になりました。これから週一くらいの頻度で牌譜検討をやっていきたいと考えています。今回は六段デビュー戦の牌譜です。 + + +牌譜 [http://tenhou.net/0/?log=2017061618gm-0029-0000-2e6ab455&tw=1](http://tenhou.net/0/?log=2017061618gm-0029-0000-2e6ab455&tw=1) + +#### 東1局 + +<img src="{{ site.url }}/assets/2017-06-18-tenhou-1/1.png" style="width: 80%"/> + +いきなり搭子オーバー。ピンズの染めを見て打1mとしました。 + +<img src="{{ site.url }}/assets/2017-06-18-tenhou-1/2.png" style="width: 80%"/> + +[B級ミス]打発 -> 打9p。発は重なる時ホンイツに移行できますけど、9pはほぼ完全にいらない牌。安全度は9pのほうが若干上ですけど発も危険な牌ではありません。 + +<img src="{{ site.url }}/assets/2017-06-18-tenhou-1/3.png" style="width: 80%"/> + +5200良形良形(鳴いたら大体2000になる)vs鳴ける愚形良形満貫。3p残り二枚しかないのと、良形良形のほうがリーチする場合打点の期待値は満貫に負けないので打2pとしました。 + +#### 東1局 1本場 + +<img src="{{ site.url }}/assets/2017-06-18-tenhou-1/5.png" style="width: 80%"/> + +親リーチ。鳴いてしらばく押した方が収支期待値が高いかもしれませんが、千点なのでベタオリとそんなに変わらないはず。スルーしてベタオリしました。 + +<img src="{{ site.url }}/assets/2017-06-18-tenhou-1/6.png" style="width: 80%"/> + +[C級ミス]打6s -> 打9m。ベタオリはなるべく手牌の形を保つべき。 + +#### 東1局 3本場 + +<img src="{{ site.url }}/assets/2017-06-18-tenhou-1/7.png" style="width: 80%"/> + +[C級ミス]打8m -> 打9p。7899の亜両面、他に頭がある場合孤立牌の28より劣っている。頭の方は<img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/3p.gif' height='32px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/4p.gif' height='32px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/4p.gif' height='32px'>でしたら孤立牌の28と同じくらい。 + +#### 東4局 2本場 + +<img src="{{ site.url }}/assets/2017-06-18-tenhou-1/8.png" style="width: 80%"/> + +5巡目の愚形満貫テンパイ。この巡目ならリーチでも良さそうですが、実戦ではダマにしました。 + +<img src="{{ site.url }}/assets/2017-06-18-tenhou-1/9.png" style="width: 80%"/> + +[A級ミス]もろひなのでリーチしても上がり率あまり変わらない(ダマのほうが高い)はず。最初からダマならダマし続けるべきだと思います。 + +#### 南1局 3本場 + +<img src="{{ site.url }}/assets/2017-06-18-tenhou-1/10.png" style="width: 80%"/> + +配牌から戸惑った。東か78s落としかの二択だと思いますが、実戦では東を切りました。 + +<img src="{{ site.url }}/assets/2017-06-18-tenhou-1/11.png" style="width: 80%"/> + +上同じく、ただし字牌の白明らかにいいので、78s落としがさらに良さそう。実戦では2pを切りました。 + +追記:ツイッターで議論した結果、配牌から78s落とし、染め一直線で良さそうに見えました。原因は + +* 7p引いて2600の両面リーチ逃しても、メンホンの一向聴なのでロスだと言えるかどうかあやしいくらい +* この巡目、69s引きの愚形2600テンパイはあまり嬉しくない。それよりピンズ染めで発が鳴ければ満貫確定 + +ただし、78s落としはなるべく目立たないように。8s->(ピンズ引いたら東/ほかの色はツモ切り)->7sでよさそうです。 + +#### 南2局 + +<img src="{{ site.url }}/assets/2017-06-18-tenhou-1/12.png" style="width: 80%"/> + +両面テンパイで対面のリーチに2600放銃。この点差ならしばらくオリないほうが良さそうと思ってましたが、微妙ですね。両無筋やドラくらいならオリ有利と言えると思います。 + +#### 南3局 + +<img src="{{ site.url }}/assets/2017-06-18-tenhou-1/13.png" style="width: 80%"/> + +平場なら押せそうな手牌だけど、南3では順位二つ下がる可能性があるのでベタオリします。 + +#### 南4局 + +<img src="{{ site.url }}/assets/2017-06-18-tenhou-1/14.png" style="width: 80%"/> + +安牌全く無いので、一番良さそうなワンチャンかつ二枚の8sを切りました。大丈夫そうですね.. + +<hr style="margin-top: 30px; margin-bottom: 30px"/> + +感想: +初めてブログで牌譜検討やってみました。とても硬い文章になってしまいました...全体的に運がとても良かった一局でしたが、東4局の愚形ダマ満貫と南1局の染め手はなかなか決めなくて、一貫性のない打ち方をしてしまいました。東4局の愚形ダマ満貫のところ、もし**リーチとダマどっちも大差ない**でしたらそれで構わないですが、今回はそういうわけではなさそうですね。 \ No newline at end of file diff --git a/_posts/2017-06-24-genma.md b/_posts/2017-06-24-genma.md new file mode 100644 index 00000000..21767df1 --- /dev/null +++ b/_posts/2017-06-24-genma.md @@ -0,0 +1,31 @@ +--- +layout: post +title: "現代麻雀技術論の中国語訳 スタート" +date: 2017-06-24 +category: blog +tags: [麻雀,語学] +description: "翻訳についても少し" +--- + +先日ネマタさんから翻訳の許可を快諾いただいて、ウェブサイト"現代麻雀技術論"の中国語訳を始めました。Github中心で翻訳を進んでいます。 + +今出来ているもの(あまり出来ていない) -> [section001 牌效率的原则](https://github.com/matsumatsu233/mahjong-tactics-chinese/blob/chapter1/chapter1/section001.md) + +ブログを書くたびに日本語むずかしいいいいい!と思うけど、母国語である中国語も、あんまりスムーズに書けない。そりゃ日本語むずかしいいいいい!と思っても仕方ないわ。 + +さて、今回翻訳のモチベーションとして、もちろんゲンマをもっと多くの中国の日本麻雀プレイヤー(麻雀はゲームだしプレイヤーでいいよね)に知ってほしいのもあるけど、僕のような自己中心で生きている奴、こんなに簡単に他人のために働くわけがない。 + +**翻訳が面白そうだから。** + +<hr style="margin-bottom: 15px"/> + +中国には、たくさんの"民間中国語訳チーム"が存在する。彼らは、日本のアニメ、漫画、ゲーム、ライトノベルなどを、中国語に翻訳して、インターネットでこっそり中国語化したものを他人にシェアする。日本の原作のスタッフたちから見ると、彼らは違法アップロードしている不法な存在であるかもしれないが、多くの日本のアニメやゲームなどが好きな中国人にとって、彼らは神のような存在である。 + +僕が知っている限り、彼らはだいたい無償で働いている。自分が翻訳できる日本語力を持っているから、この翻訳はだいたい、彼ら自身のためにならない。それに、中国のネット民もせっかちな人が少なくなく、「まだですか?」とか、「どこまで進んだ?」とかのような催促は、彼らにとって日常茶飯事だろう(もし高を括って締め切りを決めちゃって、結局守れなくなったらもっとひどいコメントが出る)。催促したい気持ちは分からなくもないが、それでも「てめぇら金払ってねぇから黙ってろ!」って言いたくなると思うw + +違法のリスクを負っても、こんなに促されても、彼らはなぜ無償に働いているのか?僕はずっと理解できなかった。翻訳の仕事を目指している人もいるだろうが、それはあくまで少数だと思う。それとも、この翻訳の中で、何かハマりそうなもの(満足感?達成感?)が存在するのか?今回の翻訳を通して少しでも分かるようになったらいいなぁ + +<hr style="margin-bottom: 15px"/> +正直、自分は日本語も中国語も中途半端で、それに加えて翻訳経験ゼロです。良い翻訳が出来る自信が全くないが、今の自分が出来る、最善を尽くしたいと思います。 + +翻訳の手順として、とりあえず適当に訳して、問題がなさそうだったらgithubにプッシュする。そして友人に少し見てもらって、変なところがあったら修正する。これで初稿完成。一つのchapterが終わると、もう一回細かくチェックして、どこかに公開する。(公開する場所はまだ決まってない。ここは一番便利だけど、中国からのアクセスがきつい。) \ No newline at end of file diff --git a/_posts/2017-07-02-jlpt-n1.md b/_posts/2017-07-02-jlpt-n1.md new file mode 100644 index 00000000..c5bc4fd2 --- /dev/null +++ b/_posts/2017-07-02-jlpt-n1.md @@ -0,0 +1,31 @@ +--- +layout: post +title: "JLPT N1受けてきました" +date: 2017-07-02 +category: blog +tags: [語学] +description: "JLPTとは、日本語能力試験の略称である" +--- + +先ず面白いことに、 + +<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">JLPT N1の読解で、ある声優が書いた実家の犬に関する文章が出ましたけど、犬の名前が「直司」で、後でググったらまさかの杉田さんでしたw</p>— まつまつ (@ssdh233) <a href="https://twitter.com/ssdh233/status/881390492876914689">2017年7月2日</a></blockquote> +<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> + +なんと、杉田さんと実家の犬の話が読解に出てきましたw + +原文は[こちら](https://matome.naver.jp/odai/2138700161017964901/2138700383719329803)。 + +杉田さんに対して、男性声優においてもどやばい(いい意味で)イメージしかなかったんですが、まさかこんな、試験に出されるほど真面目な文章を書くとはwと思ったけど、文章を書いたのは別人でしたか。 + +実は去年の12月にもN1試験を申し込んでました。しかし、2分ほど遅刻したせいで、入場拒否される始末になった。その頃体の調子が悪くて走れなかったのもありますけど、主にはスケジュール管理が至らないせいでした。というわけで、出直ししました( ・`д・´) + +試験自体は順調で、ブログに書くほどの内容はなかったです。けど、今回の試験会場である、横浜国立大学常盤台キャンパスの椅子、非常に硬かったです。試験中ずっと、お尻が苦しんでいました。これから横浜国立大学を志望する学生に一言:**鋼鉄のお尻の持ち主でない限り、座布団の常備をおすすめします。** + +これで日本語の勉強が一段落つきました。まだまだ行き届かないところは多いですが、これからしばらく英語の勉強に切り替えます。日本語は、紙の上で勉強するよりも、もっと人と交流することで、日常で使うことで(ここでブログを書くのも含めて)、少しずつ上達していければと思っています。 + +良い点数が採られますように(^_^;) + +追記: +<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">は?JLPT N1理論値出たwww <a href="https://t.co/0nfoN2RkN7">pic.twitter.com/0nfoN2RkN7</a></p>— まつまつ (@ssdh233) <a href="https://twitter.com/ssdh233/status/900136090585112576">2017年8月22日</a></blockquote> +<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> \ No newline at end of file diff --git a/_posts/2017-07-04-genmajisen-review.md b/_posts/2017-07-04-genmajisen-review.md new file mode 100644 index 00000000..3592c234 --- /dev/null +++ b/_posts/2017-07-04-genmajisen-review.md @@ -0,0 +1,102 @@ +--- +layout: post +title: "ゲンマ実戦編 PART1 review" +date: 2017-07-04 +category: blog +tags: [麻雀,天鳳] +description: "レビューじゃなくreview" +--- +レビューの意味(スーパー大辞林) + +* 評論。批評。書評。 +* 評論雑誌。 + +reviewの意味(ウィズダム英和辞典) + +* 回顧, 反省。 +* ... + +この単語のように、日本語は外来語を導入する場合、その言葉の意味の一部だけを切り出すことが多いですよね。"レビュー"で書くと、どうしてもこの本についての批評、意見のように見えてしまいます。このブログは、本を評価するつもりではなく、ただ自分の"読書過程"を顧みるつもりで書いています。 + +さて、今回はPART1 手作りの神髄!!のreviewです。 + +<hr style="margin-bottom: 15px"/> + +#### Question 2 + +南2局 親 4巡目 + +<img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/1m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/2m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/3m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/4m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/5m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/6m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/7m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/5s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/3p.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/3p.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/4p.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/0p.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/6p.gif' height='40px'><span style='margin-right:10px'></span><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/5s.gif' height='40px'><span style='margin-right:10px'></span>ドラ<img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/1s.gif' height='40px'> + +自分の答え:1m切りリーチ<br/> +著者の答え:3p切り<br/> +感想:1m切りリーチと1m切りダマしか考えませんでした...特に四連形絡みのとき、テンパイを取らない選択も頭に入れなければなりませんね。巡目が早い+四連形\*2なので変化を優先します。タンヤオが崩れる可能性はありますが、四連形\*2なのでさすがに良形を追ったほうが有利か。もし右の方は<img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/3p.gif' height='24px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/3p.gif' height='24px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/0p.gif' height='24px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/6p.gif' height='24px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/7p.gif' height='24px'>でしたら鉄で即リーします。 + +<hr style="margin-bottom: 15px"/> + +#### Question 4 + +南1局 親 3巡目 + +<img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/4m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/8m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/8m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/2p.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/2p.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/3p.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/4p.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/5p.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/6p.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/7p.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/0s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/6s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/7s.gif' height='40px'><span style='margin-right:10px'></span><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/4p.gif' height='40px'><span style='margin-right:10px'></span>ドラ<img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/5m.gif' height='40px'> + +自分の答え:4m切りリーチ<br/> +著者の答え:4m切りダマ<br/> +感想:Question2と比べて、四連形が一つになったのでテンパイを取ります。けど、ドラが<img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/5m.gif' height='24px'>なので<img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/2p.gif' height='24px'>切りとの差がそんなに大きくないと思います。もしここは40符2飜の手でしたら、<img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/2p.gif' height='24px'>切ったほうがいいと思います。愚形の40符3飜はリーチとダマの分岐点みたいなもので、状況によって判断することが大事ですね。ここは3種の良形変化がありますのでダマを選んだそうです。 + +<hr style="margin-bottom: 15px"/> + +#### Question 6 + +南1局 北家 3巡目 + +<img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/6m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/7m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/1s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/1s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/3s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/4s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/5s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/8p.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/9p.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/9p.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/5z.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/5z.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/5z.gif' height='40px'><span style='margin-right:10px'></span><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/5m.gif' height='40px'><span style='margin-right:10px'></span>ドラ<img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/8p.gif' height='40px'> + +自分の答え:9p切りリーチ<br/> +著者の答え:8p切りリーチ<br/> +感想:符の差は完全に見落としました。それに8pがドラで7pが表示牌ってわけで、枚数の差もあります(ドラを直接表示しているので、とても分かりづらい)。端牌\*2のシャボとドラそばの辺張、あまりにも上がり率の差が大きいのでシャボを選びます。 + +<hr style="margin-bottom: 15px"/> + +#### Question 7 + +東1局 1本場 西家 8巡目 1m3枚見え、4m1枚見え、2m9p0枚見え + +<img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/2m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/2m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/3m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/5m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/6m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/7m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/2s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/3s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/4s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/9s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/9s.gif' height='40px'><span style='margin-right:10px'></span><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/ura.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/6z.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/6z.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/ura.gif' height='40px'><span style='margin-right:10px'></span>ドラ<img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/2s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/5m.gif' height='40px'> + +自分の答え:3m切りリーチ<br/> +著者の答え:3m切りダマ<br/> +感想:完全に騙された...カンが入ってるので思わずリーチと思ったが、発ドラドラの70符3飜で、リーチしても満貫以上になる可能性が低いのでダマ。 + +<hr style="margin-bottom: 15px"/> + +#### Question 11 + +東3局 親 4巡目 + +<img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/1m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/2m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/7m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/8m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/9m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/5p.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/5p.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/7p.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/5s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/7s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/8s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/9s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/6z.gif' height='40px'><span style='margin-right:10px'></span><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/3p.gif' height='40px'><span style='margin-right:10px'></span>ドラ<img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/6z.gif' height='40px'> + +自分の答え:5s切り<br/> +著者の答え:1m切り<br/> +感想:愚形のみになりそうな場合、先に愚形を落としたほうが得することが多いということですね。ドラが<img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/8m.gif' height='24px'>とかでしたら、普通の3〜7浮き牌より辺張を優先したほうがいいでしょう。 + +<hr style="margin-bottom: 15px"/> + +#### Question 15 + +南2局 南家 4巡目 東113・南240・西239・北408 + +<img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/1m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/3m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/6m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/7m.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/6p.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/6p.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/8p.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/1s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/2s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/6s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/8s.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/5z.gif' height='40px'><img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/5z.gif' height='40px'><span style='margin-right:10px'></span>出た!<img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/5z.gif' height='40px'><span style='margin-right:10px'></span>ドラ<img src='https://raw.githubusercontent.com/matsumatsu233/mahjong-pai-converter/master/sources/mj-dragon/7s.gif' height='40px'> + +自分の答え:ポンして2s切り<br/> +著者の答え:スルー<br/> +感想:愚形愚形の千点なので、守備力優先でスルー。ただし、ポンした後守備力重視で手を進めても悪くない。自分は守備力重視で役牌をスルーしたことがありませんので、こういう鳴かない選択肢も頭に入れたいところですね。 + +<hr style="margin-bottom: 15px"/> + +続きは後日で(^_^;) + +追記:続きを書いている途中気付いてしまったんですが、このあとの問題はすべて、自分の手以外の情報が必要になっています。河とかの情報を全て示さないと伝わりづらいので、パスします(^_^;) + + +※ 画像は[麻雀ルール](http://www.mj-dragon.com/rule/)解説でおなじみの「麻雀の雀龍.com」の無料麻雀牌画を利用しています。 \ No newline at end of file diff --git a/_posts/2017-07-09-tenhou-2.md b/_posts/2017-07-09-tenhou-2.md new file mode 100644 index 00000000..bce875b9 --- /dev/null +++ b/_posts/2017-07-09-tenhou-2.md @@ -0,0 +1,96 @@ +--- +layout: post +title: "牌譜検討 その二" +date: 2017-07-09 +category: blog +tags: [天鳳] +description: "六段坂1665/2400" +--- + +週一くらい牌譜検討をやるとか言ってましたけど、日本語を書くのがしんどいですから、なかなか捗りません(^_^;) + +牌譜 [http://tenhou.net/0/?log=2017062323gm-0029-0000-50475c33&tw=1](http://tenhou.net/0/?log=2017062323gm-0029-0000-50475c33&tw=1) + +今回の牌譜は、アカギのアニメを見た直後でやった半荘です。変な影響を受けたせいかもしれませんが、とにかくラスりました。アカギのアニメは面白かったですが... + +#### 東2局 + +<img src="{{ site.url }}/assets/2017-07-09-tenhou-2/T2.0-1.png" style="width: 80%"/> + +親番。愚形愚形のヘッドレスからの単騎テンパイ。良形への手変わりがかなり多いですので、とりダマにしました。 + +<img src="{{ site.url }}/assets/2017-07-09-tenhou-2/T2.0-2.png" style="width: 80%"/> + +4s切り追っかけリーチ。通ったら7sは両方の筋になるのでそこそこあがれるじゃないか、と思ってましたけど、残り二枚しかないので微妙ですね。結局対面ツモりました。 + +#### 東3局 + +<img src="{{ site.url }}/assets/2017-07-09-tenhou-2/T3.0-1.png" style="width: 80%"/> + +上家リーチした同巡にテンパイ、6pはかなり安全なので(実戦では7pの壁気づかなかったんですがw)迷わず追っかけました。 + +<img src="{{ site.url }}/assets/2017-07-09-tenhou-2/T3.0-2.png" style="width: 80%"/> + +結局下家が上家に放銃。うん、上家のこののみ手、私はリーチしないですね。巡目が深いとはいえ親以外の時のみ手リーチは基本的にしない派です。赤ドラ、三暗刻への手変わりを見ます。 + +#### 東4局 + +<img src="{{ site.url }}/assets/2017-07-09-tenhou-2/T4.0-1.png" style="width: 80%"/> + +両副露から上家のリーチが入りました。一発巡の8pは押しましたが、ドラ跨ぎの3mで引きました。筋はまだ半分くらいしか通ってないので、3900の両面テンパイ(4枚)だし押したほうがよかったかも。結局上家の現物の7sで回って、ノーテン流局でした。対面もテンパイ濃厚ですが、実戦では全く気づきませんでした。もし対面が聴牌していると想定するのなら、3m(または6m)はもっと押したくなくなりますが、それでも押したほうが良かったかなぁ?分からん(´;ω;`) + +#### 東4局 1本場 + +<img src="{{ site.url }}/assets/2017-07-09-tenhou-2/T4.1-1.png" style="width: 80%"/> + +上家4巡目でリーチ。三色の可能性はあるが、愚形愚形の二向聴なのでベタオリしました。流局しました。 + +#### 南1局 2本場 + +<img src="{{ site.url }}/assets/2017-07-09-tenhou-2/N1.2-1.png" style="width: 80%"/> + +上家の親からリーチ。供託が美味しいのでかなり押したいですが、親に対して良形愚形(字牌)の一向聴から無筋を押すのは抵抗感が...対子落としで回ってみましたが結局ベタオリになりました。 + +#### 南2局 + +<img src="{{ site.url }}/assets/2017-07-09-tenhou-2/N2.0-1.png" style="width: 80%"/> + +二回目の親番。ちょっと遠いですが、ホンイツを見て打1mが良さそうに見えます。もし染めないとしたら、9pが重ならない限りだいたい1500か2900になりそうです。 + +<img src="{{ site.url }}/assets/2017-07-09-tenhou-2/N2.0-2.png" style="width: 80%"/> + +[A級ミス]チートイ本線ですので2枚切れの1pより2sを残す。 + +<img src="{{ site.url }}/assets/2017-07-09-tenhou-2/N2.0-3.png" style="width: 80%"/> + +南のポンは微妙です。チートイよりはドラがだいぶ使いにくくなりますし、1シャンテンから2シャンテンになりますし、チートイと心中したほうがマシだと思います。 + +<img src="{{ site.url }}/assets/2017-07-09-tenhou-2/N2.0-4.png" style="width: 80%"/> + +**<font color="red">[S級ミス]</font>**運良く下家のカンで満貫テンパイとなりました。2pと37pはともに3枚ですが、2pが場に明らかによさそうですからカン2pを受けるべき。二巡後見事に"裏目"りました。 + +#### 南2局 1本場 + +<img src="{{ site.url }}/assets/2017-07-09-tenhou-2/N2.1-1.png" style="width: 80%"/> + +[B級ミス]謎の8s切り。58s引いた時イーシャンテンを残るようにツモ切りします。 + +<img src="{{ site.url }}/assets/2017-07-09-tenhou-2/N2.1-2.png" style="width: 80%"/> + +上家からリーチ入ったところ。打点はあるとはいえ愚形愚形愚形の両向聴なので、ベタオリしました。ここはラスを競っているライバルのリーチ、かつ自分が親なので、押したほうがいいですかね?分からん(´;ω;`) + +<img src="{{ site.url }}/assets/2017-07-09-tenhou-2/N2.1-3.png" style="width: 80%"/> + +オリ打ち...しましたけど、筋の3pより安全な牌がありませんので、仕方ないと思います。 + +#### 南3局 1本場 + +<img src="{{ site.url }}/assets/2017-07-09-tenhou-2/N3.1-1.png" style="width: 80%"/> + +親のリーチに一発でオリ打ちしました。4p->南の手順は多分大丈夫ですよね。中筋のモロ引っ掛けはじめて見ました。 + +<hr style="margin-bottom: 15px"/> + +感想:細かい手順のミスは思ったより少なかったですが、南2局の待ち受け選択ミスは致命的でした。このようなミスを減らすには、"テンパイすると気が緩める"という悪いクセを直さないといけません。テンパイするときは、テンパイするときならではの"考えるべきこと"(手変わり、スライド、流局間際の判断など)が存在します。 + +アカギの影響に関しては、見当たりませんでしたw \ No newline at end of file diff --git a/_posts/2017-08-05-touhou.md b/_posts/2017-08-05-touhou.md new file mode 100644 index 00000000..ce13071e --- /dev/null +++ b/_posts/2017-08-05-touhou.md @@ -0,0 +1,76 @@ +--- +layout: post +title: "東方" +date: 2017-8-5 +category: blog +tags: [STG, ゲーム感想] +description: "思い出" +--- + +> 東方Project(とうほうプロジェクト)とは、ZUN(通称「神主」)が運営する個人サークル「上海アリス幻樂団」制作の弾幕シューティングゲームを中心とする作品群の総称。 (ニコニコ大百科) + +(そういえば、なんで東方という名前なんだろうね) + +先日中国の友人が東京に遊びに来て、中野ナムコで太鼓をやりに行った。その友人は薄い本が好きだから、休みの間に近くのまんだらけにぶらぶらしていた。 + +そこで僕の目に映ったのは、裸な(一部は厳密に言うと裸じゃないけど肝心な部分だけ露出している。いやどうでもいいけど)二次元女性キャラクターたちではなく、このゲームソフトだった。 + +<img src="{{ site.url }}/assets/2017-08-05-touhou/1.jpg" style="width: 80%"/> + +なぜか東方シリーズの全作がこの薄い本とエロゲーのコーナーに陳列されていた。 + +東方のゲームソフト本体、秋葉原のとらのあなで何度も見たことあるけど、windowsPCを持ってなかったので買うのを見送っていた。ちょうど少し前にsurface bookを手に入れたので、今度は迷わず購入した。 + +先週ようやく時間が空いて、開封してインストール。Windows 10でもちゃんと動くのだ。やった! + +surface bookのキーボード、stgには非常に使いにくいけど、とりあえず始めてみた。 + +**ぴちゅー!** + +あれ?低速モードでシュートする時、斜め方向への移動ができない。 + +いろいろ試してみたら、どうやらsurface bookのキーボード、三つのキーを押しっぱなしにすると、次に何を押しても反応しない。だいたいのラップトップのキーボードはこういう仕様らしい。 + +こうなると、他のデバイスを使うしかない。幸い自分はケイブのシューティングをやるためにアケコン(xbox360用)を持っているので、それを接続してみた。 + +<img src="{{ site.url }}/assets/2017-08-05-touhou/2.jpg" style="width: 80%"/> + +右のボタンはちゃんと反応するけど、デフォルト設定だと使いにくい。それをゲームの中にあるOPTION -> KEY CONFIGで調整すればいい感じになる。左のレバーはどうしても認識できないので、かの有名なJoyToKeyでキーボードの十字キーにマッピングしたら動けるようになった。斜めへの移動もばっちり(・Д・◍)b + +環境が整えたということで、プレイ再開。もちろんLunaticで。 + +**ぴちゅー!** + +あれ(´・∀・)? + +**ぴちゅー!** +**ぴちゅー!** +**ぴちゅー!** + +満身創痍。 +<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">こんなに難しかったっけこのゲーム <a href="https://t.co/4mhM9vFKqP">pic.twitter.com/4mhM9vFKqP</a></p>— まつまつ (@ssdh233) <a href="https://twitter.com/ssdh233/status/891196395046092800">2017年7月29日</a></blockquote> +<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> + +さすがに六年くらい放置したら、腕が萎えるよね。一日かかって練習して、かろうじてクリアした。 + +<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">永夜抄ルナティック、6年ぶりにクリア! <a href="https://t.co/jxmB7PtYCI">pic.twitter.com/jxmB7PtYCI</a></p>— まつまつ (@ssdh233) <a href="https://twitter.com/ssdh233/status/891572201874350080">2017年7月30日</a></blockquote> +<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> + +ボム数35だった。我ながらさすがのロイヤルボンバーだ( ・`д・´) + +>ロイヤルボンバー(royal bomber)とは、中国のSTG界隈でボムを節操無し使う人の愛称である。 + +六年ぶりに東方をプレイして、高校時代のこといろいろ思い出した。 + +僕の高校は寄宿制なので、二週間に一回くらいしか家に帰ることができない。学校では、基本的に勉強しかできなく、ゲーム機は発見されたら即没収。そんなに過酷な環境で、僕にとって数少ない娯楽の一つは、休日先生の居ない教室のパソコンで、こっそり東方をプレイすることだった。 + +その頃はノーマルくらいしかできなかったけど、とてつもなく楽しかった。多分ルナティック初クリアした時よりも。そりゃ、普段勉強以外何も出来ない環境で、ゲームをプレイするのは楽しくないわけがないだろう。多分今フリーゲーマー?を目指しているのも、当時の反発のせいだろうw + +これからも東方をゆっくりプレイしていきたい。 +<br /> +<hr /> +<br /> + +追記: +<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">東方紺珠伝ルナティッククリア!!! <a href="https://t.co/a73wCAbnwH">pic.twitter.com/a73wCAbnwH</a></p>— まつまつ (@ssdh233) <a href="https://twitter.com/ssdh233/status/897302979048488960">2017年8月15日</a></blockquote> +<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> \ No newline at end of file diff --git a/_posts/2017-09-09-kurouto.md b/_posts/2017-09-09-kurouto.md new file mode 100644 index 00000000..c6aa352d --- /dev/null +++ b/_posts/2017-09-09-kurouto.md @@ -0,0 +1,100 @@ +--- +layout: post +title: "玄人合格!!!" +date: 2017-9-9 +category: blog +tags: [音ゲー] +description: "太鼓の達人 段位道場" +--- + +<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">玄人合格!!!!!!!!!!!!!!!!!!!!!!!!!! <a href="https://t.co/AWPgZtO9Fu">pic.twitter.com/AWPgZtO9Fu</a></p>— まつまつ (@ssdh233) <a href="https://twitter.com/ssdh233/status/906473206084546560">2017年9月9日</a></blockquote> +<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> + +久しぶりに太鼓頑張りました。 + +今回太鼓を始めたのは五月の下旬くらい、ちょうどイエローの段位道場に関する開発日記(ブログ)が発表される頃でした。そしてその頃の僕の全力のリザルトを見てみましょう + +<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">フルボコ <a href="https://t.co/aMKJOacInA">pic.twitter.com/aMKJOacInA</a></p>— まつまつ (@ssdh233) <a href="https://twitter.com/ssdh233/status/867735787516731393">2017年5月25日</a></blockquote> +<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> + +レッドの十段に合格してからほとんどやってなかったから、こうなりました。 + +そこから低難易度曲の全良(主にアニメ曲)と新曲の精度詰めでリハビリして、十段までの更新を迎えました。もともと十段底辺の実力でしたから、少し頑張れば受かるとおm + +<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">かえります <a href="https://t.co/P68vImyCJ3">pic.twitter.com/P68vImyCJ3</a></p>— まつまつ (@ssdh233) <a href="https://twitter.com/ssdh233/status/871343966532157441">2017年6月4日</a></blockquote> +<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> +(説明しよう、十段の許容可数は50です) + +はい。人によってそつおめしき2ばんは十段の中で一番簡単なのかもしれないが、僕のような旧筐体老害ヴァナースドンだーにとって、BPM200はダメです。手が追い付けません。 + +(後日で無事受かりました) + +十段から玄人までの三ヶ月、★10の精度更新を中心に頑張っていました。もちろん、壁にぶつかった時、下位互換となる★9とかもそれなりにやりましたが、★10ほど力入れていなかったです。僕は玄人ではレッドの時と同じくBPM200以上の曲がメインだと想定したため、交互を猛練習していましたが、見事に裏切られました。今度の玄人は旧筐体老害ヴァナースドンだーにやさしいですね。 + +一応レッド十段からイエロー玄人までの★10更新をまとめておきます。ご参考になれば幸いです。(レッド十段の頃のスコアは必ず全力で詰めたスコアとは限らない) + +| 曲名 |レッド十段|イエロー玄人| +|:--- | ---:| ---:| +|Black Rose Apostle(裏) |47|24| +|そつおめしき2ばん|52|10| +|No Gravity|35|8| +|D's Adventure Note |27|10| +|SstTAarR*|61|14| +|Silent Jealousy(裏) |35|15| +|Gloria|50|25| +|ノるどん2000|41|23| +|Angel Halo|48|15| +|アサガオ|43|14| +|練習曲Op.10-4(裏)|40|11| +|オーブの祈り|17|9| +|きたさいたま2000|34|14| +|ギミチョコ!!(裏)|57|47| +|ミュージック・リボルバー(裏)|25|10| +|VICTORIA|17|10| +|EkiBEN2000|19|10| +|秋竜 ~Shiuryu~(裏)|67|43| +|タイコタイム(裏)|34|4| +|mint tears|5|1 +|Evidence of evil|22|10| +|白鳥の湖(裏)|53|43| +|Purple Rose Fusion|58|29| +|Got more raves?(裏)|64|19| +|旋風ノ舞【天】|2|0| +|タベルナ2000|9|3| +|承認欲Q|55|32| +|紫煌ノ乱|51|6| +|束ね糸|75|58| +|重金属フューギティブ|73|49| +|夜桜謝肉祭(裏)|23|8| +|Abyss of hell(裏)|44|7| +|Doom Noiz|58|18| +|十露盤2000|33|9| +|ウルトラマンX(裏)|58|32| +|Honey Heartbeat ~10 Stars Mix~(裏)|75|42| +|Rotter Tarmination(裏)|84|57| +|Venomous(裏)|57|19| +|ギガンティックO. T. N(裏)|47|23| +|超絶技巧系少女|68|29| +|KAGEKIYO(裏)|103|55| +|FUJIN Rumble|57|10| + +<br/> +<b>感想</b> + +* 交互でやってる曲思ったより更新してない +* ヴァナースでやってる曲のほうが全体的に上手い +* やっぱり僕は旧筐体老害ヴァナースドンだーだ! + +まだまだいろいろな目標が残っていますが、再来週あたりでポップンに戻る予定です。残った目標は次のバージョンに(^_^;) + +<br /> +<hr /> +<br /> + +#### 番外 + +ここで少し、僕が来日したきっかけを書きたいと思います。大学1年生のころ友人から太鼓の達人を勧められてから、どんちゃんの顔を叩き続ける人生を送り始めました。PSPでのdxバージョンを始め、アーケード12アジア版、3DS、WiiU...いろんなプラットフォームでやり込んでいました。 + +**しかし、中国での太鼓の達人のアーケードは、11と12のアジア版(通称11亜と12亜)しか稼働されていません(現在形)。**12亜が2009年で稼働されて、その後バージョンのアプデに関する情報は一切ありません。つまり、今(2017年)は中国でできるのは、12亜までです。(厳密に言うと魔法を使って13と14を稼働したところもありますが、さすがに魔法にも限界があって新筐体はできません) + +一方、家庭用の方もずっと新作が出ていて、こちらは中国のドンだーでもプレイできるですが、やっぱり家庭用だけでは物足りないです。みんなはボタンの達人とタッチの達人より、太鼓の達人になりたいからです。僕もそのうちの一人でした。笑い話になるかもしれませんが、一番重症な時は何度も新筐体をプレイしている夢を見て、コインを入れて、曲を選んで、腕を振るおうとする時に、目が覚めましたwけど、そんな僕は、運良く大学4年生になると同時に、日本に来るチャンスを見つけました。そして今は日本に居るわけです。(日本に来てから、ポップンミュージックをハマって太鼓を疎かにしたのは、後の話でした) \ No newline at end of file diff --git a/_posts/2017-11-25-mtc.md b/_posts/2017-11-25-mtc.md new file mode 100644 index 00000000..c7f2c7cd --- /dev/null +++ b/_posts/2017-11-25-mtc.md @@ -0,0 +1,29 @@ +--- +layout: post +title: "Mahjong Tiles Converter → MTC" +date: 2017-11-25 +category: blog +tags: [麻雀,プログラミング] +description: "麻雀牌テキストをHTMLに変換するツールを作りました" +--- + +[Mahjong Tiles Converterのリンク](http://ssdh233.me/mtc/#/) + +### 紹介 +[README](https://github.com/matsumatsu233/mtc/blob/master/README.jp.md)に参照してください。 + +### きっかけ +ゲンマ(現代麻雀技術論)の中国語訳を進んでいた時、このようなウェブサイトは、大量な麻雀牌をHTMLで表示する必要があることに気づきました。HTMLでの画像の表示は、だいたい + +`<img src="http://foo.com/bar.png">` + +のように記述しています。それを何十回、ひょっとしたら百回以上に書くのは、非常に面倒くさいことです。翻訳自体は面白いからやっているのですが、こんな大量なコピペ+細かい変更作業を手動でやると考えると、うっとうしいです。 + +というわけで、このMahjong Tiles Converter(以下MTC)を作りいたしました。MTCのちょっと前に[Mahjong Pai Converter](http://ssdh233.me/mahjong-pai-converter/)というものも作ってましたけど、最近jQuery書くのが嫌になっちゃって、全部React.jsで書き直して、このMTCを作りました:p + +### 最後に + +MTCについて何かご要望がありましたら、コメントしてください。 + +If you have any suggestions or questions about Mahjong Tiles Converter(MTC), please leave a message here. + diff --git a/_posts/2018-01-01-new-year.md b/_posts/2018-01-01-new-year.md new file mode 100644 index 00000000..5cf4f505 --- /dev/null +++ b/_posts/2018-01-01-new-year.md @@ -0,0 +1,57 @@ +--- +layout: post +title: "2018" +date: 2018-01-01 +category: blog +tags: [日記] +description: "あけおめ" +--- + +特に何も書くこともないですけど、年が変わって何か書けなければいけない気持ちになって、とりあえずSublime textを開けました。何を書いていこうかな・・・とりあえず2017年振り返ってみましょう。 + +### プログラミング + +一番に力入れたのは、自分のための単語覚えソフト(名付けてWordBook)でした。`git ls-files| xargs wc -l`で数えてみたら、なんと5000行を超えました。たまげたなぁ・・・ここだけの話、何回も会社のワーキングタイムでこっそり書いてしまった(汗)展示もしてみたかったですが、portappに全てのページを入れるのが面倒くさくて結局やめちゃいました。 + +あとは[麻雀牌のやつ](http://ssdh233.me/blog/2017/11/25/mtc.html)ですね。ゲンマの翻訳にかなり役に立っていますが、自分以外には需要がなさそうでちょっと残念でした。麻雀のブログを書いている方がいらっしゃったら是非是非使ってみたくださいね!(誰もいないのに勝手に宣伝を始める) + +今年あまり開発していない[gsv.fun](http://gsv.fun)は、新作の稼働と共にユーザーが激増しました。ドメイン名を短くしたのは大きかったですかね。ぼく自分も、最近ドラム復帰してから、他人のスキル帳を参考にしたり、自分の成長を記録したりしてます(^ ^) + +### 音ゲー + +まず音ゲーの成長をまとめてみます。ワクワク + +* ポップン:50新規クリア2、EX平均94.5k -> 96k、未フルコン602 -> 448 +* 太鼓:十段->玄人、CS復帰 +* djmax:はじめました 6B最高S14、8B最高S12 +* ドラマニ:tbreとmatixxで二回赤ネ奪還 + +ポップンのクレ数は昨年の四分の三くらいで、その分を太鼓に分けたという感じでしたね。去年は来年社会人になったらゲームの時間が少なくなるじゃないかと心配してましたが、会社のおかげでプライベートの時間を確保できました。これからも定時退社してゲーセンへGO!マンとして頑張っていきます。 + +今一番楽しんでいるドラマニですが、膝の具合が急に悪くなって、最近頻繁に外科さんにお世話になっています。なんだか怪我したスポーツ選手の気持ちを味わったようですね(苦笑) + +そろそろ新しい音ゲーを始めるのをやめよう・・・と思った途端、けいおんの音ゲー(PSP用)を購入してしまった・・・ミニゲームだと考えればセーフ!ミニゲーム! + +### ゲーム(ハード) + +音ゲー以外には、シューティングは東方をちょっとやったくらいで、格ゲーもすこしかじりました。ブレイブルーというゲームなんですが、ランマチ全く勝てませんでした。段位の近い人とマッチングしても勝てません。最初はみんな強いなぁとと思いましたが、あとで情報見たら当たってるプレイヤーは他のキャラで20段とかのような方ばかりでした。道理で勝てませんでしたね・・・ + +始めてばかりで挫折しましたが、ここでやめたら格好悪いので、腕を磨いてからランマチに出直します。ボコボコのフルコンボしてやるんですよ待ってください!(と言っても最近モチベちょっと・・・) + +天鳳は約2、3ヶ月再開して頑張ってみましたが、六段止まりでした。このゲームの一番難しいところは、僕は時間だと考えています。一半荘やるのに平均40分くらいかかりますから、自分のようなマルチプレイヤーには厳しいです(´;ω;`)鳳卓行きたいので、また気が向いたら頑張ります。 + +あと最近(というか昨日)友人がぷよテトをやっているところ見たら、やりたくなっちゃいました。スイッチ買おうかな・・・(おっと、いけないいけない) + +### ゲーム(ソフト) + +**ホワイトアルバム2最高でした。** + +ストーリーも然ることながら、言葉の使い方というか、日本語の表現も美しい。あくまで外国人としての感想ですが、これは国語の教科書に載せても違和感がないんじゃないかと思いました。まあ対話が多いので外国人向けの日本語教科書の方が相応しいですかね。自分が日本語を学んだ時使った「標準日本語」っていう教科書、対話の表現が少し硬くて、不自然と言うほどではないですが(少なくとも僕の書いたものより遥かにいい)、なんていうか、美しさが足りないですね。 + +FLOWERSも完結を迎えましたが、正直ストーリーの展開にはあまり納得できなかったです。けど世界観とかキャラ設定とか雰囲気とかは相変わらず美しく、何よりさから始まる某女性声優さんのボイスいっぱい聞こえて満足です。女性声優という世間(のコエブタ)に幸せをもたらす存在なんて素晴らしい! + +あとは閃の軌跡III、世間から酷評を受けているようですが、個人的にはまあまあよかった作品だと思いました。みから始まる某女性声優さんの出場が多いところとか、昔のキャラクターがいっぱい出てきてるところとか、いいことばかりじゃないですか(^\_^;) + +### 最後に + +2018年はもっといろんなジャンルのゲーム頑張ります! \ No newline at end of file diff --git a/_posts/2019-02-11-english.md b/_posts/2019-02-11-english.md new file mode 100644 index 00000000..93583e21 --- /dev/null +++ b/_posts/2019-02-11-english.md @@ -0,0 +1,72 @@ +--- +layout: post +title: "英語をはじめました" +date: 2019-02-11 +category: blog +tags: [語学, 日記] +description: "Why does English have so many words that mean the same damn thing?" +--- + +みなさんこんにちは!一人も来ないのに(ソース:Google Analytics)いきなりまるで訪客が沢山いるような挨拶をするまつまつでございます。 + +旧暦と新暦ともに2019年になりましたね。初詣も爆竹もやってないのに勝手に2019年になりましたね。というわけで今年もよろしくお願いしますm(__)m(ところで今年の[BiliBiliの拜年祭](https://www.bilibili.com/blackboard/bnj2019.html)がとても良かったので中国語の分かる方がいらっしゃったらぜひおすすめしたいと思います。~~誰も来ないけど~~) + +### 英語の勉強を始めた + +人間は年が変わると何か新しいことをしたくなる生き物です。その人間の一人である私は今年英語を始めることにしました。もちろん、学校で英語の授業を受けてましたので(それ以外にも英語試験とか仕事とかよく勉強~~させられ~~しました)、ゼロから始める英語勉強というわけではありません。 + +今まではただ試験のためにやってきました。十年間以上を勉強し続けてもまともに人と話せないままですけど、試験は全部低空飛行(説明しよう、「低空飛行」とは、試験などをぎりぎり通った時に使う中国語のスラングである)しましたので、勉強の方向性が間違ったとは思っていません。ただし、試験だけのために一つの言語を十年間以上勉強~~させられ~~して、その後どんどん廃れていくと思うと、あんまりにももったいないです。というわけで、今まで培った「会話を理解しなくても答えはなんとなく当てられる!読解は問題を読んでから文章を読む!TOEFLのSpeakingは大体お金を言い訳にできる!Writingの最後の段落はAs far as I knowから始めよう!」程度の英語力を人生に還元していきたいと思います。 + +### 目標 + +英語と言っても、日常会話の時使う英語と専門の本を読む時使う英語が全く違いますので、今後どういう風に英語を使いたいかによって勉強すべき領域も変わります。例えば、一般的に世間に言う外国人の「○○語が上手い」というのは、ほとんど○○語を使って日常会話をする能力が高いことを指しています。そういう「上手い」人は、本が全く読めなかったり、文法がごちゃごちゃだったり、そもそも単語のスペリングができなかったりします。逆に、多くの中国と日本の海外経験のない学生は、文法と単語をたくさん覚えても、会話力にほとんど繋がらずスムーズに話せないケースも多いです。そんなわけで、勉強の内容を決める前に一度目標を明確することが大事だと思います。 + +**High Priority** ++ 作品を楽しめる程度 + + H1.1【聴】アニメ:RWBYとか + + H1.2【読】ゲーム:World of Warcraft、他の英語圏のRPG ++ H2【書】ツイッターで呟ける程度 + +**Low Priority** ++ L1【読】小説を読める程度 ++ CS/Frontend関連の知識を獲得できる程度 + + L2.1【読】ウェブ上の情報、論文とか + + L2.2【聴】カンファレンスの動画 ++ L3【話、聴】人と日常会話できる程度 + +まとめると、読みと聴きはいろんな(今の所ほとんどファンタジー)作品を楽しむことが目標で、高いところへ目指しています。書きは比較的に低く、ツイッターでbullshitを書けるくらいで満足です。話しは特に頑張る必要がなく、ついでに上手くなったらいいなぁくらいの気持ちです。 + +### やっていること + +今年になってからもう一ヶ月ちょい経ったので、色んなことを試みてきました。やっていることの概要や、目標各項目への効果を書きます。効果は1~5の5段階で評価させていただいております。 + +| やっていること | H1.1<br/>RWBY | H1.2<br/>WOW | H2<br/>Twitter | L1<br/>小説 | L2.1<br/>CS読 | L2.2<br/>CS聴 | L3<br/>日常 | +|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|--------------|----------------|-----------|--------------|--------------|-----------| +| [Grammer In Use](https://www.amazon.co.jp/Grammar-Intermediate-Students-Answers-Interactive/dp/1108617611/ref=sr_1_16?ie=UTF8&qid=1549973732&sr=8-16&keywords=grammer+in+use)<br/>一部のチャプターだけ | | | 3 | | | | 3 | +| [American Accent Training](https://www.amazon.co.jp/American-Accent-Training-Downloadable-Traning/dp/1438010354/ref=sr_1_1?ie=UTF8&qid=1549975180&sr=8-1&keywords=american+accent+training)<br/>主に朗読用。内容自体はそんなに役に立たないと思います | 2 | | | | | | 3 | +| Drama: The Big Bang Theory <br/>Sheldon何言ってるか全く分からん。Pennyも理解してないようで大丈夫でしょう | 3 | | | | | 2 | 3 | +| Youtube: [Fujima Sakura](https://www.youtube.com/channel/UCwalpGCurSDqwSpkAR4h6LA/videos) & [Natsumi Moe](https://www.youtube.com/user/TheOtakuMoe/videos)<br/>英語のVtuber美少女が足りない!!! | 2 | | | | | 2 | 3 | +| Youtube: [Katsura Sunshine](https://www.youtube.com/watch?v=7fANWNer-rk&list=PLiIVDpqyhxHQAlr6IfnXvFk_tvr0FJQAD) <br/>英語の落語家。話すスピードが早いが内容がとても分かりやすい | 2 | | | | | 3 | 3 | +| Reading: [Tuck Everlasting](https://www.amazon.co.jp/Tuck-Everlasting-Natalie-Babbitt/dp/0312369816/ref=sr_1_1?ie=UTF8&qid=1549978034&sr=8-1&keywords=tuck+everlasting) | | 4 | | 5 | 1 | | | +| Twitter: Stalking <br/> アイドルのツイッターを一字一句、言葉遣いと文法を緻密に研究しているだけ。決して犯罪者ではない | | 1 | 4 | 1 | | | | +| Twitter: Tweet bullshits <br/> 日常呟く | | | 5 | | | | | +| Reading: Front-end related <br/> 会社での暇つぶし | | 1 | | | 5 | | | +| Youtube: Jsconf <br/> 会社での暇つぶし | 1 | | | | | 5 | 3 | + +ところで、上のやっていることの全ては、新しい単語が出た時コンテクスト含めてEudic(中国の辞書?アプリ)に登録して、次の日から復習しています。通勤時間とゲームの待ち時間とか<font color="white">(仕事のサボり時間)</font>のtime confettiを使ってやっています。 + +**H1.1【聴】アニメ:RWBYとか** + +一番方法を悩んでいます。今のレベルでアニメを見ると苦行でしかないので、比較的に興味のない体裁(ドラマ、Youtube)の作品で聴解力を鍛えています。遠回りしている気が否めませんが、英語の場合は日本語と違って**良質なアニメが圧倒的に少ないので**(実はRWBY以外全く知らない...)、そうするしかない気がします。いっそ好きなドラマとかできたらそれに越したことはありませんが、ただ頑固なオタクなのでどうして生身の人間の演じるものに抵抗が... + +**H1.2【読】ゲーム:World of Warcraft、他の英語圏のRPG** + +こちらは簡単です。Brute-forceです。山ほどの単語を覚えればなんとかなるはずです。ただし、アニメと同じように、英語はアドベンチャーゲーム(Visual novel)みたいな優秀な語学ゲームが少なく、RPGの場合ポーズできなかったりポーズするとセリフが消えたりしますので、ゲームを決める前に事前にシステムを調査する必要があります。幸い、なぜか小説とゲームで使う言葉の共通しているところが大きいので(多分同じ書き言葉だから)、しばらくはいろんな小説で語彙力を上げるつもりです。(小説も割と面白い(ただし英語の単語が多すぎる(Why does English have so many words that mean the same damn thing? + +**H2【書】ツイッターで呟ける程度** + +こちらは比較的に順調で、この一ヶ月にそれなりの上達を感じていました。ただ興味のあるアカウントが少なくて、もっとツイッターで探すか他のSNS/Forumに移るか、どちらにしてもそろそろ次のステップを考えないといけませんね。あと自分で呟く時、口が悪すぎると(仕事の文句とか)自分の精神状態へのダメージが大きく発生するので、これからネガティブな呟きはself-deprecation縛りでやります。<font color="white">(正直そもそも仕事はお金を稼ぐ手段くらいしか思っていないし嫌なことあってもなくても給料は変わらないのでツイッターに取り立てるとそれを見てる自分の気分が悪くなるだけ(まさにブーメラン</font> + +### 終わりに + +これから一ヶ月ごとに、目標を見直したりやっていることを調整したりしていこうと思います。おっと、そろそろ単語を覚えに行かないと... diff --git a/_posts/2019-07-25-hakason.md b/_posts/2019-07-25-hakason.md new file mode 100644 index 00000000..164a4a1c --- /dev/null +++ b/_posts/2019-07-25-hakason.md @@ -0,0 +1,40 @@ +--- +layout: post +title: "ひとりハッカソンチャレンジ" +date: 2019-07-25 +category: blog +tags: [ゲーセン, 音ゲー, プログラミング] +description: "ゼロからリリースまで" +--- + +### きっかけ +先日一身上の都合で京都のゲーセン状況を調べようとしました。どこにゲーセンがあるか、どれくらいあるか、それぞれのゲーセンに自分のやりたい機種が入っているのかなどの疑問を抱えつつ、博識なグーグル先生に尋ねました。さすがのグーグル先生、"ポップン 設置店舗"で検索したら有意義な結果がたくさん出てきました。その中で +* コナミの公式サイト [pop'n music 設置店舗検索](https://p.eagate.573.jp/game/facility/search/p/index.html?gkey=PMSP) +* (結果に出てないが[ポップンの公式サイト](https://p.eagate.573.jp/game/popn/peace/p/tenpo/index.html)にもいろいろ載せています。~~SEOを怠ったのでしょう~~) +* [ぽぷどこ Dream](http://popdoko.net/) +* [設置店舗 - pop'n music@wiki - アットウィキ](https://www44.atwiki.jp/popn-music/pages/100.html) + +などが挙げられます。 + +しかし、これらのサイトを眺めると、自分にとって一つ致命的な問題がありました。 + +<strong>地名が分からん!</strong> + +一つ一つグーグルマップで調べればいいんですが、どうにも気が進まない。自分の場合、ポップンを始め太鼓、ギタドラ、DDRなどいろいろやっているので、全部調べようとすると日が落ちってしまう(執筆時間:23:40)。逆にグーグルマップで"ゲーセン"を検索する手もありますが、そうすると機種が分かりませんので、上のサイトと上手く連携して使えば、手間がぎりぎり許容範囲内に収まります。けどやはり面倒くさい。 + +なので、<strong>地図上でゲーセンを表示して、機種絞り込み検索できるものがあればいいなぁと思った</strong>。想像してみましょう。地図を眺めてどこにゲーセンがあるのかが分かる、そのゲーセンにどの機種が入ってるのかも分かる、なんか面白くないですか?~~僕はそのような地図があれば一日中に地図を眺めるだけで過ごせる自信がある。~~ + +### ハッカソン +> ハッカソンとはソフトウェア開発分野のプログラマやグラフィックデザイナー、ユーザインタフェース設計者、プロジェクトマネージャらが集中的に作業をするソフトウェア関連プロジェクトのイベントである。 + +最近ウェブアプリ作る新鮮味が低下してきたので、なにかチャレンジをしてみようと思った結果がこれです。ゼロから始めるつもりですが、近日我慢できず頭の中でシステムをデザインしたり簡単な<abbr>POC</abbr>(唐突なabbrタグアピール)をしたりしましたけど、でも本番までまだほど遠いのでいいとしましょう。 + +### ルールなど +* 時間は金曜日退社してから、月曜日出社するまで +* 段階ごとに進捗をまとめる。ツイートするかも +* ご飯は食べる、睡眠も取る、Fateも少しやる。他の時間はひとりハッカソンに尽力 +* 目標はリリースするまで(最初のリリースはどこまでやるのかはひとりハッカソンの中で決める) +* 終わったら後日で反省する +* ハッカソンは成功したにせよ失敗したにせよこのプロジェクトは価値ある限り続けると思っている + +というわけで、明日から頑張ります。 \ No newline at end of file diff --git a/_posts/2020-12-01-popn-01.md b/_posts/2020-12-01-popn-01.md new file mode 100644 index 00000000..2ecf9a43 --- /dev/null +++ b/_posts/2020-12-01-popn-01.md @@ -0,0 +1,162 @@ +--- +layout: post +title: "ポップン奮闘記 其の壱" +date: 2020-11-01 +category: blog +tags: [音ゲー, ポップン] +description: "そろそろ本気を出す" +--- + +### 近況 + +お久しぶりです。まつまつです。 + +ブログを始めてから四年くらい経ったが、ようやく自分の人生の主軸にあるポップンミュージックというゲームについて記事を書くことを決めた。 + +私は2014年7月に日本に来たけど、日本での初めての住所は、なぜか高田馬場BIGBOXから徒歩5分くらいのところにあった。これはもはや運命を感じる。その運命に従って翌日から充実なポップンライフを過ごし始めた。(たしかにラピストリア稼働したばかりの頃だった) + +実は日本に来たのはもともと音ゲーのためだったけど、その頃はポップンと太鼓の達人がメインで、その他色々も触る程度だった。高田馬場という場所でなぜポップンの運命を感じたかというと、そこはポップンできる場所が3つ(BB、BB の下にあったゲーセン、ミカドの旧筐体)あった上に、100 円/1 プレイの太鼓がなかったのだ。つまり、ポップンするしかねぇ! + +というわけで、来日した翌日から今日まで、ずっと大きな9つのボタンを叩いてきた。たまに2、3月程度ほかのゲームに浮気(~~なぜか浮気を打つと予測変換に浮気攻めが出るけど、だいたい[この人](https://www.youtube.com/channel/UCwokZsOK_uEre70XayaFnzA)のせい~~)したりするけど、ポップンを全くやってない期間はなかったのだ。 + +去年の年末から今年の先月まで、WOW のアリーナというゲームで今まで最大の浮気をしてしまったけど、子供のころの夢を叶えるためだから仕方がない。新型コロナウイルスの影響もあって、外に出るのが億劫だった。 + +[その夢を無事叶えたところで](https://twitter.com/ssdh233/status/1274326784608071682)、自分の人生プランを見直した。人生はいつ何が起こるか分からないものだから、正直のところ自分がいつまで日本にいられるかもまったく見当がつかない。一生日本に居続ける可能性もあれば、数年後中国に戻る可能性もある。もしいつか中国に戻るのなら、日本での生活に悔いを残したくない。 + +自分は今までたくさんのゲームをやってきて、これからもたくさんのゲームをやっていくつもりだが、その中唯一日本でしかできないジャンルは、アーケードの音ゲーだ。つまり、ポップンするしかねぇ! + +というわけで、11 月からポップンに復帰した。今度は**全埋めするまで絶対に浮気しない**と決めた。ウワキ、ダメ、ゼッタイ + +もちのろんだが、このご時世では外出するにはとてもリスクが高い。自分の対策としては + +* マスク +* 外で手で口、鼻や眼など触らない +* ゲーム後は手洗い15秒(アルコール消毒液) +* ドアノブは手で直接触らない(肘とか) +* 外着は家に帰ったらベランダに干す。洗濯するときは界面活性剤を使う + +### リハビリ & 最近の進捗 + +ポップンを本気にやるのはおよそ一年ぶりなので、いきなり昔のスコア更新とか新規クリア狙いすると、一瞬で心が折れるだろう。 + +こんなに放置したのは初めてだったので、リハビリの内容を真剣に考えてみた。その結果はこちら: + +<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">リハビリビンゴ作りました <a href="https://t.co/xnLIFpfpON">pic.twitter.com/xnLIFpfpON</a></p>— まつまつ (@ssdh233) <a href="https://twitter.com/ssdh233/status/1324722190919479296?ref_src=twsrc%5Etfw">November 6, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> + +49の最上位の曲たちと昔クリア済みの50たちを集めて、ビンゴを作った。名付けてリハビリビンゴ。正規、鏡両方入れてまさに一粒で二度おいしい。 + +ど真ん中にある「4 時間ポップンやり続ける」のは、自分の前から抱えている、体力不足への対策。49↑ の曲を 1-2 時間連奏すると、いつも腕がへとへとになって、クリアもスコアも狙えなくなっておうちに帰るしかない羽目になってしまうのだ。このままだと今まで以上のスピードで上達するのは不可能だと認識しているため、真っ先にこれを解決して 49↑ の上位曲陣を何時間も連奏できるようになりたい。 + +11月中にかなり順調に進んで、今はトイコン正規、HYMN正規、ふるっぱー鏡と真ん中の4 時間ポップン以外は全部埋めた。やっぱり高難易度を中心に回すことが功を奏したか、今は正規鏡に関しては全盛期くらいの地力に戻った。その証拠に、 + +![ポプクロ](https://pbs.twimg.com/media/EnrJxsCUwAo63vx?format=jpg&name=small) + +すごく嬉しいリザルト + +![pp](https://pbs.twimg.com/media/EnrPRoFVQAAt3eM?format=jpg&name=small) + +とちょっと悲しいリザルト + +![サイレント](https://pbs.twimg.com/media/Em8tSqKVQAEApeu?format=jpg&name=small) + +とかなり悲しいリザルト + +が出たり。 + + +### 今の地力 + +これから(リハビリビンゴ埋めてから)何をやっていくかについてお話したいが、その前に一度今の地力をいろんな角度から評価する。 + +<table> + <tr><td>項目</td><td>今</td></tr> + <tr> + <td>未クリア</td> + <td>サイレント<br/>L-an!ma<br/>Chaos:Q<br/>o†o<br/>25 o’clock the WORLD<br/>perditus†paradisus(UPPER)<br/>Popperz Chronicle(UPPER)</td> + </tr> + <tr> + <td>銅菱、銅星</td> + <td>50以外は基本銅菱以上(クラ8,9,ヘビメタ以外)<br/>49銅星 17/59<br/>48銅星 88/104<br/>47以下基本銅星</td> + </tr> + <tr> + <td>フルコン</td> + <td>49,50: なし<br/>48: 6/103<br/>47: 46/161<br/>46: 128/184</td> + </tr> + <tr> + <td>ポックラ</td> + <td>98.90</td> + </tr> + <tr> + <td>ランダム</td> + <td>全盛期はニエンテ勝率2、3割くらい<br/>50乱クリアはカウボーイのみ<br/>トイコンとムラクモはイージーでできる</td> + </tr> + <tr> + <td>s乱</td> + <td>全盛期は14ほぼ全埋め、15三割くらい</td> + </tr> + <tr> + <td>ソフラン</td> + <td>基本苦手の方。L-an!maと25時の低速できない<br/>半速(hs360)最高48</td> + </tr> + <tr> + <td>スコア力</td> + <td>最近あんまり意識していないが一応<br/>98k以上: 300曲くらい<br/>99k以上: 50曲くらい</td> + </tr> + <tr> + <td>発狂PMS</td> + <td>●9数曲ハード<br/>●10数曲ノーマル</td> + </tr> +</table> + +### なにをやるか +まずは埋めていない曲の属性を分析して、自分の足りないところを考えて、それを埋めていく感じで練習の方向を決めていきたい。 + +曲| 苦手要素 +--|-- +サイレント|産卵の安定性、ラストあんみつでのごまかし +L-an!ma|隣接、低速、同時押し地帯、発狂 +perditus†paradisus(UPPER)|体力、ラストまでの回復、ラスト発狂 +25 o’clock the WORLD|低速、LP地帯 +Popperz Chronicle(UPPER)|Chaos:Q地帯の譜面暗記、サイレントの産卵、L-an!maの発狂、oto地帯 +Chaos:Q|サドプラつけ外しの安定性、低速 +o†o|ラストまでの安定性、ラストの縦連発狂 + +まとめると、 +* ポプクロU音Qを挑戦するには地力が圧倒的に足りない +* サイ(黒星)、L-an!ma(半分)、25時(半分)、ppU(黒菱)はハマれば行けるかもしれないけど、今すぐ特攻せずに地力上げつつたまにトライしたほうが無難 +* 低速力が圧倒的に足りない +* 曲によってある程度のあんみつ、サドプラのつけ外しなどの技術も必要だけど、今のところそれがネックでクリアできない曲がないので、あんまり考えないでおく +* otoの縦連でハンドスピード(特に左手)とかの対策が必要かもしれないけど、挑戦段階になったらまた考える + +#### 1. 48~50のメダル狙いと罰減らし +具体的に、未クリアの50はもちろん、 +1. 49正規、鏡の罰減らしと銅星狙い +2. 銅菱埋め(50とクラ8,クラ9,ヘビメタ) +3. イージー全埋め(Chaos:QとポプクロU) +4. 48のフルコン狙いと銅星埋め +などなどを中心にやっていこうと思う。 + +49〜50メインでやりたいので、49〜50はなるべく正規鏡両方をやりこむ。できなかったところの押し方を検討したり、ハイスピの調整したりするなど、いろいろ対策を考えながらやっていく。 + +ただし、高難易度曲が増えた今でも、49↑のメダルがなかなか動かないので、メダルと別に最小罰数を自分で記録する(下図)。 + +![49badcount]({{ site.url }}/assets/2020-12-01-popn-01/49badcount.png) + +#### 2. 発狂PMS +先月ようやくおうちでPMS環境を整えたので、地力上げに活用していきたい。 + +今のところでは●9数曲ハード、●10数曲ノーマルくらいだけど、数を増やしつつ最高ノーマル・ハードレベルを狙っていきたい。発狂段位もそのうち受けてみたい。(今は発狂七段4曲目落ち) + +#### 3. 乱とs乱について +乱は腕慣らし程度でたまにやるけど、s乱は今のところやる予定がない。とりあえず正規系のみで地力上げを試みる。 + +#### 4. 低速対策 +48の半速埋めをやったり、49の半速初クリアを狙ったり。そのほかに、(サドプラのできない)ソフラン曲を積極的に選曲して、苦手意識を克服していきたい。どっちも気が向いたらやる程度だが、低速がネックでクリアできない曲と向かい合う時は頻度をあげるかもしれない。 + +#### 5. その他 +もちろん、ゲームは楽しくやるもの。ポップンをするすべての時間を「上達」に割けるつもりはない。47以下のスコア、フルコンなども狙ったり、ただただ曲を聞きたいだけの選曲したりする。 + +### 最後に +11月にポップンに復帰してから、(ポップン界隈での)目まぐるしい出来事に追われる日々を送っている。Lively正式版のリリースと新しいコントローラーの発売決定はもちろん(どっちも購入済み)、MADSPEEAD狂信道とperditus†paradisusのアッパー譜面も議論を引き起こしている。私が作った[ポックラのスクリプト](https://twitter.com/ssdh233/status/1327288525473996802)もぷちバズしたけど、またの機会でお話できれば。 + +この奮闘記は月1ペースで書きたいと思っていて、今回が初回だからすごく長文になったけど、これからは成果のまとめと練習内容の見直しなどを中心に、なるべく短くまとめようと思う。では、また来月。 \ No newline at end of file diff --git a/_posts/2021-01-01-2020.md b/_posts/2021-01-01-2020.md new file mode 100644 index 00000000..cc698ee0 --- /dev/null +++ b/_posts/2021-01-01-2020.md @@ -0,0 +1,67 @@ +--- +layout: post +title: "2020 -> 2021" +date: 2021-01-01 +category: blog +tags: [日記, 中文, wow] +description: "流水账" +--- + +2019年8月魔兽怀旧服上线之后旷工玩了几天,突然发现自己还有一个远古的未曾实现的任务:在魔兽世界pvp的最高峰3v3竞技场中到达一个令自己满意的高度。以前的目标只是安定2200+,现在重新审视了一下新的匹配机制和奖励,发现角斗士(达到2400并且有50胜场)刚好可以作为一个新的目标。于是围绕着魔兽竞技场的2020年开始了... + +#### 1月 +* bfa s3结束,结束前拿到3s2200成就。bfa s4正式开始 +* popn还有ニエ乱连续3次过关的地力 + +#### 2月 +* 基本已经没有在打popn了,被popperz chronicle痛扁 +* 新赛季2s到达2200 +* 新冠开始了... + +#### 3月 +* 2s到达2300。小号戒律牧的2s到达1800 +* 因为新冠放弃了出门,popn暂停 +* 购买了健身环大冒险 + +#### 4月 +* 2s到达2400,小号术士也2400了。3s新赛季首次到达2200 +* type racer到达wpm 80(mega racer) + +#### 5月 +* 好像什么都没有发生 +* 拿popn手台接djmax打了几把之后觉得不是很好玩... + +#### 6月 +* 3s首次到达2400!并且取得了角斗士!最高2500(术元骑) +* 开始稍微回归popn + +#### 7月 +* 3s和日本的朋友也拿到了角斗士(战术僧) +* 3s最高到达2600(术元骑) +* 小号火法,贼法2s达到2000,3s达到2100 +* 发现了マクロスF这个神作 + +#### 8月 +* 开始关注nijisanji,主要爱好是看委员长玩galgame +* 2s到达2500,火法3s到达2200 +* 使用正统的黑科技在手机上玩白色相簿2 +* 发现了マクロスΔ这个神作 + +#### 9月 +* 3s到达2700!竞技场全成就解锁(术元德) +* 小号火法3s到达2400 +* 购入ps3并使用正统的黑科技在手机上玩白色相簿1 + +#### 10月 +* 3s到达2800!(术元德) +* djmax开始复健并达到了8B未S20左右的水平 + +#### 11月 +* 正式回归popn + +#### 12月 +* 继续popn的同时开始备战wow新赛季,大概这次是最后一个赛季了 + +2021年的目标,popn就先不提了,会在ポップン奮闘記中持续追踪。竞技场希望能在新赛季1-2个月完成目标(痛苦2s 2400&glad。maybe: 火法glad,毁灭glad。)后成功隐退。但是当前局势下想出门玩popn是比较困难,不知道窝在家里打pms可以坚持多久,还是尽量努力吧。 + +哦对了,还有个比较重要的事情就是明年要换一家公司工作了,之前的工作总感觉是在trolling。虽然工作上没有什么目标,那样也没什么不好的,不过拜新冠所赐现在在家就可以完成所有转职手续,所以就趁机换了一个。。 \ No newline at end of file diff --git a/_posts/2021-06-20-espgaluda2 .md b/_posts/2021-06-20-espgaluda2 .md new file mode 100644 index 00000000..35024519 --- /dev/null +++ b/_posts/2021-06-20-espgaluda2 .md @@ -0,0 +1,27 @@ +--- +layout: post +title: "Espgaluda II" +date: 2021-06-20 +category: blog +tags: [STG,ゲーム感想, 中文] +description: "(五年前から)ずっとこの時を待っていた・・・" +--- + +大概五年前在想下个要通的STG是啥的时候就决定是这个了,然后一拖就是五年。。。 + +最近想打STG的契机是差不多新冠也改好转了,魔兽竞技场是时候该永远afk了。打算找个游戏转一下注意力帮助afk(怎么感觉跟戒毒一样。。),正好听说东方出新作了,就去玩了下虹龙洞,捡回了些对STG的激情,于是就掏出了积灰已久的xbox360和摇杆开搞。<span style="color:white">~~说起来虹龙洞的感想还没谈,玩了快两年的竞技场有空也找个机会骂一下。~~</span> + +wiki标的难度是22,打下来感觉还是比较准的。到通关为止大概玩了6个晚上,每晚2小时左右。这次因为知道比较简单就一直在自己摸索路线,没怎么看攻略,结果都打到最后boss差一厘米了才偶然知道3面有个1UP,翻了下攻略学了下拿法之后就顺利通了。 + +<iframe style="width: 100%; aspect-ratio: 16/11;" src="//player.bilibili.com/player.html?aid=758744959&bvid=BV1564y197GP&cid=357017051&page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe> + +<br/> +对比一下东方虹龙洞那蛋疼的关卡设计,洞洞社还是比较厉害。从混关的角度上看,每关道中和boss的难度设计的都很不错。最终boss的最终形态虽然说是基本要求觉圣(1/2速度)打,但也没有说是有资源就能过,反而会一个不小心判断慢了被封路触发自动雷,然后眼睁睁的看着石头浪费掉,只能对着没什么卵用的半管bomb发楞。 + +目前还意犹未尽,接下来应该还会接着向充满了憎恶的Seseri努力。至于成就。。。看记录发现5年前的我连死笑(无印版)和最大往生的成就都懒得搞全,这个估计也是要歇了。有空可能会打下Black label和Arrange版,虽然估计混起来没啥意义。 + +说起来任天堂E3直面会上说要移植这个,虫姬和大复活。大复活里2以前通了,这个离真Seseri也不是太远了,难道这是暗示我下个该搞虫姬Ultra了?遠い声「君ならできるよ!」我突然想起了573服务器里Chaos:Q上的那盏没亮的灯,默默的把虫姬扔出了购物篮。<span style="color:white">~~好吧其实还有个原因是某个大盒子里有~~</span> + +<hr style="margin: 16px 0" /> + +顺便求助一下,xbox 360 slim有时候会莫名电源键响一下然后自动关机,并且初始化分辨率设置,不知道有没有什么解决方案。Google下好像很多人都有这问题,但是都说是电源线接的不稳或者电压不稳定之类的,感觉不像是我的情况。不过好在只要保持开一会机,机器就会获得"免疫"功能,这之后即使电源键响也不会自动关机了,所以没有出现最终boss差1毫米的时候自动关机的悲剧。 diff --git a/_posts/2021-06-26-arena-byebye.md b/_posts/2021-06-26-arena-byebye.md new file mode 100644 index 00000000..1cfa7c05 --- /dev/null +++ b/_posts/2021-06-26-arena-byebye.md @@ -0,0 +1,57 @@ +--- +layout: post +title: "魔兽世界(竞技场)はなぜ大失敗したのか" +date: 2021-06-26 +category: blog +tags: [wow,ゲーム感想, 中文] +description: "答えは明白である" +--- + +从bfa s3末期到sl s1中期,总共大概玩了一年半左右。在这一年半里体验了在日本公会参加raid,也超额达成了当初角斗士的目标,并且结交了来自地球各地的很多朋友,游戏体验还是不错的。虽然个人在竞技场这条路上还有很多进步的空间,也可以找出比较现实的可以达成的新的目标,不过要是没有什么意外的话,这辈子应该不会再碰这个游戏了。主要原因有二:一是日本的新冠情况好转了不少,机厅可以再开了;二是在这一年半的体验中,我终于认清了暴雪这家公司的真面目:(至少在这一年半中)他们从来没有想过把竞技场做成一个有乐趣,相对公平,游戏体验良好的多人竞技游戏,他们做这个游戏的唯一目的是消耗玩家的时间,让他们珍贵的人生浪费在一群弱智策划用屁股想出来的烂点子上。 + +### 一、毫无乐趣的grinding设计 +和每一个竞技场玩家的游戏体验息息相关的是,把一个角色练到满级并且可以进入竞技场所需要的时间。在理想状态下这个数字应该是0,也就是“打开游戏就能玩”。当然作为一款有等级的MMORPG,向玩家索要一些准备时间也是可以接受的。然而暴雪恨不得每个玩家天天待在家里,每天在他们做的这个垃圾堆里重复劳动!让我们来看一下shadowlands里,维持一个角色到能打竞技场的最佳状态大概需要的时间: + +* 50 - 60: 8-10小时,第二个角色开始大概可以在6小时左右完成。(0-50可以boost解决) +* 维持盟约renown等级:2小时/周 x 10周左右。新角色大概需要5小时才能完成所有任务。 +* Thorgast(爬塔): 3.5小时 + 1小时/周 x 5周左右(根据职业可能需要10-15周) +* the maw日常:个人没做过,不过听说大概30分钟/天,要肝完6孔大概要连续做4-5周,肝完226的导灵器则需要更多。 + +在满级之后,仅仅是维持一个角色到能玩的最佳状态竟然就需要每周5-6小时!这5-6小时可不是玩游戏的时间,放音游/格斗上可以理解成是打剧情,每周打5-6小时剧情!然而竞技场玩家是不可能只有一个角色的,从赛季的中期去练一个号到能玩的程度,大概要付出20-30小时!30个小时,只是为了真正的开始游戏! + +不要着急,上面还没有算“刷装备”这一非常重要的环节。本来这个环节在shadowlands里是可以当成打竞技场的一部分,也就是边玩边解锁的要素。比如刷第一个账号的装备时,可以选择只打竞技场,用获取荣誉和征服点数来更新装备,这样每周虽然需要几个小时来刷满装备,但是这几个小时至少是在玩游戏。然而!当到第二个账号,你的装备落后于大部分玩家的时候,这几个小时就很难说是在玩游戏了,这又是因为暴雪的另一个蛋疼设定(下面会提)。 + +这种感觉放在puyoteto上,那就是你先把剧情给我通个10遍才能开始网战;这要是放在硬核玩家圈子里,早就集体AFK了,也就MMORPG这么搞才能只落得一个被抱怨一下就没事了的下场,毕竟MMORPG的玩家本来就是来浪费时间的。值得一提的是,上一代bfa s4的时候比这稍微还好一点,可以直接boost到满级,虽然之后搞装备要比sl s1麻烦个几倍,不过整体来说负担还是要小一些。也就是说暴雪完完全全没有要削减浪费玩家的时间的念头。 + +有的玩家可能觉得,我升级,做盟约任务,爬塔,做日常,是在体验剧情,也是在玩游戏啊,怎么到你这就成了浪费时间了。好吧,第一个角色我可以理解你是在体验剧情,虽然一般人大概一个小时就觉得烦了。不过做日常就不算体验剧情了吧?重复玩一个毫无挑战性的roguelike也不算体验剧情了吧?从第二个角色开始这种体验过一次之后知道有多么垃圾的剧情也没什么“体验”了吧?事实上大部分人第二个角色都是选择跳过主线去做支线任务升级,甚至是直接花钱找人上号boost。 + +### 二、过大的装备差距 +Shadowlands开始时,暴雪PVP策划莫名其妙的取消了bfa时的[装备缩放设计](https://twitter.com/ckaleiki/status/1041878657701052416)(下面简称scaling),唯一能想到的原因是他们怕玩家骂的不够狠。有scaling的时候,同样是60级的角色,装等180的人和装等200的人打,大概是没有的时候装等185打装等195的感觉,虽然仍然不完全平等,但是可以缩小装备带来的影响,算是一个比较好的设计(虽然暴雪的算法还有很大改进空间)。然而Shadowlands因为属性压缩导致装等间装备差距过大,正是需要scaling来平衡的时候,反而一排屁股取消了,简直是雪上加霜!这主要带来两个问题: + +一、前期PVE玩家可以通过PVE方法来获得更高装等的装备,比如开赛季前两周PVE玩家可以通过刷大秘境来轻松达到200+装等,而PVP玩家只能到190左右。因为没有scaling,这10个装等的差距很难用技术去弥补,极度影响前几周游戏体验。不过好在这点只会影响到前几周,因为之后PVP获得的装备最终会成为最优解。 + +二、非常重要的一点,赛季中期之后,过大的装备差距会极度影响新角色的游戏体验。有多少个新玩家在辛苦把角色练到60级,做盟约任务,拿到橙装之后,满怀期待的进入竞技场,迎面而来的是个4万血以上的角色,自己一通操作之后对面几乎毫发无损,然后被一到两个GCD秒杀。不要说是新玩家,就算是玩了一万场以上的我和我的角斗士朋友组,如果仅仅有刚做完任务后的装备也很难在最低的匹配段保持50%左右的胜率。过大的装备差距下,用太鼓打比方就是,对面要赢就像是打个梅花的牛也牛,没装备的一方不光得全连鬼难度的幽玄之乱,还得期待对面的梅花牛也牛掉个音! + +因为第二点,导致新角色的刷装备也变成了煎熬,大部分玩家都避开竞技场选择评级战场去刷,这个本来可以边玩边刷的部分也被暴雪无情的变成了grinding。本来在Shaodowlands,PVP装备的获取可以是一个很大的改善,即使获取一件装备需要的货币(荣誉/征服点数)相对较多,只要缩小装等带来差距,玩家就可以心甘情愿的边练竞技场边刷,然而暴雪怎么可能让玩家吃到甜头! + +### 三、没有诚意的职业平衡调整 +暴雪似乎从7.0开始,就犯了每个版本不加个新系统都不好意思发布的毛病。9.0作为一个大版本,各个职业的数值调整,旧技能回归,新的导灵器/橙装效果势必会给竞技场的玩法和平衡性带来很大变化。而且为了加快游戏节奏,9.0把各职业血量调低,技能伤害数值调高。这些改动都没有什么问题,甚至可以说是往好的方向发展,只要后续平衡调整跟上,只要后续平衡调整跟上。。。 + +从这个出名的Wowishard的视频[WowItsHard - YouTube](https://www.youtube.com/c/WowItsHard/videos)里就可以看出赛季初期的强势职业有多么离谱,这个视频可以说是毫不夸张。然而暴雪当时砍了敏锐贼之后就没了动静!超模的SSS tier的火法和奶骑,脸好可以0.1秒秒人的鸟德直到awc比赛之后才开始有了一些调整;然而更多的在awc没有展现出来的问题,比如各个复合职业离谱的off heal数值,比如很多没有存在意义的弱势专精,比如防骑的存在,比如战士的援护...对战游戏自然是不可能追求每个角色的绝对平衡,不过从暴雪的平衡调整速度和新要素追加速度上来看,指望这个游戏能有相对“不是那么离谱”的平衡性,这辈子是不可能了。 + +### 四、看不到改善的游戏体验 +在竞技场中,几乎每一个玩家都要用Gladius/Omnibar/Bigdebuffs/flyplatebuffs等插件来显示重要的信息(甚至声音提示插件)。如果没有这些插件,很容易错过重要的信息,导致在游戏中无法做出及时的判断。然而暴雪几乎从来没有想过为了竞技场而改善UI,这么多年来唯一的一个改动就是在敌方姓名版上可以显示自己的一些debuff,但是要显示什么是无法自定义的。这导致了新人想要成为竞技场大师,首先得成为插件大师。而且这些第三方插件全靠社区维护,很容易出现更新慢/突然不兼容等问题。比如知名框体插件Gladius就已经有一年以上没有更新了,没有9.0新技能的递减监视,就导致了很多玩家看不到递减而在错误的时间去做控制。如果暴雪可以渐渐地把一些重要的功能内置到游戏里,则可以大大的降低新人入门的门槛。 + +还有这个万年没有改善的LFG系统,地下城模式里不能用,完美的体现了暴雪想尽办法浪费玩家时间的设计心理。LFG上不显示任何有用的信息,玩家想知道对面的水平还要去第三方网站去查。不要求有多么详细,至少在游戏内部显示出这个职业当前角色当前赛季的匹配/胜率和之前每个赛季的经验/胜率并不过分吧?(怕是暴雪根本没把这些数据存在数据库里)当然,如果可以的话显示账号其他角色的匹配/经验/胜率,甚至是组队的倾向(比如是rmp的法师还是mld的法师),则会让玩家更好的找到队友。当然暴雪也可能是想让把玩家都恶心走,这样就没人用组队系统,也就不需要什么改善了。 + +你问我支不支持soloq,那我肯定是支持的。soloq确实可能会分流一部分玩家,但是更好的结果是用这个系统吸引更多的玩家来接触,入门竞技场(当然如果到时候还是现在这个鬼样子就别害人了),培养出更多愿意组队硬核3v3的核心玩家。当然实现起来肯定没有这么简单,到时候soloq是和2v2/3v3排到一起还是分开,奖励要给到多少都会对竞技场玩家走向有很大影响。不过核心思想和本人的想法是一致的,就是降低新玩家的入门门槛。 + +然后是匹配系统,sl s1这赛季因为人口流失,导致匹配越打越低,暴雪象征性的做了一些改动,没有看到任何实质效果,到我afk的时候美服的oce时间2100+都排不到人了,明明一两个月之前2300~2400还是有人在玩,到拿龙为止是一直可以排到队伍的。大家匹配都越打越低,排名越打越靠后,那怎么还会有人玩!其实就是改一下数值的事情,然而暴雪是不可能放在心上的,因为他的目的就是把人恶心走!另外有调查([Comparing the rating distribution in Shadowlands Season 1 to BfA Season 4 \| Ludus Labs](https://luduslabs.org/articles/comparing-ratings-in-sl-and-bfa))表明sl s1的匹配比bfa s4平均要低个250,但是龙线是不会变的,也就是你跟我说去年考到省里前20%可以上一本,但是今年得考到5%。。。这种搞笑设计的出现正是暴雪不重视竞技场的结果。 + +### 再见了 + +![byebye]({{ site.url }}/assets/2021-06-26-arena-byebye/1.png) + +不知不觉写了4500字,其实要说的地方还有很多很多,然而这个游戏已经不值得浪费时间去批判了。暴雪根本没有心思去照顾所谓的“竞技场玩家”,或许本来也就没有几个“竞技场玩家”,这一切只是我的一厢情愿,大多数人们还是在享受着被暴雪浪费时间。世界上值得玩的游戏虽然现在看起来没有那么多了,不过还是够玩一辈子的,再不济也不至于回到这里来竞技了。或许五年十年之后,如果怀旧服还在的话,我又会捡起一位人类女战士,伴着艾尔文森林的音乐,听着熟悉的效果音,踏上打豺狼人的旅程... + +by Alge \ No newline at end of file diff --git a/_posts/2021-07-01-popn-02.md b/_posts/2021-07-01-popn-02.md new file mode 100644 index 00000000..4dd8b962 --- /dev/null +++ b/_posts/2021-07-01-popn-02.md @@ -0,0 +1,58 @@ +--- +layout: post +title: "ポップン奮闘記 其の弐" +date: 2021-07-01 +category: blog +tags: [音ゲー, ポップン] +description: "" +--- + +[前回](/blog/2020/11/01/popn-01.html)もお久しぶりでしたけどまたお久しぶりになってしまいましたので今回もお久しぶりです。 + +去年の年末でポップンを頑張ることを決意したけど、12月からコロナ禍がまた悪化する兆しを見せ始めて、やむを得ずゲーセンを通うことをしばらく断念した。 + +5月の後半あたりから、世界中にワクチンの接種がかなり進められていることに気づき、これから感染は少しずつ収まる可能性が高いと思った。日本にも高齢者の接種とか職域接種とかが進んでいるらしい。 + +それでゲーセンポップンを再開してみた。ただし、よくなる可能性が高いとはいえ、今はまだ油断する時期ではないので(ワクチンの接種率が高い国でもいくつか悪化しているケースがあるし)、外に出る時はマスク、消毒をきちんと行うように心掛けている。 + +世知辛い世の中で、皆さんもどうぞお体に気をつけてください。 + +### 進捗 + +![L-an!ma](https://pbs.twimg.com/media/E3NHbBBVgAAEf7p?format=jpg&name=small) + +復帰から間もなくだけど、大きな収穫が出た!ラピストリアのボス曲、L-an!maクリア! + +低速は昔から苦手なので、階段は全部右手で8分隣接同時あんみつしている。左手のゴミと合わせて`O o oxo O o oxo O o oxo`(Oは左右同時押し、oは右手、xは左手)のリズムになるので、個人的にやりやすい。低速は誤魔化せても、前半の隣接、中盤の同時押し、発狂、ラス殺し、所々で地力が要求される譜面なので、クリアできてすごく嬉しい。地力の向上を感じる。 + +あとは前回の指標の**49平均罰数**は12.08->11.71になった。ラクリマ、リナシタ、最小三倍完全数は鏡で銅菱取ったとか、特にミラー譜面の罰数減らしが捗った。辿る君とインボルクUもミラーでの初クリアを達成した。メダルの変化が少ないものの、収穫は大きいと言えるだろう。自分を褒めることが大事! + +### 悩み(先延ばし) + +ただしこれからでも本家での練習は、49罰数の指標だけ見て頑張れるかと言われると、分からない。6月のように週2回くらいの頻度で本家やるのなら別に問題ないけど、前みたいのほぼ毎日の状態に戻るのなら、さすがに49~50だけだと曲が少なすぎる(ミラー含めても)。 + +乱ノック、s乱、フルコン狙い、スコア力上げなど、練習になりそうなことを探せばたくさん出てくるけど、どれが一番自分に合うか、つまり全埋めという目標に近づけるにはどれが一番いいのかを考えると、すごく悩ましい。 + +幸い、こんな世の中ではまだゲーセンに頻繁に通えないので、この悩みの解決は先延ばしにできる。おうちで発狂PMSをやるしかない。 + +### PMS中心の練習 + +発狂PMSもかなりやり込んでた。コロナでさすがに毎日ゲーセンに行かないので、6月はだいたいポップン4:6発狂PMSの感じだった。 + +<iframe style="width: 100%; aspect-ratio: 16/11;" src="//player.bilibili.com/player.html?aid=631343464&bvid=BV1Bb4y1C7jU&cid=360684197&page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe> + +まずは発狂八段合格!難易度は七段とあんまり変わっていない気がするけど。 + +他にも●10のハードとか●11のノマゲとかいろいろ収穫あるけど、指標がないとなかなか直観的に上達を感じにくい。というわけで、指標をつけてみた。 + +とりあえずクリアラー向けの、(ゲージごとに)クリアした曲の上位30曲の難易度の平均を取って、適正難易度みたいなものを作った。自分の場合、12を3曲、11を27曲以上イージークリアしたので、イージーは●11.10になる。同じ計算方法でノマゲは●10.33、ハードは●9.63になる。 + +クリア難易度上げの打開が難しい時、この指標はなかなか動かなくなると思うが、その時はフォルダー埋めとかでモチベを保てば良いかと。 + +最後に来月の練習メニューを: + +* ●12イージー特攻 +* ●10-11ハード +* ●11イージー埋め + +このつたない文章を目にしている方に、充実で楽しいポップンライフを送るように \ No newline at end of file diff --git a/_posts/2021-07-05-divaft.md b/_posts/2021-07-05-divaft.md new file mode 100644 index 00000000..88d38807 --- /dev/null +++ b/_posts/2021-07-05-divaft.md @@ -0,0 +1,70 @@ +--- +layout: post +title: "divaFT和被遗弃的摇杆" +date: 2021-07-05 +category: blog +tags: [音ゲー, ゲーム感想,divaFT, 中文] +description: "divaFT是指PS4版的\"初音ミク Project DIVA Future Tone\"" +--- + +先宣传下视频 + +<iframe style="width: 100%; aspect-ratio: 16/11;" src="//player.bilibili.com/player.html?aid=846403804&bvid=BV1u54y1p77f&cid=363954032&page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe> +【手元】用格斗摇杆挑战歌姬计划FT 中级篇 + +<hr style="margin: 32px 25%" /> + +五年前没有想到,只会做20帧音乐游戏的世嘉,居然决定把半死不活的divaAC搬到PS4上!没记错的话是当时的街机歌曲全部收录!并且只卖8000日元!(看到这个价格,再看看switch那堆DLC,请问765你愧疚了吗;看到这个价格,再看看popn lively那个曲包的标价,请问573你愧疚了吗;看到这个价格...) + +当年感受到了世嘉良心的我,毫不犹豫的掏了腰包买了PS4和这个游戏,并且很长一段时间内PS4上只有这个游戏。divaAC虽然在街机厅跟bemani一众是拼不过,不过也可以算是一个不错的音游了(只要你不去刷分)。虽然在街机厅没有火起来,但是毕竟是街机游戏,比家用机上很多粗制滥造的音游不知道高到哪里去了。记得当年这游戏也是受到了[lain老兄的绝赞](https://djlain.com/2016/06/24/6448/)。~~不知道老兄连了holding on没有~~ + +记得最开始用手柄打,研究了一通同时押的按法之后很快就P掉了千本桜F的EX谱面,之后又攻略了裏表ラバーズ,但是看到Sadistic Music Factory的谱面之后,我陷入了深思。因为当时是用的家用版按键设置,就是和索尼手柄上面的图标一样的按键分布,然后把L和R分别改成了三角方框和圆圈交叉的同时押。这个按键面对工厂最后那串连打是毫无办法,因为在16分连打中有了方框和交叉的同时押。(现在想想其实用右手打方框交叉,左手起手应该可以解决)之后在很多9-10星里也发现许多对手柄不友好的配置,并且这还是在放弃了hold的前提下。毕竟是移植游戏,谱面本身是对街机横排4个按键设计出来的,没有办法完美适配手柄也是情有可原。当时因为这些原因,就渐渐的搁置了这个游戏。 + +<hr style="margin: 32px 25%" /> + +后来再捡起来就是两年前了,当时有两个契机。一是drummania打的多了,对非双手交互处理16分连打有了一些经验。特别是面对ooooO最后一个音是同时押的这种,当时打drummania就想世纪末舞厅的那堆连打不也可以这么打。二是当时家里沉睡了一个买来打了一个月bbtag就被冷落的RAP Hayabusa。 + +记得开始还是尝试用手柄练,直到遇到了パラジクロロベンゼン,我就觉得这游戏还是得按街机的方法玩。。。(虽然我相信有大神一定是可以用手柄拉满hold+全perfect的,哦对了,还有理论值!)偶然看youtube上有人用摇杆玩,不过只是比较简单的hard难度,于是我也把摇杆搬出来研究了一下。 + +刚开始用摇杆打,把8个按键分别设置成了 + +<div style="display: flex; text-align: center"> + <span style="width: 24px">←</span> + <span style="width: 24px">←</span> + <span style="width: 24px">→</span> + <span style="width: 24px">→</span> +</div> +<div style="display: flex; text-align: center"> + <span style="width: 24px">△</span> + <span style="width: 24px">□</span> + <span style="width: 24px">☓</span> + <span style="width: 24px">◯</span> +</div> + +上面一排用来当滑键,下面和街机一样的键位分布。然后我开了一把千本樱EX,10秒钟就放弃了。摇杆这种小按键,连打根本没法交互打!如果是这个键位不改,估计希望最大的打法就是所有的连打要么全单手打,要么就rrllrr这样两个两个打。但是这个打法一是太难,二是和街机主流打法也不一致。 + +于是就继续想怎么搞键位,我盯着摇杆想了半天,突然发现摇杆上不还有个摇杆吗!好吧其实早就想到了,但是最开始考虑的是摇杆只能往左和往右推,没办法对应左左,左右,右右这种双手slide。但是后来发现,Hayabusa的摇杆是可以切换成对应手柄的左右摇杆,或者十字键的。如果对应左右摇杆那确实没办法打双手slide,但是十字键就不一样了!经过一番验证,发现只要把左和上设置成←,右和下设置成→,就可以完美应对所有slide配置。于是最终按键设置如下 + +<div style="display: flex; text-align: center"> + <span style="width: 24px">△</span> + <span style="width: 24px">□</span> + <span style="width: 24px">☓</span> + <span style="width: 24px">◯</span> +</div> +<div style="display: flex; text-align: center"> + <span style="width: 24px">△</span> + <span style="width: 24px">□</span> + <span style="width: 24px">☓</span> + <span style="width: 24px">◯</span> +</div> +摇杆 ←↑ 左滑 →↓ 右滑 ↖左左 ↘右右 ↙/↗ 左右 + +完美解决! + +当然一部分谱面估计还是有问题,因为摇杆很难一边hold一边去推(小指够灵活的话或许可以做到?),遇到一些双手hold+滑键的谱面可能会有些困难。不过面对99%的谱面应该可以不妥协hold来解决了!而且相对手柄来说,不仅很多带同时押的连打好按了,平时的同时押的读谱也简单了许多。虽说和仿街机手台没有办法比,不过已经明显有一种“这个谱面是为了这种玩法设计”的感觉了! + +(最后还是要说摇杆只是一种不太廉价的廉价解决方案。有条件的同学可以考虑[仿街机按键的手台](https://www.bilibili.com/video/BV1wi4y1g7Xa)。) + +<hr style="margin: 32px 25%" /> + +本来只要有pop'n的话,是没有什么必要玩其他音乐游戏的。其实这几天有空玩diva也是得益于pop'n那边决定最近专攻一下发狂pms,但是发狂pms毕竟还是有噪声,没有办法在晚上打(不像pop'n是可以从9点出勤打到12点),所以晚上就有一些空闲的时间。总之趁着还想玩再好好玩玩,争取把上级篇搞出来! \ No newline at end of file diff --git a/_posts/2021-07-11-divaftdx.md b/_posts/2021-07-11-divaftdx.md new file mode 100644 index 00000000..d1722c2c --- /dev/null +++ b/_posts/2021-07-11-divaftdx.md @@ -0,0 +1,24 @@ +--- +layout: post +title: "divaFTDX" +date: 2021-07-11 +category: blog +tags: [音ゲー,ゲーム感想, divaFT, 中文] +description: "游戏好,买两份不亏!" +--- + +真是火星了,上次提到divaFT200多首歌只卖8000日元是业界良心,结果没想到今年3月。。。 + +<img style="width: 60%" src="{{ site.url }}/assets/2021-07-11/dx3900.png" alt="dx3900"> + +包含FT两大曲包和4个DLC的合集DX,238首歌,只卖3900日元!SEGA这是预感要倒闭了所以开始了閉店セール吗!? + +<img style="width: 60%" src="{{ site.url }}/assets/2021-07-11/doublemiku.jpg" alt="doublemiku"> + +不买不是初音人! + +还是讲点正经的。在有FT的两大曲包之后,买DX的主要原因是4个DLC里包含的14首歌和26个追加EEX谱面(具体可以看[这里](https://miku.sega.jp/FT/download/dlc.html#seasonpass))。而且**存档可以继承**,不用担心之前的记录白打了。 + +说起来上一次买了两份的游戏是djmax respect,开始日服没卖从港服搞了下载版,后来又买了日服限定实体版。就是日版只有一首Ask to the wind日文翻唱,早知道就不拆了。。。不过拆了也没啥倒是。 + +至于要不要买FTDX限定版。。。等我连了激唱EEX就考虑一下! \ No newline at end of file diff --git a/_posts/2021-08-01-popn-03.md b/_posts/2021-08-01-popn-03.md new file mode 100644 index 00000000..76e9ee3f --- /dev/null +++ b/_posts/2021-08-01-popn-03.md @@ -0,0 +1,53 @@ +--- +layout: post +title: "ポップン奮闘記 其の参" +date: 2021-07-28 +category: blog +tags: [音ゲー, ポップン] +description: "もうPMS奮闘記でいい気がする" +--- + +こんにちは、トイサイダー村のまつまつです。 + +### 本家 + +7月はほとんどゲーセンに行かなくて、おうちPMSを中心に練習しました。低い頻度の中、なんと。。。 + +<img style="width: 60%" src="{{ site.url }}/assets/2021-08-01-popn-03/silent.jpg" alt="サイレントクリア"> + +**サイレントEX、クリア**!!!!!!!!!!!!!!!!!!!!!!(パチパチパチパチパチパチパチパチパチパチパチパチパチパチパチパチパチパチパチパチパチパチパチパチ) + +110負1勝でした。オプションはミラーロストサドプラ。最初は正規で挑んで黒星まで来て、ラストの左手のあんみつ(3個押しx6 + 4個押しx7)ある程度覚えたら産卵で癖ついてしまい、たまに希望を見せてくれたりはしますがやっぱり全体的に正規がだんだんできなくなりました。ミラーは癖が少なく正規よりやりやすいところが多いですが、ラストは正規より圧倒的にきついです。まあそもそも正規のラストもきついし、本当にどうしようもない。どうしようもないものをなんとかするしかない。今の地力でクリアできたのは奇跡のようなものです。 + +これで始めてた当時のボス曲たち、トイサイダー村を全クリア!まだポップンチームのペースに追いついていないが、大きな一歩を踏み出しました。これからのレースにもペースを落とさないように頑張りたい。 + +その他には25時[クリアの兆し](https://twitter.com/ssdh233/status/1415306956558929928)が見えたり見えなかったりとかもありました。 + +### PMS + +PMSの方はかなり進めました。まず[前回](https://ssdh233.me/blog/2021/07/01/popn-02.html#pms%E4%B8%AD%E5%BF%83%E3%81%AE%E7%B7%B4%E7%BF%92)決めた指標でみると + +* イージー:●11.10 -> ●12.00 +* ハード:●9.63-> ●10.50 + +●12のイージー30曲、●11のハード15曲をクリアしましたので、指標が上のようになりました。 + +ノーマルクリアに関しては、ハードクリアとの難易度あんまり差がなく、イージー → ノーマル → ハードで埋めるよりイージー → ハードのほうが効率的だと考えたため、ノマゲ狙いは諦めました。 + +発狂九段は一回受けまして、二曲目落ちでした。もうちょっと地力上げたら再挑戦します。 + +●11(持ち曲のみ、164曲)をイージーで一周しました。八割くらい埋めました。現在のクリア分布は下図のような感じです。 + +<img style="width: 60%" src="{{ site.url }}/assets/2021-08-01-popn-03/clear.png" alt="PMSクリア状況"> + +8月からは +* ●13イージー特攻 +* ●12イージー埋め +* ●11ハード特攻 +* ●10ハード埋め + +を中心に回っていくつもりです。 + +### これから + +また緊急事態宣言が出ましたので、当分はこんな感じでPMS中心に続けたいと思います。皆さんもいろいろお気をつけましょう。 \ No newline at end of file diff --git a/_posts/2021-09-25-d2r.md b/_posts/2021-09-25-d2r.md new file mode 100644 index 00000000..6550a90f --- /dev/null +++ b/_posts/2021-09-25-d2r.md @@ -0,0 +1,38 @@ +--- +layout: post +title: "暗黑破坏神2:重制版" +date: 2021-09-25 +category: blog +tags: [ARPG,ゲーム感想,中文] +description: "讲个笑话,暗黑破坏神2是ARPG的先驱" +--- + +从知道重制版发售的时候我就在思考我为什么要玩这个游戏:我要玩是因为我小时候玩了这个游戏但是没有通关,我小时候玩了这个游戏是因为当时我不知道有其他的游戏可以玩。对于本作,我从来没有过“这款游戏能玩”的想法,当最终发现这款游戏的确跟想象的一样的时候,也就没有产生像WOW竞技场的时候那种失望感了。 + +这次重置做的还是很不错的,至少对于本人这种玩过原作,并且想再次通关一次的情怀玩家来说是完全合格。暴雪高管看到的话这次就不用解散开发组了。主要优点有一是基本上原汁原味的还原了原作,二是对手柄操作设计的比较用心,基本可以无障碍游玩(就是四个物品栏顺序是左上下右,设计师一看就是没玩过DDR的!)。 + +当然对于没有玩过这个游戏的人,除了对人生已经绝望,决定这辈子接下来就靠电子海洛因过日子的人以外,不建议接触任何暴雪娱乐(Blizzard Entertainment)制作的游戏。(这里应该可以加上”除了魔兽争霸3以外“,不过这年头应该没人玩RTS了。。)世界上比这个值得尝试的游戏实在是太多了,比如过两天要发售的[新月姬格斗](https://meltyblood.typelumina.com/)看起来不错,可以试试。 + +虽说本来就没有什么期望,不过暴雪这次还是惊到我了。奖杯/成就列表里这次有两个难点,一个是全职业地狱难度通关,大概要花100~200小时,因为每个职业都得从普通打到噩梦再打到地狱;另一个是Hardcore模式下练一个角色到99级,这个目前普通模式的世界纪录大概是不到300小时,一般来说听说要400~500小时,Hardcore模式(死亡后删除角色)要小心翼翼的打估计还要再慢一些。不过时间还是次要的,最主要的还是这游戏本身太无聊,基本没什么操作性,唯一的玩法就是刷,刷了装备是为了刷更好的装备,刷更好的装备是为了刷更更好的装备,...,刷到毕业?先不说这么刷有什么意义,这游戏没记错的话应该是刷到死都毕不了业(字面意思)。 + +~~哦对了,本人并没有通关D2R的地狱模式,目前仅打完噩梦的act1,不排除地狱模式下“这游戏的唯一乐趣就是刷”这个观点有反转的可能(虽然是因为看起来没可能了才没有等通关才写这个)。~~ + +追记:地狱通了,已确认这游戏不能玩,没有反转。 + +追记2:现在回想起来当年暴雪那句"Do you guys not have phones",其实就没什么好笑的了。暴雪这个游戏设计理念确实适合给那些喜欢在抽卡/养成手游上浪费时间的人。 + +### ARPG + +这次玩D2R倒是让我重新开始思考ARPG的可玩性。以前玩ARPG的态度都是看完剧情就行,从来没想过ARPG居然还是可以“玩”的。之前接触ARPG的契机基本也都是为了看剧情,而且接触的ARPG有很多是不太能玩的一类,所以就产生了这么个刻板印象。不过这次打完D2R之后,突然发现之前玩过的ARPG看起来都那么好玩了,除了FFXV。 + +正好数一下通关过的ARPG: +* 伊苏I&II 伊苏6 伊苏Original 伊苏7 伊苏S +* 鬼泣4 +* 猎天使魔女1和2 +* FFXV +* 剑侠情缘二白金版 剑侠情缘外传:月影传说 +* D1,D2和D2R + +现在回想一下,至少Original以前的伊苏系列,鬼泣4和猎天使魔女系列都还是有一定再深入研究的价值的。伊苏7开始的组队换人模式+智障AI+可以随便带血瓶的设计基本把这系列之前的主要靠“躲”的玩法给毁了;FFXV本来就不是个用来玩的游戏;剑侠情缘系列实在是太久想不起来了,不过印象里跟D2是差不多的,虽然没有刷刷刷不过这种开放式的系统应该是没啥玩头。 + +正好伊苏Original和猎天使魔女都在switch上可以搞,有空去研究一下!就是过两天新月姬格斗发售之后估计很长一段时间都不会有空了! diff --git a/_posts/2021-10-01-popn-04.md b/_posts/2021-10-01-popn-04.md new file mode 100644 index 00000000..4395b49f --- /dev/null +++ b/_posts/2021-10-01-popn-04.md @@ -0,0 +1,64 @@ +--- +layout: post +title: "ポップン奮闘記 其の肆" +date: 2021-09-30 +category: blog +tags: [音ゲー, ポップン] +description: "PMSしかやってない" +--- + +こんにちは、まつまつです。二ヶ月ぶりですね。 + +### Lively + +ぽちぽちやっています。甘判定以外の曲の判定が掴めなくて少しもやもやしていますが、とりあえずスコアをあんまり気にしすぎずフルコン埋めとかを中心にやっています。ここのサイレントはまだ未クリアです。 + +### PMS + +Livelyやっていない日ほぼ毎日PMSやっていました。先月もう少し曲数がほしいと感じて、PMSデータベースのほぼ全曲を導入しました。今のクリア状況はこんな感じです。 + +<img style="width: 60%" src="{{ site.url }}/assets/2021-10-01/pmsclear.png" alt="PMSクリア状況"> + +基本はフォルダ埋めしていますが、PMSデータベースの曲数が非常に多く、選曲に工夫しないと低難易度ばかり、あるいは適正以上の高難易度ばかりをついついやってしまいます。ここでもう少し詳しく自分やり方を話していきます。 + +まずプレイする前に目標を定めます。メイン目標とサブ目標いろいろ考えてリストアップします。 + +* ~~12のイージーを一周する~~ + * 12のイージー(未クリア)を一周する // つまり二周目 +* 13のイージー(クリアレート60%以上)を一周する + * 13のイージーを一周する +* 14のイージー(クリアレート80%以上)を一周する +* 11のイージー(プレイ済み&未クリア)を埋める +* 10のイージー(プレイ済み&未クリア)を埋める + +12のイージーを一周することが終わり、現在のメインが**13のイージー(クリアレート60%以上)を一周する**になりました。その他はサブです。 + +ちなみにどうでもいい話ですが、13のイージー(クリアレート60%以上)を一周するという言葉がとても長いので、簡略表記を定義しました。文法は下のようです。 + +``` +(難易度数値)(ゲージタイプ)[追記].[R(周数)] +``` + +* 難易度数値: ●のあとの数値のこと +* ゲージタイプ: Eはイージー、Nはノーマル、Hはハード +* 追記:数値かn。数値の場合、該当ゲージタイプでのクリア率が[数値]*10%以上の曲ということを表す。nの場合、プレイ済みだけど該当ゲージタイプで未クリアの曲ということを表す。追記がない場合はすべての曲が該当するということです。 +* 周数:いわゆる一周目、二周目のことです。ドット前の条件に該当する曲を一通りプレイしたら、二周目に入ります。 + +現在の目標を例として上げると +* ~~12のイージーを一周する~~ // 12E.R1 + * 12のイージー(未クリア)を一周する // つまり二周目 12E.R2 +* 13のイージー(クリアレート60%以上)を一周する // 13E6.R1 + * 13のイージーを一周する // 13E.R1 +* 14のイージー(クリアレート80%以上)を一周する // 14E8.R1 +* 11のイージー(プレイ済み&未クリア)を埋める // 11En (nの場合は周数がつかない) +* 10のイージー(プレイ済み&未クリア)を埋める // 10En + +いやこうして書いてみたらますますどうでもいい話感が出ました。無視してください。 + +フォルダ埋める時、一曲は大体最大2-3回試します。クリアできなかったら、放置して地力を上げて、二周目でなんとかするという考えです。 + +というわけで、これからも13E6.R1をメインとして、終わったら12E.R2か13E.R1のどちらかに移行しようと考えています。12イージー六割強くらいで13イージー埋めやるのがいささか早い気がしますが、いろいろ試行錯誤しながら進み方を模索していきたいところです。 + +### 終わりに + +近日コロナが安定してきたように見えますが、個人的にまだまだ油断できないと思います。10月はとりあえず様子見で、引きこもり生活を続けます。11月と12月あたりでアーケード復帰を検討します。では、また次回。 \ No newline at end of file diff --git a/_posts/2021-10-14-aimasu-new.md b/_posts/2021-10-14-aimasu-new.md new file mode 100644 index 00000000..04579f48 --- /dev/null +++ b/_posts/2021-10-14-aimasu-new.md @@ -0,0 +1,18 @@ +--- +layout: post +title: "偶像大师:星耀季节" +date: 2021-10-14 +category: blog +tags: [ゲーム感想,中文] +description: "结论:不能玩。" +--- + +要不是看到委员长推特我都以为偶像大师系列早完结了。听说又要出个新作,就把试玩版下下来试了下。 + +之前就听说主机上的偶像大师的游戏部分很弱智,结果还是突破了我的想象。所有歌一律全程打4分的拍子,然后就...完了...试了下试玩版的三首歌的hard难度,平时掉几个也没事,关键时刻都打准基本就过了。没有任何技巧可言。 + +哎,有空还是去搞一下Shiny Festa吧(或者PS3上的Shiny TV?),当年看到这游戏的时候本以为偶像大师系列会继续做音游,结果没想到这就是这系列的顶点了。 + +说起来当年还买了太鼓版偶像大师的两张盘,结果到现在还在放着。倒不是不想玩,但是每次想象一下psvita按键那个手感,就知难而退了。。这游戏也没对应psvita TV,真的是无解。 + +这年头真的是没啥能玩的新音游了,我还是继续去打pms吧。 \ No newline at end of file diff --git a/_posts/2021-10-14-mbtl.md b/_posts/2021-10-14-mbtl.md new file mode 100644 index 00000000..f44a0afd --- /dev/null +++ b/_posts/2021-10-14-mbtl.md @@ -0,0 +1,61 @@ +--- +layout: post +title: "MELTY BLOOD: TYPE LUMINA" +date: 2021-10-15 +category: blog +tags: [格ゲー, ゲーム感想, 中文] +description: "可能是近几年来最好的格斗入坑机会" +--- + +上次玩格斗游戏还是BBTAG发售的时候。 + +记得当时BBTAG发售半年前买了BBCF,打完剧情后去网战被各种花式吊打到10%胜率,也不知道该怎么练,就没怎么深入研究下去。 + +BBTAG出来的时候就好多了,至少有很多水平差不多的人在玩,不至于上来就被揍得太惨。说起来当时RWBY还是决定了要玩BBTAG才去看的(什么,美国人居然会做动画片!?),看了之后果断决定用Ruby/Weiss。BBTAG总共打了1300多把,学到了一些基础的combo和立回,段位也打到了钻石。不过说实话离入门还差得远,大部分时间仗着Ruby的基础技性能好瞎蹭,遇到稍微会玩儿点的就打不过。当时热度过了之后,本着“有时间还是尽量用去打popn”的原则就退坑了。 + +最近发现每天打2-3小时的发狂pms(太久了也打不动)以外还能腾出个2小时左右去干别的事情,就把这2小时用在“现在最想干的事情“上,比如之前的divaFT和STG。而这次,又轮到格斗游戏了。 + +八月底得知月姬格斗重制的消息(对,我就是这么火星--)后,就有种莫名的特别想玩的冲动。以前只知道月姬格斗是一款从同人做到街机的格斗游戏,不要说MB系列的人物,系统,风格,连月姬我都是只听说过名字(就是那个什么三大同人!)。后来才知道这次重制是因为月姬本篇也要重制了,所以设定要按照月姬重制版的来,相当于从零开始。这么好的入坑机会,这辈子应该不会再有了! + +月姬本篇的重制版(也就是月姬R)还是可以的,感觉至少比FSN要好看多了。FSN那个讲故事的方式我是真看不懂,而且一遇到打架场景就犯困,最后是迷迷糊糊的把三条线打完了。月姬R的打架场景虽然也犯困,不过毕竟少一些。而且这游戏也有点惊悚,不是那么容易睡着的。虽然程度并不是很高,对于我这种ホラー超初心者也是可以接受的范围。目前看来月姬R至少值得再打一遍,不过最后会不会像WA2一样一年打一遍就不好说了。。 + +### 一些成果 + +<img style="width: 100%" src="{{ site.url }}/assets/2021-10-14/trophy.png" alt="MBTLトロコン"> + +先说最不重要的奖杯,难度还是稍微有点的,虽然对常玩格斗游戏的玩家应该是不值一提。最难的应该是bossrush模式通关和单角色100%(要求生存模式S判定,也就是活20轮)。bossrush模式只要每次用Miyako投了之后接B连,然后boss起来继续投接B连的耍赖玩法就很容易过,正常打就要费一番功夫了。生存模式活20轮最好也要掌握一些对战CPU的技巧,比如我用的琥珀,可以爆月之后多用6BC,也可以强制开放接蓄力236BC,电脑很蠢一般防不住。 + +<img style="width: 60%" src="{{ site.url }}/assets/2021-10-14/rank.jpg" alt="MBTL rank match"> + +然后是网战的一点小成果。这个rank系统是够偷懒的,只有同等级对战才会对rank有影响,赢了+1,输了-1,初始值是0,到10就升段到-10就降段。在D的时候偶尔打赢过几次B的就高兴半天,结果一点用都没有。。 + +目前目标是保B争A,不过照现在这个胜率估计还得在BC晃一阵了。当然,个人认为rank只是反应水平的一个(不是特别准确的)标准,这次来玩格斗除了单纯想玩MBTL以外,争取还能额外提高一些格斗游戏通用的“地力”,改善一下BBCF的10%胜率。。 + +### 游戏系统 + +MBTL是一款优秀的格斗游戏,这毋庸置疑。不过MBTL和我之前认知里的格斗游戏比,还是有一些区别的。 + +先说本作新加的简易连段系统,个人觉得这非常有利于新玩家入门。在其他的重视combo的格斗游戏里,会连段的摸到人打一下能打3割,不会的可能就打一下,这样导致新人在开始游戏之前都花费在了很大的时间在练习连段上。不过个人认为格斗游戏的主要精髓是在于确认和立回上,连段更像是一个附加系统。有了简易连段之后从来没接触过格斗的新玩家至少也可以互相打的有模有样,更早的了解对战的流程。当然之后连段还是要练的,简易连段的伤害还是要低一些。我目前已经渐渐地从全部简易连段过渡到了可以在某些情况下使用民工连段,不过在有些起手的地方还是会因为确认慢或者按键不准导致进入简易连段。 + +还有就是角色的对空能力普遍不强,即使在正确的时间用了对空的技能也很容易形成相杀,未必有利。这就导致了从空中的进攻比较强势,基本每个角色玩的时候都飞来飞去的。而且这游戏还能在跳或者二段跳之后进行空中冲刺/后退,这样就导致了角色在空中的行动模式也很多,在空中的操作(跳/大跳/冲刺/后退的组合)就成了立回里十分重要的一个基础。 + +然后就是每个角色都感觉超模,特别是本作的MoonDrive(俗称"爆月")这个系统。在开启MoonDrive之后一些技能的发生会变得很快,再加上本作的相杀系统,很多技能不带无敌效果也基本算是无敌了(比如琥珀的6BC,翡翠的6BC等等),这要是放别的游戏里估计可以评到SStier了。也难怪GO1上来玩了个Saber和Arcueid就直呼强强强,然后玩了其他角色发现一个比一个猛==不过这倒并没有太破坏游戏的平衡性,因为每个角色都有可取之处,并且这作还有一个通用的强力防御技能:护盾,来专门克制各种超模技能。 + +护盾可以理解成一个比较强力的防御,使用代价小到几乎可以忽视。护盾不仅可以防御一些普通防御无法防御的技能,而且在防御成功之后还可以选择反击。护盾防御成功的瞬间游戏画面会有一个小停止让玩家做出下一步判断,然后双方就进入一种猜拳的状态。开始我担心这系统会让这游戏完全变成運ゲー,不过随着对游戏系统的理解,发现其实还好。一是护盾要求读准对方的中/下段攻击,并不是说可以随便乱放的;而且在低水平的对战中,被护盾之后A反击,基本就是确反,因为攻击方很可能不进行击中确认就连续输入攻击指令(说的就是我自己。。),这样被盾反之后就没法按护盾防守了(目前还不确定是否可以在按攻击之后再按BC强制逃脱)。目前看来与其说护盾带来了随机性,不如说是增加了对玩家的操作要求,比如要确认对方是否用了护盾之后再决定是否按下次攻击。 + +附上搞笑猜拳一则。 + +<video style="width: 100%" controls> + <source src="{{ site.url }}/assets/2021-10-14/shield.mp4" type="video/mp4"> +Your browser does not support the video tag. +</video> + +### 接下来 + +这次MBTL是打算稍微再玩的深入一点了,虽然popn还是第一要务。最近也开始了录制一些自己的MBTL的视频,主要来看看自己有没有进步。不定期投稿(大概1~2周/次),最新一期是: + +<iframe style="width: 100%; aspect-ratio: 16/11;" src="//player.bilibili.com/player.html?aid=335984296&bvid=BV15R4y1H7sJ&cid=421009503&page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe> + +目前跟会玩的比差距真的不是一般的大,经常是不知道为什么就被K.O.了。我选择的方法是用obs录下每一局的对战,不求检讨完之后能立马打过别人,不过至少把自己怎么输的看明白,然后分析找到目前最需要提升的地方去练习。 + +格斗脱新的路还很长很远,慢慢前进吧。 \ No newline at end of file diff --git a/_posts/2021-11-01-popn-05.md b/_posts/2021-11-01-popn-05.md new file mode 100644 index 00000000..a0181e91 --- /dev/null +++ b/_posts/2021-11-01-popn-05.md @@ -0,0 +1,81 @@ +--- +layout: post +title: "ポップン奮闘記 其の伍" +date: 2021-11-01 +category: blog +tags: [音ゲー, ポップン] +description: "大きな一歩" +--- + +こんにちはーですよ~だ! + +どうも、最近アルクェイド(月姫)&琥珀(メルブラ)とかぐら(ソルフェージュ)の影響で「ですよ~だ」がマイブームになっているまつまつでございます。 + +コロナが安定してきましたね。やっぱりワクチンの効果が大きいからでしょうか。私も久しぶりに外に出るようにしましたが、街はにぎやかで、店も深夜まで営業できるようになり、ポストコロナの感じになりつつありますね。これからもこのまま増えなければいいのですが。。 + +### PMS + +今月はPMS->AC復帰の流れなので、まずはPMSからの報告となります。 + +[前回の呪文](http://ssdh233.me/blog/2021/09/30/popn-04.html)でいうと、 + +* ~~13E6.R1 終わり~~ +* 12E.R2 進行中 +* 11H5.R1 (サブ)進行中 + +11月からまたPMSメインでやる予定なので、●12易を埋めつつ、●13~●14の未プレイを開拓していきたい。例えば13E6.R2 & 13E5.R1とか、14E7.R1とか。 + +一応現在のクリア分布を貼ります。先月と比べて●12と●13の緑が少し増えたくらいです。 + +<img style="width: 60%" src="{{ site.url }}/assets/2021-11-01/pmsclear.png" alt="PMSクリア状況"> + +### ポップン + +第5波以来のゲーセンなので、ACのポップンは二ヶ月半振りになります。 + +AC復帰初日に。。。 + +<img style="width: 60%" src="{{ site.url }}/assets/2021-11-01/ppu.jpg" alt="ppuクリア"> + +**perditus†paradisus UPPER クリア!** + +<img style="width: 60%" src="{{ site.url }}/assets/2021-11-01/25oclock.jpg" alt="ppuクリア"> + +**25 o’clock the WORLD クリア!** + +はい、完全にPMSで地力上げた効果だと思います。一日に二曲以上の新規クリアあるのはなんと六年ぶりとなります。(六年前はトラタワでのプロバロ、pp、スケとディアボロ初クリアだった)逆に言うとそこからの曲の難易度差が広すぎて一曲ずつ進むしかなかったんですね。 + +そして50をいろいろ伸ばしてポックラが99超えとなりました。 + +<div style="display: flex"> +<img style="width: 33%" src="{{ site.url }}/assets/2021-11-01/dirge.jpg" alt="dirge 90.5k"> +<img style="width: 33%" src="{{ site.url }}/assets/2021-11-01/en.jpg" alt="angelion 92.3k"> +<img style="width: 33%" src="{{ site.url }}/assets/2021-11-01/toikon.jpg" alt="toycon 93.6k"> +</div> + +実はもう一個個人的にとても大きな収穫がありまして、それは + +<img style="width: 60%" src="{{ site.url }}/assets/2021-11-01/chaos.jpg" alt="chaos q easy clear"> + +**Chaos:Qのイージークリア!** + +昔からソフランが苦手でChaos:Qはずっとバッド100以上の感じでしたが、ppUと25時クリアした後、そろそろソフランと真剣に向き合わないといけないとこれ以上進むのが難しいと思ったため、いろんな方法でいろんな練習を試してました。 + +そこで私が見つけた最善解は、(邪道かもしれないが)メガネサドンでした。 + +まぶたサドンと比べて、メガネのフレームが視野の上限となっているので安定性が比較的に高いです。あと目を軽く細めるだけで、まぶたサドンみたいに目が疲れることにならないのも大きいです。ただし、ある程度厚いフレームのメガネが必要です。 + +メガネサドンを使う前でサドプラ-65のHS200で(Chaos:Q最発狂模擬試験)いろんな曲を挑戦したんですが、適正は42くらいでした。メガネサドンにしたら急に45~46ができるようになって、livelyで数日練習したら最高49(ムンチャのみ)となりました。そこからChaos:Qのイージークリアを果たしました。 + +Chaos:Qイージーした後何度かポプクロUを挑戦してみたが、一回だけChaos:Qの低速までゲージが保てて、高速とotoで大失敗しました。前半もなかなか安定で赤ゲージまで行かず、まだまだ地力が足りないようです。 + +新規クリア以外にも、48を2曲新規フルコンできて、地力の成長を実感しました。 + +<div style="display: flex; margin-bottom: 20px;"> +<img style="width: 45%" src="{{ site.url }}/assets/2021-11-01/kagachi.jpg" alt="kagachi full combo"> +<img style="width: 45%" src="{{ site.url }}/assets/2021-11-01/touhou.jpg" alt="touhou full combo"> +</div> + +### これから + +ACポップンの解禁も全部できたので(歌合戦解禁逃したのが残念だったけどコロナだから仕方ない)、また発狂PMSメインの体制に戻して地力上げを専念したいと思います。otoでフィジカル力(縦連)の不足を痛感して、そこを発狂PMSで強化する方法を模索していきます。 \ No newline at end of file diff --git a/_posts/2021-11-01-popn-ex.md b/_posts/2021-11-01-popn-ex.md new file mode 100644 index 00000000..cbacad6f --- /dev/null +++ b/_posts/2021-11-01-popn-ex.md @@ -0,0 +1,37 @@ +--- +layout: post +title: "ポップン奮闘記 外伝" +date: 2021-11-01 +category: blog +tags: [音ゲー, ポップン, 中文] +description: "pop'n music portable 2" +--- + +两周前心血来潮买了psvita tv想去重温下psp和psv上的音游,搞来后发现能玩的也就ソルフェージュ和PMP2代了。打开ソルフェージュ发现这游戏默认就一首歌,想打音游得先打剧情。结果一开剧情发现。。这才是游戏的本体啊!(虽然2ch有老哥认为音游才是本体,不过本人目前还没解出来几首歌,不好判断)就是visual novel这类游戏实在是不适合在电视上玩,就买了张ソルフェージュ的二手盘移到PSP上去搞了。 + +然后是PMP2代。PSP时代的分辨率比想象的还是要好一些的,放到23寸电视上也感受不到什么违和感。(不敢想象NDS/3DS放上去会是啥样。。) + + +<img style="width: 60%" src="{{ site.url }}/assets/2021-11-01-ex/1.jpg" alt="PMP2"> + + +按键就用PMP默认的,虽然有些卡手,毕竟当年也练了挺长时间,不是一时半会能改的了。记得以前是至少能过37-38,39有没有忘了。后来popn街机水平练上来之后又玩过一两天PMP1代,把撫子ロックEX过了就变成了最高40。 + +这次回归之后就比以前顺多了,第一天就过了コンテンポラリーネイション3EX。之后随着对按键的熟悉渐渐地过了第一首41(ボールツアウトロックEX)和42(ヒップロック3EX)。不过后来发现雪上断火是个大逆诈称,正常的42根本就留不下血槽。。 + +前天刚刚解禁玩party mode,今天把没碰的几首低级歌曲也顺带埋了,这游戏也算刷完一遍了。(可惜的是初回生产特典的那20首似乎已经无法在PSN下载了。)目前9EX的战绩是: + +* 40以下全埋 +* 41 8/13 +* 42 1/8 +* 43 0/1 + +<img style="width: 60%" src="{{ site.url }}/assets/2021-11-01-ex/2.jpg" alt="PMP2"> +<img style="width: 60%" src="{{ site.url }}/assets/2021-11-01-ex/3.jpg" alt="PMP2"> +<img style="width: 60%" src="{{ site.url }}/assets/2021-11-01-ex/4.jpg" alt="PMP2"> + +这次必须要好好的赞一下这个party mode。当年不懂日语看不懂对话,为了解歌就瞎走迷宫,经常还会卡在某个地方不看攻略就走不下去,搞得十分不耐烦。结果这次重玩,不光能看懂对话了,角色也基本认全。剧情本身就很有意思,还能加深对角色设定的理解。而且开一次party平均解2-3首歌,而且每次出来的歌都不负期待!(因为年代太久已经忘了PMP2收了什么歌了,就有了看角色猜歌的乐趣) + +印象比较深的解禁party有Blind Justice回,白夜幻灯回(以及被山吹的歌声引出来的ぐわんぜさま,打不过MZD就闭关练了一千年popn,简直是音游玩家的榜样啊!),Space Dog回(终于回到地球的セルゲィ!居然要靠猴子去发信号。。),Ergosphere回(正好赶上新作的Smoke担当曲解禁),当然还有最后一个世界的1-19代宣传画回收和Rapunzel(toycon就算了。。),和最最后的(个人认为的)全作最经典ED Have a good dream。 + +接下来可能会偶尔用lively练一下手柄popn力,不过lively的解禁实在是太没劲了,有机会还是考虑连上PS2把7-14代打一圈,也可以在需要长途移动的路上打打PMP1代。不过PMP默认键位打街机谱面局限性还是比较大,目前就顺其自然想玩的时候玩一下,听歌为主,不强求过歌。 \ No newline at end of file diff --git a/_posts/2021-11-30-ddr-gp.md b/_posts/2021-11-30-ddr-gp.md new file mode 100644 index 00000000..c0bd7a11 --- /dev/null +++ b/_posts/2021-11-30-ddr-gp.md @@ -0,0 +1,18 @@ +--- +layout: post +title: "DDR Grand Prix(with 手柄)" +date: 2021-11-30 +category: blog +tags: [音ゲー, DDR, 中文] +description: "街机预习用APP" +--- + +前几天发现DDR的Konami Stage版(也就是windows版)发售了,就入了个会员搞了一搞。只交每月会员的话可以玩从初代到SuperNova2的200来首歌,以及15首新加的版权歌曲,价格还是可以接受的。不过要玩更新的歌曲就得买票,最终价格跟街机差不多,110yen/3曲。这个是有点震惊了,本来Konami Stage上的各种200yen/曲的曲包(pop'n一个30曲的曲包大概是6000yen)就已经摆明了就是要坑核心玩家的钱,结果DDR居然还搞出来了1play付费模式,KONMAI真是想钱想疯了。 + +用手柄打了几天的感觉就是,DDR这个系统,作为一款健身游戏还行,当音乐游戏实在是一般。虽说手柄的按键可以完美的适配DDR的谱面,换手研究起来也是有一些乐趣。不过过严的判定+无fast/slow表示,没有办法调透明度的谱面背景,无key音/效果音,打起来的感觉就像是太鼓达人的良判定砍一半,把效果音去了,判定的良字放到谱面快要滚到圈的时候,dancer放到谱面轨道上之后让你全换全良牛也牛。唯一的良心是可以开倍速。个人目前结论是这游戏当成街机预习用APP还可以,当成一个音游认真打就算了。 + +不过有一说一,就算只看默认曲,歌曲阵容也是很强大的。毕竟是DDR,光NAOKI的歌曲就可以听一年。这次月底就打算退订了,目前只刷了一些耳熟能详的歌曲,还有很多好的歌曲没有发掘,还是有一些遗憾的。就是现在这系统刷起来实在是蛋疼,至少等背景可以调亮度之后再考虑重新搞吧。 + +最后发一下目前阶段的小成果,MAX 300 FC+AAA: + +<iframe style="width: 100%; aspect-ratio: 16/11;" src="//player.bilibili.com/player.html?aid=252074504&bvid=BV1BY411s7ML&cid=451649761&page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe> \ No newline at end of file diff --git a/_posts/2021-12-01-popn-06.md b/_posts/2021-12-01-popn-06.md new file mode 100644 index 00000000..e84032c2 --- /dev/null +++ b/_posts/2021-12-01-popn-06.md @@ -0,0 +1,22 @@ +--- +layout: post +title: "ポップン奮闘記 其の陸" +date: 2021-12-01 +category: blog +tags: [音ゲー, ポップン] +description: "3 -> 2" +--- + +こんにちは、まつまつです。 + +実は元々今月書く予定なかったですけど、先日友人に呼び出されて今年始めてリアルワールドで人間とコミュニケーションをしました。そのついでに、なんと。。。 + +<img style="width: 60%" src="{{ site.url }}/assets/2021-12-01/oto.jpg" alt="oto clear"> + +皆さん!!!o†oクリアしてしまいましたよ!!!!! + +実はこの日o†o二回やりましたけど、一回目は早入り頑張ってみたけどボッコボコされてゲージほぼ残っていなかったです。二回目はもっと思い切り早入りしたら、まさかのクリアでした。最後の8分でクリアゲージが光ったので全くのぎりぎりでした。 + +外に出ると割といいことが起きるんですね。もっと外に出てもいい気がしてきました。 + +あとはPMSは13E6.R2 & 13E5.R1(呪文分からない方は[前々回](/blog/2021/09/30/popn-04.html)を参照)絶賛進行中でございます。そろそろ発狂九段クリアしたいですが事象が許してくれません。 diff --git a/_sass/addon/commons.scss b/_sass/addon/commons.scss new file mode 100644 index 00000000..71925af5 --- /dev/null +++ b/_sass/addon/commons.scss @@ -0,0 +1,1715 @@ +/* + The common styles +*/ +@import url('https://fonts.googleapis.com/css2?family=Lato&family=Source+Sans+Pro:wght@400;600;900&display=swap'); + +@mixin mode-toggle($dark-mode: false) { + @if $dark-mode { + @include dark-scheme; + } @else { + @include light-scheme; + } +} + +html:not([mode]), +html[mode=light] { + @include mode-toggle(); +} + +html[mode=dark] { + @include mode-toggle(true); +} + +@media (prefers-color-scheme: dark) { + html:not([mode]), + html[mode=dark] { + @include mode-toggle(true); + } + + html[mode=light] { + @include mode-toggle(); + } +} + +:root { + font-size: 16px; +} + +body { + line-height: 1.75rem; + background: var(--body-bg); + color: var(--text-color); + -webkit-font-smoothing: antialiased; + font-family: 'Source Sans Pro', 'Microsoft Yahei', sans-serif; +} + +/* --- Typography --- */ + +h1 { + @extend %heading; + + font-size: 1.8rem; +} + +h2 { + @extend %heading; + @extend %section; + @extend %anchor; + + font-size: 1.4rem; +} + +h3 { + @extend %heading; + @extend %section; + @extend %anchor; + + font-size: 1.25rem; +} + +h4 { + @extend %heading; + @extend %section; + @extend %anchor; + + font-size: 1.15rem; +} + +h5 { + @extend %heading; + @extend %section; + @extend %anchor; + + font-size: 1.1rem; +} + +ol, +ul { + ol, + ul { + margin-bottom: 1rem; + } +} + +a { + @extend %link-color; +} + +img { + max-width: 100%; + height: auto; +} + +blockquote { + border-left: 5px solid var(--blockquote-border-color); + padding-left: 1rem; + color: var(--blockquote-text-color); +} + +kbd { + margin: 0 0.3rem; +} + +footer { + position: absolute; + bottom: 0; + padding: 0 1rem; + height: $footer-height; + font-size: 0.8rem; + + > div.d-flex { + line-height: 1.2rem; + width: 95%; + max-width: 1045px; + border-top: 1px solid var(--main-border-color); + margin-bottom: 1rem; + + > div { + width: 350px; + } + } + + a { + @extend %text-color; + + &:link { + @include no-text-decoration; + } + + &:hover { + @extend %link-hover; + + @include no-text-decoration; + } + } + + .footer-right { + text-align: right; + } +} + +i { // fontawesome icons + &.far, + &.fas { + @extend %no-cursor; + } +} + +@keyframes fade-in { + from { opacity: 0; } + to { opacity: 1; } +} + +img[data-src] { + margin: 0.5rem 0; + + &[data-loaded=true] { + animation: fade-in linear 0.5s; + } + + &.left { + float: left; + margin: 0.75rem 1rem 1rem 0; + } + + &.right { + float: right; + margin: 0.75rem 0 1rem 1rem; + } + + &.shadow { + filter: drop-shadow(2px 4px 6px rgba(0, 0, 0, 0.08)); + } +} + +/* --- Panels --- */ + +.access { + top: 2rem; + transition: top 0.2s ease-in-out; + margin-right: 1.5rem; + margin-top: 3rem; + margin-bottom: 4rem; + + &:only-child { + position: -webkit-sticky; /* Safari */ + position: sticky; + } + + &.topbar-down { + top: 6rem; + } + + > div { + padding-left: 1rem; + border-left: 1px solid var(--main-border-color); + + &:not(:last-child) { + margin-bottom: 4rem; + } + } + + .post-content { + font-size: 0.9rem; + } + +} + +#panel-wrapper { + h4 { + @include panel-label; + + font-family: inherit; + } + + .post-tag { + display: inline-block; + line-height: 1rem; + font-size: 0.85rem; + background: none; + border: 1px solid var(--btn-border-color); + border-radius: 0.8rem; + padding: 0.3rem 0.5rem; + margin: 0 0.35rem 0.5rem 0; + + &:hover { + background-color: #2a408e; + border-color: #2a408e; + color: #fff; + transition: none; + } + } +} + +#access-lastmod { + li { + height: 1.8rem; + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + list-style: none; + } + + a { + &:hover { + @extend %link-hover; + } + + @extend %no-bottom-border; + + color: inherit; + } + +} + +.footnotes > ol { + padding-left: 2rem; + margin-top: 0.5rem; + + > li { + &:not(:last-child) { + margin-bottom: 0.3rem; + } + + > p { + margin-left: 0.25em; + margin-top: 0; + margin-bottom: 0; + } + + // [scroll-focus] added by `smooth-scroll.js` + &:target:not([scroll-focus]), + &[scroll-focus=true] > p { + background-color: var(--footnote-target-bg); + width: fit-content; + -webkit-transition: background-color 1.5s ease-in-out; // Safari prior 6.1 + transition: background-color 1.5s ease-in-out; + } + } +} + +.footnote { + @at-root a#{&} { + @include ml-mr(1px); + @include pl-pr(2px); + + border-bottom-style: none !important; + -webkit-transition: background-color 1.5s ease-in-out; // Safari prior 6.1 + transition: background-color 1.5s ease-in-out; + } + + // [scroll-focus] added by `smooth-scroll.js` + @at-root sup:target:not([scroll-focus]), + sup[scroll-focus=true] > a#{&} { + background-color: var(--footnote-target-bg); + } +} + +.reversefootnote { + @at-root a#{&} { + font-size: 0.6rem; + line-height: 1; + position: relative; + bottom: 0.25em; + margin-left: 0.25em; + border-bottom-style: none !important; + } +} + +/* --- Begin of Markdown table style --- */ + +.table-wrapper { // it will be created by Liquid + overflow-x: auto; + margin-bottom: 1.5rem; + + > table { + min-width: 100%; + overflow-x: auto; + border-spacing: 0; + + thead { + border-bottom: solid 2px rgba(210, 215, 217, 0.75); + + th { + @extend %table-cell; + } + } + + tbody { + tr { + border-bottom: 1px solid var(--tb-border-color); + + &:nth-child(2n) { + background-color: var(--tb-even-bg); + } + + &:nth-child(2n + 1) { + background-color: var(--tb-odd-bg); + } + + td { + @extend %table-cell; + } + } + } // tbody + }// table +} + +/* --- post --- */ + +.post { + h1 { + margin-top: 3rem; + margin-bottom: 1rem; + } + + a { + &.img-link { + @extend %no-cursor; + } + + &.popup { // created by `_includes/img-extra.html` + cursor: zoom-in; + + > img[data-src]:not(.normal):not(.left):not(.right) { + @include align-center; + } + } + + &:hover { + code { + @extend %link-hover; + } + } + } // a + +} + +.pageviews .fa-spinner { + font-size: 80%; +} + +.post-meta { + font-size: 0.85rem; + word-spacing: 1px; + + a { + &:not(:last-child) { + margin-right: 2px; + } + + &:hover { + @extend %link-hover; + } + } + + em { + @extend %normal-font-style; + } +} + +.post-content { + font-size: 1.08rem; + line-height: 1.8; + margin-top: 2rem; + overflow-wrap: break-word; + word-wrap: break-word; + + a { + &:not(.img-link) { + @extend %link-underline; + + &:hover { + @extend %link-hover; + } + } + + &.img-link + em { + display: block; + text-align: center; + font-style: normal; + font-size: 80%; + padding: 0; + color: #6d6c6c; + } + + } + + ul { + // attribute 'hide-bullet' was added by liquid + .task-list-item[hide-bullet] { + list-style-type: none; + + > i { // checkbox icon + margin: 0 0.4rem 0.2rem -1.4rem; + vertical-align: middle; + color: var(--checkbox-color); + + &.checked { + color: var(--checkbox-checked-color); + } + } + + } + + input[type=checkbox] { + margin: 0 0.5rem 0.2rem -1.3rem; + vertical-align: middle; + } + + } // ul + + > ol, + > ul { + padding-left: 2rem; + + li { + ol, + ul { // sub list + padding-left: 2rem; + margin-top: 0.3rem; + } + } + + } + + > ol { + li { + padding-left: 0.25em; + } + } + + dl > dd { + margin-left: 1rem; + } + +} // .post-content + +.tag:hover { + @extend %tag-hover; +} + +.post-tag { + display: inline-block; + min-width: 2rem; + text-align: center; + background: var(--tag-bg); + border-radius: 0.3rem; + padding: 0 0.4rem; + color: inherit; + line-height: 1.3rem; + + &:not(:last-child) { + margin-right: 0.2rem; + } + + &:hover { + @extend %tag-hover; + + border-bottom: none; + text-decoration: none; + color: #d2603a; + } +} + +/* --- buttons --- */ +.btn-lang { + border: 1px solid !important; + padding: 1px 3px; + border-radius: 3px; + color: var(--link-color); + + &:focus { + box-shadow: none; + } +} + +/* --- Effects classes --- */ + +.loaded { + display: block !important; + + @at-root .d-flex#{&} { + display: flex !important; + } +} + +.unloaded { + display: none !important; +} + +.visible { + visibility: visible !important; +} + +.hidden { + visibility: hidden !important; +} + +.flex-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; +} + +.btn-box-shadow { + box-shadow: 0 0 8px 0 var(--btn-box-shadow) !important; +} + +.topbar-up { + top: -3rem !important; /* same as topbar height. */ +} + +.no-text-decoration { + @include no-text-decoration; +} + +.tooltip-inner { /* Overrided BS4 Tooltip */ + font-size: 0.7rem; + max-width: 220px; + text-align: left; +} + +.disabled { + color: rgb(206, 196, 196); + pointer-events: auto; + cursor: not-allowed; +} + +.hide-border-bottom { + border-bottom: none !important; +} + +.input-focus { + box-shadow: none; + border-color: var(--input-focus-border-color) !important; + background: center !important; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out; +} + +/* --- Overriding --- */ + +// magnific-popup +figure .mfp-title { + text-align: center; + padding-right: 0; + margin-top: 0.5rem; +} + +// mermaid +.mermaid { + text-align: center; +} + +/* --- sidebar layout --- */ + +$sidebar-display: "sidebar-display"; + +#sidebar { + @include pl-pr(0); + + position: fixed; + top: 0; + left: 0; + height: 100%; + overflow-y: auto; + width: $sidebar-width; + z-index: 99; + background: var(--sidebar-bg); + + /* Hide scrollbar for Chrome, Safari and Opera */ + &::-webkit-scrollbar { + display: none; + } + + /* Hide scrollbar for IE, Edge and Firefox */ + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ + + a { + @extend %sidebar-links; + + &:hover { + @include no-text-decoration; + + color: var(--sidebar-active-color) !important; + } + } + + #avatar { + > a { + display: block; + width: 6rem; + height: 6rem; + border-radius: 50%; + border: 2px solid rgba(222, 222, 222, 0.7); + overflow: hidden; + transform: translateZ(0); // fixed the zoom in Safari + -webkit-transition: border-color 0.35s ease-in-out; + -moz-transition: border-color 0.35s ease-in-out; + transition: border-color 0.35s ease-in-out; + + &:hover { + border-color: white; + } + } + + img { + width: 100%; + height: 100%; + -webkit-transition: transform 0.5s; + -moz-transition: transform 0.5s; + transition: transform 0.5s; + + &:hover { + -ms-transform: scale(1.2); + -moz-transform: scale(1.2); + -webkit-transform: scale(1.2); + transform: scale(1.2); + } + } + } // #avatar + + .site-title { + a { + @extend %clickable-transition; + + font-weight: 900; + font-size: 1.5rem; + letter-spacing: 0.5px; + color: rgba(134, 133, 133, 99%); + } + } + + .site-subtitle { + font-size: 95%; + color: var(--sidebar-muted-color); + line-height: 1.2rem; + word-spacing: 1px; + margin: 0.5rem 1.5rem 0.5rem 1.5rem; + min-height: 3rem; // avoid vertical shifting in multi-line words + user-select: none; + } + + .nav-link { + border-radius: 0; + font-size: 0.95rem; + font-weight: 600; + letter-spacing: 1px; + display: table-cell; + vertical-align: middle; + } + + .nav-item { + text-align: center; + display: table; + height: $tab-height; + + &.active { + .nav-link { + color: var(--sidebar-active-color); + } + } + + &:not(.active) > a { + @extend %clickable-transition; + } + } + + ul { + height: $tab-height * $tab-count; + margin-bottom: 2rem; + padding-left: 0; + + li { + width: 100%; + + &:last-child { + a { + position: relative; + left: $cursor-width / 2; + width: 100%; + } + + &::after { // the cursor + display: table; + visibility: hidden; + content: ""; + position: relative; + right: 1px; + width: $cursor-width; + height: $tab-cursor-height; + border-radius: 1px; + background-color: var(--nav-cursor-color); + pointer-events: none; + } + } + } // li + + @mixin fix-cursor($top) { + top: $top; + visibility: visible; + } + + @for $i from 1 through $tab-count { + $offset: $tab-count - $i; + $top: -$offset * $tab-height + ($tab-height - $tab-cursor-height) / 2; + + @if $i < $tab-count { + > li.active:nth-child(#{$i}), + > li.nav-item:nth-child(#{$i}):hover { + ~ li:last-child::after { + @include fix-cursor($top); + } + } + } @else { + > li.active:nth-child(#{$i}):last-child::after, + > li.nav-item:nth-child(#{$i}):last-child:hover::after { + @include fix-cursor($top); + } + } + + } // @for + + } // ul + + .sidebar-bottom { + font-size: 1.2rem; + margin-bottom: 2.1rem; + + @include ml-mr(auto); + @include pl-pr(1rem); + + %icon { + width: 2.4rem; + text-align: center; + } + + a { + @extend %icon; + @extend %clickable-transition; + } + + i { + line-height: 1.75rem; // default line-height in body + vertical-align: middle; + + @extend %cursor-pointer; + } + + .icon-border { + @extend %no-cursor; + + background-color: var(--sidebar-muted-color); + content: ""; + width: 3px; + height: 3px; + border-radius: 50%; + } + + } // .sidebar-bottom + +} // #sidebar + +@media (hover: hover) { + #sidebar ul > li:last-child::after { + -webkit-transition: top 0.5s ease; + -moz-transition: top 0.5s ease; + -o-transition: top 0.5s ease; + transition: top 0.5s ease; + } +} + +.profile-wrapper { + margin-top: 2rem; + width: 100%; +} + +#search-result-wrapper { + display: none; + height: 100%; + overflow: auto; + + .post-content { + margin-top: 2rem; + } +} + +/* --- top-bar --- */ + +#topbar-wrapper { + height: $topbar-height; + position: fixed; + top: 0; + left: $sidebar-width; /* same as sidebar width */ + right: 0; + transition: top 0.2s ease-in-out; + z-index: 50; + border-bottom: 1px solid rgba(0, 0, 0, 0.07); + background-color: var(--topbar-wrapper-bg); +} + +#topbar { + i { // icons + color: #999; + } + + #breadcrumb { + font-size: 1rem; + color: gray; + padding-left: 0.5rem; + + a:hover { + @extend %link-hover; + } + + span { + &:not(:last-child) { + &::after { + content: "›"; + padding: 0 0.3rem; + } + } + } + } +} // #topbar + +#sidebar-trigger, +#search-trigger { + display: none; +} + +#search-wrapper { + display: flex; + width: 85%; + border-radius: 1rem; + border: 1px solid var(--search-wrapper-border-color); + background: var(--search-wrapper-bg); + padding: 0 0.5rem; + + i { + z-index: 2; + font-size: 0.9rem; + color: var(--search-icon-color); + } + + .fa-times-circle { /* button 'clean up' */ + @extend %cursor-pointer; + + visibility: hidden; + } +} + +#search-cancel { /* 'Cancel' link */ + color: var(--link-color); + margin-left: 1rem; + display: none; + + @extend %cursor-pointer; +} + +#search-input { + background: center; + border: 0; + border-radius: 0; + padding: 0.18rem 0.3rem; + color: var(--text-color); + + &:focus { + box-shadow: none; + background: center; + + &.form-control { + &::-webkit-input-placeholder { @include input-placeholder; } + &::-moz-placeholder { @include input-placeholder; } + &:-ms-input-placeholder { @include input-placeholder; } + &::placeholder { @include input-placeholder; } + } + } +} + +#search-hints { + padding: 0 1rem; + + h4 { + margin-bottom: 1.5rem; + } + + .post-tag { + display: inline-block; + line-height: 1rem; + font-size: 1rem; + background: var(--search-tag-bg); + border: none; + padding: 0.5rem; + margin: 0 1.25rem 1rem 0; + + &::before { + content: "#"; + color: var(--text-muted-color); + padding-right: 0.2rem; + } + + @extend %link-color; + } +} + +#search-results { + padding-bottom: 6rem; + + a { + &:hover { + @extend %link-hover; + } + + @extend %link-color; + @extend %no-bottom-border; + @extend %heading; + + font-size: 1.4rem; + line-height: 2.5rem; + } + + > div { + width: 100%; + + &:not(:last-child) { + margin-bottom: 1rem; + } + + i { // icons + color: #818182; + margin-right: 0.15rem; + font-size: 80%; + } + + > p { + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + } + } +} // #search-results + +#topbar-title { + display: none; + font-size: 1.1rem; + font-weight: 600; + font-family: sans-serif; + color: var(--topbar-text-color); + text-align: center; + width: 70%; + overflow: hidden; + text-overflow: ellipsis; + word-break: keep-all; + white-space: nowrap; +} + +#core-wrapper { + min-height: calc(100vh - #{$topbar-height} - #{$footer-height} - #{$bottom-min-height}) !important; + + .categories, + #tags, + #archives { + a:not(:hover) { + @extend %no-bottom-border; + } + } +} + +#mask { + display: none; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + height: 100%; + width: 100%; + z-index: 1; + + @at-root [#{$sidebar-display}] & { + display: block !important; + } +} + +/* --- main wrapper --- */ + +#main-wrapper { + background-color: var(--main-wrapper-bg); + position: relative; + min-height: 100vh; + padding-bottom: $footer-height; + + @include pl-pr(0); +} + +#main { + .row:first-child { + > div { + &:nth-child(1), + &:nth-child(2) { + margin-top: $topbar-height; /* same as the height of topbar */ + } + + &:first-child { + /* 3rem for topbar, 6rem for footer */ + min-height: calc(100vh - #{$topbar-height} - #{$footer-height} - #{$bottom-min-height}); + } + } + } + + .row.alone { + margin-bottom: 4rem; + } +} + +#topbar-wrapper.row, +#main > .row, +#search-result-wrapper > .row { + @include ml-mr(0); +} + +/* --- button back-to-top --- */ + +#back-to-top { + $size: 2.7em; + + display: none; + z-index: 1; + cursor: pointer; + position: fixed; + background: var(--button-bg); + color: var(--btn-backtotop-color); + padding: 0; + width: $size; + height: $size; + border-radius: 50%; + border: 1px solid var(--btn-backtotop-border-color); + transition: transform 0.2s ease-out; + -webkit-transition: transform 0.2s ease-out; + + i { + line-height: $size; + position: relative; + bottom: 2px; + } +} + +#back-to-top:hover { + transform: translate3d(0, -5px, 0); + -webkit-transform: translate3d(0, -5px, 0); +} + +/* + Responsive Design: + + {sidebar, content, panel} >= 1120px screen width + {sidebar, content} >= 850px screen width + {content} <= 849px screen width + +*/ + +@media all and (max-width: 576px) { + + $footer-height: $footer-height-mobile; // overwrite + + #main > div.row:first-child > div:first-child { + min-height: calc(100vh - #{$topbar-height} - #{$footer-height}); + } + + #core-wrapper { + min-height: calc(100vh - #{$topbar-height} - #{$footer-height} - #{$bottom-min-height}) !important; + + h1 { + margin-top: 2.2rem; + font-size: 1.55rem; + } + } + + #avatar > a { + width: 5rem; + height: 5rem; + } + + .site-subtitle { + @include ml-mr(1.8rem); + } + + #main-wrapper { + padding-bottom: $footer-height; + } + + footer { + height: $footer-height; + + > div.d-flex { + width: 100%; + padding: 1.5rem 0; + margin-bottom: 0.3rem; + flex-wrap: wrap; + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + + .footer-left, + .footer-right { + text-align: center; + } + } + +} + +/* hide sidebar and panel */ +@media all and (max-width: 849px) { + %slide { + -webkit-transition: transform 0.4s ease; + transition: transform 0.4s ease; + } + + html, + body { + overflow-x: hidden; + } + + .footnotes ol > li { + padding-top: 3.5rem; + margin-top: -3.2rem; + + &:first-child { + margin-top: -3.5rem; + } + } + + [#{$sidebar-display}] { + #sidebar { + transform: translateX(0); + } + + #topbar-wrapper, + #main-wrapper { + transform: translateX(#{$sidebar-width}); + } + + } + + #sidebar { + @extend %slide; + + transform: translateX(-#{$sidebar-width}); // hide + -webkit-transform: translateX(-#{$sidebar-width}); + + .cursor { + -webkit-transition: none; + -moz-transition: none; + transition: none; + } + } + + #main-wrapper { + @extend %slide; + + padding-top: $topbar-height; + } + + #search-result-wrapper { + width: 100%; + } + + #breadcrumb, + #search-wrapper { + display: none; + } + + #topbar-wrapper { + @extend %slide; + + left: 0; + } + + .topbar-up { + top: 0 !important; + } + + #main > div.row:first-child > div:nth-child(1), + #main > div.row:first-child > div:nth-child(2) { + margin-top: 0; + } + + #topbar-title, + #sidebar-trigger, + #search-trigger { + display: block; + } + + #search-wrapper { + &.loaded ~ a { + margin-right: 1rem; + } + + .fa-times-circle { + right: 5.2rem; + } + } + + #search-input { + margin-left: 0; + width: 95%; + } + + #search-result-wrapper .post-content { + letter-spacing: 0; + } + + #tags { + -webkit-box-pack: center !important; + -ms-flex-pack: center !important; + justify-content: center !important; + } + + h1.dynamic-title { + display: none; + + ~ .post-content { + margin-top: 3rem; + } + } + +} // max-width: 849px + +/* Phone & Pad */ +@media all and (min-width: 577px) and (max-width: 1199px) { + footer > .d-flex > div { + width: 312px; + } +} + +/* Sidebar is visible */ +@media all and (min-width: 850px) { + /* Solved jumping scrollbar */ + html { + overflow-y: scroll; + } + + #main-wrapper { + margin-left: $sidebar-width; + } + + .profile-wrapper { + margin-top: 3rem; + } + + #search-wrapper { + width: 22%; + min-width: 150px; + } + + #search-result-wrapper { + margin-top: 3rem; + } + + div.post-content .table-wrapper > table { + min-width: 70%; + } + + /* button 'back-to-Top' position */ + #back-to-top { + bottom: 5.5rem; + right: 1.2rem; + } + + .topbar-up { + box-shadow: none !important; + } + + #topbar-title { + text-align: left; + } + + footer > div.d-flex { + width: 92%; + } + +} + +/* Pad horizontal */ +@media all and (min-width: 992px) and (max-width: 1199px) { + #main .col-lg-11 { + -webkit-box-flex: 0; + -ms-flex: 0 0 96%; + flex: 0 0 96%; + max-width: 96%; + } +} + +/* Compact icons in sidebar & panel hidden */ +@media all and (min-width: 850px) and (max-width: 1199px) { + #sidebar { + width: $sidebar-width-small; + + .site-subtitle { + margin-left: 1rem; + margin-right: 1rem; + } + + .sidebar-bottom { + a, + span { + width: 2rem; + } + + .icon-border { + left: -3px; + } + } + } + + #topbar-wrapper { + left: 210px; + } + + #search-results > div { + max-width: 700px; + } + + .site-title { + font-size: 1.3rem; + margin-left: 0 !important; + } + + .site-subtitle { + @include ml-mr(1rem); + + font-size: 90%; + } + + #main-wrapper { + margin-left: 210px; + } + + #breadcrumb { + width: 65%; + overflow: hidden; + text-overflow: ellipsis; + word-break: keep-all; + white-space: nowrap; + } + +} + +/* panel hidden */ +@media all and (max-width: 1199px) { + #panel-wrapper { + display: none; + } + + #topbar { + padding: 0; + } + + #main > div.row { + -webkit-box-pack: center !important; + -ms-flex-pack: center !important; + justify-content: center !important; + } +} + +/* --- desktop mode, both sidebar and panel are visible --- */ + +@media all and (min-width: 1200px) { + #main > div.row > div.col-xl-8 { + -webkit-box-flex: 0; + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + padding-left: 3%; + } + + #topbar { + padding: 0; + max-width: 1070px; + } + + #panel-wrapper { + max-width: $panel-max-width; + } + + #back-to-top { + bottom: 6.5rem; + right: 4.3rem; + } + + #search-input { + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; + } + + #search-results > div { + width: 46%; + + &:nth-child(odd) { + margin-right: 1.5rem; + } + + &:nth-child(even) { + margin-left: 1.5rem; + } + + &:last-child:nth-child(odd) { + position: relative; + right: 24.3%; + } + } + + #search-hints { + display: none; + } + + .post-content { + font-size: 1.03rem; + } + + footer > div.d-felx { + width: 85%; + } + +} + +@media all and (min-width: 1400px) { + #main > div.row { + padding-left: calc((100% - #{$main-content-max-width}) / 2); + + > div.col-xl-8 { + max-width: 850px; + } + } + + #search-result-wrapper { + padding-right: 2rem; + + > div { + max-width: 1110px; + } + } + + #search-wrapper .fa-times-circle { + right: 2.6rem; + } + +} + +@media all and (min-width: 1400px) and (max-width: 1650px) { + #topbar { + padding-right: 2rem; + } +} + +@media all and (min-width: 1650px) { + #breadcrumb { + padding-left: 0; + } + + #main > div.row > div.col-xl-8 { + padding-left: 0; + + > div:first-child { + padding-left: 0.55rem !important; + padding-right: 1.9rem !important; + } + } + + #main-wrapper { + margin-left: $sidebar-width-large; + } + + #panel-wrapper { + margin-left: calc((100% - #{$main-content-max-width}) / 10); + } + + #topbar-wrapper { + left: $sidebar-width-large; + } + + #topbar { + max-width: #{$main-content-max-width}; + } + + #search-wrapper { + margin-right: 3%; + } + + #sidebar { + width: $sidebar-width-large; + + .profile-wrapper { + margin-top: 4rem; + margin-bottom: 1rem; + + &.text-center { + text-align: left !important; + } + + %profile-ml { + margin-left: 4.5rem; + } + + #avatar { + @extend %profile-ml; + + > a { + width: 6.2rem; + height: 6.2rem; + + &.mx-auto { + margin-left: 0 !important; + } + } + } + + .site-title { + @extend %profile-ml; + + a { + font-size: 1.7rem; + letter-spacing: 1px; + } + } + + .site-subtitle { + @extend %profile-ml; + + word-spacing: 0; + margin-top: 0.3rem; + } + + } // .profile-wrapper (min-width: 1650px) + + ul { + padding-left: 2.5rem; + + > li:last-child { + > a { + position: static; + } + } + + .nav-item { + text-align: left; + + .nav-link { + > span { + letter-spacing: 2px; + } + + > i { + &.unloaded { + display: inline-block !important; + } + } + } + + } + } + + .sidebar-bottom { + padding-left: 3.5rem; + width: 100%; + + $icon-block-size: 2rem; + + &.justify-content-center { + -webkit-box-pack: start !important; + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + + > span, + > a { + @include ml-mr(0.15rem); + + height: $icon-block-size; + margin-bottom: 0.5rem; // wrap line + } + + i { + background-color: var(--sidebar-btn-bg); + font-size: 1rem; + width: $icon-block-size; + height: $icon-block-size; + border-radius: 50%; + position: relative; + + &::before { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + } + + .icon-border { + top: 0.9rem; + } + + } // .sidebar-bottom + + } // #sidebar + + footer > div.d-flex { + width: 92%; + max-width: 1140px; + } + + #search-result-wrapper { + > div { + max-width: #{$main-content-max-width}; + } + } + +} // min-width: 1650px + +@media all and (min-width: 1700px) { + #topbar-wrapper { + /* 100% - 350px - (1920px - 350px); */ + padding-right: calc(100% - #{$sidebar-width-large} - (1920px - #{$sidebar-width-large})); + } + + #topbar { + max-width: calc(#{$main-content-max-width} + 20px); + } + + #main > div.row { + padding-left: calc((100% - #{$main-content-max-width} - 2%) / 2); + } + + #panel-wrapper { + margin-left: 3%; + } + + footer { + padding-left: 0; + padding-right: calc(100% - #{$sidebar-width-large} - 1180px); + } + + #back-to-top { + right: calc(100% - 1920px + 15rem); + } + +} + +@media (min-width: 1920px) { + #main > div.row { + padding-left: 190px; + } + + #search-result-wrapper { + padding-right: calc(100% - #{$sidebar-width-large} - 1180px); + } + + #panel-wrapper { + margin-left: 41px; + } +} diff --git a/_sass/addon/module.scss b/_sass/addon/module.scss new file mode 100644 index 00000000..51d3c88d --- /dev/null +++ b/_sass/addon/module.scss @@ -0,0 +1,119 @@ +/* +* Mainly scss modules, only imported to `assets/css/main.scss` +*/ + +/* ---------- scss placeholder --------- */ + +%heading { + color: var(--heading-color); + font-weight: 400; + font-family: 'Lato', 'Microsoft Yahei', sans-serif; +} + +%tag-hover { + background: var(--tag-hover); + transition: background 0.35s ease-in-out; +} + +%table-cell { + padding: 0.4rem 1rem; + font-size: 95%; + white-space: nowrap; +} + +%link-hover { + color: #d2603a !important; + border-bottom: 1px solid #d2603a; + text-decoration: none; +} + +%link-color { + color: var(--link-color); +} + +%link-underline { + border-bottom: 1px solid var(--link-underline-color); +} + +%clickable-transition { + transition: color 0.35s ease-in-out; +} + +%no-cursor { + user-select: none; +} + +%no-bottom-border { + border-bottom: none; +} + +%section { + #core-wrapper & { + line-height: 1.2; + margin-bottom: 1rem; + } +} + +%anchor { + padding-top: 3.5rem; + margin-top: -2.5rem; +} + +%cursor-pointer { + cursor: pointer; +} + +%normal-font-style { + font-style: normal; +} + +/* ---------- scss mixin --------- */ + +@mixin no-text-decoration { + text-decoration: none; +} + +%sidebar-links { + color: rgba(117, 117, 117, 0.9); + user-select: none; +} + +@mixin ml-mr($value) { + margin-left: $value; + margin-right: $value; +} + +@mixin pl-pr($val) { + padding-left: $val; + padding-right: $val; +} + +@mixin input-placeholder { + opacity: 0.6; +} + +@mixin label($font-size: 1rem, $font-weight: 600, $color: var(--label-color)) { + color: $color; + font-size: $font-size; + font-weight: $font-weight; +} + +@mixin panel-label { + @include label(inherit); + + display: block; + line-height: 1.2; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + margin-top: 0; + margin-bottom: 0; + letter-spacing: -0.02em; +} + +@mixin align-center { + position: relative; + left: 50%; + -webkit-transform: translateX(-50%); + -ms-transform: translateX(-50%); + transform: translateX(-50%); +} diff --git a/_sass/addon/syntax.scss b/_sass/addon/syntax.scss new file mode 100644 index 00000000..bff740b2 --- /dev/null +++ b/_sass/addon/syntax.scss @@ -0,0 +1,275 @@ +/* +* The syntax highlight. +*/ + +@import "colors/light-syntax"; +@import "colors/dark-syntax"; + +html:not([mode]), +html[mode=light] { + @include light-syntax; +} + +html[mode=dark] { + @include dark-syntax; +} + +@media (prefers-color-scheme: dark) { + html:not([mode]), + html[mode=dark] { + @include dark-syntax; + } + + html[mode=light] { + @include light-syntax; + } +} + +/* -- Codes Snippet -- */ + +$code-radius: 6px; + +%code-snippet-bg { + background: var(--highlight-bg-color); +} + +%code-snippet-radius { + border-radius: $code-radius; +} + +%code-snippet-padding { + padding-left: 1rem; + padding-right: 1.5rem; +} + +.highlighter-rouge { + @extend %code-snippet-bg; + @extend %code-snippet-radius; + + color: var(--highlighter-rouge-color); + margin-top: 0.5rem; + margin-bottom: 1.2em; /* Override BS Inline-code style */ +} + +.highlight { + @extend %code-snippet-radius; + @extend %code-snippet-bg; + + @at-root figure#{&} { + @extend %code-snippet-bg; + } + + overflow: auto; + padding-top: 0.5rem; + padding-bottom: 1rem; + + pre { + margin-bottom: 0; + font-size: $code-font-size; + line-height: 1.4rem; + word-wrap: normal; /* Fixed Safari overflow-x */ + } + + table { + td pre { + overflow: visible; /* Fixed iOS safari overflow-x */ + word-break: normal; /* Fixed iOS safari linenos code break */ + } + } + + .lineno { + padding-right: 0.5rem; + min-width: 2.2rem; + text-align: right; + color: var(--highlight-lineno-color); + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; + } + + /* set the dollar sign to non-selectable */ + .gp { + user-select: none; + } + +} //.highlight + +code { + -webkit-hyphens: none; + -ms-hyphens: none; + -moz-hyphens: none; + hyphens: none; + + &.highlighter-rouge { + font-size: $code-font-size; + padding: 3px 5px; + border-radius: 4px; + background-color: var(--inline-code-bg); + } + + a > &.highlighter-rouge { + padding-bottom: 0; // show link's underlinke + color: inherit; + } + + a:hover > &.highlighter-rouge { + border-bottom: none; + } + + blockquote &.highlighter-rouge { + color: inherit; + } + + .highlight > & { + color: transparent; + } +} + +td.rouge-code { + @extend %code-snippet-padding; + + // Prevent some browser extends from + // changing the URL string of code block. + a { + color: inherit !important; + border-bottom: none !important; + pointer-events: none; + } + +} + +/* Hide line numbers for default, console, and terminal code snippets */ +div { + &[class^='highlighter-rouge'], + &.language-plaintext.highlighter-rouge, + &.language-console.highlighter-rouge, + &.language-terminal.highlighter-rouge, + &.nolineno { + pre.lineno { + display: none; + } + + td.rouge-code { + padding-left: 1.5rem; + } + } +} + +.code-header { + @extend %no-cursor; + + $code-header-height: 2.25rem; + + border-top-left-radius: $code-radius; + border-top-right-radius: $code-radius; + display: flex; + justify-content: space-between; + align-items: center; + height: $code-header-height; + + &::before { + $dot-size: 0.75rem; + $dot-margin: 0.5rem; + + content: ""; + display: inline-block; + margin-left: 1rem; + width: $dot-size; + height: $dot-size; + border-radius: 50%; + background-color: var(--code-header-muted-color); + box-shadow: + ($dot-size + $dot-margin) 0 0 var(--code-header-muted-color), + ($dot-size + $dot-margin) * 2 0 0 var(--code-header-muted-color); + } + + // the label block + span { + // label icon + i { + font-size: 1rem; + margin-right: 0.4rem; + color: var(--code-header-icon-color); + + &.small { + font-size: 70%; + } + } + + @at-root [file] #{&} > i { + position: relative; + top: 1px; // center the file icon + } + + // label text + &::after { + content: attr(label-text); + font-size: 0.85rem; + font-weight: 600; + color: var(--code-header-text-color); + } + } + + // clipboard + button { + @extend %cursor-pointer; + + border: 1px solid transparent; + border-radius: $code-radius; + height: $code-header-height; + width: $code-header-height; + padding: 0; + background-color: inherit; + + i { + color: var(--code-header-icon-color); + } + + &[timeout] { + &:hover { + border-color: var(--clipboard-checked-color); + } + + i { + color: var(--clipboard-checked-color); + } + } + + &:not([timeout]):hover { + background-color: rgba(128, 128, 128, 0.37); + + i { + color: white; + } + } + + &:focus { + outline: none; + } + + } + +} + +@media all and (max-width: 576px) { + .post-content { + > div[class^='language-'] { + @include ml-mr(-1.25rem); + + border-radius: 0; + + .highlight { + padding-left: 0.25rem; + } + + .code-header { + border-radius: 0; + padding-left: 0.4rem; + padding-right: 0.5rem; + } + } + } +} diff --git a/_sass/addon/variables.scss b/_sass/addon/variables.scss new file mode 100644 index 00000000..43192f09 --- /dev/null +++ b/_sass/addon/variables.scss @@ -0,0 +1,34 @@ +/* + * The SCSS variables + */ + +/* sidebar */ + +$sidebar-width: 260px !default; // the basic width +$sidebar-width-small: 210px !default; // screen width: >= 850px, <= 1199px (iPad landscape) +$sidebar-width-large: 350px !default; // screen width: >= 1650px + +/* tabs of sidebar */ + +$tab-count: 5 !default; // backward compatible (version <= 4.0.2) +$tab-height: 3rem !default; +$tab-cursor-height: 1.6rem !default; + +$cursor-width: 2px !default; // the cursor width of the selected tab + +/* other framework sizes */ + +$topbar-height: 3rem !default; + +$footer-height: 5rem !default; +$footer-height-mobile: 6rem !default; // screen width: <= 576px + +$main-content-max-width: 1150px !default; + +$panel-max-width: 300px !default; + +$bottom-min-height: 35rem !default; + +/* syntax highlight */ + +$code-font-size: 0.85rem !default; diff --git a/_sass/colors/dark-syntax.scss b/_sass/colors/dark-syntax.scss new file mode 100644 index 00000000..03228e14 --- /dev/null +++ b/_sass/colors/dark-syntax.scss @@ -0,0 +1,88 @@ +/* + * The syntax dark mode styles. + */ + +@mixin dark-syntax { + /* syntax highlight colors from https://raw.githubusercontent.com/jwarby/pygments-css/master/monokai.css */ + .highlight pre { background-color: var(--highlight-bg-color); } + .highlight .hll { background-color: var(--highlight-bg-color); } + .highlight .c { color: #75715e; } /* Comment */ + .highlight .err { color: #960050; background-color: #1e0010; } /* Error */ + .highlight .k { color: #66d9ef; } /* Keyword */ + .highlight .l { color: #ae81ff; } /* Literal */ + .highlight .n { color: #f8f8f2; } /* Name */ + .highlight .o { color: #f92672; } /* Operator */ + .highlight .p { color: #f8f8f2; } /* Punctuation */ + .highlight .cm { color: #75715e; } /* Comment.Multiline */ + .highlight .cp { color: #75715e; } /* Comment.Preproc */ + .highlight .c1 { color: #75715e; } /* Comment.Single */ + .highlight .cs { color: #75715e; } /* Comment.Special */ + .highlight .ge { color: inherit; font-style: italic; } /* Generic.Emph */ + .highlight .gs { font-weight: bold; } /* Generic.Strong */ + .highlight .kc { color: #66d9ef; } /* Keyword.Constant */ + .highlight .kd { color: #66d9ef; } /* Keyword.Declaration */ + .highlight .kn { color: #f92672; } /* Keyword.Namespace */ + .highlight .kp { color: #66d9ef; } /* Keyword.Pseudo */ + .highlight .kr { color: #66d9ef; } /* Keyword.Reserved */ + .highlight .kt { color: #66d9ef; } /* Keyword.Type */ + .highlight .ld { color: #e6db74; } /* Literal.Date */ + .highlight .m { color: #ae81ff; } /* Literal.Number */ + .highlight .s { color: #e6db74; } /* Literal.String */ + .highlight .na { color: #a6e22e; } /* Name.Attribute */ + .highlight .nb { color: #f8f8f2; } /* Name.Builtin */ + .highlight .nc { color: #a6e22e; } /* Name.Class */ + .highlight .no { color: #66d9ef; } /* Name.Constant */ + .highlight .nd { color: #a6e22e; } /* Name.Decorator */ + .highlight .ni { color: #f8f8f2; } /* Name.Entity */ + .highlight .ne { color: #a6e22e; } /* Name.Exception */ + .highlight .nf { color: #a6e22e; } /* Name.Function */ + .highlight .nl { color: #f8f8f2; } /* Name.Label */ + .highlight .nn { color: #f8f8f2; } /* Name.Namespace */ + .highlight .nx { color: #a6e22e; } /* Name.Other */ + .highlight .py { color: #f8f8f2; } /* Name.Property */ + .highlight .nt { color: #f92672; } /* Name.Tag */ + .highlight .nv { color: #f8f8f2; } /* Name.Variable */ + .highlight .ow { color: #f92672; } /* Operator.Word */ + .highlight .w { color: #f8f8f2; } /* Text.Whitespace */ + .highlight .mf { color: #ae81ff; } /* Literal.Number.Float */ + .highlight .mh { color: #ae81ff; } /* Literal.Number.Hex */ + .highlight .mi { color: #ae81ff; } /* Literal.Number.Integer */ + .highlight .mo { color: #ae81ff; } /* Literal.Number.Oct */ + .highlight .sb { color: #e6db74; } /* Literal.String.Backtick */ + .highlight .sc { color: #e6db74; } /* Literal.String.Char */ + .highlight .sd { color: #e6db74; } /* Literal.String.Doc */ + .highlight .s2 { color: #e6db74; } /* Literal.String.Double */ + .highlight .se { color: #ae81ff; } /* Literal.String.Escape */ + .highlight .sh { color: #e6db74; } /* Literal.String.Heredoc */ + .highlight .si { color: #e6db74; } /* Literal.String.Interpol */ + .highlight .sx { color: #e6db74; } /* Literal.String.Other */ + .highlight .sr { color: #e6db74; } /* Literal.String.Regex */ + .highlight .s1 { color: #e6db74; } /* Literal.String.Single */ + .highlight .ss { color: #e6db74; } /* Literal.String.Symbol */ + .highlight .bp { color: #f8f8f2; } /* Name.Builtin.Pseudo */ + .highlight .vc { color: #f8f8f2; } /* Name.Variable.Class */ + .highlight .vg { color: #f8f8f2; } /* Name.Variable.Global */ + .highlight .vi { color: #f8f8f2; } /* Name.Variable.Instance */ + .highlight .il { color: #ae81ff; } /* Literal.Number.Integer.Long */ + .highlight .gu { color: #75715e; } /* Generic.Subheading & Diff Unified/Comment? */ + .highlight .gd { color: #f92672; background-color: #561c08; } /* Generic.Deleted & Diff Deleted */ + .highlight .gi { color: #a6e22e; background-color: #0b5858; } /* Generic.Inserted & Diff Inserted */ + + /* ----- custom styles ------ */ + + --highlight-bg-color: #252525; + --highlighter-rouge-color: #de6b18; + --highlight-lineno-color: #6c6c6d; + --inline-code-bg: #272822; + --code-header-text-color: #6a6a6a; + --code-header-muted-color: rgb(60 60 60); + --code-header-icon-color: rgb(86 86 86); + --clipboard-checked-color: #2bcc2b; + + .highlight { + .gp { color: #818c96; } + } + + pre { color: #bfbfbf; } /* override Bootstrap */ + kbd { background-color: black; } +} diff --git a/_sass/colors/dark-typography.scss b/_sass/colors/dark-typography.scss new file mode 100644 index 00000000..586ebd2a --- /dev/null +++ b/_sass/colors/dark-typography.scss @@ -0,0 +1,145 @@ +/* + * The main dark mode styles + */ + +@mixin dark-scheme { + /* Framework color */ + --body-bg: var(--main-wrapper-bg); + --mask-bg: rgb(68, 69, 70); + --main-wrapper-bg: rgb(27, 27, 30); + --main-border-color: rgb(44, 45, 45); + + /* Common color */ + --text-color: rgb(175, 176, 177); + --text-muted-color: rgb(107, 116, 124); + --heading-color: #cccccc; + --blockquote-border-color: rgb(66, 66, 66); + --blockquote-text-color: rgb(117, 117, 117); + --link-color: rgb(138, 180, 248); + --link-underline-color: rgb(82, 108, 150); + --button-bg: rgb(39, 40, 43); + --btn-border-color: rgb(63, 65, 68); + --btn-backtotop-color: var(--text-color); + --btn-backtotop-border-color: var(--btn-border-color); + --btn-box-shadow: var(--main-wrapper-bg); + --card-header-bg: rgb(51, 50, 50); + --label-color: rgb(108, 117, 125); + --checkbox-color: rgb(118 120 121); + --checkbox-checked-color: var(--link-color); + + /* Sidebar */ + --sidebar-bg: radial-gradient(circle, #242424 0%, #1d1f27 100%); + --sidebar-muted-color: #6d6c6b; + --sidebar-active-color: rgb(255 255 255 / 80%); + --nav-cursor-color: rgb(183, 182, 182); + --sidebar-btn-bg: rgb(117 116 116 / 20%); + + /* Topbar */ + --topbar-text-color: var(--text-color); + --topbar-wrapper-bg: rgb(39, 40, 43); + --search-wrapper-bg: rgb(34, 34, 39); + --search-wrapper-border-color: rgb(34, 34, 39); + --search-icon-color: rgb(100, 102, 105); + --input-focus-border-color: rgb(112, 114, 115); + + /* Home page */ + --post-list-text-color: rgb(175, 176, 177); + --btn-patinator-text-color: var(--text-color); + --btn-paginator-hover-color: rgb(64, 65, 66); + --btn-paginator-border-color: var(--btn-border-color); + --btn-text-color: var(--text-color); + --pin-bg: rgb(34 35 37); + --pin-color: inherit; + + /* Posts */ + --toc-highlight: rgb(116, 178, 243); + --tag-bg: rgb(41, 40, 40); + --tag-hover: rgb(43, 56, 62); + --tb-odd-bg: rgba(42, 47, 53, 0.52); /* odd rows of the posts' table */ + --tb-even-bg: rgb(31, 31, 34); /* even rows of the posts' table */ + --tb-border-color: var(--tb-odd-bg); + --footnote-target-bg: rgb(63, 81, 181); + --btn-share-color: #6c757d; + --btn-share-hover-color: #bfc1ca; + --relate-post-date: var(--text-muted-color); + --card-bg: rgb(39, 40, 43); + --card-border-color: rgb(53, 53, 60); + --card-box-shadow: var(--main-wrapper-bg); + --preview-img-bg: radial-gradient(circle, rgb(22 22 24) 0%, rgb(32 32 32) 100%); + + /* tags */ + --tag-border: rgb(59, 79, 88); + --tag-shadow: rgb(32, 33, 33); + --search-tag-bg: var(--tag-bg); + --dash-color: rgb(63, 65, 68); + + /* categories */ + --categories-border: rgb(64, 66, 69); + --categories-hover-bg: rgb(73, 75, 76); + --categories-icon-hover-color: white; + + /* archives */ + --timeline-node-bg: rgb(150, 152, 156); + --timeline-color: rgb(63, 65, 68); + --timeline-year-dot-color: var(--timeline-color); + + .post-content img { + filter: brightness(90%); + } + + hr { + border-color: var(--main-border-color); + } + + /* posts' toc, override BS */ + nav[data-toggle=toc] .nav-link.active, + nav[data-toggle=toc] .nav-link.active:focus, + nav[data-toggle=toc] .nav-link.active:hover, + nav[data-toggle=toc] .nav > li > a:focus, + nav[data-toggle=toc] .nav > li > a:hover { + color: var(--toc-highlight) !important; + border-left-color: var(--toc-highlight) !important; + } + + /* categories */ + .categories.card, + .list-group-item { + background-color: var(--card-bg); + } + + .categories { + .card-header { + background-color: var(--card-header-bg); + } + + .list-group-item { + border-left: none; + border-right: none; + padding-left: 2rem; + border-color: var(--categories-border); + + &:last-child { + border-bottom-color: var(--card-bg); + } + } + } + + #archives li:nth-child(odd) { + background-image: + linear-gradient( + to left, + rgb(26, 26, 30), + rgb(39, 39, 45), + rgb(39, 39, 45), + rgb(39, 39, 45), + rgb(26, 26, 30) + ); + } + + color-scheme: dark; + + #disqus_thread { + color-scheme: none; + } + +} // dark-scheme diff --git a/_sass/colors/light-syntax.scss b/_sass/colors/light-syntax.scss new file mode 100644 index 00000000..e8f1e29d --- /dev/null +++ b/_sass/colors/light-syntax.scss @@ -0,0 +1,79 @@ +/* + * The syntax light mode code snippet colors. + */ + +@mixin light-syntax { + /* see: <https://raw.githubusercontent.com/jwarby/pygments-css/master/github.css> */ + .highlight .hll { background-color: #ffffcc; } + .highlight .c { color: #999988; font-style: italic; } /* Comment */ + .highlight .err { color: #a61717; background-color: #e3d2d2; } /* Error */ + .highlight .k { color: #000000; font-weight: bold; } /* Keyword */ + .highlight .o { color: #000000; font-weight: bold; } /* Operator */ + .highlight .cm { color: #999988; font-style: italic; } /* Comment.Multiline */ + .highlight .cp { color: #999999; font-weight: bold; font-style: italic; } /* Comment.Preproc */ + .highlight .c1 { color: #999988; font-style: italic; } /* Comment.Single */ + .highlight .cs { color: #999999; font-weight: bold; font-style: italic; } /* Comment.Special */ + .highlight .gd { color: #d01040; background-color: #ffdddd; } /* Generic.Deleted */ + .highlight .ge { color: #000000; font-style: italic; } /* Generic.Emph */ + .highlight .gr { color: #aa0000; } /* Generic.Error */ + .highlight .gh { color: #999999; } /* Generic.Heading */ + .highlight .gi { color: #008080; background-color: #ddffdd; } /* Generic.Inserted */ + .highlight .go { color: #888888; } /* Generic.Output */ + .highlight .gp { color: #555555; } /* Generic.Prompt */ + .highlight .gs { font-weight: bold; } /* Generic.Strong */ + .highlight .gu { color: #aaaaaa; } /* Generic.Subheading */ + .highlight .gt { color: #aa0000; } /* Generic.Traceback */ + .highlight .kc { color: #000000; font-weight: bold; } /* Keyword.Constant */ + .highlight .kd { color: #000000; font-weight: bold; } /* Keyword.Declaration */ + .highlight .kn { color: #000000; font-weight: bold; } /* Keyword.Namespace */ + .highlight .kp { color: #000000; font-weight: bold; } /* Keyword.Pseudo */ + .highlight .kr { color: #000000; font-weight: bold; } /* Keyword.Reserved */ + .highlight .kt { color: #445588; font-weight: bold; } /* Keyword.Type */ + .highlight .m { color: #009999; } /* Literal.Number */ + .highlight .s { color: #d01040; } /* Literal.String */ + .highlight .na { color: #008080; } /* Name.Attribute */ + .highlight .nb { color: #0086b3; } /* Name.Builtin */ + .highlight .nc { color: #445588; font-weight: bold; } /* Name.Class */ + .highlight .no { color: #008080; } /* Name.Constant */ + .highlight .nd { color: #3c5d5d; font-weight: bold; } /* Name.Decorator */ + .highlight .ni { color: #800080; } /* Name.Entity */ + .highlight .ne { color: #990000; font-weight: bold; } /* Name.Exception */ + .highlight .nf { color: #990000; font-weight: bold; } /* Name.Function */ + .highlight .nl { color: #990000; font-weight: bold; } /* Name.Label */ + .highlight .nn { color: #555555; } /* Name.Namespace */ + .highlight .nt { color: #000080; } /* Name.Tag */ + .highlight .nv { color: #008080; } /* Name.Variable */ + .highlight .ow { color: #000000; font-weight: bold; } /* Operator.Word */ + .highlight .w { color: #bbbbbb; } /* Text.Whitespace */ + .highlight .mf { color: #009999; } /* Literal.Number.Float */ + .highlight .mh { color: #009999; } /* Literal.Number.Hex */ + .highlight .mi { color: #009999; } /* Literal.Number.Integer */ + .highlight .mo { color: #009999; } /* Literal.Number.Oct */ + .highlight .sb { color: #d01040; } /* Literal.String.Backtick */ + .highlight .sc { color: #d01040; } /* Literal.String.Char */ + .highlight .sd { color: #d01040; } /* Literal.String.Doc */ + .highlight .s2 { color: #d01040; } /* Literal.String.Double */ + .highlight .se { color: #d01040; } /* Literal.String.Escape */ + .highlight .sh { color: #d01040; } /* Literal.String.Heredoc */ + .highlight .si { color: #d01040; } /* Literal.String.Interpol */ + .highlight .sx { color: #d01040; } /* Literal.String.Other */ + .highlight .sr { color: #009926; } /* Literal.String.Regex */ + .highlight .s1 { color: #d01040; } /* Literal.String.Single */ + .highlight .ss { color: #990073; } /* Literal.String.Symbol */ + .highlight .bp { color: #999999; } /* Name.Builtin.Pseudo */ + .highlight .vc { color: #008080; } /* Name.Variable.Class */ + .highlight .vg { color: #008080; } /* Name.Variable.Global */ + .highlight .vi { color: #008080; } /* Name.Variable.Instance */ + .highlight .il { color: #009999; } /* Literal.Number.Integer.Long */ + + /* --- custom light colors --- */ + --highlight-bg-color: #f7f7f7; + --highlighter-rouge-color: #2f2f2f; + --highlight-lineno-color: #c2c6cc; + --inline-code-bg: #f3f3f3; + --code-header-text-color: #a3a3b1; + --code-header-muted-color: #ebebeb; + --code-header-icon-color: #d1d1d1; + --clipboard-checked-color: #43c743; + +} // light-syntax diff --git a/_sass/colors/light-typography.scss b/_sass/colors/light-typography.scss new file mode 100644 index 00000000..cf19cee6 --- /dev/null +++ b/_sass/colors/light-typography.scss @@ -0,0 +1,78 @@ +/* + * The syntax light mode typography colors + */ + +@mixin light-scheme { + /* Framework color */ + --body-bg: #fafafa; + --mask-bg: #c1c3c5; + --main-wrapper-bg: white; + --main-border-color: #f3f3f3; + + /* Common color */ + --text-color: #34343c; + --text-muted-color: gray; + --heading-color: black; + --blockquote-border-color: #eee; + --blockquote-text-color: #9a9a9a; + --link-color: #2a408e; + --link-underline-color: #dee2e6; + --button-bg: #fff; + --btn-border-color: #e9ecef; + --btn-backtotop-color: #686868; + --btn-backtotop-border-color: #f1f1f1; + --btn-box-shadow: #eaeaea; + --checkbox-color: #c5c5c5; + --checkbox-checked-color: #07a8f7; + + /* Sidebar */ + --sidebar-bg: #eeeeee; + --sidebar-muted-color: #a2a19f; + --sidebar-active-color: #424242; + --nav-cursor-color: #757575; + --sidebar-btn-bg: white; + + /* Topbar */ + --topbar-text-color: rgb(78, 78, 78); + --topbar-wrapper-bg: white; + --search-wrapper-bg: rgb(245 245 245 / 50%); + --search-wrapper-border-color: rgb(245 245 245); + --search-tag-bg: #f8f9fa; + --search-icon-color: #c2c6cc; + --input-focus-border-color: var(--btn-border-color); + + /* Home page */ + --post-list-text-color: dimgray; + --btn-patinator-text-color: #555555; + --btn-paginator-hover-color: var(--sidebar-bg); + --btn-paginator-border-color: var(--sidebar-bg); + --btn-text-color: #676666; + --pin-bg: #f5f5f5; + --pin-color: #999fa4; + + /* Posts */ + --btn-share-hover-color: var(--link-color); + --card-border-color: #f1f1f1; + --card-box-shadow: rgba(234, 234, 234, 0.7686274509803922); + --label-color: #616161; + --relate-post-date: rgba(30, 55, 70, 0.4); + --footnote-target-bg: lightcyan; + --tag-bg: rgba(0, 0, 0, 0.075); + --tag-border: #dee2e6; + --tag-shadow: var(--btn-border-color); + --tag-hover: rgb(222, 226, 230); + --tb-odd-bg: #fbfcfd; + --tb-border-color: #eaeaea; + --dash-color: silver; + --preview-img-bg: radial-gradient(circle, rgb(255 255 255) 0%, rgb(249 249 249) 100%); + + /* Categories */ + --categories-hover-bg: var(--btn-border-color); + --categories-icon-hover-color: darkslategray; + + /* Archive */ + --timeline-color: rgba(0, 0, 0, 0.075); + --timeline-node-bg: #c2c6cc; + --timeline-year-dot-color: #ffffff; + +} // light-scheme diff --git a/_sass/jekyll-theme-chirpy.scss b/_sass/jekyll-theme-chirpy.scss new file mode 100644 index 00000000..bfe01578 --- /dev/null +++ b/_sass/jekyll-theme-chirpy.scss @@ -0,0 +1,25 @@ +/*! + * The styles for Jekyll theme Chirpy + * + * Chirpy v4.3.4 (https://github.com/cotes2020/jekyll-theme-chirpy) + * © 2019 Cotes Chung + * MIT Licensed + */ + +@import + "colors/light-typography", + "colors/dark-typography", + + "addon/module", + "addon/variables", + "variables-hook", + "addon/syntax", + "addon/commons", + + "layout/home", + "layout/post", + "layout/tags", + "layout/archives", + "layout/categories", + "layout/category-tag", + "layout/project"; diff --git a/_sass/layout/archives.scss b/_sass/layout/archives.scss new file mode 100644 index 00000000..9df652fc --- /dev/null +++ b/_sass/layout/archives.scss @@ -0,0 +1,147 @@ +/* + Style for Archives +*/ + +%date-timeline { + content: ""; + width: 4px; + left: 75px; + display: inline-block; + float: left; + position: relative; + background-color: var(--timeline-color); +} + +#archives { + letter-spacing: 0.03rem; + + span.lead { + font-size: 1.5rem; + position: relative; + left: 8px; + + &::after { /* Year dot */ + content: ""; + display: block; + position: relative; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border-radius: 50%; + width: 12px; + height: 12px; + top: -26px; + left: 63px; + border: 3px solid; + background-color: var(--timeline-year-dot-color); + border-color: var(--timeline-node-bg); + box-shadow: 0 0 2px 0 #c2c6cc; + z-index: 1; + } + + &:not(:first-child) { + position: relative; + left: 4px; + + &::after { + left: 67px; + } + } + + } // #archives span.lead + + ul { + li { + font-size: 1.1rem; + line-height: 3rem; + + div { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + a { + /* post title in Archvies */ + margin-left: 2.5rem; + position: relative; + top: 0.1rem; + } + } + + &:nth-child(odd) { + background-color: var(--main-wrapper-bg, #fff); + background-image: linear-gradient(to left, #fff, #fbfbfb, #fbfbfb, #fbfbfb, #fff); + } + + &::after { + @extend %date-timeline; + + height: 2.8rem; + top: -1.3rem; + } + + &:first-child::before { + @extend %date-timeline; + + height: 3.06rem; + top: -1.61rem; + } + } + + &:not(:last-child) > li:last-child::after { + height: 3.4rem; + } + + &:last-child > li:last-child::after { + display: none; + } + } // #archives ul + + .date { + white-space: nowrap; + display: inline-block; + + &.month { + width: 1.4rem; + text-align: center; + + ~ a::before { + /* A dot for Month and Day */ + content: ""; + display: inline-block; + position: relative; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border-radius: 50%; + width: 8px; + height: 8px; + float: left; + top: 1.35rem; + left: 69px; + background-color: var(--timeline-node-bg); + box-shadow: 0 0 3px 0 #c2c6cc; + z-index: 1; + } + } + + &.day { + font-size: 85%; + font-family: 'Lato', sans-serif; + text-align: center; + margin-right: -2px; + width: 1.2rem; + position: relative; + left: -0.15rem; + } + } // #archives .date + +} // #archives + +@media all and (max-width: 576px) { + #archives { + margin-top: -1rem; + + ul { + letter-spacing: 0; + } + } +} diff --git a/_sass/layout/categories.scss b/_sass/layout/categories.scss new file mode 100644 index 00000000..29a3463e --- /dev/null +++ b/_sass/layout/categories.scss @@ -0,0 +1,67 @@ +/* + Style for Tab Categories +*/ + +%category-icon-color { + color: gray; +} + +.categories { + margin-bottom: 2rem; + + .card-header { + padding-right: 12px; + } + + i { + @extend %category-icon-color; + + font-size: 86%; // fontawesome icons + } + + .list-group-item { + border-left: none; + border-right: none; + padding-left: 2rem; + + &:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; + } + + } + +} // .categories + +.category-trigger { + width: 1.7rem; + height: 1.7rem; + border-radius: 50%; + text-align: center; + color: #6c757d !important; + + &:hover { + i { + color: var(--categories-icon-hover-color); + } + } + + i { + position: relative; + height: 0.7rem; + width: 1rem; + transition: transform 300ms ease; + } +} + +@media (hover: hover) { // only works on desktop + .category-trigger:hover { + background-color: var(--categories-hover-bg); + } +} + +.rotate { + -ms-transform: rotate(-90deg); /* IE 9 */ + -webkit-transform: rotate(-90deg); /* Safari 3-8 */ + transform: rotate(-90deg); +} diff --git a/_sass/layout/category-tag.scss b/_sass/layout/category-tag.scss new file mode 100644 index 00000000..e6d12d2f --- /dev/null +++ b/_sass/layout/category-tag.scss @@ -0,0 +1,73 @@ +/* + Style for page Category and Tag +*/ + +.dash { + margin: 0 0.5rem 0.6rem 0.5rem; + border-bottom: 2px dotted var(--dash-color); +} + +#page-category, +#page-tag { + ul > li { + line-height: 1.5rem; + padding: 0.6rem 0; + + &::before { // dot + background: #999; + width: 5px; + height: 5px; + border-radius: 50%; + display: block; + content: ""; + position: relative; + top: 0.6rem; + margin-right: 0.5rem; + } + + > a { /* post's title */ + @extend %no-bottom-border; + + font-size: 1.1rem; + } + + > span:last-child { + white-space: nowrap; + } /* post's date */ + } +} + +#page-tag h1 > i { // tag icon + font-size: 1.2rem; +} + +#page-category h1 > i { + font-size: 1.25rem; +} + +#page-category, +#page-tag, +#access-lastmod { + a:hover { + @extend %link-hover; + + margin-bottom: -1px; // Avoid jumping + } +} + +@media all and (max-width: 576px) { + #page-category, + #page-tag { + ul > li { + &::before { + margin: 0 0.5rem; + } + + > a { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + } + } +} diff --git a/_sass/layout/home.scss b/_sass/layout/home.scss new file mode 100644 index 00000000..af80ba32 --- /dev/null +++ b/_sass/layout/home.scss @@ -0,0 +1,184 @@ +/* + Style for Homepage +*/ + +.pagination { + color: var(--btn-patinator-text-color); + font-family: 'Lato', sans-serif; + + a:hover { + text-decoration: none; + } + + .page-item { + .page-link { + color: inherit; + width: 2.5rem; + height: 2.5rem; + padding: 0; + display: -webkit-box; + -webkit-box-pack: center; + -webkit-box-align: center; + border-radius: 50%; + border: 1px solid var(--btn-paginator-border-color); + background-color: var(--button-bg); + + &:hover { + background-color: var(--btn-paginator-hover-color); + } + } + + &.active { + .page-link { + background-color: var(--btn-paginator-hover-color); + color: var(--btn-text-color); + } + } + + &.disabled { + cursor: not-allowed; + + .page-link { + color: rgba(108, 117, 125, 0.57); + border-color: var(--btn-paginator-border-color); + background-color: var(--button-bg); + } + } + + &:first-child .page-link, + &:last-child .page-link { + border-radius: 50%; + } + } // .page-item + +} // .pagination + +#post-list { + margin-top: 1rem; + padding-right: 0.5rem; + + .post-preview { + padding-top: 1.5rem; + padding-bottom: 1rem; + border-bottom: 1px solid var(--main-border-color); + + a:hover { + @extend %link-hover; + } + + h1 { + font-size: 1.4rem; + margin: 0; + } + + .post-meta { + i { + font-size: 0.73rem; + + &:not(:first-child) { + margin-left: 1.2rem; + } + } + + em { + @extend %normal-font-style; + } + } + + .post-content { + margin-top: 0.6rem; + margin-bottom: 0.6rem; + color: var(--post-list-text-color); + + > p { + /* Make preview shorter on the homepage */ + margin: 0; + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + } + } + + .pin { + > i { + transform: rotate(45deg); + padding-left: 3px; + color: var(--pin-color); + } + + > span { + display: none; + } + } + + } // .post-preview +} // #post-list + +/* Hide SideBar and TOC */ +@media all and (max-width: 830px) { + .pagination { + justify-content: space-evenly; + + .page-item { + &:not(:first-child):not(:last-child) { + display: none; + } + + } + + } +} + +/* Sidebar is visible */ +@media all and (min-width: 831px) { + #post-list { + margin-top: 1.5rem; + + .post-preview .post-meta { + .pin { + background: var(--pin-bg); + border-radius: 5px; + line-height: 1.4rem; + height: 1.3rem; + margin-top: 3px; + padding-left: 1px; + padding-right: 6px; + + > span { + display: inline; + } + } + } + } + + .pagination { + font-size: 0.85rem; + + .page-item { + &:not(:last-child) { + margin-right: 0.7rem; + } + + .page-link { + width: 2rem; + height: 2rem; + } + + } + + .page-index { + display: none; + } + + } // .pagination + +} + +/* Pannel hidden */ +@media all and (max-width: 1200px) { + #post-list { + padding-right: 0; + } +} diff --git a/_sass/layout/post.scss b/_sass/layout/post.scss new file mode 100644 index 00000000..bcb811f8 --- /dev/null +++ b/_sass/layout/post.scss @@ -0,0 +1,371 @@ +/* + Post-specific style +*/ + +@mixin btn-sharing-color($light-color, $important: false) { + @if $important { + color: var(--btn-share-color, $light-color) !important; + } @else { + color: var(--btn-share-color, $light-color); + } +} + +@mixin btn-post-nav { + width: 50%; + position: relative; + border-color: var(--btn-border-color); +} + +@mixin dot($pl: 0.25rem, $pr: 0.25rem) { + content: "\2022"; + padding-left: $pl; + padding-right: $pr; +} + +%text-color { + color: var(--text-color); +} + +h1 + .post-meta { + span + span::before { + @include dot; + } + + em { + @extend %text-color; + + a { + @extend %text-color; + } + } +} + +img.preview-img { + margin-top: 3.75rem; + margin-bottom: 0; + border-radius: 6px; + + &.bg[data-loaded=true] { + background: var(--preview-img-bg); + } +} + +.post-tail-wrapper { + margin-top: 6rem; + border-bottom: 1px double var(--main-border-color); + font-size: 0.85rem; + + .post-meta a { + @extend %link-underline; + } +} + +.post-tags { + line-height: 2rem; +} + +.post-navigation { + padding-top: 3rem; + padding-bottom: 4rem; + + .btn { + @include btn-post-nav; + + color: var(--link-color); + + &:hover { + background: #2a408e; + color: #fff; + border-color: #2a408e; + } + + &.disabled { + @include btn-post-nav; + + pointer-events: auto; + cursor: not-allowed; + background: none; + color: gray; + + &:hover { + border-color: none; + } + } + + &.btn-outline-primary.disabled:focus { + box-shadow: none; + } + + &::before { + color: var(--text-muted-color); + font-size: 0.65rem; + text-transform: uppercase; + content: attr(prompt); + } + + &:first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + left: 0.5px; + } + + &:last-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + right: 0.5px; + } + } + + p { + font-size: 1.1rem; + line-height: 1.5rem; + margin-top: 0.3rem; + white-space: normal; + } + +} // .post-navigation + +@keyframes fade-up { + from { + opacity: 0; + position: relative; + top: 2rem; + } + to { + opacity: 1; + position: relative; + top: 0; + } +} + +#toc-wrapper { + border-left: 1px solid rgba(158, 158, 158, 0.17); + position: -webkit-sticky; + position: sticky; + top: 4rem; + transition: top 0.2s ease-in-out; + animation: fade-up 0.8s; + + &.topbar-down { + top: 6rem; + } + + > span { + @include panel-label; + } +} + +#toc li a { + font-size: 0.8rem; + + &.nav-link:not(.active) { + color: inherit; + } + +} + +nav[data-toggle=toc] { + .nav { + .nav > li > a.active { + font-weight: 600 !important; + } + } +} + +/* --- Related Posts --- */ + +#related-posts { + > h3 { + @include label(1.1rem, 600); + } + + em { + @extend %normal-font-style; + } + + .card { + border-color: var(--card-border-color); + background-color: var(--card-bg); + box-shadow: 0 0 5px 0 var(--card-box-shadow); + -webkit-transition: all 0.3s ease-in-out; + -moz-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; + + h3 { + @extend %text-color; + } + + &:hover { + -webkit-transform: translate3d(0, -3px, 0); + transform: translate3d(0, -3px, 0); + box-shadow: 0 10px 15px -4px rgba(0, 0, 0, 0.15); + } + } + + .timeago { + color: var(--relate-post-date); + } + + p { + font-size: 0.9rem; + margin-bottom: 0.5rem; + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + } + + a:hover { + text-decoration: none; + } + + ul { + list-style-type: none; + padding-inline-start: 1.5rem; + + > li::before { + background: #c2c9d4; + width: 5px; + height: 5px; + border-radius: 1px; + display: block; + content: ""; + position: relative; + top: 1rem; + right: 1rem; + } + } +} + +#tail-wrapper { + min-height: 2rem; + + #disqus_thread { + min-height: 7.5rem; + margin-bottom: 2rem; + } + +} + +.post-tail-bottom a { + color: inherit; +} + +%btn-share-hovor { + color: var(--btn-share-hover-color) !important; +} + +.share-wrapper { + vertical-align: middle; + user-select: none; + + .share-icons { + font-size: 1.2rem; + + a { + &:not(:last-child) { + margin-right: 0.25rem; + } + + &:hover { + text-decoration: none; + + > i { + @extend %btn-share-hovor; + } + } + } + + > i { + position: relative; + bottom: 1px; + + @extend %cursor-pointer; + + &:hover { + @extend %btn-share-hovor; + } + } + + .fab { + &.fa-twitter { + @include btn-sharing-color(rgba(29, 161, 242, 1)); + } + + &.fa-facebook-square { + @include btn-sharing-color(rgb(66, 95, 156)); + } + + &.fa-telegram { + @include btn-sharing-color(rgb(39, 159, 217)); + } + + &.fa-weibo { + @include btn-sharing-color(rgb(229, 20, 43)); + } + } + + } // .share-icons + + .fas.fa-link { + @include btn-sharing-color(rgb(171, 171, 171)); + } + +} // .share-wrapper + +.share-label { + @include label(inherit, 400, inherit); + + &::after { + content: ":"; + } +} + +.license-wrapper { + line-height: 1.2rem; + + > a { + color: var(--text-color); + + &:hover { + @extend %link-hover; + } + } + + span:last-child { + font-size: 0.85rem; + } +} // .license-wrapper + +@media all and (max-width: 576px) { + .preview-img[data-src] { + margin-top: 2.2rem; + } + + .post-tail-bottom { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + + > div:first-child { + width: 100%; + margin-top: 1rem; + } + } +} + +@media all and (max-width: 768px) { + .post-content > p > img { + max-width: calc(100% + 1rem); + } +} + +/* Hide SideBar and TOC */ +@media all and (max-width: 830px) { + .post-navigation { + padding-left: 0; + padding-right: 0; + margin-left: -0.5rem; + margin-right: -0.5rem; + } +} diff --git a/_sass/layout/project.scss b/_sass/layout/project.scss new file mode 100644 index 00000000..e1c15ace --- /dev/null +++ b/_sass/layout/project.scss @@ -0,0 +1,19 @@ +.project { +} + +.project-list-item { +} + +.project-title { + a { + margin: 4px; + border-bottom: none !important; + } + + i { + font-size: 20px; + } +} + +.project-desc { +} diff --git a/_sass/layout/tags.scss b/_sass/layout/tags.scss new file mode 100644 index 00000000..ab6c7b52 --- /dev/null +++ b/_sass/layout/tags.scss @@ -0,0 +1,19 @@ +/* + Styles for Tab Tags +*/ + +.tag { + border-radius: 0.7em; + padding: 6px 8px 7px; + margin-right: 0.8rem; + line-height: 3rem; + letter-spacing: 0; + border: 1px solid var(--tag-border) !important; + box-shadow: 0 0 3px 0 var(--tag-shadow); + + span { + margin-left: 0.6em; + font-size: 0.7em; + font-family: 'Oswald', sans-serif; + } +} diff --git a/_sass/variables-hook.scss b/_sass/variables-hook.scss new file mode 100644 index 00000000..f27e0eb8 --- /dev/null +++ b/_sass/variables-hook.scss @@ -0,0 +1,3 @@ +/* + Appending custom SCSS variables will override the default ones in `_sass/addon/variables.scsss` +*/ diff --git a/_tabs/about.md b/_tabs/about.md new file mode 100644 index 00000000..35a7b85b --- /dev/null +++ b/_tabs/about.md @@ -0,0 +1,83 @@ +--- +title: About +icon: fas fa-info-circle +order: 4 +--- + +ゲームと語学が好きな中国人です。たまにソースコードも書きます。 + +#### <font color="red">ポップン/発狂PMS</font> +* 未クリア2 全埋め頑張る +* ポプともID:632820141042 登録はお気軽に +* PMS五期発狂八段、●10~●14を中心にプレイしている + +#### 格ゲー +* MBTL 琥珀使い。最高Aランク。初心者脱出目指す。1500戦くらい +* BBCF セリカかわいい。誰にも勝てない。 +* BBTAG ルビー&ワイス早く結婚して 1300戦 + +#### シューティング +* 基本はヘタレなクリアラーです +* クリアリスト + * 怒首領蜂 大復活 裏二周目 Bスト + * 虫姫さま ふたり マニアック レコ・ノーマル + * デススマイルズ [ウィンディア(LV3縛り・EXあり)](https://www.bilibili.com/video/BV18h411i7UE) + * 怒首領蜂 最大往生 [A-S(陽蜂なし・オートボムON)](https://www.bilibili.com/video/BV1iA411w7zG) + * エスプガルーダII [アゲハ](https://www.bilibili.com/video/BV1564y197GP) [アサギ(真セセリあり)](https://www.bilibili.com/video/BV1Q44y1t7Xy/) + * 怒首領蜂 大復活 ブラックラーベル [Bボム(ヒバチあり)](https://www.bilibili.com/video/BV1wq4y1r7V2) + * 東方永夜抄L 結界組 + * 東方紺珠伝L 早苗 + * 東方天空璋L [霊夢冬(季節開放封印)](https://www.bilibili.com/video/BV1AW411g745) + * 東方虹龍洞L [霊夢(手動ボム封印)](https://www.bilibili.com/video/BV1Bq4y1j7Q5) 早苗 +* スコアタ + * 2016.11.24 ウィンディア Ex-off [3.20億](https://www.bilibili.com/video/BV1uQ4y1m7Bh) + +#### diva FT +* アケコンでやってる [動画1](https://www.bilibili.com/video/BV1RW411k7VZ) [動画2](https://www.bilibili.com/video/BV1u54y1p77f) + +#### ぷよテト +* テトリスメイン +* ぷよテトS 40ライン1:09 レート12000台 +* ぷよテト2 40ライン[1:11.96](https://www.bilibili.com/video/BV1sy4y1L7Dr) ウルトラ[4万ちょい](https://www.bilibili.com/video/BV1pv411J7W5) レート1400(パズル)/1500(テト)くらい + +#### djmax repsect +* 8BのS埋め頑張ってます + +#### 太鼓の達人 +* ACおに全良12譜面(★10 1譜面) +* 家庭用もよくやります + +#### ギタドラ +* ドラム 最高銅ネ 最近やってない +* ギター 最高赤ネ 最近やってない + +#### 麻雀 +* 天鳳特南六段 +* 今までの段位遷移:4545456 + +#### WOW +* 引退しました +* Alge#11734 アリーナ勢 基本はHorde +* <font color="#8787ED">Warlock: <a href="https://worldofwarcraft.com/en-us/character/us/blackrock/algetest">Algetest</a>, <a href="https://worldofwarcraft.com/en-us/character/us/blackrock/algezest">Algezest</a>, <a href="https://worldofwarcraft.com/en-us/character/us/proudmoore/algenest">Algenest</a></font> + * bfa s3: 2s 2400, 3s 2100 + * bfa s4: 2s 2500, 3s Glad x3 最高2800 + * sl s1: destro Glad, aff 最高2300 +* <font color="#40C7EB">Mage: <a href="https://worldofwarcraft.com/en-us/character/us/blackrock/algepest">Algepest</a></font> + * bfa s4: 2s 2200, 3s 2400 + * sl s1: Glad + +#### 語学ゲーム(日本語) +* 軌跡シリーズ 空fc/空sc/空3rd/零/碧/閃/閃II/閃III/閃IV +* イース セルセタの樹海 +* ファイナルファンタジーX/X-2/XV +* メモリーズオフ 6 complete/ゆびきりの記憶 +* ダンガンロンパ1・2 Reload +* FLOWERS 春篇/夏篇/秋篇/冬篇 +* ホワイトアルバム1/2 +* Fate/stay night +* 月姫R +* 逆転裁判1/6 + +#### 語学ゲーム(英語) +* Life Is Strange 日本語バージョンもあるので皆さんもやってみよう! +* Diablo 2: Resurrected 語学の価値ほぼない diff --git a/_tabs/archives.md b/_tabs/archives.md new file mode 100644 index 00000000..f969f92f --- /dev/null +++ b/_tabs/archives.md @@ -0,0 +1,7 @@ +--- +layout: archives +title: Archives +icon: fas fa-archive +order: 3 +--- + diff --git a/_tabs/projects.md b/_tabs/projects.md new file mode 100644 index 00000000..d361423b --- /dev/null +++ b/_tabs/projects.md @@ -0,0 +1,19 @@ +--- +layout: page +title: Projects +icon: fas fa-project-diagram +order: 2 +--- + +<div class="project"> + {% for project in site.projects %} + <div class="project-list-item"> + <h2 class="project-title"> + {{ project.title }} + <span><a href="{{ project.url }}"><i class="fa fa-link"></i></a></span> + <span><a href="{{ project.github }}"><i class="fab fa-github"></i></a></span> + </h2> + <p class="project-desc">{{ project.description }}</p> + </div> + {% endfor %} +</div> \ No newline at end of file diff --git a/_tabs/tags.md b/_tabs/tags.md new file mode 100644 index 00000000..2108d24a --- /dev/null +++ b/_tabs/tags.md @@ -0,0 +1,6 @@ +--- +layout: tags +title: Tags +icon: fas fa-tag +order: 2 +--- diff --git a/assets/2016-12-29-version-1-1-2/1.jpg b/assets/2016-12-29-version-1-1-2/1.jpg new file mode 100644 index 00000000..fb7d3f2a Binary files /dev/null and b/assets/2016-12-29-version-1-1-2/1.jpg differ diff --git a/assets/2017-01-15-game-center/1.jpeg b/assets/2017-01-15-game-center/1.jpeg new file mode 100644 index 00000000..9429461e Binary files /dev/null and b/assets/2017-01-15-game-center/1.jpeg differ diff --git a/assets/2017-01-23-kac/1.png b/assets/2017-01-23-kac/1.png new file mode 100644 index 00000000..59cab835 Binary files /dev/null and b/assets/2017-01-23-kac/1.png differ diff --git a/assets/2017-01-23-kac/2.png b/assets/2017-01-23-kac/2.png new file mode 100644 index 00000000..4cb3e5cc Binary files /dev/null and b/assets/2017-01-23-kac/2.png differ diff --git a/assets/2017-06-18-tenhou-1/1.png b/assets/2017-06-18-tenhou-1/1.png new file mode 100644 index 00000000..1cd0ed0b Binary files /dev/null and b/assets/2017-06-18-tenhou-1/1.png differ diff --git a/assets/2017-06-18-tenhou-1/10.png b/assets/2017-06-18-tenhou-1/10.png new file mode 100644 index 00000000..f9516510 Binary files /dev/null and b/assets/2017-06-18-tenhou-1/10.png differ diff --git a/assets/2017-06-18-tenhou-1/11.png b/assets/2017-06-18-tenhou-1/11.png new file mode 100644 index 00000000..220f530d Binary files /dev/null and b/assets/2017-06-18-tenhou-1/11.png differ diff --git a/assets/2017-06-18-tenhou-1/12.png b/assets/2017-06-18-tenhou-1/12.png new file mode 100644 index 00000000..5fc6fcca Binary files /dev/null and b/assets/2017-06-18-tenhou-1/12.png differ diff --git a/assets/2017-06-18-tenhou-1/13.png b/assets/2017-06-18-tenhou-1/13.png new file mode 100644 index 00000000..f5772f6b Binary files /dev/null and b/assets/2017-06-18-tenhou-1/13.png differ diff --git a/assets/2017-06-18-tenhou-1/14.png b/assets/2017-06-18-tenhou-1/14.png new file mode 100644 index 00000000..52eb0256 Binary files /dev/null and b/assets/2017-06-18-tenhou-1/14.png differ diff --git a/assets/2017-06-18-tenhou-1/2.png b/assets/2017-06-18-tenhou-1/2.png new file mode 100644 index 00000000..de2d5583 Binary files /dev/null and b/assets/2017-06-18-tenhou-1/2.png differ diff --git a/assets/2017-06-18-tenhou-1/3.png b/assets/2017-06-18-tenhou-1/3.png new file mode 100644 index 00000000..6556e642 Binary files /dev/null and b/assets/2017-06-18-tenhou-1/3.png differ diff --git a/assets/2017-06-18-tenhou-1/4.png b/assets/2017-06-18-tenhou-1/4.png new file mode 100644 index 00000000..ee58cf96 Binary files /dev/null and b/assets/2017-06-18-tenhou-1/4.png differ diff --git a/assets/2017-06-18-tenhou-1/5.png b/assets/2017-06-18-tenhou-1/5.png new file mode 100644 index 00000000..1808f82e Binary files /dev/null and b/assets/2017-06-18-tenhou-1/5.png differ diff --git a/assets/2017-06-18-tenhou-1/6.png b/assets/2017-06-18-tenhou-1/6.png new file mode 100644 index 00000000..7dade2f3 Binary files /dev/null and b/assets/2017-06-18-tenhou-1/6.png differ diff --git a/assets/2017-06-18-tenhou-1/7.png b/assets/2017-06-18-tenhou-1/7.png new file mode 100644 index 00000000..4dae9a40 Binary files /dev/null and b/assets/2017-06-18-tenhou-1/7.png differ diff --git a/assets/2017-06-18-tenhou-1/8.png b/assets/2017-06-18-tenhou-1/8.png new file mode 100644 index 00000000..3dd5afad Binary files /dev/null and b/assets/2017-06-18-tenhou-1/8.png differ diff --git a/assets/2017-06-18-tenhou-1/9.png b/assets/2017-06-18-tenhou-1/9.png new file mode 100644 index 00000000..1a09a06e Binary files /dev/null and b/assets/2017-06-18-tenhou-1/9.png differ diff --git a/assets/2017-07-09-tenhou-2/N1.2-1.png b/assets/2017-07-09-tenhou-2/N1.2-1.png new file mode 100644 index 00000000..74f83e55 Binary files /dev/null and b/assets/2017-07-09-tenhou-2/N1.2-1.png differ diff --git a/assets/2017-07-09-tenhou-2/N2.0-1.png b/assets/2017-07-09-tenhou-2/N2.0-1.png new file mode 100644 index 00000000..735877f9 Binary files /dev/null and b/assets/2017-07-09-tenhou-2/N2.0-1.png differ diff --git a/assets/2017-07-09-tenhou-2/N2.0-2.png b/assets/2017-07-09-tenhou-2/N2.0-2.png new file mode 100644 index 00000000..375ffef9 Binary files /dev/null and b/assets/2017-07-09-tenhou-2/N2.0-2.png differ diff --git a/assets/2017-07-09-tenhou-2/N2.0-3.png b/assets/2017-07-09-tenhou-2/N2.0-3.png new file mode 100644 index 00000000..5a9d4f37 Binary files /dev/null and b/assets/2017-07-09-tenhou-2/N2.0-3.png differ diff --git a/assets/2017-07-09-tenhou-2/N2.0-4.png b/assets/2017-07-09-tenhou-2/N2.0-4.png new file mode 100644 index 00000000..ad1a6cfe Binary files /dev/null and b/assets/2017-07-09-tenhou-2/N2.0-4.png differ diff --git a/assets/2017-07-09-tenhou-2/N2.1-1.png b/assets/2017-07-09-tenhou-2/N2.1-1.png new file mode 100644 index 00000000..17118dfc Binary files /dev/null and b/assets/2017-07-09-tenhou-2/N2.1-1.png differ diff --git a/assets/2017-07-09-tenhou-2/N2.1-2.png b/assets/2017-07-09-tenhou-2/N2.1-2.png new file mode 100644 index 00000000..1d033aa5 Binary files /dev/null and b/assets/2017-07-09-tenhou-2/N2.1-2.png differ diff --git a/assets/2017-07-09-tenhou-2/N2.1-3.png b/assets/2017-07-09-tenhou-2/N2.1-3.png new file mode 100644 index 00000000..3586cc8c Binary files /dev/null and b/assets/2017-07-09-tenhou-2/N2.1-3.png differ diff --git a/assets/2017-07-09-tenhou-2/N3.1-1.png b/assets/2017-07-09-tenhou-2/N3.1-1.png new file mode 100644 index 00000000..08b99bb6 Binary files /dev/null and b/assets/2017-07-09-tenhou-2/N3.1-1.png differ diff --git a/assets/2017-07-09-tenhou-2/T2.0-1.png b/assets/2017-07-09-tenhou-2/T2.0-1.png new file mode 100644 index 00000000..13846410 Binary files /dev/null and b/assets/2017-07-09-tenhou-2/T2.0-1.png differ diff --git a/assets/2017-07-09-tenhou-2/T2.0-2.png b/assets/2017-07-09-tenhou-2/T2.0-2.png new file mode 100644 index 00000000..5bc44a09 Binary files /dev/null and b/assets/2017-07-09-tenhou-2/T2.0-2.png differ diff --git a/assets/2017-07-09-tenhou-2/T3.0-1.png b/assets/2017-07-09-tenhou-2/T3.0-1.png new file mode 100644 index 00000000..fb6cc214 Binary files /dev/null and b/assets/2017-07-09-tenhou-2/T3.0-1.png differ diff --git a/assets/2017-07-09-tenhou-2/T3.0-2.png b/assets/2017-07-09-tenhou-2/T3.0-2.png new file mode 100644 index 00000000..b3a38aa3 Binary files /dev/null and b/assets/2017-07-09-tenhou-2/T3.0-2.png differ diff --git a/assets/2017-07-09-tenhou-2/T4.0-1.png b/assets/2017-07-09-tenhou-2/T4.0-1.png new file mode 100644 index 00000000..5d54ab73 Binary files /dev/null and b/assets/2017-07-09-tenhou-2/T4.0-1.png differ diff --git a/assets/2017-07-09-tenhou-2/T4.1-1.png b/assets/2017-07-09-tenhou-2/T4.1-1.png new file mode 100644 index 00000000..eb9dc378 Binary files /dev/null and b/assets/2017-07-09-tenhou-2/T4.1-1.png differ diff --git a/assets/2017-07-09-tenhou-2/T4.1-2.png b/assets/2017-07-09-tenhou-2/T4.1-2.png new file mode 100644 index 00000000..9fb84118 Binary files /dev/null and b/assets/2017-07-09-tenhou-2/T4.1-2.png differ diff --git a/assets/2017-08-05-touhou/1.jpg b/assets/2017-08-05-touhou/1.jpg new file mode 100644 index 00000000..a4799244 Binary files /dev/null and b/assets/2017-08-05-touhou/1.jpg differ diff --git a/assets/2017-08-05-touhou/2.jpg b/assets/2017-08-05-touhou/2.jpg new file mode 100644 index 00000000..1a5eab89 Binary files /dev/null and b/assets/2017-08-05-touhou/2.jpg differ diff --git a/assets/2020-12-01-popn-01/49badcount.png b/assets/2020-12-01-popn-01/49badcount.png new file mode 100644 index 00000000..8a255b3d Binary files /dev/null and b/assets/2020-12-01-popn-01/49badcount.png differ diff --git a/assets/2021-06-26-arena-byebye/1.png b/assets/2021-06-26-arena-byebye/1.png new file mode 100644 index 00000000..46073962 Binary files /dev/null and b/assets/2021-06-26-arena-byebye/1.png differ diff --git a/assets/2021-07-11/doublemiku.jpg b/assets/2021-07-11/doublemiku.jpg new file mode 100644 index 00000000..e575d6d2 Binary files /dev/null and b/assets/2021-07-11/doublemiku.jpg differ diff --git a/assets/2021-07-11/dx3900.png b/assets/2021-07-11/dx3900.png new file mode 100644 index 00000000..c7593d65 Binary files /dev/null and b/assets/2021-07-11/dx3900.png differ diff --git a/assets/2021-08-01-popn-03/clear.png b/assets/2021-08-01-popn-03/clear.png new file mode 100644 index 00000000..ce1bf05c Binary files /dev/null and b/assets/2021-08-01-popn-03/clear.png differ diff --git a/assets/2021-08-01-popn-03/silent.jpg b/assets/2021-08-01-popn-03/silent.jpg new file mode 100644 index 00000000..82ffa33c Binary files /dev/null and b/assets/2021-08-01-popn-03/silent.jpg differ diff --git a/assets/2021-10-01/pmsclear.png b/assets/2021-10-01/pmsclear.png new file mode 100644 index 00000000..0bb92f48 Binary files /dev/null and b/assets/2021-10-01/pmsclear.png differ diff --git a/assets/2021-10-14/rank.jpg b/assets/2021-10-14/rank.jpg new file mode 100644 index 00000000..f92f064a Binary files /dev/null and b/assets/2021-10-14/rank.jpg differ diff --git a/assets/2021-10-14/shield.mp4 b/assets/2021-10-14/shield.mp4 new file mode 100644 index 00000000..22568c91 Binary files /dev/null and b/assets/2021-10-14/shield.mp4 differ diff --git a/assets/2021-10-14/trophy.png b/assets/2021-10-14/trophy.png new file mode 100644 index 00000000..56fd91fb Binary files /dev/null and b/assets/2021-10-14/trophy.png differ diff --git a/assets/2021-11-01-ex/1.jpg b/assets/2021-11-01-ex/1.jpg new file mode 100644 index 00000000..75fbfb9f Binary files /dev/null and b/assets/2021-11-01-ex/1.jpg differ diff --git a/assets/2021-11-01-ex/2.jpg b/assets/2021-11-01-ex/2.jpg new file mode 100644 index 00000000..cfca74fb Binary files /dev/null and b/assets/2021-11-01-ex/2.jpg differ diff --git a/assets/2021-11-01-ex/3.jpg b/assets/2021-11-01-ex/3.jpg new file mode 100644 index 00000000..507eee00 Binary files /dev/null and b/assets/2021-11-01-ex/3.jpg differ diff --git a/assets/2021-11-01-ex/4.jpg b/assets/2021-11-01-ex/4.jpg new file mode 100644 index 00000000..b49ac7db Binary files /dev/null and b/assets/2021-11-01-ex/4.jpg differ diff --git a/assets/2021-11-01/25oclock.jpg b/assets/2021-11-01/25oclock.jpg new file mode 100644 index 00000000..79ef7884 Binary files /dev/null and b/assets/2021-11-01/25oclock.jpg differ diff --git a/assets/2021-11-01/chaos.jpg b/assets/2021-11-01/chaos.jpg new file mode 100644 index 00000000..01242e19 Binary files /dev/null and b/assets/2021-11-01/chaos.jpg differ diff --git a/assets/2021-11-01/dirge.jpg b/assets/2021-11-01/dirge.jpg new file mode 100644 index 00000000..2cce5448 Binary files /dev/null and b/assets/2021-11-01/dirge.jpg differ diff --git a/assets/2021-11-01/en.jpg b/assets/2021-11-01/en.jpg new file mode 100644 index 00000000..f055716f Binary files /dev/null and b/assets/2021-11-01/en.jpg differ diff --git a/assets/2021-11-01/kagachi.jpg b/assets/2021-11-01/kagachi.jpg new file mode 100644 index 00000000..aa532517 Binary files /dev/null and b/assets/2021-11-01/kagachi.jpg differ diff --git a/assets/2021-11-01/pmsclear.png b/assets/2021-11-01/pmsclear.png new file mode 100644 index 00000000..f6e77ae3 Binary files /dev/null and b/assets/2021-11-01/pmsclear.png differ diff --git a/assets/2021-11-01/ppu.jpg b/assets/2021-11-01/ppu.jpg new file mode 100644 index 00000000..66a2d0e7 Binary files /dev/null and b/assets/2021-11-01/ppu.jpg differ diff --git a/assets/2021-11-01/toikon.jpg b/assets/2021-11-01/toikon.jpg new file mode 100644 index 00000000..edf03dc1 Binary files /dev/null and b/assets/2021-11-01/toikon.jpg differ diff --git a/assets/2021-11-01/touhou.jpg b/assets/2021-11-01/touhou.jpg new file mode 100644 index 00000000..152d2e5b Binary files /dev/null and b/assets/2021-11-01/touhou.jpg differ diff --git a/assets/2021-12-01/oto.jpg b/assets/2021-12-01/oto.jpg new file mode 100644 index 00000000..b82a06fc Binary files /dev/null and b/assets/2021-12-01/oto.jpg differ diff --git a/assets/404.html b/assets/404.html new file mode 100644 index 00000000..dde158a5 --- /dev/null +++ b/assets/404.html @@ -0,0 +1,33 @@ +--- +layout: page +title: "404: Page not found" +permalink: /404.html + +redirect_from: + - /norobots/ + - /assets/ + - /posts/ + +dynamic_title: true +--- + +{% include lang.html %} + +<div class="lead"> + + {%- capture _head_back -%} + <a href="{{ '/' | relative_url }}">{{ site.data.locales[lang].not_found.head_back }}</a> + {%- endcapture -%} + + {%- capture _archives_page -%} + <a href="{{ 'archives' | relative_url }}">{{ site.data.locales[lang].not_found.archives_page }}</a> + {%- endcapture -%} + + <p>{{site.data.locales[lang].not_found.statment }}</p> + + <p>{{ site.data.locales[lang].not_found.hint_template + | replace: ':HEAD_BAK', _head_back + | replace: ':ARCHIVES_PAGE', _archives_page }} + </p> + +</div> diff --git a/assets/avatar.jpg b/assets/avatar.jpg new file mode 100644 index 00000000..f638346e Binary files /dev/null and b/assets/avatar.jpg differ diff --git a/assets/css/style.scss b/assets/css/style.scss new file mode 100644 index 00000000..6ff7046e --- /dev/null +++ b/assets/css/style.scss @@ -0,0 +1,12 @@ +--- +--- + +/* + If the number of TAB files has changed, the following variable is required. + And it must be defined before `@import`. +*/ +$tab-count: {{ site.tabs | size | plus: 1 }}; // plus 1 for home tab + +@import "{{ site.theme }}"; + +/* append your custom style below */ diff --git a/assets/feed.xml b/assets/feed.xml new file mode 100644 index 00000000..b36f4afa --- /dev/null +++ b/assets/feed.xml @@ -0,0 +1,61 @@ +--- +layout: compress +permalink: /feed.xml +# Atom Feed, reference: https://validator.w3.org/feed/docs/atom.html +--- + +{% capture source %} +<feed xmlns="http://www.w3.org/2005/Atom"> + <id>{{ "/" | absolute_url }}</id> + <title>{{ site.title }} + {{ site.description }} + {{ site.time | date_to_xmlschema }} + + {{ site.social.name }} + {{ "/" | absolute_url }} + + + + Jekyll + © {{ 'now' | date: '%Y' }} {{ site.social.name }} + {{ site.baseurl }}/assets/img/favicons/favicon.ico + {{ site.baseurl }}/assets/img/favicons/favicon-96x96.png + +{% for post in site.posts limit: 5 %} + {% assign post_absolute_url = post.url | absolute_url %} + + {{ post.title }} + + {{ post.date | date_to_xmlschema }} + {% if post.last_modified_at %} + {{ post.last_modified_at | date_to_xmlschema }} + {% else %} + {{ post.date | date_to_xmlschema }} + {% endif %} + {{ post_absolute_url }} + + + {{ post.author | default: site.social.name }} + + + {% if post.categories %} + {% for category in post.categories %} + + {% endfor %} + {% endif %} + + {% if post.summary %} + {{ post.summary | strip }} + {% else %} + + {% include no-linenos.html content=post.content %} + {{ content | strip_html | truncate: 400 }} + + {% endif %} + + +{% endfor %} + +{% endcapture %} +{{ source | replace: '&', '&' }} diff --git a/assets/img/favicons/browserconfig.xml b/assets/img/favicons/browserconfig.xml new file mode 100644 index 00000000..a02a5c74 --- /dev/null +++ b/assets/img/favicons/browserconfig.xml @@ -0,0 +1,13 @@ +--- +layout: compress +--- + + + + + + + #da532c + + + diff --git a/assets/img/favicons/favicon.ico b/assets/img/favicons/favicon.ico new file mode 100644 index 00000000..0b0c562d Binary files /dev/null and b/assets/img/favicons/favicon.ico differ diff --git a/assets/img/favicons/site.webmanifest b/assets/img/favicons/site.webmanifest new file mode 100644 index 00000000..03c6113b --- /dev/null +++ b/assets/img/favicons/site.webmanifest @@ -0,0 +1,26 @@ +--- +layout: compress +--- + +{% assign favicon_path = "/assets/img/favicons" | relative_url %} + +{ + "name": "{{ site.title }}", + "short_name": "{{ site.title }}", + "description": "{{ site.description }}", + "icons": [ + { + "src": "{{ favicon_path }}/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "{{ favicon_path }}/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + }], + "start_url": "{{ '/index.html' | relative_url }}", + "theme_color": "#2a1e6b", + "background_color": "#ffffff", + "display": "fullscreen" +} diff --git a/assets/js/data/search.json b/assets/js/data/search.json new file mode 100644 index 00000000..76bee416 --- /dev/null +++ b/assets/js/data/search.json @@ -0,0 +1,17 @@ +--- +layout: compress +--- + +[ + {% for post in site.posts %} + { + "title": "{{ post.title | escape }}", + "url": "{{ post.url | relative_url }}", + "categories": "{{ post.categories | join: ', '}}", + "tags": "{{ post.tags | join: ', ' }}", + "date": "{{ post.date }}", + {% include no-linenos.html content=post.content %} + "snippet": "{{ content | strip_html | strip_newlines | remove_chars | escape | replace: '\', '\\\\' }}" + }{% unless forloop.last %},{% endunless %} + {% endfor %} +] diff --git a/assets/js/data/swcache.js b/assets/js/data/swcache.js new file mode 100644 index 00000000..ec648a02 --- /dev/null +++ b/assets/js/data/swcache.js @@ -0,0 +1,64 @@ +--- +layout: compress + +# The list to be cached by PWA +--- + +const resource = [ + + /* --- CSS --- */ + '{{ "/assets/css/style.css" | relative_url }}', + + /* --- JavaScripts --- */ + {% assign js_path = "/assets/js" | relative_url %} + '{{ js_path }}/dist/home.min.js', + '{{ js_path }}/dist/page.min.js', + '{{ js_path }}/dist/post.min.js', + '{{ js_path }}/dist/categories.min.js', + '{{ js_path }}/data/search.json', + '{{ "/app.js" | relative_url }}', + '{{ "/sw.js" | relative_url }}', + + /* --- HTML --- */ + '{{ "/index.html" | relative_url }}', + '{{ "/404.html" | relative_url }}', + {% for tab in site.tabs %} + '{{ tab.url | relative_url }}', + {% endfor %} + + /* --- Favicons --- */ + {% assign favicon_path = "/assets/img/favicons" | relative_url %} + + '{{ favicon_path }}/android-chrome-192x192.png', + '{{ favicon_path }}/android-chrome-512x512.png', + '{{ favicon_path }}/apple-touch-icon.png', + '{{ favicon_path }}/favicon-16x16.png', + '{{ favicon_path }}/favicon-32x32.png', + '{{ favicon_path }}/favicon.ico', + '{{ favicon_path }}/mstile-150x150.png', + '{{ favicon_path }}/site.webmanifest', + '{{ favicon_path }}/browserconfig.xml' + +]; + +/* The request url with below domain will be cached */ +const allowedDomains = [ + {% if site.google_analytics.id != '' %} + 'www.googletagmanager.com', + 'www.google-analytics.com', + {% endif %} + + '{{ site.url | split: "//" | last }}', + + 'fonts.gstatic.com', + 'fonts.googleapis.com', + 'cdn.jsdelivr.net', + 'polyfill.io' +]; + +/* Requests that include the following path will be banned */ +const denyUrls = [ + {% if site.google_analytics.pv.cache_path %} + '{{ site.google_analytics.pv.cache_path | absolute_url }}' + {% endif %} +]; diff --git a/assets/js/dist/categories.min.js b/assets/js/dist/categories.min.js new file mode 100644 index 00000000..11161103 --- /dev/null +++ b/assets/js/dist/categories.min.js @@ -0,0 +1,6 @@ +/*! + * Chirpy v4.3.4 (https://github.com/cotes2020/jekyll-theme-chirpy/) + * © 2019 Cotes Chung + * MIT Licensed + */ +$(function(){$(window).scroll(()=>{50<$(this).scrollTop()&&"none"===$("#sidebar-trigger").css("display")?$("#back-to-top").fadeIn():$("#back-to-top").fadeOut()}),$("#back-to-top").click(()=>($("body,html").animate({scrollTop:0},800),!1))}),$(function(){$("#mode-toggle-wrapper").keyup(e=>{13===e.keyCode&&flipMode()})}),$(function(){const e=$("#sidebar-trigger"),o=$("#search-trigger"),s=$("#search-cancel"),t=$("#search-cleaner"),a=$("#main"),l=$("#topbar-title"),n=$("#search-wrapper"),r=$("#search-result-wrapper"),d=$("#search-results"),i=$("#search-input"),c=$("#search-hints"),u=function(){let e=0;return{block(){e=window.scrollY,$("html,body").scrollTop(0)},release(){$("html,body").scrollTop(e)},getOffset(){return e}}}(),f={on(){e.addClass("unloaded"),l.addClass("unloaded"),o.addClass("unloaded"),n.addClass("d-flex"),s.addClass("loaded")},off(){s.removeClass("loaded"),n.removeClass("d-flex"),e.removeClass("unloaded"),l.removeClass("unloaded"),o.removeClass("unloaded")}},p=function(){let e=!1;return{on(){e||(u.block(),r.removeClass("unloaded"),a.addClass("unloaded"),e=!0)},off(){e&&(d.empty(),c.hasClass("unloaded")&&c.removeClass("unloaded"),r.addClass("unloaded"),t.removeClass("visible"),a.removeClass("unloaded"),u.release(),i.val(""),e=!1)},isVisible(){return e}}}();function h(){return s.hasClass("loaded")}o.click(function(){f.on(),p.on(),i.focus()}),s.click(function(){f.off(),p.off()}),i.focus(function(){n.addClass("input-focus")}),i.focusout(function(){n.removeClass("input-focus")}),i.on("keyup",function(e){8===e.keyCode&&""===i.val()?h()?c.removeClass("unloaded"):p.off():""!==i.val()&&(p.on(),t.hasClass("visible")||t.addClass("visible"),h()&&c.addClass("unloaded"))}),t.on("click",function(){i.val(""),h()?(c.removeClass("unloaded"),d.empty()):p.off(),i.focus(),t.removeClass("visible")})}),$(function(){var e=function(){const e="sidebar-display";let o=!1;const s=$("body");return{toggle(){!1===o?s.attr(e,""):s.removeAttr(e),o=!o}}}();$("#sidebar-trigger").click(e.toggle),$("#mask").click(e.toggle)}),$(function(){$('[data-toggle="tooltip"]').tooltip()}),$(function(){const o=$("#topbar-wrapper"),s=$("#toc-wrapper"),t=$(".access"),a=$("#search-input");let l,n=0;const r=o.outerHeight();$(window).scroll(function(e){$("#topbar-title").is(":hidden")&&(l=!0)}),setInterval(function(){l&&(function(){var e=$(this).scrollTop();Math.abs(n-e)<=5||(e>n&&e>r?(o.removeClass("topbar-down").addClass("topbar-up"),0h1"),s=e.text().trim();let t=(0{50<$(this).scrollTop()&&"none"===$("#sidebar-trigger").css("display")?$("#back-to-top").fadeIn():$("#back-to-top").fadeOut()}),$("#back-to-top").click(()=>($("body,html").animate({scrollTop:0},800),!1))}),$(function(){$("#mode-toggle-wrapper").keyup(e=>{13===e.keyCode&&flipMode()})}),$(function(){const e=$("#sidebar-trigger"),o=$("#search-trigger"),s=$("#search-cancel"),t=$("#search-cleaner"),a=$("#main"),l=$("#topbar-title"),n=$("#search-wrapper"),d=$("#search-result-wrapper"),r=$("#search-results"),i=$("#search-input"),c=$("#search-hints"),u=function(){let e=0;return{block(){e=window.scrollY,$("html,body").scrollTop(0)},release(){$("html,body").scrollTop(e)},getOffset(){return e}}}(),p={on(){e.addClass("unloaded"),l.addClass("unloaded"),o.addClass("unloaded"),n.addClass("d-flex"),s.addClass("loaded")},off(){s.removeClass("loaded"),n.removeClass("d-flex"),e.removeClass("unloaded"),l.removeClass("unloaded"),o.removeClass("unloaded")}},f=function(){let e=!1;return{on(){e||(u.block(),d.removeClass("unloaded"),a.addClass("unloaded"),e=!0)},off(){e&&(r.empty(),c.hasClass("unloaded")&&c.removeClass("unloaded"),d.addClass("unloaded"),t.removeClass("visible"),a.removeClass("unloaded"),u.release(),i.val(""),e=!1)},isVisible(){return e}}}();function h(){return s.hasClass("loaded")}o.click(function(){p.on(),f.on(),i.focus()}),s.click(function(){p.off(),f.off()}),i.focus(function(){n.addClass("input-focus")}),i.focusout(function(){n.removeClass("input-focus")}),i.on("keyup",function(e){8===e.keyCode&&""===i.val()?h()?c.removeClass("unloaded"):f.off():""!==i.val()&&(f.on(),t.hasClass("visible")||t.addClass("visible"),h()&&c.addClass("unloaded"))}),t.on("click",function(){i.val(""),h()?(c.removeClass("unloaded"),r.empty()):f.off(),i.focus(),t.removeClass("visible")})}),$(function(){var e=function(){const e="sidebar-display";let o=!1;const s=$("body");return{toggle(){!1===o?s.attr(e,""):s.removeAttr(e),o=!o}}}();$("#sidebar-trigger").click(e.toggle),$("#mask").click(e.toggle)}),$(function(){$('[data-toggle="tooltip"]').tooltip()}),$(function(){const o=$("#topbar-wrapper"),s=$("#toc-wrapper"),t=$(".access"),a=$("#search-input");let l,n=0;const d=o.outerHeight();$(window).scroll(function(e){$("#topbar-title").is(":hidden")&&(l=!0)}),setInterval(function(){l&&(function(){var e=$(this).scrollTop();Math.abs(n-e)<=5||(e>n&&e>d?(o.removeClass("topbar-down").addClass("topbar-up"),0h1"),s=e.text().trim();let t=(0{50<$(this).scrollTop()&&"none"===$("#sidebar-trigger").css("display")?$("#back-to-top").fadeIn():$("#back-to-top").fadeOut()}),$("#back-to-top").click(()=>($("body,html").animate({scrollTop:0},800),!1))}),$(function(){$("#mode-toggle-wrapper").keyup(t=>{13===t.keyCode&&flipMode()})}),$(function(){const t=$("#sidebar-trigger"),e=$("#search-trigger"),o=$("#search-cancel"),a=$("#search-cleaner"),s=$("#main"),n=$("#topbar-title"),l=$("#search-wrapper"),r=$("#search-result-wrapper"),d=$("#search-results"),i=$("#search-input"),c=$("#search-hints"),u=function(){let t=0;return{block(){t=window.scrollY,$("html,body").scrollTop(0)},release(){$("html,body").scrollTop(t)},getOffset(){return t}}}(),p={on(){t.addClass("unloaded"),n.addClass("unloaded"),e.addClass("unloaded"),l.addClass("d-flex"),o.addClass("loaded")},off(){o.removeClass("loaded"),l.removeClass("d-flex"),t.removeClass("unloaded"),n.removeClass("unloaded"),e.removeClass("unloaded")}},f=function(){let t=!1;return{on(){t||(u.block(),r.removeClass("unloaded"),s.addClass("unloaded"),t=!0)},off(){t&&(d.empty(),c.hasClass("unloaded")&&c.removeClass("unloaded"),r.addClass("unloaded"),a.removeClass("visible"),s.removeClass("unloaded"),u.release(),i.val(""),t=!1)},isVisible(){return t}}}();function h(){return o.hasClass("loaded")}e.click(function(){p.on(),f.on(),i.focus()}),o.click(function(){p.off(),f.off()}),i.focus(function(){l.addClass("input-focus")}),i.focusout(function(){l.removeClass("input-focus")}),i.on("keyup",function(t){8===t.keyCode&&""===i.val()?h()?c.removeClass("unloaded"):f.off():""!==i.val()&&(f.on(),a.hasClass("visible")||a.addClass("visible"),h()&&c.addClass("unloaded"))}),a.on("click",function(){i.val(""),h()?(c.removeClass("unloaded"),d.empty()):f.off(),i.focus(),a.removeClass("visible")})}),$(function(){var t=function(){const t="sidebar-display";let e=!1;const o=$("body");return{toggle(){!1===e?o.attr(t,""):o.removeAttr(t),e=!e}}}();$("#sidebar-trigger").click(t.toggle),$("#mask").click(t.toggle)}),$(function(){$('[data-toggle="tooltip"]').tooltip()}),$(function(){const e=$("#topbar-wrapper"),o=$("#toc-wrapper"),a=$(".access"),s=$("#search-input");let n,l=0;const r=e.outerHeight();$(window).scroll(function(t){$("#topbar-title").is(":hidden")&&(n=!0)}),setInterval(function(){n&&(function(){var t=$(this).scrollTop();Math.abs(l-t)<=5||(t>l&&t>r?(e.removeClass("topbar-down").addClass("topbar-up"),0h1"),o=t.text().trim();let a=(0{50<$(this).scrollTop()&&"none"===$("#sidebar-trigger").css("display")?$("#back-to-top").fadeIn():$("#back-to-top").fadeOut()}),$("#back-to-top").click(()=>($("body,html").animate({scrollTop:0},800),!1))}),$(function(){$("#mode-toggle-wrapper").keyup(e=>{13===e.keyCode&&flipMode()})}),$(function(){const e=$("#sidebar-trigger"),t=$("#search-trigger"),o=$("#search-cancel"),a=$("#search-cleaner"),l=$("#main"),s=$("#topbar-title"),n=$("#search-wrapper"),i=$("#search-result-wrapper"),r=$("#search-results"),c=$("#search-input"),d=$("#search-hints"),u=function(){let e=0;return{block(){e=window.scrollY,$("html,body").scrollTop(0)},release(){$("html,body").scrollTop(e)},getOffset(){return e}}}(),p={on(){e.addClass("unloaded"),s.addClass("unloaded"),t.addClass("unloaded"),n.addClass("d-flex"),o.addClass("loaded")},off(){o.removeClass("loaded"),n.removeClass("d-flex"),e.removeClass("unloaded"),s.removeClass("unloaded"),t.removeClass("unloaded")}},f=function(){let e=!1;return{on(){e||(u.block(),i.removeClass("unloaded"),l.addClass("unloaded"),e=!0)},off(){e&&(r.empty(),d.hasClass("unloaded")&&d.removeClass("unloaded"),i.addClass("unloaded"),a.removeClass("visible"),l.removeClass("unloaded"),u.release(),c.val(""),e=!1)},isVisible(){return e}}}();function h(){return o.hasClass("loaded")}t.click(function(){p.on(),f.on(),c.focus()}),o.click(function(){p.off(),f.off()}),c.focus(function(){n.addClass("input-focus")}),c.focusout(function(){n.removeClass("input-focus")}),c.on("keyup",function(e){8===e.keyCode&&""===c.val()?h()?d.removeClass("unloaded"):f.off():""!==c.val()&&(f.on(),a.hasClass("visible")||a.addClass("visible"),h()&&d.addClass("unloaded"))}),a.on("click",function(){c.val(""),h()?(d.removeClass("unloaded"),r.empty()):f.off(),c.focus(),a.removeClass("visible")})}),$(function(){var e=function(){const e="sidebar-display";let t=!1;const o=$("body");return{toggle(){!1===t?o.attr(e,""):o.removeAttr(e),t=!t}}}();$("#sidebar-trigger").click(e.toggle),$("#mask").click(e.toggle)}),$(function(){$('[data-toggle="tooltip"]').tooltip()}),$(function(){const t=$("#topbar-wrapper"),o=$("#toc-wrapper"),a=$(".access"),l=$("#search-input");let s,n=0;const i=t.outerHeight();$(window).scroll(function(e){$("#topbar-title").is(":hidden")&&(s=!0)}),setInterval(function(){s&&(function(){var e=$(this).scrollTop();Math.abs(n-e)<=5||(e>n&&e>i?(t.removeClass("topbar-down").addClass("topbar-up"),0h1"),o=e.text().trim();let a=(0'),$("input[type=checkbox]:not([checked])").before('')}),$(function(){var e="#main > div.row:first-child > div:first-child";if(!($(e+" img").length<=0)){var t=document.querySelectorAll(e+" img[data-src]");const o=lozad(t);o.observe(),$(e+` p > img[data-src],${e} img[data-src].preview-img`).each(function(){let e=$(this).next();var t="EM"===e.prop("tagName")?e.text():"",o=$(this).attr("data-src");$(this).wrap(``)}),$(".popup").magnificPopup({type:"image",closeOnContentClick:!0,showCloseBtn:!1,zoom:{enabled:!0,duration:300,easing:"ease-in-out"}}),$(e+" a").has("img").addClass("img-link")}}),$(function(){var e=".code-header>button";const t="timeout";function l(e){if($(e)[0].hasAttribute(t)){e=$(e).attr(t);if(Number(e)>Date.now())return 1}}function s(e){$(e).attr(t,Date.now()+2e3)}function n(e){$(e).removeAttr(t)}const o=new ClipboardJS(e,{target(e){let t=e.parentNode.nextElementSibling;return t.querySelector("code .rouge-code")}});$(e).tooltip({trigger:"hover",placement:"left"});const a=function(e){let t=$(e).children();return t.attr("class")}(e);o.on("success",e=>{e.clearSelection();const t=e.trigger;var o;l(t)||(function(e){let t=$(e),o=t.children();o.attr("class","fas fa-check")}(t),o=t,e=$(o).attr("title-succeed"),$(o).attr("data-original-title",e).tooltip("show"),s(t),setTimeout(()=>{var e;e=t,$(e).tooltip("hide").removeAttr("data-original-title"),function(e){let t=$(e),o=t.children();o.attr("class",a)}(t),n(t)},2e3))}),$("#copy-link").click(e=>{let t=$(e.target);if(!l(t)){e=window.location.href;const o=$("");$("body").append(o),o.val(e).select(),document.execCommand("copy"),o.remove();const a=t.attr("data-original-title");e=t.attr("title-succeed");t.attr("data-original-title",e).tooltip("show"),s(t),setTimeout(()=>{t.attr("data-original-title",a),n(t)},2e3)}})}); \ No newline at end of file diff --git a/assets/js/dist/post.min.js b/assets/js/dist/post.min.js new file mode 100644 index 00000000..0aa5f91c --- /dev/null +++ b/assets/js/dist/post.min.js @@ -0,0 +1,6 @@ +/*! + * Chirpy v4.3.4 (https://github.com/cotes2020/jekyll-theme-chirpy/) + * © 2019 Cotes Chung + * MIT Licensed + */ +$(function(){$(window).scroll(()=>{50<$(this).scrollTop()&&"none"===$("#sidebar-trigger").css("display")?$("#back-to-top").fadeIn():$("#back-to-top").fadeOut()}),$("#back-to-top").click(()=>($("body,html").animate({scrollTop:0},800),!1))}),$(function(){$("#mode-toggle-wrapper").keyup(t=>{13===t.keyCode&&flipMode()})}),$(function(){const t=$("#sidebar-trigger"),e=$("#search-trigger"),o=$("#search-cancel"),a=$("#search-cleaner"),n=$("#main"),l=$("#topbar-title"),r=$("#search-wrapper"),s=$("#search-result-wrapper"),i=$("#search-results"),c=$("#search-input"),d=$("#search-hints"),u=function(){let t=0;return{block(){t=window.scrollY,$("html,body").scrollTop(0)},release(){$("html,body").scrollTop(t)},getOffset(){return t}}}(),p={on(){t.addClass("unloaded"),l.addClass("unloaded"),e.addClass("unloaded"),r.addClass("d-flex"),o.addClass("loaded")},off(){o.removeClass("loaded"),r.removeClass("d-flex"),t.removeClass("unloaded"),l.removeClass("unloaded"),e.removeClass("unloaded")}},h=function(){let t=!1;return{on(){t||(u.block(),s.removeClass("unloaded"),n.addClass("unloaded"),t=!0)},off(){t&&(i.empty(),d.hasClass("unloaded")&&d.removeClass("unloaded"),s.addClass("unloaded"),a.removeClass("visible"),n.removeClass("unloaded"),u.release(),c.val(""),t=!1)},isVisible(){return t}}}();function f(){return o.hasClass("loaded")}e.click(function(){p.on(),h.on(),c.focus()}),o.click(function(){p.off(),h.off()}),c.focus(function(){r.addClass("input-focus")}),c.focusout(function(){r.removeClass("input-focus")}),c.on("keyup",function(t){8===t.keyCode&&""===c.val()?f()?d.removeClass("unloaded"):h.off():""!==c.val()&&(h.on(),a.hasClass("visible")||a.addClass("visible"),f()&&d.addClass("unloaded"))}),a.on("click",function(){c.val(""),f()?(d.removeClass("unloaded"),i.empty()):h.off(),c.focus(),a.removeClass("visible")})}),$(function(){var t=function(){const t="sidebar-display";let e=!1;const o=$("body");return{toggle(){!1===e?o.attr(t,""):o.removeAttr(t),e=!e}}}();$("#sidebar-trigger").click(t.toggle),$("#mask").click(t.toggle)}),$(function(){$('[data-toggle="tooltip"]').tooltip()}),$(function(){const e=$("#topbar-wrapper"),o=$("#toc-wrapper"),a=$(".access"),n=$("#search-input");let l,r=0;const s=e.outerHeight();$(window).scroll(function(t){$("#topbar-title").is(":hidden")&&(l=!0)}),setInterval(function(){l&&(function(){var t=$(this).scrollTop();Math.abs(r-t)<=5||(t>r&&t>s?(e.removeClass("topbar-down").addClass("topbar-up"),0h1"),o=t.text().trim();let a=(0 img[data-src],${t} img[data-src].preview-img`).each(function(){let t=$(this).next();var e="EM"===t.prop("tagName")?t.text():"",o=$(this).attr("data-src");$(this).wrap(``)}),$(".popup").magnificPopup({type:"image",closeOnContentClick:!0,showCloseBtn:!1,zoom:{enabled:!0,duration:300,easing:"ease-in-out"}}),$(t+" a").has("img").addClass("img-link")}}),$(function(){let o=$(".timeago").length,t=void 0;const n=$("meta[name=day-prompt]").attr("content"),l=$("meta[name=hour-prompt]").attr("content"),r=$("meta[name=minute-prompt]").attr("content"),s=$("meta[name=justnow-prompt]").attr("content");function e(){return $(".timeago").each(function(){var t,e;!1!==$(this)[0].hasAttribute("date")?(e=function(t,e){let o=new Date,a=new Date(t);return a.getFullYear()!==o.getFullYear()||a.getMonth()!==o.getMonth()?e:(t=Math.floor((o-a)/1e3),1<=(e=Math.floor(t/86400))?` ${e} `+n:1<=(e=Math.floor(t/3600))?` ${e} `+l:1<=(t=Math.floor(t/60))?` ${t} `+r:s)}($(this).attr("date"),t=$(this).text()))===t?$(this).removeAttr("date"):$(this).text(e):--o}),0===o&&void 0!==t&&clearInterval(t),o}0!==o&&0'),$("input[type=checkbox]:not([checked])").before('')}),$(function(){var t=".code-header>button";const e="timeout";function n(t){if($(t)[0].hasAttribute(e)){t=$(t).attr(e);if(Number(t)>Date.now())return 1}}function l(t){$(t).attr(e,Date.now()+2e3)}function r(t){$(t).removeAttr(e)}const o=new ClipboardJS(t,{target(t){let e=t.parentNode.nextElementSibling;return e.querySelector("code .rouge-code")}});$(t).tooltip({trigger:"hover",placement:"left"});const a=function(t){let e=$(t).children();return e.attr("class")}(t);o.on("success",t=>{t.clearSelection();const e=t.trigger;var o;n(e)||(function(t){let e=$(t),o=e.children();o.attr("class","fas fa-check")}(e),o=e,t=$(o).attr("title-succeed"),$(o).attr("data-original-title",t).tooltip("show"),l(e),setTimeout(()=>{var t;t=e,$(t).tooltip("hide").removeAttr("data-original-title"),function(t){let e=$(t),o=e.children();o.attr("class",a)}(e),r(e)},2e3))}),$("#copy-link").click(t=>{let e=$(t.target);if(!n(e)){t=window.location.href;const o=$("");$("body").append(o),o.val(t).select(),document.execCommand("copy"),o.remove();const a=e.attr("data-original-title");t=e.attr("title-succeed");e.attr("data-original-title",t).tooltip("show"),l(e),setTimeout(()=>{e.attr("data-original-title",a),r(e)},2e3)}})}),$(function(){$("a[href*='#']").not("[href='#']").not("[href='#0']").click(function(e){if(this.pathname.replace(/^\//,"")===location.pathname.replace(/^\//,"")&&location.hostname===this.hostname){const r=decodeURI(this.hash);let o=RegExp(/^#fnref:/).test(r),a=!o&&RegExp(/^#fn:/).test(r);var l=r.includes(":")?r.replace(/\:/g,"\\:"):r;let n=$(l);if(n.length){e.preventDefault(),history.pushState&&history.pushState(null,null,r);l=$(this).offset().top;let t=n.offset().top;e=t{const t=$(n);t.focus();var e="scroll-focus";if($(`[${e}=true]`).length&&$(`[${e}=true]`).attr(e,!1),$(":target").length&&$(":target").attr(e,!1),(a||o)&&t.attr(e,!0),t.is(":focus"))return!1;t.attr("tabindex","-1"),t.focus()})}}})}); \ No newline at end of file diff --git a/assets/js/dist/pvreport.min.js b/assets/js/dist/pvreport.min.js new file mode 100644 index 00000000..22b788e9 --- /dev/null +++ b/assets/js/dist/pvreport.min.js @@ -0,0 +1,6 @@ +/*! + * Chirpy v4.3.4 (https://github.com/cotes2020/jekyll-theme-chirpy/) + * © 2019 Cotes Chung + * MIT Licensed + */ +const getInitStatus=function(){let t=!1;return()=>{var e=t;return t=t||!0,e}}(),PvOpts=function(){function t(e){return $(e).attr("content")}function e(e){e=t(e);return void 0!==e&&!1!==e}return{getProxyMeta(){return t("meta[name=pv-proxy-endpoint]")},getLocalMeta(){return t("meta[name=pv-cache-path]")},hasProxyMeta(){return e("meta[name=pv-proxy-endpoint]")},hasLocalMeta(){return e("meta[name=pv-cache-path]")}}}(),PvStorage=function(){const a={KEY_PV:"pv",KEY_PV_SRC:"pv_src",KEY_CREATION:"pv_created_date"},t={LOCAL:"same-origin",PROXY:"cors"};function r(e){return localStorage.getItem(e)}function o(e,t){localStorage.setItem(e,t)}function n(e,t){o(a.KEY_PV,e),o(a.KEY_PV_SRC,t),o(a.KEY_CREATION,(new Date).toJSON())}return{keysCount(){return Object.keys(a).length},hasCache(){return null!==localStorage.getItem(a.KEY_PV)},getCache(){return JSON.parse(localStorage.getItem(a.KEY_PV))},saveLocalCache(e){n(e,t.LOCAL)},saveProxyCache(e){n(e,t.PROXY)},isExpired(){let e=new Date(r(a.KEY_CREATION));return e.setHours(e.getHours()+1),Date.now()>=e.getTime()},isFromLocal(){return r(a.KEY_PV_SRC)===t.LOCAL},isFromProxy(){return r(a.KEY_PV_SRC)===t.PROXY},newerThan(e){return PvStorage.getCache().totalsForAllResults["ga:pageviews"]>e.totalsForAllResults["ga:pageviews"]},inspectKeys(){if(localStorage.length===PvStorage.keysCount())for(let e=0;er&&countUp(r,o,a.attr("id"))):a.text((new Intl.NumberFormat).format(o))}function displayPageviews(e){if(void 0!==e){let t=getInitStatus();const a=e.rows;0<$("#post-list").length?$(".post-preview").each(function(){var e=$(this).find("a").attr("href");tacklePV(a,e,$(this).find(".pageviews"),t)}):0<$(".post").length&&(e=window.location.pathname,tacklePV(a,e,$("#pv"),t))}}function fetchProxyPageviews(){PvOpts.hasProxyMeta()&&$.ajax({type:"GET",url:PvOpts.getProxyMeta(),dataType:"jsonp",jsonpCallback:"displayPageviews",success:e=>{PvStorage.saveProxyCache(JSON.stringify(e))},error:(e,t,a)=>{console.log("Failed to load pageviews from proxy server: "+a)}})}function fetchLocalPageviews(t=!1){return fetch(PvOpts.getLocalMeta()).then(e=>e.json()).then(e=>{t&&PvStorage.isFromProxy()&&PvStorage.newerThan(e)||(displayPageviews(e),PvStorage.saveLocalCache(JSON.stringify(e)))})}$(function(){$(".pageviews").length<=0||(PvStorage.inspectKeys(),PvStorage.hasCache()?(displayPageviews(PvStorage.getCache()),PvStorage.isExpired()?PvOpts.hasLocalMeta()?fetchLocalPageviews(!0).then(fetchProxyPageviews):fetchProxyPageviews():PvStorage.isFromLocal()&&fetchProxyPageviews()):PvOpts.hasLocalMeta()?fetchLocalPageviews().then(fetchProxyPageviews):fetchProxyPageviews())}); \ No newline at end of file diff --git a/assets/js/pwa/app.js b/assets/js/pwa/app.js new file mode 100644 index 00000000..fff0cc6f --- /dev/null +++ b/assets/js/pwa/app.js @@ -0,0 +1,9 @@ +--- +layout: compress +permalink: '/app.js' +--- + +/* Registering Service Worker */ +if('serviceWorker' in navigator) { + navigator.serviceWorker.register('{{ "/sw.js" | relative_url }}'); +}; diff --git a/assets/js/pwa/sw.js b/assets/js/pwa/sw.js new file mode 100644 index 00000000..1f85e3b7 --- /dev/null +++ b/assets/js/pwa/sw.js @@ -0,0 +1,87 @@ +--- +layout: compress +permalink: '/sw.js' +# PWA service worker +--- + +self.importScripts('{{ "/assets/js/data/swcache.js" | relative_url }}'); + +const cacheName = 'chirpy-{{ "now" | date: "%Y%m%d.%H%M" }}'; + +function verifyDomain(url) { + for (const domain of allowedDomains) { + const regex = RegExp(`^http(s)?:\/\/${domain}\/`); + if (regex.test(url)) { + return true; + } + } + + return false; +} + +function isExcluded(url) { + for (const item of denyUrls) { + if (url === item) { + return true; + } + } + return false; +} + +self.addEventListener('install', e => { + self.skipWaiting(); + e.waitUntil( + caches.open(cacheName).then(cache => { + return cache.addAll(resource); + }) + ); +}); + +self.addEventListener('fetch', event => { + event.respondWith( + caches.match(event.request) + .then(response => { + if (response) { + return response; + } + + return fetch(event.request) + .then(response => { + const url = event.request.url; + + if (event.request.method !== 'GET' || + !verifyDomain(url) || + isExcluded(url)) { + return response; + } + + /* + see: + */ + let responseToCache = response.clone(); + + caches.open(cacheName) + .then(cache => { + /* console.log('[sw] Caching new resource: ' + event.request.url); */ + cache.put(event.request, responseToCache); + }); + + return response; + }); + }) + ); +}); + +self.addEventListener('activate', e => { + e.waitUntil( + caches.keys().then(keyList => { + return Promise.all( + keyList.map(key => { + if(key !== cacheName) { + return caches.delete(key); + } + }) + ); + }) + ); +}); diff --git a/assets/robots.txt b/assets/robots.txt new file mode 100644 index 00000000..45c34e0e --- /dev/null +++ b/assets/robots.txt @@ -0,0 +1,10 @@ +--- +permalink: /robots.txt +# The robots rules +--- + +User-agent: * + +Disallow: /norobots/ + +Sitemap: {{ '/sitemap.xml' | absolute_url }} diff --git a/docs/README.zh-CN.md b/docs/README.zh-CN.md new file mode 100644 index 00000000..0d332eb6 --- /dev/null +++ b/docs/README.zh-CN.md @@ -0,0 +1,245 @@ +
    + + [EN](https://github.com/cotes2020/jekyll-theme-chirpy#readme) / 中文 + +
    + +
    + + # Chirpy Jekyll Theme + + 一款简约而强大、采用响应式设计的 Jekyll 主题,适合展示专业写作内容。 + + [![Gem Version](https://img.shields.io/gem/v/jekyll-theme-chirpy?color=brightgreen)](https://rubygems.org/gems/jekyll-theme-chirpy) + [![Build Status](https://github.com/cotes2020/jekyll-theme-chirpy/workflows/build/badge.svg?branch=master&event=push)](https://github.com/cotes2020/jekyll-theme-chirpy/actions?query=branch%3Amaster+event%3Apush) + [![Codacy Badge](https://app.codacy.com/project/badge/Grade/4e556876a3c54d5e8f2d2857c4f43894)](https://www.codacy.com/gh/cotes2020/jekyll-theme-chirpy/dashboard?utm_source=github.com&utm_medium=referral&utm_content=cotes2020/jekyll-theme-chirpy&utm_campaign=Badge_Grade) + [![GitHub license](https://img.shields.io/github/license/cotes2020/jekyll-theme-chirpy.svg)](https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/LICENSE) + [![996.icu](https://img.shields.io/badge/link-996.icu-%23FF4D5B.svg)](https://996.icu) + + [**线上体验 →**](https://chirpy.cotes.info) + + [![Devices Mockup](https://cdn.jsdelivr.net/gh/cotes2020/chirpy-images@0a003683c0c3ca549d12c309f9b3e03ea20981e5/commons/devices-mockup.png)](https://chirpy.cotes.info) + +
    + +## 功能一览 + +- 本地化外观语言 +- 可配置的主题颜色 +- 文章置顶 +- 文章最后修改日期 +- 文章目录 +- 自动推荐相关文章 +- 语法高亮 +- 二级目录 +- 数学表达式 +- Mermaid 图表 +- 搜索 +- Atom 订阅 +- Disqus 评论 +- Google 分析 +- GA 浏览报告(高级功能) +- SEO 优化 +- 网站性能优化 + +## 前提要求 + +参考 [Jekyll Docs](https://jekyllrb.com/docs/installation/) 安装 `Ruby`,`RubyGems`,`Jekyll` 和 `Bundler`。 + +## 安装 + +### 创建新仓库 + +有两种方式可以创建一个使用本主题的仓库: + +- [**使用 Chirpy Starter**](#使用-chirpy-starter) - 易于版本升级,隔离无关的主题项目文件,让您的仓库舒适清爽。 +- [**从 GitHub 上 Fork**](#从-github-上-fork) - 对个性化二次开发友好,但是难于升级。除非您决定魔改此款主题或者参与代码贡献,否则不推荐使用此方式。 + +#### 使用 Chirpy Starter + +[使用 Chirpy Starter][use-starter] 来快速创建 Jekyll 站点,命名为 `.github.io`,其中 `GH_USERNAME` 是您的 GitHub username。 + +#### 从 GitHub 上 Fork + +[Fork **Chirpy**](https://github.com/cotes2020/jekyll-theme-chirpy/fork) 并改名为 `.github.io`。友情提示:默认分支的代码处于开发状态,如果您想博客更加稳定,请切换到最新的 [Tag][latest-tag] 开始写作。 + +接着执行文件初始化: + +```console +$ bash tools/init.sh +``` + +> **注**:如果您不打算部署到 GitHub Pages, 在上述命令后附加参数选项 `--no-gh`。 + +上述脚本将会: + +1. 从您的仓库中删除了: + + - `.travis.yml` + - `_posts` 下的文件 + - `docs` 目录 + +2. 如果使用了参数 `--no-gh`,则会怒删文件夹 `.github`。否则,配置 GitHub Actions:把 `.github/workflows/pages-deploy.yml.hook` 的后缀 `.hook` 去除,然后删除 `.github` 里的其他目录和文件。 + +3. 从 `.gitignore` 中删除 `Gemfile.lock`。 + +4. 自动提交一个 Commit 以保存上述文件的更改。 + +### 安装依赖: + +首次运行本项目,需要先安装依赖: + +```console +$ bundle +``` + +## 使用 + +### 配置文件 + +根据个人需要去修改 `_config.yml` 的变量,大部分都有注释介绍用法。典型的几个选项是: + +- `url` +- `avatar` +- `timezone` +- `lang` + +### 自定义样式 + +如果您需要自定义样式, 拷贝主题的文件 `assets/css/style.scss` 到您站点的相同路径上,然后在该文件末尾添加样式。 + +自 [`v4.1.0`][chirpy-4.1.0] 起,如果您想覆盖文件 `_sass/addon/variables.scss` 里定义的 SASS 变量的默认值,新建文件 `_sass/variables-hook.scss`,然后重写您需要的变量即可。 + +### 本地运行 + +发布之前,在本地预览: + +```terminal +$ bundle exec jekyll s +``` + +或者用 Docker 运行: + +```terminal +$ docker run -it --rm \ + --volume="$PWD:/srv/jekyll" \ + -p 4000:4000 jekyll/jekyll \ + jekyll serve +``` + +稍候片刻,即可访问本地服务:__ + +### 部署 + +部署开始前,把 `_config.yml` 的 `url` 改为 `https://.github.io`(或者您的私有域名,如:`https://yourdomain.com`)。另外,如果您想使用 [Project 类型网站](https://help.github.com/en/github/working-with-github-pages/about-github-pages#types-of-github-pages-sites),修改配置文件的 `baseurl` 为项目名称,以斜杠开头,如:`/project`。 + +现在您可以选择下列其中一个方式去站点部署。 + +#### 使用 GitHub Actions 部署 + +由于安全原因,默认的 GitHub Pages 的构建强制加了 `safe`参数,这导致了我们不能使用插件去创建所需的附加页面。因此,我们可以使用 GitHub Actions 去构建站点,把站点文件存储在一个新分支上,再指定该分支作为 Pages 服务的源。 + +快速检查 GitHub Actions 构建需要的文件: + +- 确保您的 Jekyll 站点存在文件 `.github/workflows/pages-deploy.yml`。没有的话,新建并填入「[示例 Workflow][workflow]」的内容,注意参数 `on.push.branches` 的值必须和您的仓库默认分支名相同。 + +- 检查您的 Jekyll 站点是否有文件 `tools/deploy.sh`。没有的话, 从本仓库拷贝到您的 Jekyll 项目。 + +- 再者,如果您已经把文件 `Gemfile.lock` 提交到了仓库里面,并且您运行本项目的操作系统不是 Linux,需要添加新的平台信息: + + ```console + $ bundle lock --add-platform x86_64-linux + ``` + +完成上述条目后,到 GitHub 把您的仓库命名为 `.github.io`,然后开始发布: + +1. 推送任意一个 commit 到 `origin/master` 以触发 GitHub Actions workflow。一旦 build 完毕并且成功,远端将会自动出现一个新分支 `gh-pages` 用来存储构建的站点文件。 + +2. 回到 GitHub 上的仓库,选择标签 _Settings_ → 点击左侧导航栏的 _Pages_ → _GitHub Pages_ 选择分支 `gh-pages` 的 `/(root)` 作为「[发布源][pages-src]」: + + ![gh-pages-sources](https://cdn.jsdelivr.net/gh/cotes2020/chirpy-images@0a003683c0c3ca549d12c309f9b3e03ea20981e5/posts/20190809/gh-pages-sources.png) + +3. 按照 GitHub 指示的地址去访问您的网站。 + +#### 手动构建部署 + +在 GitHub 之外的平台,就没法享受 **GitHub Actions** 的便利了。因此您需要在本地构建站点,然后推送站点文件到服务器上。 + +在项目根目录,运行: + +```console +$ JEKYLL_ENV=production bundle exec jekyll b +``` + +或者通过 Docker 构建: + +```terminal +$ docker run -it --rm \ + --env JEKYLL_ENV=production \ + --volume="$PWD:/srv/jekyll" \ + jekyll/jekyll \ + jekyll build +``` + +生成的静态文件将会在 `_site`, 把内部的文件上传到服务器即可。 + +### 升级 + +这取决于您如何使用这个 theme: + +- 如果您是使用 theme gem(`Gemfile` 会有 `gem "jekyll-theme-chirpy"`),编辑 `Gemfile` 并更新 them gem 的版本号,譬如: + + ```diff + - gem "jekyll-theme-chirpy", "~> 3.2", ">= 3.2.1" + + gem "jekyll-theme-chirpy", "~> 3.3", ">= 3.3.0" + ``` + + 接着执行以下命令: + + ```console + $ bundle update jekyll-theme-chirpy + ``` + + 随着 theme 版本的升级,运行站点的必要文件(详见 [Chirpy Starter][starter])以及配置选项会出现变化,请参阅「[升级指南](https://github.com/cotes2020/jekyll-theme-chirpy/wiki/Upgrade-Guide)」的改动细节去保持您仓库中的相关文件同步到最新版本。 + +- 如果您是以 fork 的方式使用(您站点的 `Gemfile` 会有 `gemspec`),那么合并上游 [最新的 tag][latest-tag] 到您的 Repo 以完成升级。期间很有可能会产生冲突 (conflicts),请务必耐心谨慎地解决它们。 + +## 文档 + +若想要更多细节以及更佳的阅读体验,请参阅「[线上教程](https://chirpy.cotes.info/categories/tutorial/)」。 与此同时,「[Wiki](https://github.com/cotes2020/jekyll-theme-chirpy/wiki)」也有一份教程的拷贝。请注意,Demo 网站和 Wiki 上的文档都是基于最新的发行版本,而 `master` 分支的功能往往领先于现有文档。 + +## 参与贡献 + +三人行必有我师,欢迎提报告 bug,帮助改进代码质量,或者提交新功能。具体操作规则请参考「[贡献指南](../.github/CONTRIBUTING.md)」,谢谢 🙏。 + +## 鸣谢 + +此款主题的开发主要基于 [Jekyll](https://jekyllrb.com/) 生态、[Bootstrap](https://getbootstrap.com/)、[Font Awesome](https://fontawesome.com/) 和其他一些出色的工具 (相关文件中可以找到这些工具的版权信息)。头像和图标的设计来自于 [Clipart Max](https://www.clipartmax.com/middle/m2i8b1m2K9Z5m2K9_ant-clipart-childrens-ant-cute/)。 + +:tada: 感谢所有参与代码贡献的小伙伴,他们的 GayHub ID 在这个「[列表](https://github.com/cotes2020/jekyll-theme-chirpy/graphs/contributors)」。 另外,提交过 issues(或者未被合并 PR)的高富帅和白富美也不会被遗忘,他/她们帮助报告 bug、分享新点子或者启发了我写出更通俗易懂的文档。 + +还有,感谢 [JetBrains][jb] 提供开源 License! + +## 赞助 + +如果您喜欢此款主题或者它对您有帮助,请考虑打赏作者,您的支持将会极大地鼓励作者,并帮助作者更好地维护项目! + +[![Ko-fi](https://img.shields.io/badge/-请作者喝杯咖啡-ff5f5f?logo=ko-fi&logoColor=white)](https://ko-fi.com/coteschung) +[![Wechat Pay](https://img.shields.io/badge/-微信打赏作者-brightgreen?logo=wechat&logoColor=white)][cn-donation] +[![Alipay](https://img.shields.io/badge/-支付宝打赏作者-blue?logo=alipay&logoColor=white)][cn-donation] + +## 许可证书 + +本项目开源,基于 [MIT](https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/LICENSE) 许可。 + +[starter]: https://github.com/cotes2020/chirpy-starter +[use-starter]: https://github.com/cotes2020/chirpy-starter/generate +[workflow]: https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/.github/workflows/pages-deploy.yml.hook +[chirpy-4.1.0]: https://github.com/cotes2020/jekyll-theme-chirpy/releases/tag/v4.1.0 +[pages-src]: https://docs.github.com/en/github/working-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site +[latest-tag]: https://github.com/cotes2020/jekyll-theme-chirpy/tags + + + +[jb]: https://www.jetbrains.com/?from=jekyll-theme-chirpy +[cn-donation]: https://cotes.gitee.io/alipay-wechat-donation/ diff --git a/gulpfile.js/index.js b/gulpfile.js/index.js new file mode 100644 index 00000000..14692fb6 --- /dev/null +++ b/gulpfile.js/index.js @@ -0,0 +1,10 @@ +#!/usr/bin/env node + +"use strict"; + +const js = require('./tasks/js'); + +exports.default = js.build; + +/* keep-alive develop mode, without uglify */ +exports.dev = js.liveRebuild; diff --git a/gulpfile.js/tasks/js.js b/gulpfile.js/tasks/js.js new file mode 100644 index 00000000..101a4f79 --- /dev/null +++ b/gulpfile.js/tasks/js.js @@ -0,0 +1,93 @@ +#!/usr/bin/env node + +"use strict"; + +const { src, dest, watch, series, parallel} = require('gulp'); + +const concat = require('gulp-concat'); +const rename = require("gulp-rename"); +const uglify = require('gulp-uglify'); +const insert = require('gulp-insert'); +const fs = require('fs'); + +const JS_SRC = '_javascript'; +const JS_DEST = `assets/js/dist/`; + +function concatJs(files, output) { + return src(files) + .pipe(concat(output)) + .pipe(rename({ extname: '.min.js' })) + .pipe(dest(JS_DEST)); +} + +function minifyJs() { + return src(`${ JS_DEST }/*.js`) + .pipe(insert.prepend(fs.readFileSync(`${ JS_SRC }/copyright`, 'utf8'))) + .pipe(uglify({output: {comments: /^!|@preserve|@license|@cc_on/i}})) + .pipe(dest(JS_DEST)); +} + +const commonsJs = () => { + return concatJs(`${JS_SRC}/commons/*.js`, 'commons'); +}; + +const homeJs = () => { + return concatJs([ + `${JS_SRC}/commons/*.js`, + `${JS_SRC}/utils/timeago.js` + ], + 'home' + ); +}; + +const postJs = () => { + return concatJs([ + `${JS_SRC}/commons/*.js`, + `${JS_SRC}/utils/img-extra.js`, + `${JS_SRC}/utils/timeago.js`, + `${JS_SRC}/utils/checkbox.js`, + `${JS_SRC}/utils/clipboard.js`, + // 'smooth-scroll.js' must be called after ToC is ready + `${JS_SRC}/utils/smooth-scroll.js` + ], 'post' + ); +}; + +const categoriesJs = () => { + return concatJs([ + `${JS_SRC}/commons/*.js`, + `${JS_SRC}/utils/category-collapse.js` + ], 'categories' + ); +}; + +const pageJs = () => { + return concatJs([ + `${JS_SRC}/commons/*.js`, + `${JS_SRC}/utils/checkbox.js`, + `${JS_SRC}/utils/img-extra.js`, + `${JS_SRC}/utils/clipboard.js` + ], 'page' + ); +}; + +// GA pageviews report +const pvreportJs = () => { + return concatJs(`${JS_SRC}/utils/pageviews.js`, 'pvreport'); +}; + +const buildJs = parallel(commonsJs, homeJs, postJs, categoriesJs, pageJs, pvreportJs); + +exports.build = series(buildJs, minifyJs); + +exports.liveRebuild = () => { + buildJs(); + + watch([ + `${ JS_SRC }/commons/*.js`, + `${ JS_SRC }/utils/*.js`, + `${ JS_SRC }/lib/*.js` + ], + buildJs + ); +}; diff --git a/index.html b/index.html new file mode 100644 index 00000000..1357b080 --- /dev/null +++ b/index.html @@ -0,0 +1,4 @@ +--- +layout: home +# Index page +--- diff --git a/jekyll-theme-chirpy.gemspec b/jekyll-theme-chirpy.gemspec new file mode 100644 index 00000000..026d1b3c --- /dev/null +++ b/jekyll-theme-chirpy.gemspec @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +Gem::Specification.new do |spec| + spec.name = "jekyll-theme-chirpy" + spec.version = "4.3.4" + spec.authors = ["Cotes Chung"] + spec.email = ["cotes.chung@gmail.com"] + + spec.summary = "Chirpy is a minimal, sidebar, responsive web design Jekyll theme that focuses on text presentation." + spec.homepage = "https://github.com/cotes2020/jekyll-theme-chirpy" + spec.license = "MIT" + + spec.files = `git ls-files -z`.split("\x0").select { |f| + f.match(%r!^((_(includes|layouts|sass|data|tabs|plugins)|assets)\/|_config|README|LICENSE|index)!i) + } + + spec.metadata = { + "bug_tracker_uri" => "https://github.com/cotes2020/jekyll-theme-chirpy/issues", + "documentation_uri" => "https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/README.md", + "homepage_uri" => "https://cotes2020.github.io/chirpy-demo", + "source_code_uri" => "https://github.com/cotes2020/jekyll-theme-chirpy", + "wiki_uri" => "https://github.com/cotes2020/jekyll-theme-chirpy/wiki", + "plugin_type" => "theme" + } + + spec.required_ruby_version = ">= 2.4" + + spec.add_runtime_dependency "jekyll", "~> 4.1" + spec.add_runtime_dependency "jekyll-paginate", "~> 1.1" + spec.add_runtime_dependency "jekyll-redirect-from", "~> 0.16" + spec.add_runtime_dependency "jekyll-seo-tag", "~> 2.7" + spec.add_runtime_dependency "jekyll-archives", "~> 2.2" + spec.add_runtime_dependency "jekyll-sitemap", "~> 1.4" + +end diff --git a/package.json b/package.json new file mode 100644 index 00000000..46f2f5a9 --- /dev/null +++ b/package.json @@ -0,0 +1,30 @@ +{ + "name": "jekyll-theme-chirpy", + "version": "4.3.4", + "description": "A minimal, sidebar, responsive web design Jekyll theme that focuses on text presentation.", + "main": "index.js", + "directories": { + "doc": "docs" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/cotes2020/jekyll-theme-chirpy.git" + }, + "author": "Cotes Chung", + "license": "MIT", + "bugs": { + "url": "https://github.com/cotes2020/jekyll-theme-chirpy/issues" + }, + "homepage": "https://github.com/cotes2020/jekyll-theme-chirpy#readme", + "dependencies": { + "gulp": "^4.0.2", + "gulp-concat": "^2.6.1", + "gulp-insert": "^0.5.0", + "gulp-rename": "^2.0.0", + "gulp-uglify": "^3.0.2", + "uglify-js": "^3.14.3" + } +} diff --git a/tools/bump.sh b/tools/bump.sh new file mode 100644 index 00000000..8d2b6f6b --- /dev/null +++ b/tools/bump.sh @@ -0,0 +1,107 @@ +#!/usr/bin/env bash +# +# +# 1. Bump latest version number to the following files: +# +# - _sass/jekyll-theme-chirpy.scss +# - _javascript/copyright +# - assets/js/dist/*.js (will be built by gulp later) +# - jekyll-theme-chirpy.gemspec +# - package.json +# +# 2. Then create a commit to automatically save the changes. +# +# Usage: +# +# Run on the default branch or hotfix branch +# +# Requires: Git, Gulp + +set -eu + +ASSETS=( + "_sass/jekyll-theme-chirpy.scss" + "_javascript/copyright" +) + +GEM_SPEC="jekyll-theme-chirpy.gemspec" + +NODE_META="package.json" + +_check_src() { + if [[ ! -f $1 && ! -d $1 ]]; then + echo -e "Error: Missing file \"$1\"!\n" + exit -1 + fi +} + +check() { + if [[ -n $(git status . -s) ]]; then + echo "Error: Commit unstaged files first, and then run this tool againt." + exit -1 + fi + + for i in "${!ASSETS[@]}"; do + _check_src "${ASSETS[$i]}" + done + + _check_src "$NODE_META" + _check_src "$GEM_SPEC" +} + +_bump_assets() { + for i in "${!ASSETS[@]}"; do + sed -i "s/v[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+/v$1/" "${ASSETS[$i]}" + done + + gulp +} + +_bump_gemspec() { + sed -i "s/[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+/$1/" "$GEM_SPEC" +} + +_bump_node() { + sed -i \ + "s,[\"]version[\"]: [\"][[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+[\"],\"version\": \"$1\"," \ + $NODE_META +} + +bump() { + _bump_assets "$1" + _bump_gemspec "$1" + _bump_node "$1" + + if [[ -n $(git status . -s) ]]; then + git add . + git commit -m "Bump version to $1" + fi +} + +main() { + check + + _latest_tag="$(git describe --tags $(git rev-list --tags --max-count=1))" + + echo "Input a version number (hint: latest version is ${_latest_tag:1})" + + read _version + + if [[ $_version =~ ^[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]$ ]]; then + + if git tag --list | egrep -q "^v$_version$"; then + echo "Error: version '$_version' already exists" + exit -1 + fi + + echo -e "Bump version to $_version\n" + bump "$_version" + + else + + echo "Error: Illegal version number: '$_version'" + fi + +} + +main diff --git a/tools/deploy.sh b/tools/deploy.sh new file mode 100644 index 00000000..84b2b10a --- /dev/null +++ b/tools/deploy.sh @@ -0,0 +1,159 @@ +#!/usr/bin/env bash +# +# Build, test and then deploy the site content to 'origin/' +# +# Requirement: html-proofer, jekyll +# +# Usage: See help information + +set -eu + +PAGES_BRANCH="gh-pages" + +SITE_DIR="_site" + +_opt_dry_run=false + +_config="_config.yml" + +_no_pages_branch=false + +_backup_dir="$(mktemp -d)" + +_baseurl="" + +help() { + echo "Build, test and then deploy the site content to 'origin/'" + echo + echo "Usage:" + echo + echo " bash ./tools/deploy.sh [options]" + echo + echo "Options:" + echo ' -c, --config "" Specify config file(s)' + echo " --dry-run Build site and test, but not deploy" + echo " -h, --help Print this information." +} + +init() { + if [[ -z ${GITHUB_ACTION+x} && $_opt_dry_run == 'false' ]]; then + echo "ERROR: It is not allowed to deploy outside of the GitHub Action envrionment." + echo "Type option '-h' to see the help information." + exit -1 + fi + + _baseurl="$(grep '^baseurl:' _config.yml | sed "s/.*: *//;s/['\"]//g;s/#.*//")" +} + +build() { + # clean up + if [[ -d $SITE_DIR ]]; then + rm -rf "$SITE_DIR" + fi + + # build + JEKYLL_ENV=production bundle exec jekyll b -d "$SITE_DIR$_baseurl" --config "$_config" +} + +test() { + bundle exec htmlproofer \ + --disable-external \ + --check-html \ + --allow_hash_href \ + "$SITE_DIR" +} + +resume_site_dir() { + if [[ -n $_baseurl ]]; then + # Move the site file to the regular directory '_site' + mv "$SITE_DIR$_baseurl" "${SITE_DIR}-rename" + rm -rf "$SITE_DIR" + mv "${SITE_DIR}-rename" "$SITE_DIR" + fi +} + +setup_gh() { + if [[ -z $(git branch -av | grep "$PAGES_BRANCH") ]]; then + _no_pages_branch=true + git checkout -b "$PAGES_BRANCH" + else + git checkout "$PAGES_BRANCH" + fi +} + +backup() { + mv "$SITE_DIR"/* "$_backup_dir" + mv .git "$_backup_dir" + + # When adding custom domain from Github website, + # the CANME only exist on `gh-pages` branch + if [[ -f CNAME ]]; then + mv CNAME "$_backup_dir" + fi +} + +flush() { + rm -rf ./* + rm -rf .[^.] .??* + + shopt -s dotglob nullglob + mv "$_backup_dir"/* . +} + +deploy() { + git config --global user.name "GitHub Actions" + git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" + + git update-ref -d HEAD + git add -A + git commit -m "[Automation] Site update No.${GITHUB_RUN_NUMBER}" + + if $_no_pages_branch; then + git push -u origin "$PAGES_BRANCH" + else + git push -f + fi +} + +main() { + init + build + test + resume_site_dir + + if $_opt_dry_run; then + exit 0 + fi + + setup_gh + backup + flush + deploy +} + +while (($#)); do + opt="$1" + case $opt in + -c | --config) + _config="$2" + shift + shift + ;; + --dry-run) + # build & test, but not deploy + _opt_dry_run=true + shift + ;; + -h | --help) + help + exit 0 + ;; + *) + # unknown option + help + exit 1 + ;; + esac +done + +main diff --git a/tools/init.sh b/tools/init.sh new file mode 100644 index 00000000..e8c7b18a --- /dev/null +++ b/tools/init.sh @@ -0,0 +1,117 @@ +#!/usr/bin/env bash +# +# Init the evrionment for new user. + +set -eu + +ACTIONS_WORKFLOW=pages-deploy.yml + +TEMP_SUFFIX="to-delete" # temporary file suffixes that make `sed -i` compatible with BSD and Linux + +help() { + echo "Usage:" + echo + echo " bash /path/to/init.sh [options]" + echo + echo "Options:" + echo " --no-gh Do not deploy to Github." + echo " -h, --help Print this help information." +} + +check_status() { + if [[ -n $(git status . -s) ]]; then + echo "Error: Commit unstaged files first, and then run this tool againt." + exit -1 + fi +} + +check_init() { + local _has_inited=false + + if [[ ! -d docs ]]; then + if [[ ! -d .github ]]; then + _has_inited=true # --no-gh + else + if [[ -f .github/workflows/$ACTIONS_WORKFLOW ]]; then + # on BSD, the `wc` could contains blank + local _count="$(find .github/workflows/ -type f -name "*.yml" | wc -l)" + if [[ ${_count//[[:blank:]]/} == 1 ]]; then + _has_inited=true + fi + fi + fi + fi + + if $_has_inited; then + echo "Already initialized." + exit 0 + fi +} + +init_files() { + if $_no_gh; then + rm -rf .github + else + ## Change the files of `.github` + + mv .github/workflows/$ACTIONS_WORKFLOW.hook . + rm -rf .github + mkdir -p .github/workflows + mv ./${ACTIONS_WORKFLOW}.hook .github/workflows/${ACTIONS_WORKFLOW} + + ## Ensure the gh-actions trigger branch + + _workflow=".github/workflows/${ACTIONS_WORKFLOW}" + _default_branch="$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@')" + _lineno="$(sed -n "/branches:/=" "$_workflow")" + + sed -i.$TEMP_SUFFIX "$((_lineno + 1))s/- .*/- ${_default_branch}/" "$_workflow" + rm -f "$_workflow.$TEMP_SUFFIX" + + ## Cleanup image settings in site config + sed -i.$TEMP_SUFFIX "s/^img_cdn:.*/img_cdn:/;s/^avatar:.*/avatar:/" _config.yml + rm -f _config.yml.$TEMP_SUFFIX + + fi + + # trace the gem lockfile on user-end + sed -i.$TEMP_SUFFIX "/Gemfile.lock/d" .gitignore + rm -f ".gitignore.$TEMP_SUFFIX" + + # remove the other fies + rm -f .travis.yml + rm -rf _posts/* docs + + # save changes + git add -A + git commit -m "[Automation] Initialize the environment." -q + + echo "[INFO] Initialization successful!" +} + +check_status + +check_init + +_no_gh=false + +while (($#)); do + opt="$1" + case $opt in + --no-gh) + _no_gh=true + shift + ;; + -h | --help) + help + exit 0 + ;; + *) + # unknown option + help + exit 1 + ;; + esac +done + +init_files diff --git a/tools/release.sh b/tools/release.sh new file mode 100644 index 00000000..00a363ac --- /dev/null +++ b/tools/release.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +# +# According to the GitLab flow release branching model, +# cherry-pick the last commit on the main branch to the release branch, +# and then create a tag and gem package on the release branch (naming format: 'release/'). +# +# +# Usage: +# +# It can be run on main branch, and it should be used after just finishing the last feature in the version plan, +# or just after merging the hotfix to the main branch. +# +# Requires: Git, Gulp + +set -eu + +GEM_SPEC="jekyll-theme-chirpy.gemspec" + +check() { + if [[ -n $(git status . -s) ]]; then + echo "Error: Commit unstaged files first, and then run this tool againt." + exit -1 + fi + + if [[ ! -f $GEM_SPEC ]]; then + echo -e "Error: Missing file \"$GEM_SPEC\"!\n" + exit -1 + fi +} + +## Remove unnecessary theme settings +cleanup_config() { + cp _config.yml _config.yml.bak + sed -i "s/^img_cdn:.*/img_cdn:/;s/^avatar:.*/avatar:/" _config.yml +} + +resume_config() { + mv _config.yml.bak _config.yml +} + +release() { + _default_branch="$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@')" + _version="$(grep "spec.version" jekyll-theme-chirpy.gemspec | sed 's/.*= "//;s/".*//')" # X.Y.Z + _release_branch="release/${_version%.*}" + + if [[ -z $(git branch -v | grep "$_release_branch") ]]; then + # create a new release branch + git checkout -b "$_release_branch" + else + # cherry-pick the latest commit from default branch to release branch + _last_commit="$(git rev-parse "$_default_branch")" + git checkout "$_release_branch" + git cherry-pick "$_last_commit" -m 1 + fi + + # create new tag + echo -e "Create tag v$_version\n" + git tag "v$_version" + + # build a gem package + echo -e "Build the gem pakcage for v$_version\n" + cleanup_config + rm -f ./*.gem + gem build "$GEM_SPEC" + resume_config +} + +main() { + check + release +} + +main diff --git a/tools/run.sh b/tools/run.sh new file mode 100644 index 00000000..8072e414 --- /dev/null +++ b/tools/run.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# +# Run jekyll serve and then launch the site + +bundle exec jekyll s -H 0.0.0.0 -l