Repository: Uni-Gal/Ayaka (language: rust)

Issue:
Allow plugins execute scripts.
Fixes #14


Discussion / hints:

Fix patch:
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000..57feaded
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,16 @@
+version: 2
+updates:
+- package-ecosystem: cargo
+  directory: "/utils"
+  schedule:
+    interval: daily
+
+- package-ecosystem: cargo
+  directory: "/plugins"
+  schedule:
+    interval: daily
+
+- package-ecosystem: cargo
+  directory: "/bins"
+  schedule:
+    interval: daily
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 00000000..365940ef
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,51 @@
+name: Release
+on:
+  push:
+    branches: ["master"]
+jobs:
+  Build:
+    strategy:
+      matrix:
+        platform:
+          - name: linux-x64
+            os: ubuntu-latest
+            target: x86_64-unknown-linux-gnu
+            postfix:
+          - name: windows-x64
+            os: windows-latest
+            target: x86_64-pc-windows-msvc
+            postfix: .exe
+          - name: macos-x64
+            os: macos-latest
+            target: x86_64-apple-darwin
+            postfix:
+          - name: macos-arm64
+            os: macos-latest
+            target: aarch64-apple-darwin
+            postfix:
+    runs-on: ${{ matrix.platform.os }}
+    steps:
+      - uses: actions/checkout@v2
+      - name: Install dependencies
+        run: sudo apt-get install -y libwebkit2gtk-4.0-dev
+        if: matrix.platform.name == 'linux-x64'
+      - name: Install targets
+        run: |
+          rustup target add ${{ matrix.platform.target }}
+          rustup target add wasm32-unknown-unknown
+          rustup target add wasm32-wasi
+      - name: Build
+        run: make plugins release-cross TARGET=${{ matrix.platform.target }}
+      - name: Publish plugins
+        uses: actions/upload-artifact@v3
+        with:
+          name: plugins
+          path: examples/plugins/
+      - name: Publish binaries
+        uses: actions/upload-artifact@v3
+        with:
+          name: release-${{ matrix.platform.name }}
+          path: |
+            bins/target/${{ matrix.platform.target }}/release/ayaka-check${{ matrix.platform.postfix }}
+            bins/target/${{ matrix.platform.target }}/release/ayaka-gui${{ matrix.platform.postfix }}
+            bins/target/${{ matrix.platform.target }}/release/ayaka-latex${{ matrix.platform.postfix }}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..ac2019cf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+**/target
+**/*.rs.bk
+.cargo
+Cargo.lock
+
+.vscode
+.cache
+.clangd
+.vs
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 00000000..8ecf2287
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2022 Berrysoft
+
+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/Makefile b/Makefile
new file mode 100644
index 00000000..9861764d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,51 @@
+.PHONY: test nextest clean update doc serve-book
+test: plugins
+	cd utils && $(MAKE) test
+nextest: plugins
+	cd utils && $(MAKE) nextest
+clean:
+	cd bins && $(MAKE) clean
+	cd utils && $(MAKE) clean
+	cd plugins && $(MAKE) clean
+	cd book && $(MAKE) clean
+update:
+	cd bins && $(MAKE) update
+	cd utils && $(MAKE) update
+	cd plugins && $(MAKE) update
+doc:
+	cd utils && $(MAKE) doc
+	cd book && $(MAKE) build
+serve-book:
+	cd book && $(MAKE) serve
+
+.PHONY: plugins release release-cross
+plugins:
+	cd plugins && $(MAKE) plugins
+release:
+	cd bins && $(MAKE) release
+release-cross:
+	cd bins && $(MAKE) release-cross TARGET=$(TARGET)
+
+EXAMPLES:=Fibonacci Fibonacci2 Gacha Live2D Orga Styles
+
+define example-tpl
+.PHONY: example-$(1) example-$(1)-gui example-$(1)-release example-$(1)-gui-release examples/$(1)/config.tex
+example-$(1): examples/$(1)/config.yaml plugins
+	cd bins && $$(MAKE) run FILE=$$(realpath $$<)
+example-$(1)-gui: examples/$(1)/config.yaml plugins
+	cd bins && $$(MAKE) run-gui FILE=$$(realpath $$<)
+example-$(1)-release: examples/$(1)/config.yaml plugins release
+	bins/target/release/ayaka-check $$< --auto
+example-$(1)-gui-release: examples/$(1)/config.yaml plugins release
+	bins/target/release/ayaka-gui $$<
+examples/$(1)/config.tex: examples/$(1)/config.yaml
+	cd bins && $$(MAKE) run-latex FILE=$$(realpath $$<)
+
+endef
+
+$(eval $(foreach ex,$(EXAMPLES),$(call example-tpl,$(ex))))
+
+%.pdf: %.tex
+	cd $(dir $<) && latexmk -lualatex $(notdir $<)
+
+.SECONDARY:
diff --git a/README.md b/README.md
index 6767b43f..f05023bc 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,33 @@
 # Ayaka
 
-This is the main repository of Ayaka, a visual novel engine written by Rust.
+Ayaka is currently a project for [OSPP 2022](https://summer-ospp.ac.cn/).
+
+## About the name
+The frontend is Ayaka. The runtime is Ayaka. The script is Ayaka. [Just Ayaka.](https://bbs.mihoyo.com/ys/article/21828380)
+
+## What we've done
+* A cross-platform visual noval (VN) runtime with rust
+* A well-defined and easy-to-author VN config file format, based on YAML.
+* An embedded custom script.
+* [CLDR](https://github.com/unicode-org/cldr)-based i18n support.
+* A flexible plugin system based on [WebAssembly](https://webassembly.org/). It provides hooks of the runtime and interop functionalities with the script.
+* A decoupled framework - the frontend, backend and plugins are decoupled.
+* A CLI frontend to check grammar errors and debug quickly.
+* A GUI frontend powered by [Tauri](https://tauri.app/) and [Vue](https://vuejs.org/).
+* A proto LaTeX frontend to generate PDF from the config.
+
+## Docs
+See Ayaka Book:
+``` bash
+$ make serve-book
+```
+If you don't have `mdbook` installed, simply read the markdown files in `book` folder.
+To start quickly, follow the instructions in [Quick start](./book/src/quick_start.md).
+
+Build API docs into `utils/target/doc`:
+``` bash
+$ make doc
+```
+
+## Screenshot
+![Orga](assets/galgui.png)
diff --git a/assets/galgui.png b/assets/galgui.png
new file mode 100644
index 00000000..46f712b6
Binary files /dev/null and b/assets/galgui.png differ
diff --git a/assets/glogo.png b/assets/glogo.png
new file mode 100644
index 00000000..e134cd98
Binary files /dev/null and b/assets/glogo.png differ
diff --git a/bins/Cargo.toml b/bins/Cargo.toml
new file mode 100644
index 00000000..301633d8
--- /dev/null
+++ b/bins/Cargo.toml
@@ -0,0 +1,12 @@
+[workspace]
+members = [
+    "ayaka-check",
+    "ayaka-gui/src-tauri",
+    "ayaka-latex",
+]
+
+resolver = "2"
+
+[profile.release]
+lto = true
+codegen-units = 1
diff --git a/bins/Makefile b/bins/Makefile
new file mode 100644
index 00000000..126df22e
--- /dev/null
+++ b/bins/Makefile
@@ -0,0 +1,22 @@
+.PHONY: clean update
+clean:
+	cargo clean
+	cd ayaka-gui && $(MAKE) clean
+update:
+	cargo update
+
+.PHONY: dist release release-cross
+dist:
+	cd ayaka-gui && $(MAKE) dist
+release: dist
+	STATIC_VCRUNTIME=false cargo build --release
+release-cross: dist
+	STATIC_VCRUNTIME=false PKG_CONFIG_ALLOW_CROSS=1 cargo build --release --target=$(TARGET)
+
+.PHONY: run run-gui run-latex
+run:
+	RUST_LOG=info cargo run --package ayaka-check -- $(FILE) --auto
+run-gui:
+	cd ayaka-gui && $(MAKE) run FILE=$(FILE)
+run-latex:
+	RUST_LOG=info cargo run --package ayaka-latex -- $(FILE) -o $(basename $(FILE)).tex
diff --git a/bins/ayaka-check/Cargo.toml b/bins/ayaka-check/Cargo.toml
new file mode 100644
index 00000000..8d141052
--- /dev/null
+++ b/bins/ayaka-check/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "ayaka-check"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+ayaka-runtime = { path = "../../utils/ayaka-runtime" }
+tokio = { version = "1", features = ["macros", "rt"] }
+clap = { version = "3.1", features = ["derive"] }
+env_logger = "0.9"
diff --git a/bins/ayaka-check/src/main.rs b/bins/ayaka-check/src/main.rs
new file mode 100644
index 00000000..f1a55531
--- /dev/null
+++ b/bins/ayaka-check/src/main.rs
@@ -0,0 +1,96 @@
+use ayaka_runtime::{
+    anyhow::{bail, Result},
+    log::LevelFilter,
+    *,
+};
+use clap::Parser;
+use std::{
+    ffi::OsString,
+    io::{stdin, stdout, Write},
+};
+
+#[derive(Debug, Parser)]
+#[clap(about, version, author)]
+pub struct Options {
+    input: OsString,
+    #[clap(long)]
+    check: bool,
+    #[clap(long)]
+    auto: bool,
+    #[clap(short, long)]
+    locale: Option<Locale>,
+}
+
+fn read_line() -> Result<String> {
+    stdout().flush()?;
+    let mut s = String::new();
+    stdin().read_line(&mut s)?;
+    Ok(s)
+}
+
+fn pause(auto: bool) -> Result<()> {
+    if auto {
+        println!();
+    } else {
+        read_line()?;
+    }
+    Ok(())
+}
+
+#[tokio::main(flavor = "current_thread")]
+async fn main() -> Result<()> {
+    let opts = Options::parse();
+    env_logger::Builder::from_default_env()
+        .filter_module("wasmer", LevelFilter::Warn)
+        .try_init()?;
+    let context = Context::open(&opts.input, FrontendType::Text);
+    pin_mut!(context);
+    while let Some(status) = context.next().await {
+        match status {
+            OpenStatus::LoadProfile => println!("Loading profile..."),
+            OpenStatus::CreateRuntime => println!("Creating runtime..."),
+            OpenStatus::LoadPlugin(name, i, len) => {
+                println!("Loading plugin {} ({}/{})", name, i + 1, len)
+            }
+        }
+    }
+    let mut ctx = context.await?;
+    if opts.check && !ctx.check() {
+        bail!("Check failed.");
+    }
+    ctx.init_new();
+    ctx.set_locale(opts.locale.unwrap_or_else(Locale::current));
+    while let Some(action) = ctx.next_run() {
+        if let Some(name) = &action.character {
+            print!("_{}_", name);
+        }
+        for s in action.line {
+            print!("{}", s.as_str());
+        }
+        if !action.switches.is_empty() {
+            for (i, s) in action.switches.iter().enumerate() {
+                if s.enabled {
+                    print!("\n-{}- {}", i + 1, s.text);
+                } else {
+                    print!("\n-x- {}", s.text);
+                }
+            }
+            println!();
+            loop {
+                let s = read_line()?;
+                if let Ok(i) = s.trim().parse::<usize>() {
+                    let valid =
+                        i > 0 && i <= action.switches.len() && action.switches[i - 1].enabled;
+                    if valid {
+                        ctx.call(&action.switches[i - 1].action);
+                        break;
+                    }
+                }
+                println!("Invalid switch, enter again!");
+            }
+        } else {
+            pause(opts.auto)?;
+        }
+    }
+    Ok(())
+}
diff --git a/bins/ayaka-gui/.gitignore b/bins/ayaka-gui/.gitignore
new file mode 100644
index 00000000..f2419174
--- /dev/null
+++ b/bins/ayaka-gui/.gitignore
@@ -0,0 +1,29 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+.DS_Store
+dist
+dist-ssr
+coverage
+*.local
+package-lock.json
+
+/cypress/videos/
+/cypress/screenshots/
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/bins/ayaka-gui/Makefile b/bins/ayaka-gui/Makefile
new file mode 100644
index 00000000..7b779a34
--- /dev/null
+++ b/bins/ayaka-gui/Makefile
@@ -0,0 +1,14 @@
+node_modules: package.json
+	npm install
+
+.PHONY: clean
+clean:
+	rm -rf node_modules
+	rm -rf dist
+	rm -f package-lock.json
+
+.PHONY: run dist
+run: node_modules
+	npm run tauri dev -- -- --no-default-features -- $(FILE)
+dist: node_modules
+	npm run build
diff --git a/bins/ayaka-gui/index.html b/bins/ayaka-gui/index.html
new file mode 100644
index 00000000..5bba33a0
--- /dev/null
+++ b/bins/ayaka-gui/index.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <link rel="icon" href="/favicon.ico" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>Vite App</title>
+  </head>
+  <body>
+    <div id="app"></div>
+    <script src="/live2d.min.js"></script>
+    <script src="/live2dcubismcore.min.js"></script>
+    <script type="module" src="/src/main.ts"></script>
+  </body>
+</html>
diff --git a/bins/ayaka-gui/package.json b/bins/ayaka-gui/package.json
new file mode 100644
index 00000000..e53cafc1
--- /dev/null
+++ b/bins/ayaka-gui/package.json
@@ -0,0 +1,39 @@
+{
+  "name": "ayaka-gui",
+  "private": true,
+  "version": "0.1.0",
+  "scripts": {
+    "dev": "vite",
+    "build": "vue-tsc --noEmit && vite build",
+    "preview": "vite preview",
+    "tauri": "tauri"
+  },
+  "dependencies": {
+    "@fortawesome/fontawesome-svg-core": "^6.1.2",
+    "@fortawesome/free-solid-svg-icons": "^6.1.2",
+    "@fortawesome/vue-fontawesome": "^3.0.1",
+    "@tauri-apps/api": "^1.0.2",
+    "async-mutex": "^0.3.2",
+    "bootstrap": "^5.2.0",
+    "bootstrap-dark-5": "^1.1.3",
+    "lodash": "^4.17.21",
+    "pixi-live2d-display": "^0.4.0-beta.2",
+    "pixi.js": "^6.5.2",
+    "timers-promises": "^1.0.1",
+    "vue": "^3.2.37",
+    "vue-i18n": "^9.2.2",
+    "vue-router": "^4.1.4"
+  },
+  "devDependencies": {
+    "@tauri-apps/cli": "^1.0.5",
+    "@types/bootstrap": "^5.2.0",
+    "@types/lodash": "^4.14.184",
+    "@types/node": "^18.7.13",
+    "@vitejs/plugin-vue": "^3.0.3",
+    "@vue/tsconfig": "^0.1.3",
+    "process": "^0.11.10",
+    "typescript": "~4.8.2",
+    "vite": "^3.0.9",
+    "vue-tsc": "^0.40.1"
+  }
+}
\ No newline at end of file
diff --git a/bins/ayaka-gui/public/live2d.min.js b/bins/ayaka-gui/public/live2d.min.js
new file mode 100644
index 00000000..8d3c0a98
--- /dev/null
+++ b/bins/ayaka-gui/public/live2d.min.js
@@ -0,0 +1,2 @@
+
+(function(){var j=true;function aa(){if(j){return;}this._$MT=null;this._$5S=null;this._$NP=0;aa._$42++;this._$5S=new y(this);}aa._$0s=1;aa._$4s=2;aa._$42=0;aa._$62=function(aQ,aU){try{if(aU instanceof ArrayBuffer){aU=new DataView(aU);}if(!(aU instanceof DataView)){throw new J("_$SS#loadModel(b) / b _$x be DataView or ArrayBuffer");}var aS=new K(aU);var aM=aS._$ST();var aK=aS._$ST();var aJ=aS._$ST();var aN;if(aM==109&&aK==111&&aJ==99){aN=aS._$ST();}else{throw new J("_$gi _$C _$li , _$Q0 _$P0.");}aS._$gr(aN);if(aN>ay._$T7){aQ._$NP|=aa._$4s;var aR=ay._$T7;var aI="_$gi _$C _$li , _$n0 _$_ version _$li ( SDK : "+aR+" < _$f0 : "+aN+" )@_$SS#loadModel()\n";throw new J(aI);}var aL=aS._$nP();if(aN>=ay._$s7){var aH=aS._$9T();var aT=aS._$9T();if(aH!=-30584||aT!=-30584){aQ._$NP|=aa._$0s;throw new J("_$gi _$C _$li , _$0 _$6 _$Ui.");}}aQ._$KS(aL);var aP=aQ.getModelContext();aP.setDrawParam(aQ.getDrawParam());aP.init();}catch(aO){q._$Rb(aO);}};aa.prototype._$KS=function(aH){this._$MT=aH;};aa.prototype.getModelImpl=function(){if(this._$MT==null){this._$MT=new w();this._$MT._$zP();}return this._$MT;};aa.prototype.getCanvasWidth=function(){if(this._$MT==null){return 0;}return this._$MT.getCanvasWidth();};aa.prototype.getCanvasHeight=function(){if(this._$MT==null){return 0;}return this._$MT.getCanvasHeight();};aa.prototype.getParamFloat=function(aH){if(typeof aH!="number"){aH=this._$5S.getParamIndex(z.getID(aH));}return this._$5S.getParamFloat(aH);};aa.prototype.setParamFloat=function(aH,aJ,aI){if(typeof aH!="number"){aH=this._$5S.getParamIndex(z.getID(aH));}if(arguments.length<3){aI=1;}this._$5S.setParamFloat(aH,this._$5S.getParamFloat(aH)*(1-aI)+aJ*aI);};aa.prototype.addToParamFloat=function(aH,aJ,aI){if(typeof aH!="number"){aH=this._$5S.getParamIndex(z.getID(aH));}if(arguments.length<3){aI=1;}this._$5S.setParamFloat(aH,this._$5S.getParamFloat(aH)+aJ*aI);};aa.prototype.multParamFloat=function(aH,aJ,aI){if(typeof aH!="number"){aH=this._$5S.getParamIndex(z.getID(aH));}if(arguments.length<3){aI=1;}this._$5S.setParamFloat(aH,this._$5S.getParamFloat(aH)*(1+(aJ-1)*aI));};aa.prototype.getParamIndex=function(aH){return this._$5S.getParamIndex(z.getID(aH));};aa.prototype.loadParam=function(){this._$5S.loadParam();};aa.prototype.saveParam=function(){this._$5S.saveParam();};aa.prototype.init=function(){this._$5S.init();};aa.prototype.update=function(){this._$5S.update();};aa.prototype._$Rs=function(){q._$li("_$60 _$PT _$Rs()");return -1;};aa.prototype._$Ds=function(aH){q._$li("_$60 _$PT _$SS#_$Ds() \n");};aa.prototype._$K2=function(){};aa.prototype.draw=function(){};aa.prototype.getModelContext=function(){return this._$5S;};aa.prototype._$s2=function(){return this._$NP;};aa.prototype._$P7=function(aK,aR,aH,a0){var aU=-1;var aY=0;var aM=this;var aJ=0.5;var aI=0.15;var aX=true;if(aH==0){for(var aV=0;aV<aK.length;aV++){var aP=aK[aV];var aO=aR[aV];var aS=(aM.getParamFloat(aP)!=0);aM.setPartsOpacity(aO,(aS?1:0));}return;}else{if(aK.length==1){var aP=aK[0];var aT=(aM.getParamFloat(aP)!=0);var aO=aR[0];var aQ=aM.getPartsOpacity(aO);var aW=aH/a0;if(aT){aQ+=aW;if(aQ>1){aQ=1;}}else{aQ-=aW;if(aQ<0){aQ=0;}}aM.setPartsOpacity(aO,aQ);}else{for(var aV=0;aV<aK.length;aV++){var aP=aK[aV];var aS=(aM.getParamFloat(aP)!=0);if(aS){if(aU>=0){break;}aU=aV;var aO=aR[aV];aY=aM.getPartsOpacity(aO);aY+=aH/a0;if(aY>1){aY=1;}}}if(aU<0){console.log("No _$wi _$q0/ _$U default[%s]",aK[0]);aU=0;aY=1;aM.loadParam();aM.setParamFloat(aK[aU],aY);aM.saveParam();}for(var aV=0;aV<aK.length;aV++){var aO=aR[aV];if(aU==aV){aM.setPartsOpacity(aO,aY);}else{var aL=aM.getPartsOpacity(aO);var aZ;if(aY<aJ){aZ=aY*(aJ-1)/aJ+1;}else{aZ=(1-aY)*aJ/(1-aJ);}if(aX){var aN=(1-aZ)*(1-aY);if(aN>aI){aZ=1-aI/(1-aY);}}if(aL>aZ){aL=aZ;}aM.setPartsOpacity(aO,aL);}}}}};aa.prototype.setPartsOpacity=function(aI,aH){if(typeof aI!="number"){aI=this._$5S.getPartsDataIndex(i.getID(aI));}this._$5S.setPartsOpacity(aI,aH);};aa.prototype.getPartsDataIndex=function(aH){if(!(aH instanceof i)){aH=i.getID(aH);}return this._$5S.getPartsDataIndex(aH);};aa.prototype.getPartsOpacity=function(aH){if(typeof aH!="number"){aH=this._$5S.getPartsDataIndex(i.getID(aH));}if(aH<0){return 0;}return this._$5S.getPartsOpacity(aH);};aa.prototype.getDrawParam=function(){};aa.prototype.getDrawDataIndex=function(aH){return this._$5S.getDrawDataIndex(Z.getID(aH));};aa.prototype.getDrawData=function(aH){return this._$5S.getDrawData(aH);};aa.prototype.getTransformedPoints=function(aH){var aI=this._$5S._$C2(aH);if(aI instanceof ag){return(aI).getTransformedPoints();}return null;};aa.prototype.getIndexArray=function(aI){if(aI<0||aI>=this._$5S._$aS.length){return null;}var aH=this._$5S._$aS[aI];if(aH!=null&&aH.getType()==a._$wb){if(aH instanceof b){return aH.getIndexArray();}}return null;};function W(aJ){if(j){return;}this.clipContextList=new Array();this.glcontext=aJ.gl;this.dp_webgl=aJ;this.curFrameNo=0;this.firstError_clipInNotUpdate=true;this.colorBuffer=0;this.isInitGLFBFunc=false;this.tmpBoundsOnModel=new av();if(Q.glContext.length>Q.frameBuffers.length){this.curFrameNo=this.getMaskRenderTexture();}else{}this.tmpModelToViewMatrix=new ac();this.tmpMatrix2=new ac();this.tmpMatrixForMask=new ac();this.tmpMatrixForDraw=new ac();this.CHANNEL_COLORS=new Array();var aI=new o();aI=new o();aI.r=0;aI.g=0;aI.b=0;aI.a=1;this.CHANNEL_COLORS.push(aI);aI=new o();aI.r=1;aI.g=0;aI.b=0;aI.a=0;this.CHANNEL_COLORS.push(aI);aI=new o();aI.r=0;aI.g=1;aI.b=0;aI.a=0;this.CHANNEL_COLORS.push(aI);aI=new o();aI.r=0;aI.g=0;aI.b=1;aI.a=0;this.CHANNEL_COLORS.push(aI);for(var aH=0;aH<this.CHANNEL_COLORS.length;aH++){this.dp_webgl.setChannelFlagAsColor(aH,this.CHANNEL_COLORS[aH]);}}W.CHANNEL_COUNT=4;W.RENDER_TEXTURE_USE_MIPMAP=false;W.NOT_USED_FRAME=-100;W.prototype._$L7=function(){if(this.tmpModelToViewMatrix){this.tmpModelToViewMatrix=null;}if(this.tmpMatrix2){this.tmpMatrix2=null;}if(this.tmpMatrixForMask){this.tmpMatrixForMask=null;}if(this.tmpMatrixForDraw){this.tmpMatrixForDraw=null;}if(this.tmpBoundsOnModel){this.tmpBoundsOnModel=null;}if(this.CHANNEL_COLORS){for(var aH=this.CHANNEL_COLORS.length-1;aH>=0;--aH){this.CHANNEL_COLORS.splice(aH,1);}this.CHANNEL_COLORS=[];}this.releaseShader();};W.prototype.releaseShader=function(){var aI=Q.frameBuffers.length;for(var aH=0;aH<aI;aH++){this.gl.deleteFramebuffer(Q.frameBuffers[aH].framebuffer);}Q.frameBuffers=[];Q.glContext=[];};W.prototype.init=function(aO,aN,aL){for(var aM=0;aM<aN.length;aM++){var aH=aN[aM].getClipIDList();if(aH==null){continue;}var aJ=this.findSameClip(aH);if(aJ==null){aJ=new U(this,aO,aH);this.clipContextList.push(aJ);}var aI=aN[aM].getDrawDataID();var aK=aO.getDrawDataIndex(aI);aJ.addClippedDrawData(aI,aK);var aP=aL[aM];aP.clipBufPre_clipContext=aJ;}};W.prototype.getMaskRenderTexture=function(){var aH=null;aH=this.dp_webgl.createFramebuffer();Q.frameBuffers[this.dp_webgl.glno]=aH;return this.dp_webgl.glno;};W.prototype.setupClip=function(a1,aQ){var aK=0;for(var aO=0;aO<this.clipContextList.length;aO++){var aP=this.clipContextList[aO];this.calcClippedDrawTotalBounds(a1,aP);if(aP.isUsing){aK++;}}if(aK>0){var aM=aQ.gl.getParameter(aQ.gl.FRAMEBUFFER_BINDING);var aW=new Array(4);aW[0]=0;aW[1]=0;aW[2]=aQ.gl.canvas.width;aW[3]=aQ.gl.canvas.height;aQ.gl.viewport(0,0,Q.clippingMaskBufferSize,Q.clippingMaskBufferSize);this.setupLayoutBounds(aK);aQ.gl.bindFramebuffer(aQ.gl.FRAMEBUFFER,Q.frameBuffers[this.curFrameNo].framebuffer);aQ.gl.clearColor(0,0,0,0);aQ.gl.clear(aQ.gl.COLOR_BUFFER_BIT);for(var aO=0;aO<this.clipContextList.length;aO++){var aP=this.clipContextList[aO];var aT=aP.allClippedDrawRect;var aN=aP.layoutChannelNo;var aV=aP.layoutBounds;var aJ=0.05;this.tmpBoundsOnModel._$jL(aT);this.tmpBoundsOnModel.expand(aT.width*aJ,aT.height*aJ);var aZ=aV.width/this.tmpBoundsOnModel.width;var aY=aV.height/this.tmpBoundsOnModel.height;this.tmpMatrix2.identity();this.tmpMatrix2.translate(-1,-1,0);this.tmpMatrix2.scale(2,2,1);this.tmpMatrix2.translate(aV.x,aV.y,0);this.tmpMatrix2.scale(aZ,aY,1);this.tmpMatrix2.translate(-this.tmpBoundsOnModel.x,-this.tmpBoundsOnModel.y,0);this.tmpMatrixForMask.setMatrix(this.tmpMatrix2.m);this.tmpMatrix2.identity();this.tmpMatrix2.translate(aV.x,aV.y,0);this.tmpMatrix2.scale(aZ,aY,1);this.tmpMatrix2.translate(-this.tmpBoundsOnModel.x,-this.tmpBoundsOnModel.y,0);this.tmpMatrixForDraw.setMatrix(this.tmpMatrix2.m);var aH=this.tmpMatrixForMask.getArray();for(var aX=0;aX<16;aX++){aP.matrixForMask[aX]=aH[aX];}var a0=this.tmpMatrixForDraw.getArray();for(var aX=0;aX<16;aX++){aP.matrixForDraw[aX]=a0[aX];}var aS=aP.clippingMaskDrawIndexList.length;for(var aU=0;aU<aS;aU++){var aR=aP.clippingMaskDrawIndexList[aU];var aI=a1.getDrawData(aR);var aL=a1._$C2(aR);aQ.setClipBufPre_clipContextForMask(aP);aI.draw(aQ,a1,aL);}}aQ.gl.bindFramebuffer(aQ.gl.FRAMEBUFFER,aM);aQ.setClipBufPre_clipContextForMask(null);aQ.gl.viewport(aW[0],aW[1],aW[2],aW[3]);}};W.prototype.getColorBuffer=function(){return this.colorBuffer;};W.prototype.findSameClip=function(aK){for(var aN=0;aN<this.clipContextList.length;aN++){var aO=this.clipContextList[aN];var aH=aO.clipIDList.length;if(aH!=aK.length){continue;}var aI=0;for(var aM=0;aM<aH;aM++){var aL=aO.clipIDList[aM];for(var aJ=0;aJ<aH;aJ++){if(aK[aJ]==aL){aI++;break;}}}if(aI==aH){return aO;}}return null;};W.prototype.calcClippedDrawTotalBounds=function(a6,aV){var aU=a6._$Ri.getModelImpl().getCanvasWidth();var a5=a6._$Ri.getModelImpl().getCanvasHeight();var aJ=aU>a5?aU:a5;var aT=aJ;var aR=aJ;var aS=0;var aP=0;var aL=aV.clippedDrawContextList.length;for(var aM=0;aM<aL;aM++){var aW=aV.clippedDrawContextList[aM];var aN=aW.drawDataIndex;var aK=a6._$C2(aN);if(aK._$yo()){var aX=aK.getTransformedPoints();var a4=aX.length;var aI=[];var aH=[];var aO=0;for(var a3=aw._$i2;a3<a4;a3+=aw._$No){aI[aO]=aX[a3];aH[aO]=aX[a3+1];aO++;}var a2=Math.min.apply(null,aI);var a1=Math.min.apply(null,aH);var a0=Math.max.apply(null,aI);var aZ=Math.max.apply(null,aH);if(a2<aT){aT=a2;}if(a1<aR){aR=a1;}if(a0>aS){aS=a0;}if(aZ>aP){aP=aZ;}}}if(aT==aJ){aV.allClippedDrawRect.x=0;aV.allClippedDrawRect.y=0;aV.allClippedDrawRect.width=0;aV.allClippedDrawRect.height=0;aV.isUsing=false;}else{var aQ=aS-aT;var aY=aP-aR;aV.allClippedDrawRect.x=aT;aV.allClippedDrawRect.y=aR;aV.allClippedDrawRect.width=aQ;aV.allClippedDrawRect.height=aY;aV.isUsing=true;}};W.prototype.setupLayoutBounds=function(aQ){var aI=aQ/W.CHANNEL_COUNT;var aP=aQ%W.CHANNEL_COUNT;aI=~~aI;aP=~~aP;var aH=0;for(var aJ=0;aJ<W.CHANNEL_COUNT;aJ++){var aM=aI+(aJ<aP?1:0);if(aM==0){}else{if(aM==1){var aL=this.clipContextList[aH++];aL.layoutChannelNo=aJ;aL.layoutBounds.x=0;aL.layoutBounds.y=0;aL.layoutBounds.width=1;aL.layoutBounds.height=1;}else{if(aM==2){for(var aO=0;aO<aM;aO++){var aN=aO%2;var aK=0;aN=~~aN;var aL=this.clipContextList[aH++];aL.layoutChannelNo=aJ;aL.layoutBounds.x=aN*0.5;aL.layoutBounds.y=0;aL.layoutBounds.width=0.5;aL.layoutBounds.height=1;}}else{if(aM<=4){for(var aO=0;aO<aM;aO++){var aN=aO%2;var aK=aO/2;aN=~~aN;aK=~~aK;var aL=this.clipContextList[aH++];aL.layoutChannelNo=aJ;aL.layoutBounds.x=aN*0.5;aL.layoutBounds.y=aK*0.5;aL.layoutBounds.width=0.5;aL.layoutBounds.height=0.5;}}else{if(aM<=9){for(var aO=0;aO<aM;aO++){var aN=aO%3;var aK=aO/3;aN=~~aN;aK=~~aK;var aL=this.clipContextList[aH++];aL.layoutChannelNo=aJ;aL.layoutBounds.x=aN/3;aL.layoutBounds.y=aK/3;aL.layoutBounds.width=1/3;aL.layoutBounds.height=1/3;}}else{q._$li("_$6 _$0P mask count : %d",aM);}}}}}}};function U(aH,aK,aI){this.clipIDList=new Array();this.clipIDList=aI;this.clippingMaskDrawIndexList=new Array();for(var aJ=0;aJ<aI.length;aJ++){this.clippingMaskDrawIndexList.push(aK.getDrawDataIndex(aI[aJ]));}this.clippedDrawContextList=new Array();this.isUsing=true;this.layoutChannelNo=0;this.layoutBounds=new av();this.allClippedDrawRect=new av();this.matrixForMask=new Float32Array(16);this.matrixForDraw=new Float32Array(16);this.owner=aH;}U.prototype.addClippedDrawData=function(aJ,aI){var aH=new R(aJ,aI);this.clippedDrawContextList.push(aH);};function R(aI,aH){this._$gP=aI;this.drawDataIndex=aH;}function I(){if(j){return;}this.color=null;}function ah(){if(j){return;}this._$dP=null;this._$eo=null;this._$V0=null;this._$dP=1000;this._$eo=1000;this._$V0=1;this._$a0();}ah._$JT=function(aP,aN,aO){var aQ=aP/aN;var a1=aO/aN;var aU=a1;var aZ=1/3;var aR=2/3;var a0=1-(1-a1)*(1-a1);var a2=1-(1-aU)*(1-aU);var aM=0;var aL=((1-a1)*aZ)*a0+(aU*aR+(1-aU)*aZ)*(1-a0);var aK=(aU+(1-aU)*aR)*a2+(a1*aZ+(1-a1)*aR)*(1-a2);var aJ=1;var aY=aJ-3*aK+3*aL-aM;var aX=3*aK-6*aL+3*aM;var aW=3*aL-3*aM;var aV=aM;if(aQ<=0){return 0;}else{if(aQ>=1){return 1;}}var aS=aQ;var aI=aS*aS;var aH=aS*aI;var aT=aY*aH+aX*aI+aW*aS+aV;return aT;};ah.prototype._$a0=function(){};ah.prototype.setFadeIn=function(aH){this._$dP=aH;};ah.prototype.setFadeOut=function(aH){this._$eo=aH;};ah.prototype._$pT=function(aH){this._$V0=aH;};ah.prototype.getFadeOut=function(){return this._$eo;};ah.prototype._$4T=function(){return this._$eo;};ah.prototype._$mT=function(){return this._$V0;};ah.prototype.getDurationMSec=function(){return -1;};ah.prototype.getLoopDurationMSec=function(){return -1;};ah.prototype.updateParam=function(aJ,aN){if(!aN._$AT||aN._$9L){return;}var aL=P.getUserTimeMSec();if(aN._$z2<0){aN._$z2=aL;aN._$bs=aL;var aM=this.getDurationMSec();if(aN._$Do<0){aN._$Do=(aM<=0)?-1:aN._$z2+aM;}}var aI=this._$V0;var aH=(this._$dP==0)?1:A._$r2(((aL-aN._$bs)/(this._$dP)));var aK=(this._$eo==0||aN._$Do<0)?1:A._$r2(((aN._$Do-aL)/(this._$eo)));aI=aI*aH*aK;if(!((0<=aI&&aI<=1))){console.log("### assert!! ### ");}this.updateParamExe(aJ,aL,aI,aN);if(aN._$Do>0&&aN._$Do<aL){aN._$9L=true;}};ah.prototype.updateParamExe=function(aH,aI,aJ,aK){};function q(){}q._$8s=0;q._$fT=new Object();q.start=function(aI){var aH=q._$fT[aI];if(aH==null){aH=new af();aH._$r=aI;q._$fT[aI]=aH;}aH._$0S=P.getSystemTimeMSec();};q.dump=function(aJ){var aH=q._$fT[aJ];if(aH!=null){var aI=P.getSystemTimeMSec();var aK=aI-aH._$0S;console.log(aJ+" : "+aK+"ms");return aK;}else{return -1;}};q.end=function(aJ){var aH=q._$fT[aJ];if(aH!=null){var aI=P.getSystemTimeMSec();return aI-aH._$0S;}else{return -1;}};q._$li=function(aI,aH){console.log("_$li : "+aI+"\n",aH);};q._$Ji=function(aI,aH){console.log(aI,aH);};q._$dL=function(aI,aH){console.log(aI,aH);console.log("\n");};q._$KL=function(aJ,aI){for(var aH=0;aH<aI;aH++){if(aH%16==0&&aH>0){console.log("\n");}else{if(aH%8==0&&aH>0){console.log("  ");}}console.log("%02X ",(aJ[aH]&255));}console.log("\n");};q._$nr=function(aL,aI,aK){console.log("%s\n",aL);var aH=aI.length;for(var aJ=0;aJ<aH;++aJ){console.log("%5d",aI[aJ]);console.log("%s\n",aK);console.log(",");}console.log("\n");};q._$Rb=function(aH){console.log("dump exception : "+aH);console.log("stack :: "+aH.stack);};function af(){this._$r=null;this._$0S=null;}function F(){if(j){return;}this.x=null;this.y=null;this.width=null;this.height=null;}F.prototype._$8P=function(){return 0.5*(this.x+this.x+this.width);};F.prototype._$6P=function(){return 0.5*(this.y+this.y+this.height);};F.prototype._$EL=function(){return this.x+this.width;};F.prototype._$5T=function(){return this.y+this.height;};F.prototype._$jL=function(aI,aK,aJ,aH){this.x=aI;this.y=aK;this.width=aJ;this.height=aH;};F.prototype._$jL=function(aH){this.x=aH.x;this.y=aH.y;this.width=aH.width;this.height=aH.height;};function i(aH){if(j){return;}ak.prototype.constructor.call(this,aH);}i.prototype=new ak();i._$tP=new Object();i._$27=function(){i._$tP.clear();};i.getID=function(aH){var aI=i._$tP[aH];if(aI==null){aI=new i(aH);i._$tP[aH]=aI;}return aI;};i.prototype._$3s=function(){return new i();};function S(){}function z(aH){if(j){return;}ak.prototype.constructor.call(this,aH);}z.prototype=new ak();z._$tP=new Object();z._$27=function(){z._$tP.clear();};z.getID=function(aH){var aI=z._$tP[aH];if(aI==null){aI=new z(aH);z._$tP[aH]=aI;}return aI;};z.prototype._$3s=function(){return new z();};function w(){if(j){return;}this._$vo=null;this._$F2=null;this._$ao=400;this._$1S=400;w._$42++;}w._$42=0;w.prototype._$zP=function(){if(this._$vo==null){this._$vo=new an();}if(this._$F2==null){this._$F2=new Array();}};w.prototype.getCanvasWidth=function(){return this._$ao;};w.prototype.getCanvasHeight=function(){return this._$1S;};w.prototype._$F0=function(aH){this._$vo=aH._$nP();this._$F2=aH._$nP();this._$ao=aH._$6L();this._$1S=aH._$6L();};w.prototype._$6S=function(aH){this._$F2.push(aH);};w.prototype._$Xr=function(){return this._$F2;};w.prototype._$E2=function(){return this._$vo;};function u(){if(j){return;}this.p1=new N();this.p2=new N();this._$Fo=0;this._$Db=0;this._$L2=0;this._$M2=0;this._$ks=0;this._$9b=0;this._$iP=0;this._$iT=0;this._$lL=new Array();this._$qP=new Array();this.setup(0.3,0.5,0.1);}u.prototype.setup=function(aJ,aI,aH){this._$ks=this._$Yb();this.p2._$xT();if(arguments.length==3){this._$Fo=aJ;this._$L2=aI;this.p1._$p=aH;this.p2._$p=aH;this.p2.y=aJ;this.setup();}};u.prototype.getPhysicsPoint1=function(){return this.p1;};u.prototype.getPhysicsPoint2=function(){return this.p2;};u.prototype._$qr=function(){return this._$Db;};u.prototype._$pr=function(aH){this._$Db=aH;};u.prototype._$5r=function(){return this._$M2;};u.prototype._$Cs=function(){return this._$9b;};u.prototype._$Yb=function(){return(-180*(Math.atan2(this.p1.x-this.p2.x,-(this.p1.y-this.p2.y)))/Math.PI);};u.prototype.addSrcParam=function(aJ,aH,aL,aI){var aK=new h(aJ,aH,aL,aI);this._$lL.push(aK);};u.prototype.addTargetParam=function(aJ,aH,aK,aI){var aL=new aF(aJ,aH,aK,aI);this._$qP.push(aL);};u.prototype.update=function(aI,aL){if(this._$iP==0){this._$iP=this._$iT=aL;this._$Fo=(Math.sqrt((this.p1.x-this.p2.x)*(this.p1.x-this.p2.x)+(this.p1.y-this.p2.y)*(this.p1.y-this.p2.y)));return;}var aK=(aL-this._$iT)/1000;if(aK!=0){for(var aJ=this._$lL.length-1;aJ>=0;--aJ){var aM=this._$lL[aJ];aM._$oP(aI,this);}this._$oo(aI,aK);this._$M2=this._$Yb();this._$9b=(this._$M2-this._$ks)/aK;this._$ks=this._$M2;}for(var aJ=this._$qP.length-1;aJ>=0;--aJ){var aH=this._$qP[aJ];aH._$YS(aI,this);}this._$iT=aL;};u.prototype._$oo=function(aN,aI){if(aI<0.033){aI=0.033;}var aU=1/aI;this.p1.vx=(this.p1.x-this.p1._$s0)*aU;this.p1.vy=(this.p1.y-this.p1._$70)*aU;this.p1.ax=(this.p1.vx-this.p1._$7L)*aU;this.p1.ay=(this.p1.vy-this.p1._$HL)*aU;this.p1.fx=this.p1.ax*this.p1._$p;this.p1.fy=this.p1.ay*this.p1._$p;this.p1._$xT();var aM=-(Math.atan2((this.p1.y-this.p2.y),this.p1.x-this.p2.x));var aL;var aV;var aR=Math.cos(aM);var aH=Math.sin(aM);var aW=9.8*this.p2._$p;var aQ=(this._$Db*aC._$bS);var aP=(aW*Math.cos(aM-aQ));aL=(aP*aH);aV=(aP*aR);var aK=(-this.p1.fx*aH*aH);var aT=(-this.p1.fy*aH*aR);var aJ=((-this.p2.vx*this._$L2));var aS=((-this.p2.vy*this._$L2));this.p2.fx=((aL+aK+aJ));this.p2.fy=((aV+aT+aS));this.p2.ax=this.p2.fx/this.p2._$p;this.p2.ay=this.p2.fy/this.p2._$p;this.p2.vx+=this.p2.ax*aI;this.p2.vy+=this.p2.ay*aI;this.p2.x+=this.p2.vx*aI;this.p2.y+=this.p2.vy*aI;var aO=(Math.sqrt((this.p1.x-this.p2.x)*(this.p1.x-this.p2.x)+(this.p1.y-this.p2.y)*(this.p1.y-this.p2.y)));this.p2.x=this.p1.x+this._$Fo*(this.p2.x-this.p1.x)/aO;this.p2.y=this.p1.y+this._$Fo*(this.p2.y-this.p1.y)/aO;this.p2.vx=(this.p2.x-this.p2._$s0)*aU;this.p2.vy=(this.p2.y-this.p2._$70)*aU;this.p2._$xT();};function N(){this._$p=1;this.x=0;this.y=0;this.vx=0;this.vy=0;this.ax=0;this.ay=0;this.fx=0;this.fy=0;this._$s0=0;this._$70=0;this._$7L=0;this._$HL=0;}N.prototype._$xT=function(){this._$s0=this.x;this._$70=this.y;this._$7L=this.vx;this._$HL=this.vy;};function at(aJ,aI,aH){this._$wL=null;this.scale=null;this._$V0=null;this._$wL=aJ;this.scale=aI;this._$V0=aH;}at.prototype._$oP=function(aI,aH){};function h(aJ,aK,aI,aH){at.prototype.constructor.call(this,aK,aI,aH);this._$tL=null;this._$tL=aJ;}h.prototype=new at();h.prototype._$oP=function(aJ,aH){var aK=this.scale*aJ.getParamFloat(this._$wL);var aL=aH.getPhysicsPoint1();switch(this._$tL){default:case u.Src.SRC_TO_X:aL.x=aL.x+(aK-aL.x)*this._$V0;break;case u.Src.SRC_TO_Y:aL.y=aL.y+(aK-aL.y)*this._$V0;break;case u.Src.SRC_TO_G_ANGLE:var aI=aH._$qr();aI=aI+(aK-aI)*this._$V0;aH._$pr(aI);break;}};function d(aJ,aI,aH){this._$wL=null;this.scale=null;this._$V0=null;this._$wL=aJ;this.scale=aI;this._$V0=aH;}d.prototype._$YS=function(aI,aH){};function aF(aI,aK,aJ,aH){d.prototype.constructor.call(this,aK,aJ,aH);this._$YP=null;this._$YP=aI;}aF.prototype=new d();aF.prototype._$YS=function(aI,aH){switch(this._$YP){default:case u.Target.TARGET_FROM_ANGLE:aI.setParamFloat(this._$wL,this.scale*aH._$5r(),this._$V0);break;case u.Target.TARGET_FROM_ANGLE_V:aI.setParamFloat(this._$wL,this.scale*aH._$Cs(),this._$V0);break;}};u.Src=function(){};u.Src.SRC_TO_X="SRC_TO_X";u.Src.SRC_TO_Y="SRC_TO_Y";u.Src.SRC_TO_G_ANGLE="SRC_TO_G_ANGLE";u.Target=function(){};u.Target.TARGET_FROM_ANGLE="TARGET_FROM_ANGLE";u.Target.TARGET_FROM_ANGLE_V="TARGET_FROM_ANGLE_V";function X(){if(j){return;}this._$fL=0;this._$gL=0;this._$B0=1;this._$z0=1;this._$qT=0;this.reflectX=false;this.reflectY=false;}X.prototype.init=function(aH){this._$fL=aH._$fL;this._$gL=aH._$gL;this._$B0=aH._$B0;this._$z0=aH._$z0;this._$qT=aH._$qT;this.reflectX=aH.reflectX;this.reflectY=aH.reflectY;};X.prototype._$F0=function(aH){this._$fL=aH._$_T();this._$gL=aH._$_T();this._$B0=aH._$_T();this._$z0=aH._$_T();this._$qT=aH._$_T();if(aH.getFormatVersion()>=ay.LIVE2D_FORMAT_VERSION_V2_10_SDK2){this.reflectX=aH._$po();this.reflectY=aH._$po();}};X.prototype._$e=function(){};var ad=function(){};ad._$ni=function(aL,aJ,aR,aQ,aK,aI,aH,aS,aN){var aM=(aH*aI-aS*aK);if(aM==0){return null;}else{var aO=((aL-aR)*aI-(aJ-aQ)*aK)/aM;var aP;if(aK!=0){aP=(aL-aR-aO*aH)/aK;}else{aP=(aJ-aQ-aO*aS)/aI;}if(isNaN(aP)){aP=(aL-aR-aO*aH)/aK;if(isNaN(aP)){aP=(aJ-aQ-aO*aS)/aI;}if(isNaN(aP)){console.log("a is NaN @UtVector#_$ni() ");console.log("v1x : "+aK);console.log("v1x != 0 ? "+(aK!=0));}}if(aN==null){return new Array(aP,aO);}else{aN[0]=aP;aN[1]=aO;return aN;}}};function av(){if(j){return;}this.x=null;this.y=null;this.width=null;this.height=null;}av.prototype._$8P=function(){return this.x+0.5*this.width;};av.prototype._$6P=function(){return this.y+0.5*this.height;};av.prototype._$EL=function(){return this.x+this.width;};av.prototype._$5T=function(){return this.y+this.height;};av.prototype._$jL=function(aI,aK,aJ,aH){this.x=aI;this.y=aK;this.width=aJ;this.height=aH;};av.prototype._$jL=function(aH){this.x=aH.x;this.y=aH.y;this.width=aH.width;this.height=aH.height;};av.prototype.contains=function(aH,aI){return this.x<=this.x&&this.y<=this.y&&(this.x<=this.x+this.width)&&(this.y<=this.y+this.height);};av.prototype.expand=function(aH,aI){this.x-=aH;this.y-=aI;this.width+=aH*2;this.height+=aI*2;};function aG(){}aG._$Z2=function(bb,bo,bp,a2){var a1=bo._$Q2(bb,bp);var a3=bb._$vs();var ba=bb._$Tr();bo._$zr(a3,ba,a1);if(a1<=0){return a2[a3[0]];}else{if(a1==1){var bj=a2[a3[0]];var bi=a2[a3[1]];var a9=ba[0];return(bj+(bi-bj)*a9)|0;}else{if(a1==2){var bj=a2[a3[0]];var bi=a2[a3[1]];var a0=a2[a3[2]];var aZ=a2[a3[3]];var a9=ba[0];var a8=ba[1];var br=(bj+(bi-bj)*a9)|0;var bq=(a0+(aZ-a0)*a9)|0;return(br+(bq-br)*a8)|0;}else{if(a1==3){var aP=a2[a3[0]];var aO=a2[a3[1]];var bn=a2[a3[2]];var bm=a2[a3[3]];var aK=a2[a3[4]];var aJ=a2[a3[5]];var bg=a2[a3[6]];var bf=a2[a3[7]];var a9=ba[0];var a8=ba[1];var a6=ba[2];var bj=(aP+(aO-aP)*a9)|0;var bi=(bn+(bm-bn)*a9)|0;var a0=(aK+(aJ-aK)*a9)|0;var aZ=(bg+(bf-bg)*a9)|0;var br=(bj+(bi-bj)*a8)|0;var bq=(a0+(aZ-a0)*a8)|0;return(br+(bq-br)*a6)|0;}else{if(a1==4){var aT=a2[a3[0]];var aS=a2[a3[1]];var bu=a2[a3[2]];var bt=a2[a3[3]];var aN=a2[a3[4]];var aM=a2[a3[5]];var bl=a2[a3[6]];var bk=a2[a3[7]];var be=a2[a3[8]];var bc=a2[a3[9]];var aX=a2[a3[10]];var aW=a2[a3[11]];var a7=a2[a3[12]];var a5=a2[a3[13]];var aR=a2[a3[14]];var aQ=a2[a3[15]];var a9=ba[0];var a8=ba[1];var a6=ba[2];var a4=ba[3];var aP=(aT+(aS-aT)*a9)|0;var aO=(bu+(bt-bu)*a9)|0;var bn=(aN+(aM-aN)*a9)|0;var bm=(bl+(bk-bl)*a9)|0;var aK=(be+(bc-be)*a9)|0;var aJ=(aX+(aW-aX)*a9)|0;var bg=(a7+(a5-a7)*a9)|0;var bf=(aR+(aQ-aR)*a9)|0;var bj=(aP+(aO-aP)*a8)|0;var bi=(bn+(bm-bn)*a8)|0;var a0=(aK+(aJ-aK)*a8)|0;var aZ=(bg+(bf-bg)*a8)|0;var br=(bj+(bi-bj)*a6)|0;var bq=(a0+(aZ-a0)*a6)|0;return(br+(bq-br)*a4)|0;}else{var aV=1<<a1;var aY=new Float32Array(aV);for(var bh=0;bh<aV;bh++){var aI=bh;var aH=1;for(var aL=0;aL<a1;aL++){aH*=(aI%2==0)?(1-ba[aL]):ba[aL];aI/=2;}aY[bh]=aH;}var bs=new Float32Array(aV);for(var aU=0;aU<aV;aU++){bs[aU]=a2[a3[aU]];}var bd=0;for(var aU=0;aU<aV;aU++){bd+=aY[aU]*bs[aU];}return(bd+0.5)|0;}}}}}};aG._$br=function(ba,bo,bp,bg){var a1=bo._$Q2(ba,bp);var a2=ba._$vs();var a9=ba._$Tr();bo._$zr(a2,a9,a1);if(a1<=0){return bg[a2[0]];}else{if(a1==1){var bj=bg[a2[0]];var bi=bg[a2[1]];var a8=a9[0];return bj+(bi-bj)*a8;}else{if(a1==2){var bj=bg[a2[0]];var bi=bg[a2[1]];var a0=bg[a2[2]];var aZ=bg[a2[3]];var a8=a9[0];var a7=a9[1];return(1-a7)*(bj+(bi-bj)*a8)+a7*(a0+(aZ-a0)*a8);}else{if(a1==3){var aP=bg[a2[0]];var aO=bg[a2[1]];var bn=bg[a2[2]];var bm=bg[a2[3]];var aK=bg[a2[4]];var aJ=bg[a2[5]];var bf=bg[a2[6]];var be=bg[a2[7]];var a8=a9[0];var a7=a9[1];var a5=a9[2];return(1-a5)*((1-a7)*(aP+(aO-aP)*a8)+a7*(bn+(bm-bn)*a8))+a5*((1-a7)*(aK+(aJ-aK)*a8)+a7*(bf+(be-bf)*a8));}else{if(a1==4){var aT=bg[a2[0]];var aS=bg[a2[1]];var bs=bg[a2[2]];var br=bg[a2[3]];var aN=bg[a2[4]];var aM=bg[a2[5]];var bl=bg[a2[6]];var bk=bg[a2[7]];var bd=bg[a2[8]];var bb=bg[a2[9]];var aX=bg[a2[10]];var aW=bg[a2[11]];var a6=bg[a2[12]];var a4=bg[a2[13]];var aR=bg[a2[14]];var aQ=bg[a2[15]];var a8=a9[0];var a7=a9[1];var a5=a9[2];var a3=a9[3];return(1-a3)*((1-a5)*((1-a7)*(aT+(aS-aT)*a8)+a7*(bs+(br-bs)*a8))+a5*((1-a7)*(aN+(aM-aN)*a8)+a7*(bl+(bk-bl)*a8)))+a3*((1-a5)*((1-a7)*(bd+(bb-bd)*a8)+a7*(aX+(aW-aX)*a8))+a5*((1-a7)*(a6+(a4-a6)*a8)+a7*(aR+(aQ-aR)*a8)));}else{var aV=1<<a1;var aY=new Float32Array(aV);for(var bh=0;bh<aV;bh++){var aI=bh;var aH=1;for(var aL=0;aL<a1;aL++){aH*=(aI%2==0)?(1-a9[aL]):a9[aL];aI/=2;}aY[bh]=aH;}var bq=new Float32Array(aV);for(var aU=0;aU<aV;aU++){bq[aU]=bg[a2[aU]];}var bc=0;for(var aU=0;aU<aV;aU++){bc+=aY[aU]*bq[aU];}return bc;}}}}}};aG._$Vr=function(bV,bW,a5,aI,bC,a3,bX,bH){var aN=bW._$Q2(bV,a5);var bw=bV._$vs();var a2=bV._$Tr();bW._$zr(bw,a2,aN);var aJ=aI*2;var aQ=bX;if(aN<=0){var bI=bw[0];var bq=bC[bI];if(bH==2&&bX==0){P._$jT(bq,0,a3,0,aJ);}else{for(var bt=0;bt<aJ;){a3[aQ]=bq[bt++];a3[aQ+1]=bq[bt++];aQ+=bH;}}}else{if(aN==1){var bq=bC[bw[0]];var bp=bC[bw[1]];var b3=a2[0];var bT=1-b3;for(var bt=0;bt<aJ;){a3[aQ]=bq[bt]*bT+bp[bt]*b3;++bt;a3[aQ+1]=bq[bt]*bT+bp[bt]*b3;++bt;aQ+=bH;}}else{if(aN==2){var bq=bC[bw[0]];var bp=bC[bw[1]];var aZ=bC[bw[2]];var aY=bC[bw[3]];var b3=a2[0];var b1=a2[1];var bT=1-b3;var bP=1-b1;var b2=bP*bT;var b0=bP*b3;var bM=b1*bT;var bL=b1*b3;for(var bt=0;bt<aJ;){a3[aQ]=b2*bq[bt]+b0*bp[bt]+bM*aZ[bt]+bL*aY[bt];++bt;a3[aQ+1]=b2*bq[bt]+b0*bp[bt]+bM*aZ[bt]+bL*aY[bt];++bt;aQ+=bH;}}else{if(aN==3){var ba=bC[bw[0]];var a9=bC[bw[1]];var aP=bC[bw[2]];var aO=bC[bw[3]];var a6=bC[bw[4]];var a4=bC[bw[5]];var aL=bC[bw[6]];var aK=bC[bw[7]];var b3=a2[0];var b1=a2[1];var bZ=a2[2];var bT=1-b3;var bP=1-b1;var bN=1-bZ;var b8=bN*bP*bT;var b7=bN*bP*b3;var bU=bN*b1*bT;var bS=bN*b1*b3;var b6=bZ*bP*bT;var b5=bZ*bP*b3;var bQ=bZ*b1*bT;var bO=bZ*b1*b3;for(var bt=0;bt<aJ;){a3[aQ]=b8*ba[bt]+b7*a9[bt]+bU*aP[bt]+bS*aO[bt]+b6*a6[bt]+b5*a4[bt]+bQ*aL[bt]+bO*aK[bt];++bt;a3[aQ+1]=b8*ba[bt]+b7*a9[bt]+bU*aP[bt]+bS*aO[bt]+b6*a6[bt]+b5*a4[bt]+bQ*aL[bt]+bO*aK[bt];++bt;aQ+=bH;}}else{if(aN==4){var bD=bC[bw[0]];var bB=bC[bw[1]];var bo=bC[bw[2]];var bm=bC[bw[3]];var by=bC[bw[4]];var bx=bC[bw[5]];var be=bC[bw[6]];var bd=bC[bw[7]];var bG=bC[bw[8]];var bE=bC[bw[9]];var bv=bC[bw[10]];var bu=bC[bw[11]];var bA=bC[bw[12]];var bz=bC[bw[13]];var bn=bC[bw[14]];var bl=bC[bw[15]];var b3=a2[0];var b1=a2[1];var bZ=a2[2];var bY=a2[3];var bT=1-b3;var bP=1-b1;var bN=1-bZ;var bK=1-bY;var bk=bK*bN*bP*bT;var bi=bK*bN*bP*b3;var aW=bK*bN*b1*bT;var aV=bK*bN*b1*b3;var bc=bK*bZ*bP*bT;var bb=bK*bZ*bP*b3;var aS=bK*bZ*b1*bT;var aR=bK*bZ*b1*b3;var bs=bY*bN*bP*bT;var br=bY*bN*bP*b3;var a1=bY*bN*b1*bT;var a0=bY*bN*b1*b3;var bh=bY*bZ*bP*bT;var bf=bY*bZ*bP*b3;var aU=bY*bZ*b1*bT;var aT=bY*bZ*b1*b3;for(var bt=0;bt<aJ;){a3[aQ]=bk*bD[bt]+bi*bB[bt]+aW*bo[bt]+aV*bm[bt]+bc*by[bt]+bb*bx[bt]+aS*be[bt]+aR*bd[bt]+bs*bG[bt]+br*bE[bt]+a1*bv[bt]+a0*bu[bt]+bh*bA[bt]+bf*bz[bt]+aU*bn[bt]+aT*bl[bt];++bt;a3[aQ+1]=bk*bD[bt]+bi*bB[bt]+aW*bo[bt]+aV*bm[bt]+bc*by[bt]+bb*bx[bt]+aS*be[bt]+aR*bd[bt]+bs*bG[bt]+br*bE[bt]+a1*bv[bt]+a0*bu[bt]+bh*bA[bt]+bf*bz[bt]+aU*bn[bt]+aT*bl[bt];++bt;aQ+=bH;}}else{var b4=1<<aN;var bJ=new Float32Array(b4);for(var bj=0;bj<b4;bj++){var aH=bj;var aM=1;for(var bF=0;bF<aN;bF++){aM*=(aH%2==0)?(1-a2[bF]):a2[bF];aH/=2;}bJ[bj]=aM;}var bg=new Float32Array(b4);for(var aX=0;aX<b4;aX++){bg[aX]=bC[bw[aX]];}for(var bt=0;bt<aJ;){var a8=0,a7=0;var bR=bt+1;for(var aX=0;aX<b4;aX++){a8+=bJ[aX]*bg[aX][bt];a7+=bJ[aX]*bg[aX][bR];}bt+=2;a3[aQ]=a8;a3[aQ+1]=a7;aQ+=bH;}}}}}}};function e(){if(j){return;}this.x=null;this.y=null;}e.prototype._$HT=function(aH,aI){this.x=aH;this.y=aI;};e.prototype._$HT=function(aH){this.x=aH.x;this.y=aH.y;};function ae(){if(j){return;}this._$gP=null;this._$dr=null;this._$GS=null;this._$qb=null;this._$Lb=null;this._$mS=null;this.clipID=null;this.clipIDList=new Array();}ae._$ur=-2;ae._$ES=500;ae._$wb=2;ae._$8S=3;ae._$52=ae._$ES;ae._$R2=ae._$ES;ae._$or=function(){return ae._$52;};ae._$Pr=function(){return ae._$R2;};ae.prototype.convertClipIDForV2_11=function(aI){var aH=[];if(aI==null){return null;}if(aI.length==0){return null;}if(!/,/.test(aI)){aH.push(aI.id);return aH;}aH=aI.id.split(",");return aH;};ae.prototype._$F0=function(aH){this._$gP=aH._$nP();this._$dr=aH._$nP();this._$GS=aH._$nP();this._$qb=aH._$6L();this._$Lb=aH._$cS();this._$mS=aH._$Tb();if(aH.getFormatVersion()>=ay._$T7){this.clipID=aH._$nP();this.clipIDList=this.convertClipIDForV2_11(this.clipID);}else{this.clipIDList=[];}this._$MS(this._$Lb);};ae.prototype.getClipIDList=function(){return this.clipIDList;};ae.prototype.init=function(aH){};ae.prototype._$Nr=function(aH,aI){aI._$IS[0]=false;aI._$Us=aG._$Z2(aH,this._$GS,aI._$IS,this._$Lb);if(Q._$Zs){}else{if(aI._$IS[0]){return;}}aI._$7s=aG._$br(aH,this._$GS,aI._$IS,this._$mS);};ae.prototype._$2b=function(aH,aI){};ae.prototype.getDrawDataID=function(){return this._$gP;};ae.prototype._$j2=function(aH){this._$gP=aH;};ae.prototype.getOpacity=function(aH,aI){return aI._$7s;};ae.prototype._$zS=function(aH,aI){return aI._$Us;};ae.prototype._$MS=function(aJ){for(var aI=aJ.length-1;aI>=0;--aI){var aH=aJ[aI];if(aH<ae._$52){ae._$52=aH;}else{if(aH>ae._$R2){ae._$R2=aH;}}}};ae.prototype.getTargetBaseDataID=function(){return this._$dr;};ae.prototype._$gs=function(aH){this._$dr=aH;};ae.prototype._$32=function(){return(this._$dr!=null&&(this._$dr!=n._$2o()));};ae.prototype.preDraw=function(aJ,aH,aI){};ae.prototype.draw=function(aJ,aH,aI){};ae.prototype.getType=function(){};ae.prototype._$B2=function(aI,aH,aJ){};function ax(){if(j){return;}this._$Eb=ax._$ps;this._$lT=1;this._$C0=1;this._$tT=1;this._$WL=1;this.culling=false;this.matrix4x4=new Float32Array(16);this.premultipliedAlpha=false;this.anisotropy=0;this.clippingProcess=ax.CLIPPING_PROCESS_NONE;this.clipBufPre_clipContextMask=null;this.clipBufPre_clipContextDraw=null;this.CHANNEL_COLORS=new Array();}ax._$ps=32;ax.CLIPPING_PROCESS_NONE=0;ax.CLIPPING_PROCESS_OVERWRITE_ALPHA=1;ax.CLIPPING_PROCESS_MULTIPLY_ALPHA=2;ax.CLIPPING_PROCESS_DRAW=3;ax.CLIPPING_PROCESS_CLEAR_ALPHA=4;ax.prototype.setChannelFlagAsColor=function(aH,aI){this.CHANNEL_COLORS[aH]=aI;};ax.prototype.getChannelFlagAsColor=function(aH){return this.CHANNEL_COLORS[aH];};ax.prototype._$ZT=function(){};ax.prototype._$Uo=function(aM,aK,aJ,aL,aN,aI,aH){};ax.prototype._$Rs=function(){return -1;};ax.prototype._$Ds=function(aH){};ax.prototype.setBaseColor=function(aK,aJ,aI,aH){if(aK<0){aK=0;}else{if(aK>1){aK=1;}}if(aJ<0){aJ=0;}else{if(aJ>1){aJ=1;}}if(aI<0){aI=0;}else{if(aI>1){aI=1;}}if(aH<0){aH=0;}else{if(aH>1){aH=1;}}this._$lT=aK;this._$C0=aJ;this._$tT=aI;this._$WL=aH;};ax.prototype._$WP=function(aH){this.culling=aH;};ax.prototype.setMatrix=function(aH){for(var aI=0;aI<16;aI++){this.matrix4x4[aI]=aH[aI];}};ax.prototype._$IT=function(){return this.matrix4x4;};ax.prototype.setPremultipliedAlpha=function(aH){this.premultipliedAlpha=aH;};ax.prototype.isPremultipliedAlpha=function(){return this.premultipliedAlpha;};ax.prototype.setAnisotropy=function(aH){this.anisotropy=aH;};ax.prototype.getAnisotropy=function(){return this.anisotropy;};ax.prototype.getClippingProcess=function(){return this.clippingProcess;};ax.prototype.setClippingProcess=function(aH){this.clippingProcess=aH;};ax.prototype.setClipBufPre_clipContextForMask=function(aH){this.clipBufPre_clipContextMask=aH;};ax.prototype.getClipBufPre_clipContextMask=function(){return this.clipBufPre_clipContextMask;};ax.prototype.setClipBufPre_clipContextForDraw=function(aH){this.clipBufPre_clipContextDraw=aH;};ax.prototype.getClipBufPre_clipContextDraw=function(){return this.clipBufPre_clipContextDraw;};function o(){if(j){return;}this.a=1;this.r=1;this.g=1;this.b=1;this.scale=1;this._$ho=1;this.blendMode=Q.L2D_COLOR_BLEND_MODE_MULT;}function c(){if(j){return;}this._$kP=null;this._$dr=null;this._$Ai=true;this._$mS=null;}c._$ur=-2;c._$c2=1;c._$_b=2;c.prototype._$F0=function(aH){this._$kP=aH._$nP();this._$dr=aH._$nP();};c.prototype.readV2_opacity=function(aH){if(aH.getFormatVersion()>=ay.LIVE2D_FORMAT_VERSION_V2_10_SDK2){this._$mS=aH._$Tb();}};c.prototype.init=function(aH){};c.prototype._$Nr=function(aI,aH){};c.prototype.interpolateOpacity=function(aJ,aK,aI,aH){if(this._$mS==null){aI.setInterpolatedOpacity(1);}else{aI.setInterpolatedOpacity(aG._$br(aJ,aK,aH,this._$mS));}};c.prototype._$2b=function(aI,aH){};c.prototype._$nb=function(aL,aK,aM,aH,aI,aJ,aN){};c.prototype.getType=function(){};c.prototype._$gs=function(aH){this._$dr=aH;};c.prototype._$a2=function(aH){this._$kP=aH;};c.prototype.getTargetBaseDataID=function(){return this._$dr;};c.prototype.getBaseDataID=function(){return this._$kP;};c.prototype._$32=function(){return(this._$dr!=null&&(this._$dr!=n._$2o()));};function P(){}P._$W2=0;P._$CS=P._$W2;P._$Mo=function(){return true;};P._$XP=function(aI){try{var aJ=getTimeMSec();while(getTimeMSec()-aJ<aI){}}catch(aH){aH._$Rb();}};P.getUserTimeMSec=function(){return(P._$CS==P._$W2)?P.getSystemTimeMSec():P._$CS;};P.setUserTimeMSec=function(aH){P._$CS=aH;};P.updateUserTimeMSec=function(){return(P._$CS=P.getSystemTimeMSec());};P.getTimeMSec=function(){return new Date().getTime();};P.getSystemTimeMSec=function(){return new Date().getTime();};P._$Q=function(aH){};P._$jT=function(aM,aJ,aI,aL,aH){for(var aK=0;aK<aH;aK++){aI[aL+aK]=aM[aJ+aK];}};function aA(){if(j){return;}this._$VP=0;this._$wL=null;this._$GP=null;this._$8o=aA._$ds;this._$2r=-1;this._$O2=0;this._$ri=0;}aA._$ds=-2;aA.prototype._$F0=function(aH){this._$wL=aH._$nP();this._$VP=aH._$6L();this._$GP=aH._$nP();};aA.prototype.getParamIndex=function(aH){if(this._$2r!=aH){this._$8o=aA._$ds;}return this._$8o;};aA.prototype._$Pb=function(aI,aH){this._$8o=aI;this._$2r=aH;};aA.prototype.getParamID=function(){return this._$wL;};aA.prototype._$yP=function(aH){this._$wL=aH;};aA.prototype._$N2=function(){return this._$VP;};aA.prototype._$d2=function(){return this._$GP;};aA.prototype._$t2=function(aI,aH){this._$VP=aI;this._$GP=aH;};aA.prototype._$Lr=function(){return this._$O2;};aA.prototype._$wr=function(aH){this._$O2=aH;};aA.prototype._$SL=function(){return this._$ri;};aA.prototype._$AL=function(aH){this._$ri=aH;};function G(){}G.startsWith=function(aJ,aL,aK){var aH=aL+aK.length;if(aH>=aJ.length){return false;}for(var aI=aL;aI<aH;aI++){if(G.getChar(aJ,aI)!=aK.charAt(aI-aL)){return false;}}return true;};G.getChar=function(aI,aH){return String.fromCharCode(aI.getUint8(aH));};G.createString=function(aM,aL,aJ){var aH=new ArrayBuffer(aJ*2);var aK=new Uint16Array(aH);for(var aI=0;aI<aJ;aI++){aK[aI]=aM.getUint8(aL+aI);}return String.fromCharCode.apply(null,aK);};G._$LS=function(aP,aM,aR,aK){if(aP instanceof ArrayBuffer){aP=new DataView(aP);}var aL=aR;var aJ=false;var aQ=false;var aS=0;var aO=G.getChar(aP,aL);if(aO=="-"){aJ=true;aL++;}var aN=false;for(;aL<aM;aL++){aO=G.getChar(aP,aL);switch(aO){case"0":aS=aS*10;break;case"1":aS=aS*10+1;break;case"2":aS=aS*10+2;break;case"3":aS=aS*10+3;break;case"4":aS=aS*10+4;break;case"5":aS=aS*10+5;break;case"6":aS=aS*10+6;break;case"7":aS=aS*10+7;break;case"8":aS=aS*10+8;break;case"9":aS=aS*10+9;break;case".":aQ=true;aL++;aN=true;break;default:aN=true;break;}if(aN){break;}}if(aQ){var aI=0.1;var aH=false;for(;aL<aM;aL++){aO=G.getChar(aP,aL);switch(aO){case"0":break;case"1":aS+=aI*1;break;case"2":aS+=aI*2;break;case"3":aS+=aI*3;break;case"4":aS+=aI*4;break;case"5":aS+=aI*5;break;case"6":aS+=aI*6;break;case"7":aS+=aI*7;break;case"8":aS+=aI*8;break;case"9":aS+=aI*9;break;default:aH=true;break;}aI*=0.1;if(aH){break;}}}if(aJ){aS=-aS;}aK[0]=aL;return aS;};function g(){if(j){return;}this._$Ob=null;}g.prototype._$zP=function(){this._$Ob=new Array();};g.prototype._$F0=function(aH){this._$Ob=aH._$nP();};g.prototype._$Ur=function(aK){if(aK._$WS()){return true;}var aH=aK._$v2();for(var aJ=this._$Ob.length-1;aJ>=0;--aJ){var aI=this._$Ob[aJ].getParamIndex(aH);if(aI==aA._$ds){aI=aK.getParamIndex(this._$Ob[aJ].getParamID());}if(aK._$Xb(aI)){return true;}}return false;};g.prototype._$Q2=function(aL,aV){var aX=this._$Ob.length;var aJ=aL._$v2();var aN=0;var aI;var aQ;for(var aK=0;aK<aX;aK++){var aH=this._$Ob[aK];aI=aH.getParamIndex(aJ);if(aI==aA._$ds){aI=aL.getParamIndex(aH.getParamID());aH._$Pb(aI,aJ);}if(aI<0){throw new Exception("err 23242 : "+aH.getParamID());}var aU=aI<0?0:aL.getParamFloat(aI);aQ=aH._$N2();var aM=aH._$d2();var aP=-1;var aT=0;var aS;var aR;if(aQ<1){}else{if(aQ==1){aS=aM[0];if(aS-aw._$J<aU&&aU<aS+aw._$J){aP=0;aT=0;}else{aP=0;aV[0]=true;}}else{aS=aM[0];if(aU<aS-aw._$J){aP=0;aV[0]=true;}else{if(aU<aS+aw._$J){aP=0;}else{var aW=false;for(var aO=1;aO<aQ;++aO){aR=aM[aO];if(aU<aR+aw._$J){if(aR-aw._$J<aU){aP=aO;}else{aP=aO-1;aT=(aU-aS)/(aR-aS);aN++;}aW=true;break;}aS=aR;}if(!aW){aP=aQ-1;aT=0;aV[0]=true;}}}}}aH._$wr(aP);aH._$AL(aT);}return aN;};g.prototype._$zr=function(aN,aT,aP){var aR=1<<aP;if(aR+1>aw._$Qb){console.log("err 23245\n");}var aS=this._$Ob.length;var aK=1;var aH=1;var aJ=0;for(var aQ=0;aQ<aR;++aQ){aN[aQ]=0;}for(var aL=0;aL<aS;++aL){var aI=this._$Ob[aL];if(aI._$SL()==0){var aO=aI._$Lr()*aK;if(aO<0&&Q._$3T){throw new Exception("err 23246");}for(var aQ=0;aQ<aR;++aQ){aN[aQ]+=aO;}}else{var aO=aK*aI._$Lr();var aM=aK*(aI._$Lr()+1);for(var aQ=0;aQ<aR;++aQ){aN[aQ]+=((aQ/aH|0)%2==0)?aO:aM;}aT[aJ++]=aI._$SL();aH*=2;}aK*=aI._$N2();}aN[aR]=65535;aT[aJ]=-1;};g.prototype._$h2=function(aJ,aH,aK){var aM=new Float32Array(aH);for(var aL=0;aL<aH;++aL){aM[aL]=aK[aL];}var aI=new aA();aI._$yP(aJ);aI._$t2(aH,aM);this._$Ob.push(aI);};g.prototype._$J2=function(aO){var aN=aO;var aM=this._$Ob.length;for(var aK=0;aK<aM;++aK){var aI=this._$Ob[aK];var aH=aI._$N2();var aJ=aN%aI._$N2();var aL=aI._$d2()[aJ];console.log("%s[%d]=%7.2f / ",aI.getParamID(),aJ,aL);aN/=aH;}console.log("\n");};g.prototype.getParamCount=function(){return this._$Ob.length;};g.prototype._$zs=function(){return this._$Ob;};function ac(){this.m=new Float32Array(16);this.identity();}ac.prototype.identity=function(){for(var aH=0;aH<16;aH++){this.m[aH]=((aH%5)==0)?1:0;}};ac.prototype.getArray=function(){return this.m;};ac.prototype.getCopyMatrix=function(){return new Float32Array(this.m);};ac.prototype.setMatrix=function(aI){if(aI==null||aI.length!=16){return;}for(var aH=0;aH<16;aH++){this.m[aH]=aI[aH];}};ac.prototype.mult=function(aH,aJ,aI){if(aJ==null){return null;}if(this==aJ){this.mult_safe(this.m,aH.m,aJ.m,aI);}else{this.mult_fast(this.m,aH.m,aJ.m,aI);}return aJ;};ac.prototype.mult_safe=function(aI,aH,aM,aJ){if(aI==aM){var aL=new Array(16);this.mult_fast(aI,aH,aL,aJ);for(var aK=15;aK>=0;--aK){aM[aK]=aL[aK];}}else{this.mult_fast(aI,aH,aM,aJ);}};ac.prototype.mult_fast=function(aI,aH,aK,aJ){if(aJ){aK[0]=aI[0]*aH[0]+aI[4]*aH[1]+aI[8]*aH[2];aK[4]=aI[0]*aH[4]+aI[4]*aH[5]+aI[8]*aH[6];aK[8]=aI[0]*aH[8]+aI[4]*aH[9]+aI[8]*aH[10];aK[12]=aI[0]*aH[12]+aI[4]*aH[13]+aI[8]*aH[14]+aI[12];aK[1]=aI[1]*aH[0]+aI[5]*aH[1]+aI[9]*aH[2];aK[5]=aI[1]*aH[4]+aI[5]*aH[5]+aI[9]*aH[6];aK[9]=aI[1]*aH[8]+aI[5]*aH[9]+aI[9]*aH[10];aK[13]=aI[1]*aH[12]+aI[5]*aH[13]+aI[9]*aH[14]+aI[13];aK[2]=aI[2]*aH[0]+aI[6]*aH[1]+aI[10]*aH[2];aK[6]=aI[2]*aH[4]+aI[6]*aH[5]+aI[10]*aH[6];aK[10]=aI[2]*aH[8]+aI[6]*aH[9]+aI[10]*aH[10];aK[14]=aI[2]*aH[12]+aI[6]*aH[13]+aI[10]*aH[14]+aI[14];aK[3]=aK[7]=aK[11]=0;aK[15]=1;}else{aK[0]=aI[0]*aH[0]+aI[4]*aH[1]+aI[8]*aH[2]+aI[12]*aH[3];aK[4]=aI[0]*aH[4]+aI[4]*aH[5]+aI[8]*aH[6]+aI[12]*aH[7];aK[8]=aI[0]*aH[8]+aI[4]*aH[9]+aI[8]*aH[10]+aI[12]*aH[11];aK[12]=aI[0]*aH[12]+aI[4]*aH[13]+aI[8]*aH[14]+aI[12]*aH[15];aK[1]=aI[1]*aH[0]+aI[5]*aH[1]+aI[9]*aH[2]+aI[13]*aH[3];aK[5]=aI[1]*aH[4]+aI[5]*aH[5]+aI[9]*aH[6]+aI[13]*aH[7];aK[9]=aI[1]*aH[8]+aI[5]*aH[9]+aI[9]*aH[10]+aI[13]*aH[11];aK[13]=aI[1]*aH[12]+aI[5]*aH[13]+aI[9]*aH[14]+aI[13]*aH[15];aK[2]=aI[2]*aH[0]+aI[6]*aH[1]+aI[10]*aH[2]+aI[14]*aH[3];aK[6]=aI[2]*aH[4]+aI[6]*aH[5]+aI[10]*aH[6]+aI[14]*aH[7];aK[10]=aI[2]*aH[8]+aI[6]*aH[9]+aI[10]*aH[10]+aI[14]*aH[11];aK[14]=aI[2]*aH[12]+aI[6]*aH[13]+aI[10]*aH[14]+aI[14]*aH[15];aK[3]=aI[3]*aH[0]+aI[7]*aH[1]+aI[11]*aH[2]+aI[15]*aH[3];aK[7]=aI[3]*aH[4]+aI[7]*aH[5]+aI[11]*aH[6]+aI[15]*aH[7];aK[11]=aI[3]*aH[8]+aI[7]*aH[9]+aI[11]*aH[10]+aI[15]*aH[11];aK[15]=aI[3]*aH[12]+aI[7]*aH[13]+aI[11]*aH[14]+aI[15]*aH[15];}};ac.prototype.translate=function(aH,aJ,aI){this.m[12]=this.m[0]*aH+this.m[4]*aJ+this.m[8]*aI+this.m[12];this.m[13]=this.m[1]*aH+this.m[5]*aJ+this.m[9]*aI+this.m[13];this.m[14]=this.m[2]*aH+this.m[6]*aJ+this.m[10]*aI+this.m[14];this.m[15]=this.m[3]*aH+this.m[7]*aJ+this.m[11]*aI+this.m[15];};ac.prototype.scale=function(aJ,aI,aH){this.m[0]*=aJ;this.m[4]*=aI;this.m[8]*=aH;this.m[1]*=aJ;this.m[5]*=aI;this.m[9]*=aH;this.m[2]*=aJ;this.m[6]*=aI;this.m[10]*=aH;this.m[3]*=aJ;this.m[7]*=aI;this.m[11]*=aH;};ac.prototype.rotateX=function(aH){var aK=aC.fcos(aH);var aJ=aC._$9(aH);var aI=this.m[4];this.m[4]=aI*aK+this.m[8]*aJ;this.m[8]=aI*-aJ+this.m[8]*aK;aI=this.m[5];this.m[5]=aI*aK+this.m[9]*aJ;this.m[9]=aI*-aJ+this.m[9]*aK;aI=this.m[6];this.m[6]=aI*aK+this.m[10]*aJ;this.m[10]=aI*-aJ+this.m[10]*aK;aI=this.m[7];this.m[7]=aI*aK+this.m[11]*aJ;this.m[11]=aI*-aJ+this.m[11]*aK;};ac.prototype.rotateY=function(aH){var aK=aC.fcos(aH);var aJ=aC._$9(aH);var aI=this.m[0];this.m[0]=aI*aK+this.m[8]*-aJ;this.m[8]=aI*aJ+this.m[8]*aK;aI=this.m[1];this.m[1]=aI*aK+this.m[9]*-aJ;this.m[9]=aI*aJ+this.m[9]*aK;aI=m[2];this.m[2]=aI*aK+this.m[10]*-aJ;this.m[10]=aI*aJ+this.m[10]*aK;aI=m[3];this.m[3]=aI*aK+this.m[11]*-aJ;this.m[11]=aI*aJ+this.m[11]*aK;};ac.prototype.rotateZ=function(aH){var aK=aC.fcos(aH);var aJ=aC._$9(aH);var aI=this.m[0];this.m[0]=aI*aK+this.m[4]*aJ;this.m[4]=aI*-aJ+this.m[4]*aK;aI=this.m[1];this.m[1]=aI*aK+this.m[5]*aJ;this.m[5]=aI*-aJ+this.m[5]*aK;aI=this.m[2];this.m[2]=aI*aK+this.m[6]*aJ;this.m[6]=aI*-aJ+this.m[6]*aK;aI=this.m[3];this.m[3]=aI*aK+this.m[7]*aJ;this.m[7]=aI*-aJ+this.m[7]*aK;};function Z(aH){if(j){return;}ak.prototype.constructor.call(this,aH);}Z.prototype=new ak();Z._$tP=new Object();Z._$27=function(){Z._$tP.clear();};Z.getID=function(aH){var aI=Z._$tP[aH];if(aI==null){aI=new Z(aH);Z._$tP[aH]=aI;}return aI;};Z.prototype._$3s=function(){return new Z();};function aD(){if(j){return;}this._$7=1;this._$f=0;this._$H=0;this._$g=1;this._$k=0;this._$w=0;this._$hi=STATE_IDENTITY;this._$Z=_$pS;}aD._$kS=-1;aD._$pS=0;aD._$hb=1;aD.STATE_IDENTITY=0;aD._$gb=1;aD._$fo=2;aD._$go=4;aD.prototype.transform=function(aK,aI,aH){var aT,aS,aR,aM,aL,aJ;var aQ=0;var aN=0;switch(this._$hi){default:return;case (aD._$go|aD._$fo|aD._$gb):aT=this._$7;aS=this._$H;aR=this._$k;aM=this._$f;aL=this._$g;aJ=this._$w;while(--aH>=0){var aP=aK[aQ++];var aO=aK[aQ++];aI[aN++]=(aT*aP+aS*aO+aR);aI[aN++]=(aM*aP+aL*aO+aJ);}return;case (aD._$go|aD._$fo):aT=this._$7;aS=this._$H;aM=this._$f;aL=this._$g;while(--aH>=0){var aP=aK[aQ++];var aO=aK[aQ++];aI[aN++]=(aT*aP+aS*aO);aI[aN++]=(aM*aP+aL*aO);}return;case (aD._$go|aD._$gb):aS=this._$H;aR=this._$k;aM=this._$f;aJ=this._$w;while(--aH>=0){var aP=aK[aQ++];aI[aN++]=(aS*aK[aQ++]+aR);aI[aN++]=(aM*aP+aJ);}return;case (aD._$go):aS=this._$H;aM=this._$f;while(--aH>=0){var aP=aK[aQ++];aI[aN++]=(aS*aK[aQ++]);aI[aN++]=(aM*aP);}return;case (aD._$fo|aD._$gb):aT=this._$7;aR=this._$k;aL=this._$g;aJ=this._$w;while(--aH>=0){aI[aN++]=(aT*aK[aQ++]+aR);aI[aN++]=(aL*aK[aQ++]+aJ);}return;case (aD._$fo):aT=this._$7;aL=this._$g;while(--aH>=0){aI[aN++]=(aT*aK[aQ++]);aI[aN++]=(aL*aK[aQ++]);}return;case (aD._$gb):aR=this._$k;aJ=this._$w;while(--aH>=0){aI[aN++]=(aK[aQ++]+aR);aI[aN++]=(aK[aQ++]+aJ);}return;case (aD.STATE_IDENTITY):if(aK!=aI||aQ!=aN){P._$jT(aK,aQ,aI,aN,aH*2);}return;}};aD.prototype.update=function(){if(this._$H==0&&this._$f==0){if(this._$7==1&&this._$g==1){if(this._$k==0&&this._$w==0){this._$hi=aD.STATE_IDENTITY;this._$Z=aD._$pS;}else{this._$hi=aD._$gb;this._$Z=aD._$hb;}}else{if(this._$k==0&&this._$w==0){this._$hi=aD._$fo;this._$Z=aD._$kS;}else{this._$hi=(aD._$fo|aD._$gb);this._$Z=aD._$kS;}}}else{if(this._$7==0&&this._$g==0){if(this._$k==0&&this._$w==0){this._$hi=aD._$go;this._$Z=aD._$kS;}else{this._$hi=(aD._$go|aD._$gb);this._$Z=aD._$kS;}}else{if(this._$k==0&&this._$w==0){this._$hi=(aD._$go|aD._$fo);this._$Z=aD._$kS;}else{this._$hi=(aD._$go|aD._$fo|aD._$gb);this._$Z=aD._$kS;}}}};aD.prototype._$RT=function(aK){this._$IT(aK);var aJ=aK[0];var aH=aK[2];var aN=aK[1];var aM=aK[3];var aI=Math.sqrt(aJ*aJ+aN*aN);var aL=aJ*aM-aH*aN;if(aI==0){if(Q._$so){console.log("affine._$RT() / rt==0");}}else{aK[0]=aI;aK[1]=aL/aI;aK[2]=(aN*aM+aJ*aH)/aL;aK[3]=Math.atan2(aN,aJ);}};aD.prototype._$ho=function(aN,aM,aI,aH){var aL=new Float32Array(6);var aK=new Float32Array(6);aN._$RT(aL);aM._$RT(aK);var aJ=new Float32Array(6);aJ[0]=aL[0]+(aK[0]-aL[0])*aI;aJ[1]=aL[1]+(aK[1]-aL[1])*aI;aJ[2]=aL[2]+(aK[2]-aL[2])*aI;aJ[3]=aL[3]+(aK[3]-aL[3])*aI;aJ[4]=aL[4]+(aK[4]-aL[4])*aI;aJ[5]=aL[5]+(aK[5]-aL[5])*aI;aH._$CT(aJ);};aD.prototype._$CT=function(aJ){var aI=Math.cos(aJ[3]);var aH=Math.sin(aJ[3]);this._$7=aJ[0]*aI;this._$f=aJ[0]*aH;this._$H=aJ[1]*(aJ[2]*aI-aH);this._$g=aJ[1]*(aJ[2]*aH+aI);this._$k=aJ[4];this._$w=aJ[5];this.update();};aD.prototype._$IT=function(aH){aH[0]=this._$7;aH[1]=this._$f;aH[2]=this._$H;aH[3]=this._$g;aH[4]=this._$k;aH[5]=this._$w;};function Y(){if(j){return;}ah.prototype.constructor.call(this);this.motions=new Array();this._$7r=null;this._$7r=Y._$Co++;this._$D0=30;this._$yT=0;this._$E=true;this.loopFadeIn=true;this._$AS=-1;_$a0();}Y.prototype=new ah();Y._$cs="VISIBLE:";Y._$ar="LAYOUT:";Y._$Co=0;Y._$D2=[];Y._$1T=1;Y.loadMotion=function(aR){var aM=new Y();var aI=[0];var aP=aR.length;aM._$yT=0;for(var aJ=0;aJ<aP;++aJ){var aQ=(aR[aJ]&255);if(aQ=="\n"||aQ=="\r"){continue;}if(aQ=="#"){for(;aJ<aP;++aJ){if(aR[aJ]=="\n"||aR[aJ]=="\r"){break;}}continue;}if(aQ=="$"){var aT=aJ;var aK=-1;for(;aJ<aP;++aJ){aQ=(aR[aJ]&255);if(aQ=="\r"||aQ=="\n"){break;}if(aQ=="="){aK=aJ;break;}}var aO=false;if(aK>=0){if(aK==aT+4&&aR[aT+1]=="f"&&aR[aT+2]=="p"&&aR[aT+3]=="s"){aO=true;}for(aJ=aK+1;aJ<aP;++aJ){aQ=(aR[aJ]&255);if(aQ=="\r"||aQ=="\n"){break;}if(aQ==","||aQ==" "||aQ=="\t"){continue;}var aL=G._$LS(aR,aP,aJ,aI);if(aI[0]>0){if(aO&&5<aL&&aL<121){aM._$D0=aL;}}aJ=aI[0];}}for(;aJ<aP;++aJ){if(aR[aJ]=="\n"||aR[aJ]=="\r"){break;}}continue;}if(("a"<=aQ&&aQ<="z")||("A"<=aQ&&aQ<="Z")||aQ=="_"){var aT=aJ;var aK=-1;for(;aJ<aP;++aJ){aQ=(aR[aJ]&255);if(aQ=="\r"||aQ=="\n"){break;}if(aQ=="="){aK=aJ;break;}}if(aK>=0){var aN=new t();if(G.startsWith(aR,aT,Y._$cs)){aN._$RP=t._$hs;aN._$4P=new String(aR,aT,aK-aT);}else{if(G.startsWith(aR,aT,Y._$ar)){aN._$4P=new String(aR,aT+7,aK-aT-7);if(G.startsWith(aR,aT+7,"ANCHOR_X")){aN._$RP=t._$xs;}else{if(G.startsWith(aR,aT+7,"ANCHOR_Y")){aN._$RP=t._$us;}else{if(G.startsWith(aR,aT+7,"SCALE_X")){aN._$RP=t._$qs;}else{if(G.startsWith(aR,aT+7,"SCALE_Y")){aN._$RP=t._$Ys;}else{if(G.startsWith(aR,aT+7,"X")){aN._$RP=t._$ws;}else{if(G.startsWith(aR,aT+7,"Y")){aN._$RP=t._$Ns;}}}}}}}else{aN._$RP=t._$Fr;aN._$4P=new String(aR,aT,aK-aT);}}aM.motions.push(aN);var aS=0;Y._$D2.clear();for(aJ=aK+1;aJ<aP;++aJ){aQ=(aR[aJ]&255);if(aQ=="\r"||aQ=="\n"){break;}if(aQ==","||aQ==" "||aQ=="\t"){continue;}var aL=G._$LS(aR,aP,aJ,aI);if(aI[0]>0){Y._$D2.push(aL);aS++;var aH=aI[0];if(aH<aJ){console.log("_$n0 _$hi . @Live2DMotion loadMotion()\n");break;}aJ=aH;}}aN._$I0=Y._$D2._$BL();if(aS>aM._$yT){aM._$yT=aS;}}}}aM._$AS=((1000*aM._$yT)/aM._$D0)|0;return aM;};Y.prototype.getDurationMSec=function(){return this._$AS;};Y.prototype.dump=function(){for(var aJ=0;aJ<this.motions.length;aJ++){var aH=this.motions[aJ];console.log("_$wL[%s] [%d]. ",aH._$4P,aH._$I0.length);for(var aI=0;aI<aH._$I0.length&&aI<10;aI++){console.log("%5.2f ,",aH._$I0[aI]);}console.log("\n");}};Y.prototype.updateParamExe=function(aH,aL,aO,aX){var aM=aL-aX._$z2;var aV=aM*this._$D0/1000;var aJ=aV|0;var aP=aV-aJ;for(var aU=0;aU<this.motions.length;aU++){var aS=this.motions[aU];var aK=aS._$I0.length;var aQ=aS._$4P;if(aS._$RP==t._$hs){var aT=aS._$I0[(aJ>=aK?aK-1:aJ)];aH.setParamFloat(aQ,aT);}else{if(t._$ws<=aS._$RP&&aS._$RP<=t._$Ys){}else{var aR=aH.getParamFloat(aQ);var aY=aS._$I0[(aJ>=aK?aK-1:aJ)];var aW=aS._$I0[(aJ+1>=aK?aK-1:aJ+1)];var aI=aY+(aW-aY)*aP;var aN=aR+(aI-aR)*aO;aH.setParamFloat(aQ,aN);}}}if(aJ>=this._$yT){if(this._$E){aX._$z2=aL;if(this.loopFadeIn){aX._$bs=aL;}}else{aX._$9L=true;}}};Y.prototype._$r0=function(){return this._$E;};Y.prototype._$aL=function(aH){this._$E=aH;};Y.prototype.isLoopFadeIn=function(){return this.loopFadeIn;};Y.prototype.setLoopFadeIn=function(aH){this.loopFadeIn=aH;};function aE(){this._$P=new Float32Array(100);this.size=0;}aE.prototype.clear=function(){this.size=0;};aE.prototype.add=function(aI){if(this._$P.length<=this.size){var aH=new Float32Array(this.size*2);P._$jT(this._$P,0,aH,0,this.size);this._$P=aH;}this._$P[this.size++]=aI;};aE.prototype._$BL=function(){var aH=new Float32Array(this.size);P._$jT(this._$P,0,aH,0,this.size);return aH;};function t(){this._$4P=null;this._$I0=null;this._$RP=null;}t._$Fr=0;t._$hs=1;t._$ws=100;t._$Ns=101;t._$xs=102;t._$us=103;t._$qs=104;t._$Ys=105;function aw(){}aw._$Ms=1;aw._$Qs=2;aw._$i2=0;aw._$No=2;aw._$do=aw._$Ms;aw._$Ls=true;aw._$1r=5;aw._$Qb=65;aw._$J=0.0001;aw._$FT=0.001;aw._$Ss=3;function ay(){}ay._$o7=6;ay._$S7=7;ay._$s7=8;ay._$77=9;ay.LIVE2D_FORMAT_VERSION_V2_10_SDK2=10;ay.LIVE2D_FORMAT_VERSION_V2_11_SDK2_1=11;ay._$T7=ay.LIVE2D_FORMAT_VERSION_V2_11_SDK2_1;ay._$Is=-2004318072;ay._$h0=0;ay._$4L=23;ay._$7P=33;ay._$uT=function(aH){console.log("_$bo :: _$6 _$mo _$E0 : %d\n",aH);};ay._$9o=function(aH){if(aH<40){ay._$uT(aH);return null;}else{if(aH<50){ay._$uT(aH);return null;}else{if(aH<60){ay._$uT(aH);return null;}else{if(aH<100){switch(aH){case 65:return new E();case 66:return new g();case 67:return new aA();case 68:return new ab();case 69:return new X();case 70:return new b();default:ay._$uT(aH);return null;}}else{if(aH<150){switch(aH){case 131:return new f();case 133:return new s();case 136:return new w();case 137:return new an();case 142:return new aq();}}}}}}ay._$uT(aH);return null;};function y(aH){if(j){return;}this._$QT=true;this._$co=-1;this._$qo=0;this._$pb=new Array(y._$is);this._$_2=new Float32Array(y._$is);this._$vr=new Float32Array(y._$is);this._$Rr=new Float32Array(y._$is);this._$Or=new Float32Array(y._$is);this._$fs=new Float32Array(y._$is);this._$Js=new Array(y._$is);this._$3S=new Array();this._$aS=new Array();this._$Bo=null;this._$F2=new Array();this._$db=new Array();this._$8b=new Array();this._$Hr=new Array();this._$Ws=null;this._$Vs=null;this._$Er=null;this._$Es=new Int16Array(aw._$Qb);this._$ZP=new Float32Array(aw._$1r*2);this._$Ri=aH;this._$b0=y._$HP++;this.clipManager=null;this.dp_webgl=null;}y._$HP=0;y._$_0=true;y._$V2=-1;y._$W0=-1;y._$jr=false;y._$ZS=true;y._$tr=(-1000000);y._$lr=(1000000);y._$is=32;y._$e=false;y.prototype.getDrawDataIndex=function(aI){for(var aH=this._$aS.length-1;aH>=0;--aH){if(this._$aS[aH]!=null&&this._$aS[aH].getDrawDataID()==aI){return aH;}}return -1;};y.prototype.getDrawData=function(aH){if(aH instanceof Z){if(this._$Bo==null){this._$Bo=new Object();var aJ=this._$aS.length;for(var aI=0;aI<aJ;aI++){var aL=this._$aS[aI];var aK=aL.getDrawDataID();if(aK==null){continue;}this._$Bo[aK]=aL;}}return this._$Bo[id];}else{if(aH<this._$aS.length){return this._$aS[aH];}else{return null;}}};y.prototype.release=function(){this._$3S.clear();this._$aS.clear();this._$F2.clear();if(this._$Bo!=null){this._$Bo.clear();}this._$db.clear();this._$8b.clear();this._$Hr.clear();};y.prototype.init=function(){this._$co++;if(this._$F2.length>0){this.release();}var aO=this._$Ri.getModelImpl();var aT=aO._$Xr();var aS=aT.length;var aH=new Array();var a3=new Array();for(var aV=0;aV<aS;++aV){var a4=aT[aV];this._$F2.push(a4);this._$Hr.push(a4.init(this));var aK=a4.getBaseData();var aR=aK.length;for(var aU=0;aU<aR;++aU){aH.push(aK[aU]);}for(var aU=0;aU<aR;++aU){var aM=aK[aU].init(this);aM._$l2(aV);a3.push(aM);}var a1=a4.getDrawData();var aP=a1.length;for(var aU=0;aU<aP;++aU){var aZ=a1[aU];var a0=aZ.init(this);a0._$IP=aV;this._$aS.push(aZ);this._$8b.push(a0);}}var aY=aH.length;var aN=n._$2o();while(true){var aX=false;for(var aV=0;aV<aY;++aV){var aL=aH[aV];if(aL==null){continue;}var a2=aL.getTargetBaseDataID();if(a2==null||a2==aN||this.getBaseDataIndex(a2)>=0){this._$3S.push(aL);this._$db.push(a3[aV]);aH[aV]=null;aX=true;}}if(!aX){break;}}var aI=aO._$E2();if(aI!=null){var aJ=aI._$1s();if(aJ!=null){var aW=aJ.length;for(var aV=0;aV<aW;++aV){var aQ=aJ[aV];if(aQ==null){continue;}this._$02(aQ.getParamID(),aQ.getDefaultValue(),aQ.getMinValue(),aQ.getMaxValue());}}}this.clipManager=new W(this.dp_webgl);this.clipManager.init(this,this._$aS,this._$8b);this._$QT=true;};y.prototype.update=function(){if(y._$e){q.start("_$zL");}var aK=this._$_2.length;for(var aW=0;aW<aK;aW++){if(this._$_2[aW]!=this._$vr[aW]){this._$Js[aW]=y._$ZS;this._$vr[aW]=this._$_2[aW];}}var aX=false;var aQ=this._$3S.length;var aN=this._$aS.length;var aS=a._$or();var aZ=a._$Pr();var aU=aZ-aS+1;if(this._$Ws==null||this._$Ws.length<aU){this._$Ws=new Int16Array(aU);this._$Vs=new Int16Array(aU);}for(var aW=0;aW<aU;aW++){this._$Ws[aW]=y._$V2;this._$Vs[aW]=y._$V2;}if(this._$Er==null||this._$Er.length<aN){this._$Er=new Int16Array(aN);}for(var aW=0;aW<aN;aW++){this._$Er[aW]=y._$W0;}if(y._$e){q.dump("_$zL");}if(y._$e){q.start("_$UL");}var aL=null;for(var aV=0;aV<aQ;++aV){var aJ=this._$3S[aV];var aH=this._$db[aV];try{aJ._$Nr(this,aH);aJ._$2b(this,aH);}catch(aY){if(aL==null){aL=aY;}}}if(aL!=null){if(y._$_0){q._$Rb(aL);}}if(y._$e){q.dump("_$UL");}if(y._$e){q.start("_$DL");}var aR=null;for(var aO=0;aO<aN;++aO){var aM=this._$aS[aO];var aI=this._$8b[aO];try{aM._$Nr(this,aI);if(aI._$u2()){continue;}aM._$2b(this,aI);var aT=Math.floor(aM._$zS(this,aI)-aS);var aP;try{aP=this._$Vs[aT];}catch(aY){console.log("_$li :: %s / %s 				@@_$fS\n",aY.toString(),aM.getDrawDataID().toString());aT=Math.floor(aM._$zS(this,aI)-aS);continue;}if(aP==y._$V2){this._$Ws[aT]=aO;}else{this._$Er[aP]=aO;}this._$Vs[aT]=aO;}catch(aY){if(aR==null){aR=aY;Q._$sT(Q._$H7);}}}if(aR!=null){if(y._$_0){q._$Rb(aR);}}if(y._$e){q.dump("_$DL");}if(y._$e){q.start("_$eL");}for(var aW=this._$Js.length-1;aW>=0;aW--){this._$Js[aW]=y._$jr;}this._$QT=false;if(y._$e){q.dump("_$eL");}return aX;};y.prototype.preDraw=function(aH){if(this.clipManager!=null){aH._$ZT();this.clipManager.setupClip(this,aH);}};y.prototype.draw=function(aM){if(this._$Ws==null){q._$li("call _$Ri.update() before _$Ri.draw() ");return;}var aP=this._$Ws.length;aM._$ZT();for(var aK=0;aK<aP;++aK){var aN=this._$Ws[aK];if(aN==y._$V2){continue;}do{var aH=this._$aS[aN];var aI=this._$8b[aN];if(aI._$yo()){var aJ=aI._$IP;var aL=this._$Hr[aJ];aI._$VS=aL.getPartsOpacity();aH.draw(aM,this,aI);}var aO=this._$Er[aN];if(aO<=aN||aO==y._$W0){break;}aN=aO;}while(true);}};y.prototype.getParamIndex=function(aH){for(var aI=this._$pb.length-1;aI>=0;--aI){if(this._$pb[aI]==aH){return aI;}}return this._$02(aH,0,y._$tr,y._$lr);};y.prototype._$BS=function(aH){return this.getBaseDataIndex(aH);};y.prototype.getBaseDataIndex=function(aH){for(var aI=this._$3S.length-1;aI>=0;--aI){if(this._$3S[aI]!=null&&this._$3S[aI].getBaseDataID()==aH){return aI;}}return -1;};y.prototype._$UT=function(aJ,aH){var aI=new Float32Array(aH);P._$jT(aJ,0,aI,0,aJ.length);return aI;};y.prototype._$02=function(aN,aM,aL,aH){if(this._$qo>=this._$pb.length){var aK=this._$pb.length;var aJ=new Array(aK*2);P._$jT(this._$pb,0,aJ,0,aK);this._$pb=aJ;this._$_2=this._$UT(this._$_2,aK*2);this._$vr=this._$UT(this._$vr,aK*2);this._$Rr=this._$UT(this._$Rr,aK*2);this._$Or=this._$UT(this._$Or,aK*2);var aI=new Array();P._$jT(this._$Js,0,aI,0,aK);this._$Js=aI;}this._$pb[this._$qo]=aN;this._$_2[this._$qo]=aM;this._$vr[this._$qo]=aM;this._$Rr[this._$qo]=aL;this._$Or[this._$qo]=aH;this._$Js[this._$qo]=y._$ZS;return this._$qo++;};y.prototype._$Zo=function(aI,aH){this._$3S[aI]=aH;};y.prototype.setParamFloat=function(aH,aI){if(aI<this._$Rr[aH]){aI=this._$Rr[aH];}if(aI>this._$Or[aH]){aI=this._$Or[aH];}this._$_2[aH]=aI;};y.prototype.loadParam=function(){var aH=this._$_2.length;if(aH>this._$fs.length){aH=this._$fs.length;}P._$jT(this._$fs,0,this._$_2,0,aH);};y.prototype.saveParam=function(){var aH=this._$_2.length;if(aH>this._$fs.length){this._$fs=new Float32Array(aH);}P._$jT(this._$_2,0,this._$fs,0,aH);};y.prototype._$v2=function(){return this._$co;};y.prototype._$WS=function(){return this._$QT;};y.prototype._$Xb=function(aH){return this._$Js[aH]==y._$ZS;};y.prototype._$vs=function(){return this._$Es;};y.prototype._$Tr=function(){return this._$ZP;};y.prototype.getBaseData=function(aH){return this._$3S[aH];};y.prototype.getParamFloat=function(aH){return this._$_2[aH];};y.prototype.getParamMax=function(aH){return this._$Or[aH];};y.prototype.getParamMin=function(aH){return this._$Rr[aH];};y.prototype.setPartsOpacity=function(aJ,aH){var aI=this._$Hr[aJ];aI.setPartsOpacity(aH);};y.prototype.getPartsOpacity=function(aI){var aH=this._$Hr[aI];return aH.getPartsOpacity();};y.prototype.getPartsDataIndex=function(aI){for(var aH=this._$F2.length-1;aH>=0;--aH){if(this._$F2[aH]!=null&&this._$F2[aH]._$p2()==aI){return aH;}}return -1;};y.prototype._$q2=function(aH){return this._$db[aH];};y.prototype._$C2=function(aH){return this._$8b[aH];};y.prototype._$Bb=function(aH){return this._$Hr[aH];};y.prototype._$5s=function(aO,aK){var aJ=this._$Ws.length;var aN=aO;for(var aL=0;aL<aJ;++aL){var aI=this._$Ws[aL];if(aI==y._$V2){continue;}do{var aM=this._$8b[aI];if(aM._$yo()){aM._$GT()._$B2(this,aM,aN);aN+=aK;}var aH=this._$Er[aI];if(aH<=aI||aH==y._$W0){break;}aI=aH;}while(true);}};y.prototype.setDrawParam=function(aH){this.dp_webgl=aH;};y.prototype.getDrawParam=function(){return this.dp_webgl;};function ap(){}ap._$0T=function(aH){return ap._$0T(new _$5(aH));};ap._$0T=function(aJ){if(!aJ.exists()){throw new _$ls(aJ._$3b());}var aH=aJ.length();var aI=new Int8Array(aH);var aM=new _$Xs(new _$kb(aJ),8192);var aK;var aL=0;while((aK=aM.read(aI,aL,aH-aL))>0){aL+=aK;}return aI;};ap._$C=function(aJ){var aI=null;var aL=null;try{aI=(aJ instanceof Array)?aJ:new _$Xs(aJ,8192);aL=new _$js();var aM=1000;var aK;var aH=new Int8Array(aM);while((aK=aI.read(aH))>0){aL.write(aH,0,aK);}return aL._$TS();}finally{if(aJ!=null){aJ.close();}if(aL!=null){aL.flush();aL.close();}}};function ar(){if(j){return;}this._$12=null;this._$bb=null;this._$_L=null;this._$jo=null;this._$iL=null;this._$0L=null;this._$Br=null;this._$Dr=null;this._$Cb=null;this._$mr=null;this._$_L=az.STATE_FIRST;this._$Br=4000;this._$Dr=100;this._$Cb=50;this._$mr=150;this._$jo=true;this._$iL="PARAM_EYE_L_OPEN";this._$0L="PARAM_EYE_R_OPEN";}ar.prototype._$T2=function(){var aI=P.getUserTimeMSec();var aH=Math._$10();return(aI+aH*(2*this._$Br-1));};ar.prototype._$uo=function(aH){this._$Br=aH;};ar.prototype._$QS=function(aI,aH,aJ){this._$Dr=aI;this._$Cb=aH;this._$mr=aJ;};ar.prototype._$7T=function(aI){var aK=P.getUserTimeMSec();var aH;var aJ=0;switch(this._$_L){case STATE_CLOSING:aJ=(aK-this._$bb)/this._$Dr;if(aJ>=1){aJ=1;this._$_L=az.STATE_CLOSED;this._$bb=aK;}aH=1-aJ;break;case STATE_CLOSED:aJ=(aK-this._$bb)/this._$Cb;if(aJ>=1){this._$_L=az.STATE_OPENING;this._$bb=aK;}aH=0;break;case STATE_OPENING:aJ=(aK-this._$bb)/this._$mr;if(aJ>=1){aJ=1;this._$_L=az.STATE_INTERVAL;this._$12=this._$T2();}aH=aJ;break;case STATE_INTERVAL:if(this._$12<aK){this._$_L=az.STATE_CLOSING;this._$bb=aK;}aH=1;break;case STATE_FIRST:default:this._$_L=az.STATE_INTERVAL;this._$12=this._$T2();aH=1;break;}if(!this._$jo){aH=-aH;}aI.setParamFloat(this._$iL,aH);aI.setParamFloat(this._$0L,aH);};var az=function(){};az.STATE_FIRST="STATE_FIRST";az.STATE_INTERVAL="STATE_INTERVAL";az.STATE_CLOSING="STATE_CLOSING";az.STATE_CLOSED="STATE_CLOSED";az.STATE_OPENING="STATE_OPENING";function x(){if(j){return;}ax.prototype.constructor.call(this);this._$sb=new Int32Array(x._$As);this._$U2=new Array();this.transform=null;this.gl=null;if(x._$NT==null){x._$NT=x._$9r(256);x._$vS=x._$9r(256);x._$no=x._$vb(256);}}x.prototype=new ax();x._$As=32;x._$Gr=false;x._$NT=null;x._$vS=null;x._$no=null;x._$9r=function(aH){var aI=new Float32Array(aH);return aI;};x._$vb=function(aH){var aI=new Int16Array(aH);return aI;};x._$cr=function(aI,aH){if(aI==null||aI._$yL()<aH.length){aI=x._$9r(aH.length*2);aI.put(aH);aI._$oT(0);}else{aI.clear();aI.put(aH);aI._$oT(0);}return aI;};x._$mb=function(aI,aH){if(aI==null||aI._$yL()<aH.length){aI=x._$vb(aH.length*2);aI.put(aH);aI._$oT(0);}else{aI.clear();aI.put(aH);aI._$oT(0);}return aI;};x._$Hs=function(){return x._$Gr;};x._$as=function(aH){x._$Gr=aH;};x.prototype.setGL=function(aH){this.gl=aH;};x.prototype.setTransform=function(aH){this.transform=aH;};x.prototype._$ZT=function(){};x.prototype._$Uo=function(aO,aH,aP,aI,aQ,aM,aK,aJ){if(aM<0.01){return;}var aL=this._$U2[aO];var aN=aM>0.9?Q.EXPAND_W:0;this.gl.drawElements(aL,aP,aI,aQ,aM,aN,this.transform,aJ);};x.prototype._$Rs=function(){throw new Error("_$Rs");};x.prototype._$Ds=function(aH){throw new Error("_$Ds");};x.prototype._$K2=function(){for(var aH=0;aH<this._$sb.length;aH++){var aI=this._$sb[aH];if(aI!=0){this.gl._$Sr(1,this._$sb,aH);this._$sb[aH]=0;}}};x.prototype.setTexture=function(aI,aH){if(this._$sb.length<aI+1){this._$nS(aI);}this._$sb[aI]=aH;};x.prototype.setTexture=function(aH,aI){if(this._$sb.length<aH+1){this._$nS(aH);}this._$U2[aH]=aI;};x.prototype._$nS=function(aH){var aK=Math.max(this._$sb.length*2,aH+1+10);var aI=new Int32Array(aK);P._$jT(this._$sb,0,aI,0,this._$sb.length);this._$sb=aI;var aJ=new Array();P._$jT(this._$U2,0,aJ,0,this._$U2.length);this._$U2=aJ;};function ab(){if(j){return;}c.prototype.constructor.call(this);this._$GS=null;this._$Y0=null;}ab.prototype=new c();ab._$Xo=new Float32Array(2);ab._$io=new Float32Array(2);ab._$0o=new Float32Array(2);ab._$Lo=new Float32Array(2);ab._$To=new Float32Array(2);ab._$Po=new Float32Array(2);ab._$gT=new Array();ab.prototype._$zP=function(){this._$GS=new g();this._$GS._$zP();this._$Y0=new Array();};ab.prototype.getType=function(){return c._$c2;};ab.prototype._$F0=function(aH){c.prototype._$F0.call(this,aH);this._$GS=aH._$nP();this._$Y0=aH._$nP();c.prototype.readV2_opacity.call(this,aH);};ab.prototype.init=function(aH){var aI=new al(this);aI._$Yr=new X();if(this._$32()){aI._$Wr=new X();}return aI;};ab.prototype._$Nr=function(bf,bx){if(!((this==bx._$GT()))){console.log("### assert!! ### ");}var bm=bx;if(!this._$GS._$Ur(bf)){return;}var bw=ab._$gT;bw[0]=false;var a2=this._$GS._$Q2(bf,bw);bx._$Ib(bw[0]);this.interpolateOpacity(bf,this._$GS,bx,bw);var a3=bf._$vs();var ba=bf._$Tr();this._$GS._$zr(a3,ba,a2);if(a2<=0){var bn=this._$Y0[a3[0]];bm._$Yr.init(bn);}else{if(a2==1){var bn=this._$Y0[a3[0]];var bl=this._$Y0[a3[1]];var a9=ba[0];bm._$Yr._$fL=bn._$fL+(bl._$fL-bn._$fL)*a9;bm._$Yr._$gL=bn._$gL+(bl._$gL-bn._$gL)*a9;bm._$Yr._$B0=bn._$B0+(bl._$B0-bn._$B0)*a9;bm._$Yr._$z0=bn._$z0+(bl._$z0-bn._$z0)*a9;bm._$Yr._$qT=bn._$qT+(bl._$qT-bn._$qT)*a9;}else{if(a2==2){var bn=this._$Y0[a3[0]];var bl=this._$Y0[a3[1]];var a1=this._$Y0[a3[2]];var a0=this._$Y0[a3[3]];var a9=ba[0];var a8=ba[1];var bC=bn._$fL+(bl._$fL-bn._$fL)*a9;var bB=a1._$fL+(a0._$fL-a1._$fL)*a9;bm._$Yr._$fL=bC+(bB-bC)*a8;bC=bn._$gL+(bl._$gL-bn._$gL)*a9;bB=a1._$gL+(a0._$gL-a1._$gL)*a9;bm._$Yr._$gL=bC+(bB-bC)*a8;bC=bn._$B0+(bl._$B0-bn._$B0)*a9;bB=a1._$B0+(a0._$B0-a1._$B0)*a9;bm._$Yr._$B0=bC+(bB-bC)*a8;bC=bn._$z0+(bl._$z0-bn._$z0)*a9;bB=a1._$z0+(a0._$z0-a1._$z0)*a9;bm._$Yr._$z0=bC+(bB-bC)*a8;bC=bn._$qT+(bl._$qT-bn._$qT)*a9;bB=a1._$qT+(a0._$qT-a1._$qT)*a9;bm._$Yr._$qT=bC+(bB-bC)*a8;}else{if(a2==3){var aP=this._$Y0[a3[0]];var aO=this._$Y0[a3[1]];var bu=this._$Y0[a3[2]];var bs=this._$Y0[a3[3]];var aK=this._$Y0[a3[4]];var aJ=this._$Y0[a3[5]];var bj=this._$Y0[a3[6]];var bi=this._$Y0[a3[7]];var a9=ba[0];var a8=ba[1];var a6=ba[2];var bC=aP._$fL+(aO._$fL-aP._$fL)*a9;var bB=bu._$fL+(bs._$fL-bu._$fL)*a9;var bz=aK._$fL+(aJ._$fL-aK._$fL)*a9;var by=bj._$fL+(bi._$fL-bj._$fL)*a9;bm._$Yr._$fL=(1-a6)*(bC+(bB-bC)*a8)+a6*(bz+(by-bz)*a8);bC=aP._$gL+(aO._$gL-aP._$gL)*a9;bB=bu._$gL+(bs._$gL-bu._$gL)*a9;bz=aK._$gL+(aJ._$gL-aK._$gL)*a9;by=bj._$gL+(bi._$gL-bj._$gL)*a9;bm._$Yr._$gL=(1-a6)*(bC+(bB-bC)*a8)+a6*(bz+(by-bz)*a8);bC=aP._$B0+(aO._$B0-aP._$B0)*a9;bB=bu._$B0+(bs._$B0-bu._$B0)*a9;bz=aK._$B0+(aJ._$B0-aK._$B0)*a9;by=bj._$B0+(bi._$B0-bj._$B0)*a9;bm._$Yr._$B0=(1-a6)*(bC+(bB-bC)*a8)+a6*(bz+(by-bz)*a8);bC=aP._$z0+(aO._$z0-aP._$z0)*a9;bB=bu._$z0+(bs._$z0-bu._$z0)*a9;bz=aK._$z0+(aJ._$z0-aK._$z0)*a9;by=bj._$z0+(bi._$z0-bj._$z0)*a9;bm._$Yr._$z0=(1-a6)*(bC+(bB-bC)*a8)+a6*(bz+(by-bz)*a8);bC=aP._$qT+(aO._$qT-aP._$qT)*a9;bB=bu._$qT+(bs._$qT-bu._$qT)*a9;bz=aK._$qT+(aJ._$qT-aK._$qT)*a9;by=bj._$qT+(bi._$qT-bj._$qT)*a9;bm._$Yr._$qT=(1-a6)*(bC+(bB-bC)*a8)+a6*(bz+(by-bz)*a8);}else{if(a2==4){var aT=this._$Y0[a3[0]];var aS=this._$Y0[a3[1]];var bE=this._$Y0[a3[2]];var bD=this._$Y0[a3[3]];var aN=this._$Y0[a3[4]];var aM=this._$Y0[a3[5]];var bp=this._$Y0[a3[6]];var bo=this._$Y0[a3[7]];var bh=this._$Y0[a3[8]];var bg=this._$Y0[a3[9]];var aY=this._$Y0[a3[10]];var aW=this._$Y0[a3[11]];var a7=this._$Y0[a3[12]];var a5=this._$Y0[a3[13]];var aR=this._$Y0[a3[14]];var aQ=this._$Y0[a3[15]];var a9=ba[0];var a8=ba[1];var a6=ba[2];var a4=ba[3];var bC=aT._$fL+(aS._$fL-aT._$fL)*a9;var bB=bE._$fL+(bD._$fL-bE._$fL)*a9;var bz=aN._$fL+(aM._$fL-aN._$fL)*a9;var by=bp._$fL+(bo._$fL-bp._$fL)*a9;var bv=bh._$fL+(bg._$fL-bh._$fL)*a9;var bt=aY._$fL+(aW._$fL-aY._$fL)*a9;var br=a7._$fL+(a5._$fL-a7._$fL)*a9;var bq=aR._$fL+(aQ._$fL-aR._$fL)*a9;bm._$Yr._$fL=(1-a4)*((1-a6)*(bC+(bB-bC)*a8)+a6*(bz+(by-bz)*a8))+a4*((1-a6)*(bv+(bt-bv)*a8)+a6*(br+(bq-br)*a8));bC=aT._$gL+(aS._$gL-aT._$gL)*a9;bB=bE._$gL+(bD._$gL-bE._$gL)*a9;bz=aN._$gL+(aM._$gL-aN._$gL)*a9;by=bp._$gL+(bo._$gL-bp._$gL)*a9;bv=bh._$gL+(bg._$gL-bh._$gL)*a9;bt=aY._$gL+(aW._$gL-aY._$gL)*a9;br=a7._$gL+(a5._$gL-a7._$gL)*a9;bq=aR._$gL+(aQ._$gL-aR._$gL)*a9;bm._$Yr._$gL=(1-a4)*((1-a6)*(bC+(bB-bC)*a8)+a6*(bz+(by-bz)*a8))+a4*((1-a6)*(bv+(bt-bv)*a8)+a6*(br+(bq-br)*a8));bC=aT._$B0+(aS._$B0-aT._$B0)*a9;bB=bE._$B0+(bD._$B0-bE._$B0)*a9;bz=aN._$B0+(aM._$B0-aN._$B0)*a9;by=bp._$B0+(bo._$B0-bp._$B0)*a9;bv=bh._$B0+(bg._$B0-bh._$B0)*a9;bt=aY._$B0+(aW._$B0-aY._$B0)*a9;br=a7._$B0+(a5._$B0-a7._$B0)*a9;bq=aR._$B0+(aQ._$B0-aR._$B0)*a9;bm._$Yr._$B0=(1-a4)*((1-a6)*(bC+(bB-bC)*a8)+a6*(bz+(by-bz)*a8))+a4*((1-a6)*(bv+(bt-bv)*a8)+a6*(br+(bq-br)*a8));bC=aT._$z0+(aS._$z0-aT._$z0)*a9;bB=bE._$z0+(bD._$z0-bE._$z0)*a9;bz=aN._$z0+(aM._$z0-aN._$z0)*a9;by=bp._$z0+(bo._$z0-bp._$z0)*a9;bv=bh._$z0+(bg._$z0-bh._$z0)*a9;bt=aY._$z0+(aW._$z0-aY._$z0)*a9;br=a7._$z0+(a5._$z0-a7._$z0)*a9;bq=aR._$z0+(aQ._$z0-aR._$z0)*a9;bm._$Yr._$z0=(1-a4)*((1-a6)*(bC+(bB-bC)*a8)+a6*(bz+(by-bz)*a8))+a4*((1-a6)*(bv+(bt-bv)*a8)+a6*(br+(bq-br)*a8));bC=aT._$qT+(aS._$qT-aT._$qT)*a9;bB=bE._$qT+(bD._$qT-bE._$qT)*a9;bz=aN._$qT+(aM._$qT-aN._$qT)*a9;by=bp._$qT+(bo._$qT-bp._$qT)*a9;bv=bh._$qT+(bg._$qT-bh._$qT)*a9;bt=aY._$qT+(aW._$qT-aY._$qT)*a9;br=a7._$qT+(a5._$qT-a7._$qT)*a9;bq=aR._$qT+(aQ._$qT-aR._$qT)*a9;bm._$Yr._$qT=(1-a4)*((1-a6)*(bC+(bB-bC)*a8)+a6*(bz+(by-bz)*a8))+a4*((1-a6)*(bv+(bt-bv)*a8)+a6*(br+(bq-br)*a8));}else{var aV=Math.pow(2,a2)|0;var aZ=new Float32Array(aV);for(var bk=0;bk<aV;bk++){var aI=bk;var aH=1;for(var aL=0;aL<a2;aL++){aH*=(aI%2==0)?(1-ba[aL]):ba[aL];aI/=2;}aZ[bk]=aH;}var bA=new Array();for(var aU=0;aU<aV;aU++){bA[aU]=this._$Y0[a3[aU]];}var be=0,bc=0,bd=0,bb=0,aX=0;for(var aU=0;aU<aV;aU++){be+=aZ[aU]*bA[aU]._$fL;bc+=aZ[aU]*bA[aU]._$gL;bd+=aZ[aU]*bA[aU]._$B0;bb+=aZ[aU]*bA[aU]._$z0;aX+=aZ[aU]*bA[aU]._$qT;}bm._$Yr._$fL=be;bm._$Yr._$gL=bc;bm._$Yr._$B0=bd;bm._$Yr._$z0=bb;bm._$Yr._$qT=aX;}}}}}var bn=this._$Y0[a3[0]];bm._$Yr.reflectX=bn.reflectX;bm._$Yr.reflectY=bn.reflectY;};ab.prototype._$2b=function(aM,aH){if(!((this==aH._$GT()))){console.log("### assert!! ### ");}var aR=aH;aR._$hS(true);if(!this._$32()){aR.setTotalScale_notForClient(aR._$Yr._$B0);aR.setTotalOpacity(aR.getInterpolatedOpacity());}else{var aT=this.getTargetBaseDataID();if(aR._$8r==c._$ur){aR._$8r=aM.getBaseDataIndex(aT);}if(aR._$8r<0){if(Q._$so){q._$li("_$L _$0P _$G :: %s",aT);}aR._$hS(false);}else{var aI=aM.getBaseData(aR._$8r);if(aI!=null){var aL=aM._$q2(aR._$8r);var aS=ab._$Xo;aS[0]=aR._$Yr._$fL;aS[1]=aR._$Yr._$gL;var aJ=ab._$io;aJ[0]=0;aJ[1]=-0.1;var aO=aL._$GT().getType();if(aO==c._$c2){aJ[1]=-10;}else{aJ[1]=-0.1;}var aQ=ab._$0o;this._$Jr(aM,aI,aL,aS,aJ,aQ);var aP=aC._$92(aJ,aQ);aI._$nb(aM,aL,aS,aS,1,0,2);aR._$Wr._$fL=aS[0];aR._$Wr._$gL=aS[1];aR._$Wr._$B0=aR._$Yr._$B0;aR._$Wr._$z0=aR._$Yr._$z0;aR._$Wr._$qT=aR._$Yr._$qT-aP*aC._$NS;var aK=aL.getTotalScale();aR.setTotalScale_notForClient(aK*aR._$Wr._$B0);var aN=aL.getTotalOpacity();aR.setTotalOpacity(aN*aR.getInterpolatedOpacity());aR._$Wr.reflectX=aR._$Yr.reflectX;aR._$Wr.reflectY=aR._$Yr.reflectY;aR._$hS(aL._$yo());}else{aR._$hS(false);}}}};ab.prototype._$nb=function(aJ,aR,aL,a4,aT,aO,a2){if(!((this==aR._$GT()))){console.log("### assert!! ### ");}var aH=aR;var aU=aH._$Wr!=null?aH._$Wr:aH._$Yr;var a0=Math.sin(aC._$bS*aU._$qT);var aP=Math.cos(aC._$bS*aU._$qT);var a3=aH.getTotalScale();var aW=aU.reflectX?-1:1;var aV=aU.reflectY?-1:1;var aS=aP*a3*aW;var aQ=-a0*a3*aV;var a1=a0*a3*aW;var aZ=aP*a3*aV;var aY=aU._$fL;var aX=aU._$gL;var aN,aM;var aI=aT*a2;for(var aK=aO;aK<aI;aK+=a2){aN=aL[aK];aM=aL[aK+1];a4[aK]=aS*aN+aQ*aM+aY;a4[aK+1]=a1*aN+aZ*aM+aX;}};ab.prototype._$Jr=function(aP,aK,aI,aR,aQ,aH){if(!((aK==aI._$GT()))){console.log("### assert!! ### ");}var aO=ab._$Lo;ab._$Lo[0]=aR[0];ab._$Lo[1]=aR[1];aK._$nb(aP,aI,aO,aO,1,0,2);var aL=ab._$To;var aS=ab._$Po;var aN=10;var aJ=1;for(var aM=0;aM<aN;aM++){aS[0]=aR[0]+aJ*aQ[0];aS[1]=aR[1]+aJ*aQ[1];aK._$nb(aP,aI,aS,aL,1,0,2);aL[0]-=aO[0];aL[1]-=aO[1];if(aL[0]!=0||aL[1]!=0){aH[0]=aL[0];aH[1]=aL[1];return;}aS[0]=aR[0]-aJ*aQ[0];aS[1]=aR[1]-aJ*aQ[1];aK._$nb(aP,aI,aS,aL,1,0,2);aL[0]-=aO[0];aL[1]-=aO[1];if(aL[0]!=0||aL[1]!=0){aL[0]=-aL[0];aL[0]=-aL[0];aH[0]=aL[0];aH[1]=aL[1];return;}aJ*=0.1;}if(Q._$so){console.log("_$L0 to transform _$SP\n");}};function al(aH){B.prototype.constructor.call(this,aH);this._$8r=c._$ur;this._$Yr=null;this._$Wr=null;}al.prototype=new B();function a(){if(j){return;}ae.prototype.constructor.call(this);this._$gP=null;this._$dr=null;this._$GS=null;this._$qb=null;this._$Lb=null;this._$mS=null;}a.prototype=new ae();a._$ur=-2;a._$ES=500;a._$wb=2;a._$8S=3;a._$os=4;a._$52=a._$ES;a._$R2=a._$ES;a._$Sb=function(aJ){for(var aI=aJ.length-1;aI>=0;--aI){var aH=aJ[aI];if(aH<a._$52){a._$52=aH;}else{if(aH>a._$R2){a._$R2=aH;}}}};a._$or=function(){return a._$52;};a._$Pr=function(){return a._$R2;};a.prototype._$F0=function(aH){this._$gP=aH._$nP();this._$dr=aH._$nP();this._$GS=aH._$nP();this._$qb=aH._$6L();this._$Lb=aH._$cS();this._$mS=aH._$Tb();if(aH.getFormatVersion()>=ay._$T7){this.clipID=aH._$nP();this.clipIDList=this.convertClipIDForV2_11(this.clipID);}else{this.clipIDList=null;}a._$Sb(this._$Lb);};a.prototype.getClipIDList=function(){return this.clipIDList;};a.prototype._$Nr=function(aI,aH){aH._$IS[0]=false;aH._$Us=aG._$Z2(aI,this._$GS,aH._$IS,this._$Lb);if(Q._$Zs){}else{if(aH._$IS[0]){return;}}aH._$7s=aG._$br(aI,this._$GS,aH._$IS,this._$mS);};a.prototype._$2b=function(aH){};a.prototype.getDrawDataID=function(){return this._$gP;};a.prototype._$j2=function(aH){this._$gP=aH;};a.prototype.getOpacity=function(aH,aI){return aI._$7s;};a.prototype._$zS=function(aH,aI){return aI._$Us;};a.prototype.getTargetBaseDataID=function(){return this._$dr;};a.prototype._$gs=function(aH){this._$dr=aH;};a.prototype._$32=function(){return(this._$dr!=null&&(this._$dr!=n._$2o()));};a.prototype.getType=function(){};function aq(){if(j){return;}this._$NL=null;this._$3S=null;this._$aS=null;aq._$42++;}aq._$42=0;aq.prototype._$1b=function(){return this._$3S;};aq.prototype.getDrawDataList=function(){return this._$aS;};aq.prototype._$F0=function(aH){this._$NL=aH._$nP();this._$aS=aH._$nP();this._$3S=aH._$nP();};aq.prototype._$kr=function(aH){aH._$Zo(this._$3S);aH._$xo(this._$aS);this._$3S=null;this._$aS=null;};function v(){if(j){return;}aa.prototype.constructor.call(this);this._$zo=new x();}v.prototype=new aa();v.loadModel=function(aI){var aH=new v();aa._$62(aH,aI);return aH;};v.loadModel=function(aI){var aH=new v();aa._$62(aH,aI);return aH;};v._$to=function(){var aH=new v();return aH;};v._$er=function(aM){var aJ=new _$5("../_$_r/_$t0/_$Ri/_$_P._$d");if(aJ.exists()==false){throw new _$ls("_$t0 _$_ _$6 _$Ui :: "+aJ._$PL());}var aH=["../_$_r/_$t0/_$Ri/_$_P.512/_$CP._$1","../_$_r/_$t0/_$Ri/_$_P.512/_$vP._$1","../_$_r/_$t0/_$Ri/_$_P.512/_$EP._$1","../_$_r/_$t0/_$Ri/_$_P.512/_$pP._$1"];var aK=v.loadModel(aJ._$3b());for(var aI=0;aI<aH.length;aI++){var aL=new _$5(aH[aI]);if(aL.exists()==false){throw new _$ls("_$t0 _$_ _$6 _$Ui :: "+aL._$PL());}aK.setTexture(aI,_$nL._$_o(aM,aL._$3b()));}return aK;};v.prototype.setGL=function(aH){this._$zo.setGL(aH);};v.prototype.setTransform=function(aH){this._$zo.setTransform(aH);};v.prototype.draw=function(){this._$5S.draw(this._$zo);};v.prototype._$K2=function(){this._$zo._$K2();};v.prototype.setTexture=function(aI,aH){if(this._$zo==null){q._$li("_$Yi for QT _$ki / _$XS() is _$6 _$ui!!");}this._$zo.setTexture(aI,aH);};v.prototype.setTexture=function(aI,aH){if(this._$zo==null){q._$li("_$Yi for QT _$ki / _$XS() is _$6 _$ui!!");}this._$zo.setTexture(aI,aH);};v.prototype._$Rs=function(){return this._$zo._$Rs();};v.prototype._$Ds=function(aH){this._$zo._$Ds(aH);};v.prototype.getDrawParam=function(){return this._$zo;};function ao(){if(j){return;}ah.prototype.constructor.call(this);this.motions=new Array();this._$o2=null;this._$7r=ao._$Co++;this._$D0=30;this._$yT=0;this._$E=false;this.loopFadeIn=true;this._$rr=-1;this._$eP=0;}ao.prototype=new ah();ao._$cs="VISIBLE:";ao._$ar="LAYOUT:";ao.MTN_PREFIX_FADEIN="FADEIN:";ao.MTN_PREFIX_FADEOUT="FADEOUT:";ao._$Co=0;ao._$1T=1;ao.loadMotion=function(aJ){var aI=ap._$C(aJ);var aH=ao.loadMotion(aI);return aH;};function p(aI,aH){return String.fromCharCode(aI.getUint8(aH));}ao.loadMotion=function(aT){if(aT instanceof ArrayBuffer){aT=new DataView(aT);}var aN=new ao();var aI=[0];var aQ=aT.byteLength;aN._$yT=0;for(var aJ=0;aJ<aQ;++aJ){var aS=p(aT,aJ);var aL=aS.charCodeAt(0);if(aS=="\n"||aS=="\r"){continue;}if(aS=="#"){for(;aJ<aQ;++aJ){if(p(aT,aJ)=="\n"||p(aT,aJ)=="\r"){break;}}continue;}if(aS=="$"){var aV=aJ;var aK=-1;for(;aJ<aQ;++aJ){aS=p(aT,aJ);if(aS=="\r"||aS=="\n"){break;}if(aS=="="){aK=aJ;break;}}var aP=false;if(aK>=0){if(aK==aV+4&&p(aT,aV+1)=="f"&&p(aT,aV+2)=="p"&&p(aT,aV+3)=="s"){aP=true;}for(aJ=aK+1;aJ<aQ;++aJ){aS=p(aT,aJ);if(aS=="\r"||aS=="\n"){break;}if(aS==","||aS==" "||aS=="\t"){continue;}var aM=G._$LS(aT,aQ,aJ,aI);if(aI[0]>0){if(aP&&5<aM&&aM<121){aN._$D0=aM;}}aJ=aI[0];}}for(;aJ<aQ;++aJ){if(p(aT,aJ)=="\n"||p(aT,aJ)=="\r"){break;}}continue;}if((97<=aL&&aL<=122)||(65<=aL&&aL<=90)||aS=="_"){var aV=aJ;var aK=-1;for(;aJ<aQ;++aJ){aS=p(aT,aJ);if(aS=="\r"||aS=="\n"){break;}if(aS=="="){aK=aJ;break;}}if(aK>=0){var aO=new t();if(G.startsWith(aT,aV,ao._$cs)){aO._$RP=t._$hs;aO._$4P=G.createString(aT,aV,aK-aV);}else{if(G.startsWith(aT,aV,ao._$ar)){aO._$4P=G.createString(aT,aV+7,aK-aV-7);if(G.startsWith(aT,aV+7,"ANCHOR_X")){aO._$RP=t._$xs;}else{if(G.startsWith(aT,aV+7,"ANCHOR_Y")){aO._$RP=t._$us;}else{if(G.startsWith(aT,aV+7,"SCALE_X")){aO._$RP=t._$qs;}else{if(G.startsWith(aT,aV+7,"SCALE_Y")){aO._$RP=t._$Ys;}else{if(G.startsWith(aT,aV+7,"X")){aO._$RP=t._$ws;}else{if(G.startsWith(aT,aV+7,"Y")){aO._$RP=t._$Ns;}}}}}}}else{aO._$RP=t._$Fr;aO._$4P=G.createString(aT,aV,aK-aV);}}aN.motions.push(aO);var aU=0;var aR=[];for(aJ=aK+1;aJ<aQ;++aJ){aS=p(aT,aJ);if(aS=="\r"||aS=="\n"){break;}if(aS==","||aS==" "||aS=="\t"){continue;}var aM=G._$LS(aT,aQ,aJ,aI);if(aI[0]>0){aR.push(aM);aU++;var aH=aI[0];if(aH<aJ){console.log("_$n0 _$hi . @Live2DMotion loadMotion()\n");break;}aJ=aH-1;}}aO._$I0=new Float32Array(aR);if(aU>aN._$yT){aN._$yT=aU;}}}}aN._$rr=((1000*aN._$yT)/aN._$D0)|0;return aN;};ao.prototype.getDurationMSec=function(){return this._$E?-1:this._$rr;};ao.prototype.getLoopDurationMSec=function(){return this._$rr;};ao.prototype.dump=function(){for(var aJ=0;aJ<this.motions.length;aJ++){var aH=this.motions[aJ];console.log("_$wL[%s] [%d]. ",aH._$4P,aH._$I0.length);for(var aI=0;aI<aH._$I0.length&&aI<10;aI++){console.log("%5.2f ,",aH._$I0[aI]);}console.log("\n");}};ao.prototype.updateParamExe=function(aJ,aN,aQ,a3){var aO=aN-a3._$z2;var a0=aO*this._$D0/1000;var aK=a0|0;var aR=a0-aK;for(var aZ=0;aZ<this.motions.length;aZ++){var aV=this.motions[aZ];var aL=aV._$I0.length;var aT=aV._$4P;if(aV._$RP==t._$hs){var aX=aV._$I0[(aK>=aL?aL-1:aK)];aJ.setParamFloat(aT,aX);}else{if(t._$ws<=aV._$RP&&aV._$RP<=t._$Ys){}else{var aH=aJ.getParamIndex(aT);var a4=aJ.getModelContext();var aY=a4.getParamMax(aH);var aW=a4.getParamMin(aH);var aM=0.4;var aS=aM*(aY-aW);var aU=a4.getParamFloat(aH);var a2=aV._$I0[(aK>=aL?aL-1:aK)];var a1=aV._$I0[(aK+1>=aL?aL-1:aK+1)];var aI;if((a2<a1&&a1-a2>aS)||(a2>a1&&a2-a1>aS)){aI=a2;}else{aI=a2+(a1-a2)*aR;}var aP=aU+(aI-aU)*aQ;aJ.setParamFloat(aT,aP);}}}if(aK>=this._$yT){if(this._$E){a3._$z2=aN;if(this.loopFadeIn){a3._$bs=aN;}}else{a3._$9L=true;}}this._$eP=aQ;};ao.prototype._$r0=function(){return this._$E;};ao.prototype._$aL=function(aH){this._$E=aH;};ao.prototype._$S0=function(){return this._$D0;};ao.prototype._$U0=function(aH){this._$D0=aH;};ao.prototype.isLoopFadeIn=function(){return this.loopFadeIn;};ao.prototype.setLoopFadeIn=function(aH){this.loopFadeIn=aH;};function aE(){this._$P=new Float32Array(100);this.size=0;}aE.prototype.clear=function(){this.size=0;};aE.prototype.add=function(aI){if(this._$P.length<=this.size){var aH=new Float32Array(this.size*2);P._$jT(this._$P,0,aH,0,this.size);this._$P=aH;}this._$P[this.size++]=aI;};aE.prototype._$BL=function(){var aH=new Float32Array(this.size);P._$jT(this._$P,0,aH,0,this.size);return aH;};function t(){this._$4P=null;this._$I0=null;this._$RP=null;}t._$Fr=0;t._$hs=1;t._$ws=100;t._$Ns=101;t._$xs=102;t._$us=103;t._$qs=104;t._$Ys=105;function E(){if(j){return;}c.prototype.constructor.call(this);this._$o=0;this._$A=0;this._$GS=null;this._$Eo=null;}E.prototype=new c();E._$gT=new Array();E.prototype._$zP=function(){this._$GS=new g();this._$GS._$zP();};E.prototype._$F0=function(aH){c.prototype._$F0.call(this,aH);this._$A=aH._$6L();this._$o=aH._$6L();this._$GS=aH._$nP();this._$Eo=aH._$nP();c.prototype.readV2_opacity.call(this,aH);};E.prototype.init=function(aH){var aI=new H(this);var aJ=(this._$o+1)*(this._$A+1);if(aI._$Cr!=null){aI._$Cr=null;}aI._$Cr=new Float32Array(aJ*2);if(aI._$hr!=null){aI._$hr=null;}if(this._$32()){aI._$hr=new Float32Array(aJ*2);}else{aI._$hr=null;}return aI;};E.prototype._$Nr=function(aJ,aI){var aK=aI;if(!this._$GS._$Ur(aJ)){return;}var aL=this._$VT();var aH=E._$gT;aH[0]=false;aG._$Vr(aJ,this._$GS,aH,aL,this._$Eo,aK._$Cr,0,2);aI._$Ib(aH[0]);this.interpolateOpacity(aJ,this._$GS,aI,aH);};E.prototype._$2b=function(aK,aJ){var aL=aJ;aL._$hS(true);if(!this._$32()){aL.setTotalOpacity(aL.getInterpolatedOpacity());}else{var aH=this.getTargetBaseDataID();if(aL._$8r==c._$ur){aL._$8r=aK.getBaseDataIndex(aH);}if(aL._$8r<0){if(Q._$so){q._$li("_$L _$0P _$G :: %s",aH);}aL._$hS(false);}else{var aN=aK.getBaseData(aL._$8r);var aI=aK._$q2(aL._$8r);if(aN!=null&&aI._$yo()){var aM=aI.getTotalScale();aL.setTotalScale_notForClient(aM);var aO=aI.getTotalOpacity();aL.setTotalOpacity(aO*aL.getInterpolatedOpacity());aN._$nb(aK,aI,aL._$Cr,aL._$hr,this._$VT(),0,2);aL._$hS(true);}else{aL._$hS(false);}}}};E.prototype._$nb=function(aL,aI,aH,aM,aO,aK,aJ){if(true){var aN=aI;var aP=(aN._$hr!=null)?aN._$hr:aN._$Cr;E.transformPoints_sdk2(aH,aM,aO,aK,aJ,aP,this._$o,this._$A);}else{this.transformPoints_sdk1(aL,aI,aH,aM,aO,aK,aJ);}};E.transformPoints_sdk2=function(a0,bc,a5,aP,aI,aR,aQ,aU){var aW=a5*aI;var aV;var bn,bm;var aT=0;var aS=0;var bl=0;var bk=0;var bf=0;var be=0;var aZ=false;for(var ba=aP;ba<aW;ba+=aI){var bd,a7,a4,aX;a4=a0[ba];aX=a0[ba+1];bd=a4*aQ;a7=aX*aU;if(bd<0||a7<0||aQ<=bd||aU<=a7){var a1=aQ+1;if(!aZ){aZ=true;aT=0.25*(aR[((0)+(0)*a1)*2]+aR[((aQ)+(0)*a1)*2]+aR[((0)+(aU)*a1)*2]+aR[((aQ)+(aU)*a1)*2]);aS=0.25*(aR[((0)+(0)*a1)*2+1]+aR[((aQ)+(0)*a1)*2+1]+aR[((0)+(aU)*a1)*2+1]+aR[((aQ)+(aU)*a1)*2+1]);var aM=aR[((aQ)+(aU)*a1)*2]-aR[((0)+(0)*a1)*2];var aL=aR[((aQ)+(aU)*a1)*2+1]-aR[((0)+(0)*a1)*2+1];var bh=aR[((aQ)+(0)*a1)*2]-aR[((0)+(aU)*a1)*2];var bg=aR[((aQ)+(0)*a1)*2+1]-aR[((0)+(aU)*a1)*2+1];bl=(aM+bh)*0.5;bk=(aL+bg)*0.5;bf=(aM-bh)*0.5;be=(aL-bg)*0.5;if(bl==0&&bk==0){}if(bf==0&&be==0){}aT-=0.5*(bl+bf);aS-=0.5*(bk+be);}if((-2<a4&&a4<3)&&(-2<aX&&aX<3)){if(a4<=0){if(aX<=0){var a3=aR[((0)+(0)*a1)*2];var a2=aR[((0)+(0)*a1)*2+1];var a8=aT-2*bl;var a6=aS-2*bk;var aK=aT-2*bf;var aJ=aS-2*be;var aO=aT-2*bl-2*bf;var aN=aS-2*bk-2*be;var bj=0.5*(a4-(-2));var bi=0.5*(aX-(-2));if(bj+bi<=1){bc[ba]=aO+(aK-aO)*bj+(a8-aO)*bi;bc[ba+1]=aN+(aJ-aN)*bj+(a6-aN)*bi;}else{bc[ba]=a3+(a8-a3)*(1-bj)+(aK-a3)*(1-bi);bc[ba+1]=a2+(a6-a2)*(1-bj)+(aJ-a2)*(1-bi);}}else{if(aX>=1){var aK=aR[((0)+(aU)*a1)*2];var aJ=aR[((0)+(aU)*a1)*2+1];var aO=aT-2*bl+1*bf;var aN=aS-2*bk+1*be;var a3=aT+3*bf;var a2=aS+3*be;var a8=aT-2*bl+3*bf;var a6=aS-2*bk+3*be;var bj=0.5*(a4-(-2));var bi=0.5*(aX-(1));if(bj+bi<=1){bc[ba]=aO+(aK-aO)*bj+(a8-aO)*bi;bc[ba+1]=aN+(aJ-aN)*bj+(a6-aN)*bi;}else{bc[ba]=a3+(a8-a3)*(1-bj)+(aK-a3)*(1-bi);bc[ba+1]=a2+(a6-a2)*(1-bj)+(aJ-a2)*(1-bi);}}else{var aH=(a7|0);if(aH==aU){aH=aU-1;}var bj=0.5*(a4-(-2));var bi=a7-aH;var bb=aH/aU;var a9=(aH+1)/aU;var aK=aR[((0)+(aH)*a1)*2];var aJ=aR[((0)+(aH)*a1)*2+1];var a3=aR[((0)+(aH+1)*a1)*2];var a2=aR[((0)+(aH+1)*a1)*2+1];var aO=aT-2*bl+bb*bf;var aN=aS-2*bk+bb*be;var a8=aT-2*bl+a9*bf;var a6=aS-2*bk+a9*be;if(bj+bi<=1){bc[ba]=aO+(aK-aO)*bj+(a8-aO)*bi;bc[ba+1]=aN+(aJ-aN)*bj+(a6-aN)*bi;}else{bc[ba]=a3+(a8-a3)*(1-bj)+(aK-a3)*(1-bi);bc[ba+1]=a2+(a6-a2)*(1-bj)+(aJ-a2)*(1-bi);}}}}else{if(1<=a4){if(aX<=0){var a8=aR[((aQ)+(0)*a1)*2];var a6=aR[((aQ)+(0)*a1)*2+1];var a3=aT+3*bl;var a2=aS+3*bk;var aO=aT+1*bl-2*bf;var aN=aS+1*bk-2*be;var aK=aT+3*bl-2*bf;var aJ=aS+3*bk-2*be;var bj=0.5*(a4-(1));var bi=0.5*(aX-(-2));if(bj+bi<=1){bc[ba]=aO+(aK-aO)*bj+(a8-aO)*bi;bc[ba+1]=aN+(aJ-aN)*bj+(a6-aN)*bi;}else{bc[ba]=a3+(a8-a3)*(1-bj)+(aK-a3)*(1-bi);bc[ba+1]=a2+(a6-a2)*(1-bj)+(aJ-a2)*(1-bi);}}else{if(aX>=1){var aO=aR[((aQ)+(aU)*a1)*2];var aN=aR[((aQ)+(aU)*a1)*2+1];var aK=aT+3*bl+1*bf;var aJ=aS+3*bk+1*be;var a8=aT+1*bl+3*bf;var a6=aS+1*bk+3*be;var a3=aT+3*bl+3*bf;var a2=aS+3*bk+3*be;var bj=0.5*(a4-(1));var bi=0.5*(aX-(1));if(bj+bi<=1){bc[ba]=aO+(aK-aO)*bj+(a8-aO)*bi;bc[ba+1]=aN+(aJ-aN)*bj+(a6-aN)*bi;}else{bc[ba]=a3+(a8-a3)*(1-bj)+(aK-a3)*(1-bi);bc[ba+1]=a2+(a6-a2)*(1-bj)+(aJ-a2)*(1-bi);}}else{var aH=(a7|0);if(aH==aU){aH=aU-1;}var bj=0.5*(a4-(1));var bi=a7-aH;var bb=aH/aU;var a9=(aH+1)/aU;var aO=aR[((aQ)+(aH)*a1)*2];var aN=aR[((aQ)+(aH)*a1)*2+1];var a8=aR[((aQ)+(aH+1)*a1)*2];var a6=aR[((aQ)+(aH+1)*a1)*2+1];var aK=aT+3*bl+bb*bf;var aJ=aS+3*bk+bb*be;var a3=aT+3*bl+a9*bf;var a2=aS+3*bk+a9*be;if(bj+bi<=1){bc[ba]=aO+(aK-aO)*bj+(a8-aO)*bi;bc[ba+1]=aN+(aJ-aN)*bj+(a6-aN)*bi;}else{bc[ba]=a3+(a8-a3)*(1-bj)+(aK-a3)*(1-bi);bc[ba+1]=a2+(a6-a2)*(1-bj)+(aJ-a2)*(1-bi);}}}}else{if(aX<=0){var aY=(bd|0);if(aY==aQ){aY=aQ-1;}var bj=bd-aY;var bi=0.5*(aX-(-2));var bp=aY/aQ;var bo=(aY+1)/aQ;var a8=aR[((aY)+(0)*a1)*2];var a6=aR[((aY)+(0)*a1)*2+1];var a3=aR[((aY+1)+(0)*a1)*2];var a2=aR[((aY+1)+(0)*a1)*2+1];var aO=aT+bp*bl-2*bf;var aN=aS+bp*bk-2*be;var aK=aT+bo*bl-2*bf;var aJ=aS+bo*bk-2*be;if(bj+bi<=1){bc[ba]=aO+(aK-aO)*bj+(a8-aO)*bi;bc[ba+1]=aN+(aJ-aN)*bj+(a6-aN)*bi;}else{bc[ba]=a3+(a8-a3)*(1-bj)+(aK-a3)*(1-bi);bc[ba+1]=a2+(a6-a2)*(1-bj)+(aJ-a2)*(1-bi);}}else{if(aX>=1){var aY=(bd|0);if(aY==aQ){aY=aQ-1;}var bj=bd-aY;var bi=0.5*(aX-(1));var bp=aY/aQ;var bo=(aY+1)/aQ;var aO=aR[((aY)+(aU)*a1)*2];var aN=aR[((aY)+(aU)*a1)*2+1];var aK=aR[((aY+1)+(aU)*a1)*2];var aJ=aR[((aY+1)+(aU)*a1)*2+1];var a8=aT+bp*bl+3*bf;var a6=aS+bp*bk+3*be;var a3=aT+bo*bl+3*bf;var a2=aS+bo*bk+3*be;if(bj+bi<=1){bc[ba]=aO+(aK-aO)*bj+(a8-aO)*bi;bc[ba+1]=aN+(aJ-aN)*bj+(a6-aN)*bi;}else{bc[ba]=a3+(a8-a3)*(1-bj)+(aK-a3)*(1-bi);bc[ba+1]=a2+(a6-a2)*(1-bj)+(aJ-a2)*(1-bi);}}else{System.err.printf("_$li calc : %.4f , %.4f					@@BDBoxGrid\n",a4,aX);}}}}}else{bc[ba]=aT+a4*bl+aX*bf;bc[ba+1]=aS+a4*bk+aX*be;}}else{bn=bd-(bd|0);bm=a7-(a7|0);aV=2*((bd|0)+((a7|0))*(aQ+1));if(bn+bm<1){bc[ba]=aR[aV]*(1-bn-bm)+aR[aV+2]*bn+aR[aV+2*(aQ+1)]*bm;bc[ba+1]=aR[aV+1]*(1-bn-bm)+aR[aV+3]*bn+aR[aV+2*(aQ+1)+1]*bm;}else{bc[ba]=aR[aV+2*(aQ+1)+2]*(bn-1+bm)+aR[aV+2*(aQ+1)]*(1-bn)+aR[aV+2]*(1-bm);bc[ba+1]=aR[aV+2*(aQ+1)+3]*(bn-1+bm)+aR[aV+2*(aQ+1)+1]*(1-bn)+aR[aV+3]*(1-bm);}}}};E.prototype.transformPoints_sdk1=function(aJ,aR,aL,a0,aU,aP,aZ){var aH=aR;var aO,aN;var aM=this._$o;var aQ=this._$A;var aI=aU*aZ;var aS,aY;var aV;var aX,aW;var aT=(aH._$hr!=null)?aH._$hr:aH._$Cr;for(var aK=aP;aK<aI;aK+=aZ){if(Q._$ts){aO=aL[aK];aN=aL[aK+1];if(aO<0){aO=0;}else{if(aO>1){aO=1;}}if(aN<0){aN=0;}else{if(aN>1){aN=1;}}aO*=aM;aN*=aQ;aS=(aO|0);aY=(aN|0);if(aS>aM-1){aS=aM-1;}if(aY>aQ-1){aY=aQ-1;}aX=aO-aS;aW=aN-aY;aV=2*(aS+aY*(aM+1));}else{aO=aL[aK]*aM;aN=aL[aK+1]*aQ;aX=aO-(aO|0);aW=aN-(aN|0);aV=2*((aO|0)+(aN|0)*(aM+1));}if(aX+aW<1){a0[aK]=aT[aV]*(1-aX-aW)+aT[aV+2]*aX+aT[aV+2*(aM+1)]*aW;a0[aK+1]=aT[aV+1]*(1-aX-aW)+aT[aV+3]*aX+aT[aV+2*(aM+1)+1]*aW;}else{a0[aK]=aT[aV+2*(aM+1)+2]*(aX-1+aW)+aT[aV+2*(aM+1)]*(1-aX)+aT[aV+2]*(1-aW);a0[aK+1]=aT[aV+2*(aM+1)+3]*(aX-1+aW)+aT[aV+2*(aM+1)+1]*(1-aX)+aT[aV+3]*(1-aW);}}};E.prototype._$VT=function(){return(this._$o+1)*(this._$A+1);};E.prototype.getType=function(){return c._$_b;};function H(aH){B.prototype.constructor.call(this,aH);this._$8r=c._$ur;this._$Cr=null;this._$hr=null;}H.prototype=new B();function s(){if(j){return;}this.visible=true;this._$g0=false;this._$NL=null;this._$3S=null;this._$aS=null;s._$42++;}s._$42=0;s.prototype._$zP=function(){this._$3S=new Array();this._$aS=new Array();};s.prototype._$F0=function(aH){this._$g0=aH._$8L();this.visible=aH._$8L();this._$NL=aH._$nP();this._$3S=aH._$nP();this._$aS=aH._$nP();};s.prototype.init=function(aI){var aH=new aj(this);aH.setPartsOpacity(this.isVisible()?1:0);return aH;};s.prototype._$6o=function(aH){if(this._$3S==null){throw new Error("_$3S _$6 _$Wo@_$6o");}this._$3S.push(aH);};s.prototype._$3o=function(aH){if(this._$aS==null){throw new Error("_$aS _$6 _$Wo@_$3o");}this._$aS.push(aH);};s.prototype._$Zo=function(aH){this._$3S=aH;};s.prototype._$xo=function(aH){this._$aS=aH;};s.prototype.isVisible=function(){return this.visible;};s.prototype._$uL=function(){return this._$g0;};s.prototype._$KP=function(aH){this.visible=aH;};s.prototype._$ET=function(aH){this._$g0=aH;};s.prototype.getBaseData=function(){return this._$3S;};s.prototype.getDrawData=function(){return this._$aS;};s.prototype._$p2=function(){return this._$NL;};s.prototype._$ob=function(aH){this._$NL=aH;};s.prototype.getPartsID=function(){return this._$NL;};s.prototype._$MP=function(aH){this._$NL=aH;};function aj(aH){this._$VS=null;this._$e0=null;this._$e0=aH;}aj.prototype=new S();aj.prototype.getPartsOpacity=function(){return this._$VS;};aj.prototype.setPartsOpacity=function(aH){this._$VS=aH;};function ak(aH){if(j){return;}this.id=aH;}ak._$L7=function(){z._$27();n._$27();Z._$27();i._$27();};ak.prototype.toString=function(){return this.id;};function D(){}D.prototype._$F0=function(aH){};function an(){if(j){return;}this._$4S=null;}an.prototype._$1s=function(){return this._$4S;};an.prototype._$zP=function(){this._$4S=new Array();};an.prototype._$F0=function(aH){this._$4S=aH._$nP();};an.prototype._$Ks=function(aH){this._$4S.push(aH);};function au(aH,aI){this.canvas=aH;this.context=aI;this.viewport=new Array(0,0,aH.width,aH.height);this._$6r=1;this._$xP=0;this._$3r=1;this._$uP=0;this._$Qo=-1;this.cacheImages={};}au.tr=new am();au._$50=new am();au._$Ti=new Array(0,0);au._$Pi=new Array(0,0);au._$B=new Array(0,0);au.prototype._$lP=function(aI,aK,aJ,aH){this.viewport=new Array(aI,aK,aJ,aH);};au.prototype._$bL=function(){this.context.save();var aH=this.viewport;if(aH!=null){this.context.beginPath();this.context._$Li(aH[0],aH[1],aH[2],aH[3]);this.context.clip();}};au.prototype._$ei=function(){this.context.restore();};au.prototype.drawElements=function(bc,bm,aX,aJ,bA,aM,bl,bz){try{if(bA!=this._$Qo){this._$Qo=bA;this.context.globalAlpha=bA;}var a2=bm.length;var aP=bc.width;var a5=bc.height;var bE=this.context;var a7=this._$xP;var a6=this._$uP;var a1=this._$6r;var aZ=this._$3r;var bD=au.tr;var aI=au._$Ti;var aH=au._$Pi;var bu=au._$B;for(var by=0;by<a2;by+=3){bE.save();var aW=bm[by];var aV=bm[by+1];var aT=bm[by+2];var aL=a7+a1*aX[aW*2];var aK=a6+aZ*aX[aW*2+1];var br=a7+a1*aX[aV*2];var bp=a6+aZ*aX[aV*2+1];var bh=a7+a1*aX[aT*2];var bf=a6+aZ*aX[aT*2+1];if(bl){bl._$PS(aL,aK,bu);aL=bu[0];aK=bu[1];bl._$PS(br,bp,bu);br=bu[0];bp=bu[1];bl._$PS(bh,bf,bu);bh=bu[0];bf=bu[1];}var aS=aP*aJ[aW*2];var aQ=a5-a5*aJ[aW*2+1];var bx=aP*aJ[aV*2];var bw=a5-a5*aJ[aV*2+1];var bk=aP*aJ[aT*2];var bj=a5-a5*aJ[aT*2+1];var a3=Math.atan2(bw-aQ,bx-aS);var a0=Math.atan2(bp-aK,br-aL);var aO=br-aL;var aN=bp-aK;var bi=Math.sqrt(aO*aO+aN*aN);var aU=bx-aS;var aR=bw-aQ;var bt=Math.sqrt(aU*aU+aR*aR);var bv=bi/bt;ad._$ni(bk,bj,aS,aQ,(bx-aS),(bw-aQ),-(bw-aQ),(bx-aS),aI);ad._$ni(bh,bf,aL,aK,(br-aL),(bp-aK),-(bp-aK),(br-aL),aH);var aY=(aH[0]-aI[0])/aI[1];var bs=Math.min(aS,bx,bk);var bg=Math.max(aS,bx,bk);var bq=Math.min(aQ,bw,bj);var be=Math.max(aQ,bw,bj);var bo=Math.floor(bs);var bb=Math.floor(bq);var a4=Math.ceil(bg);var bC=Math.ceil(be);bD.identity();bD.translate(aL,aK);bD.rotate(a0);bD.scale(1,aH[1]/aI[1]);bD.shear(aY,0);bD.scale(bv,bv);bD.rotate(-a3);bD.translate(-aS,-aQ);bD.setContext(bE);var a8=true;var a9=1.2;if(!aM){aM=a8?a9:0;}if(Q.IGNORE_EXPAND){aM=0;}if(Q.USE_CACHED_POLYGON_IMAGE){var bd=bz._$e0;bd.gl_cacheImage=bd.gl_cacheImage||{};if(!bd.gl_cacheImage[by]){var bn=au.createCanvas(a4-bo,bC-bb);Q.DEBUG_DATA.LDGL_CANVAS_MB=Q.DEBUG_DATA.LDGL_CANVAS_MB||0;Q.DEBUG_DATA.LDGL_CANVAS_MB+=(a4-bo)*(bC-bb)*4;var ba=bn.getContext("2d");ba.translate(-bo,-bb);au.clip(ba,bD,aM,bi,aS,aQ,bx,bw,bk,bj,aL,aK,br,bp,bh,bf);ba.drawImage(bc,0,0);bd.gl_cacheImage[by]={cacheCanvas:bn,cacheContext:ba};}bE.drawImage(bd.gl_cacheImage[by]["cacheCanvas"],bo,bb);}else{if(!Q.IGNORE_CLIP){au.clip(bE,bD,aM,bi,aS,aQ,bx,bw,bk,bj,aL,aK,br,bp,bh,bf);}if(Q.USE_ADJUST_TRANSLATION){bs=0;bg=aP;bq=0;be=a5;}bE.drawImage(bc,bs,bq,bg-bs,be-bq,bs,bq,bg-bs,be-bq);}bE.restore();}}catch(bB){q._$Rb(bB);}};au.clip=function(aK,aJ,aV,aI,aM,aL,aU,aT,aQ,aP,aO,aN,aH,aW,aS,aR){if(aV>0.02){au.expandClip(aK,aJ,aV,aI,aO,aN,aH,aW,aS,aR);}else{au.clipWithTransform(aK,null,aM,aL,aU,aT,aQ,aP);}};au.expandClip=function(aV,bg,aK,a3,aJ,aI,be,ba,aZ,aX){var aP=be-aJ;var aO=ba-aI;var bi=aZ-aJ;var bh=aX-aI;var bj=aP*bh-aO*bi>0?aK:-aK;var aL=-aO;var aH=aP;var bc=aZ-be;var a8=aX-ba;var a7=-a8;var a6=bc;var aQ=Math.sqrt(bc*bc+a8*a8);var bf=-bh;var bb=bi;var a2=Math.sqrt(bi*bi+bh*bh);var bd=aJ-bj*aL/a3;var a9=aI-bj*aH/a3;var aY=be-bj*aL/a3;var aW=ba-bj*aH/a3;var a5=be-bj*a7/aQ;var a4=ba-bj*a6/aQ;var aS=aZ-bj*a7/aQ;var aR=aX-bj*a6/aQ;var aN=aJ+bj*bf/a2;var aM=aI+bj*bb/a2;var a1=aZ+bj*bf/a2;var a0=aX+bj*bb/a2;var aU=au._$50;var aT=bg._$P2(aU);if(aT==null){return false;}au.clipWithTransform(aV,aU,bd,a9,aY,aW,a5,a4,aS,aR,a1,a0,aN,aM);return true;};au.clipWithTransform=function(aH,aI,aS,aN,aQ,aK,aP,aJ){if(arguments.length<(1+3*2)){q._$li("err : @LDGL.clip()");return;}if(!(arguments[1] instanceof am)){q._$li("err : a[0] is _$6 LDTransform @LDGL.clip()");return;}var aM=au._$B;var aO=aI;var aR=arguments;aH.beginPath();if(aO){aO._$PS(aR[2],aR[3],aM);aH.moveTo(aM[0],aM[1]);for(var aL=4;aL<aR.length;aL+=2){aO._$PS(aR[aL],aR[aL+1],aM);aH.lineTo(aM[0],aM[1]);}}else{aH.moveTo(aR[2],aR[3]);for(var aL=4;aL<aR.length;aL+=2){aH.lineTo(aR[aL],aR[aL+1]);}}aH.clip();};au.createCanvas=function(aH,aJ){var aI=document.createElement("canvas");aI.setAttribute("width",aH);aI.setAttribute("height",aJ);if(!aI){q._$li("err : "+aI);}return aI;};au.dumpValues=function(){var aI="";for(var aH=0;aH<arguments.length;aH++){aI+="["+aH+"]= "+arguments[aH].toFixed(3)+" , ";}console.log(aI);};function f(){if(j){return;}this._$TT=null;this._$LT=null;this._$FS=null;this._$wL=null;}f.prototype._$F0=function(aH){this._$TT=aH._$_T();this._$LT=aH._$_T();this._$FS=aH._$_T();this._$wL=aH._$nP();};f.prototype.getMinValue=function(){return this._$TT;};f.prototype.getMaxValue=function(){return this._$LT;};f.prototype.getDefaultValue=function(){return this._$FS;};f.prototype.getParamID=function(){return this._$wL;};function B(aH){if(j){return;}this._$e0=null;this._$IP=null;this._$JS=false;this._$AT=true;this._$e0=aH;this.totalScale=1;this._$7s=1;this.totalOpacity=1;}B.prototype._$yo=function(){return this._$AT&&!this._$JS;};B.prototype._$hS=function(aH){this._$AT=aH;};B.prototype._$GT=function(){return this._$e0;};B.prototype._$l2=function(aH){this._$IP=aH;};B.prototype.getPartsIndex=function(){return this._$IP;};B.prototype._$x2=function(){return this._$JS;};B.prototype._$Ib=function(aH){this._$JS=aH;};B.prototype.getTotalScale=function(){return this.totalScale;};B.prototype.setTotalScale_notForClient=function(aH){this.totalScale=aH;};B.prototype.getInterpolatedOpacity=function(){return this._$7s;};B.prototype.setInterpolatedOpacity=function(aH){this._$7s=aH;};B.prototype.getTotalOpacity=function(aH){return this.totalOpacity;};B.prototype.setTotalOpacity=function(aH){this.totalOpacity=aH;};function Q(){}Q._$2s="2.1.00_1";Q._$Kr=201001000;Q._$sP=true;Q._$so=true;Q._$cb=false;Q._$3T=true;Q._$Ts=true;Q._$fb=true;Q._$ts=true;Q.L2D_DEFORMER_EXTEND=true;Q._$Wb=false;Q._$yr=false;Q._$Zs=false;Q.L2D_NO_ERROR=0;Q._$i7=1000;Q._$9s=1001;Q._$es=1100;Q._$r7=2000;Q._$07=2001;Q._$b7=2002;Q._$H7=4000;Q.L2D_COLOR_BLEND_MODE_MULT=0;Q.L2D_COLOR_BLEND_MODE_ADD=1;Q.L2D_COLOR_BLEND_MODE_INTERPOLATE=2;Q._$6b=true;Q._$cT=0;Q.clippingMaskBufferSize=256;Q.glContext=new Array();Q.frameBuffers=new Array();Q.fTexture=new Array();Q.IGNORE_CLIP=false;Q.IGNORE_EXPAND=false;Q.EXPAND_W=2;Q.USE_ADJUST_TRANSLATION=true;Q.USE_CANVAS_TRANSFORM=true;Q.USE_CACHED_POLYGON_IMAGE=false;Q.DEBUG_DATA={};Q.PROFILE_IOS_SPEED={PROFILE_NAME:"iOS Speed",USE_ADJUST_TRANSLATION:true,USE_CACHED_POLYGON_IMAGE:true,EXPAND_W:4};Q.PROFILE_IOS_QUALITY={PROFILE_NAME:"iOS HiQ",USE_ADJUST_TRANSLATION:true,USE_CACHED_POLYGON_IMAGE:false,EXPAND_W:2};Q.PROFILE_IOS_DEFAULT=Q.PROFILE_IOS_QUALITY;Q.PROFILE_ANDROID={PROFILE_NAME:"Android",USE_ADJUST_TRANSLATION:false,USE_CACHED_POLYGON_IMAGE:false,EXPAND_W:2};Q.PROFILE_DESKTOP={PROFILE_NAME:"Desktop",USE_ADJUST_TRANSLATION:false,USE_CACHED_POLYGON_IMAGE:false,EXPAND_W:2};Q.initProfile=function(){if(r.isIOS()){Q.setupProfile(Q.PROFILE_IOS_DEFAULT);}else{if(r.isAndroid()){Q.setupProfile(Q.PROFILE_ANDROID);}else{Q.setupProfile(Q.PROFILE_DESKTOP);}}};Q.setupProfile=function(aI,aJ){if(typeof aI=="number"){switch(aI){case 9901:aI=Q.PROFILE_IOS_SPEED;break;case 9902:aI=Q.PROFILE_IOS_QUALITY;break;case 9903:aI=Q.PROFILE_IOS_DEFAULT;break;case 9904:aI=Q.PROFILE_ANDROID;break;case 9905:aI=Q.PROFILE_DESKTOP;break;default:alert("profile _$6 _$Ui : "+aI);break;}}if(arguments.length<2){aJ=true;}if(aJ){console.log("profile : "+aI.PROFILE_NAME);}for(var aH in aI){Q[aH]=aI[aH];if(aJ){console.log("  ["+aH+"] = "+aI[aH]);}}};Q.init=function(){if(Q._$6b){console.log("Live2D %s",Q._$2s);Q._$6b=false;var aH=false;aH=true;Q.initProfile();}};Q.getVersionStr=function(){return Q._$2s;};Q.getVersionNo=function(){return Q._$Kr;};Q._$sT=function(aH){Q._$cT=aH;};Q.getError=function(){var aH=Q._$cT;Q._$cT=0;return aH;};Q.dispose=function(){Q.glContext=[];Q.frameBuffers=[];Q.fTexture=[];};Q.setGL=function(aJ,aI){var aH=aI||0;Q.glContext[aH]=aJ;};Q.getGL=function(aH){return Q.glContext[aH];};Q.setClippingMaskBufferSize=function(aH){Q.clippingMaskBufferSize=aH;};Q.getClippingMaskBufferSize=function(){return Q.clippingMaskBufferSize;};Q.deleteBuffer=function(aI){var aH=Q.getGL(aI);aH.deleteFramebuffer(Q.frameBuffers[aI].framebuffer);delete Q.frameBuffers[aI];delete Q.glContext[aI];};function A(){}A._$r2=function(aH){if(aH<0){return 0;}else{if(aH>1){return 1;}}return(0.5-0.5*Math.cos(aH*aC.PI_F));};function J(aH){if(j){return;}this._$ib=aH;}J._$fr=-1;J.prototype.toString=function(){return this._$ib;};function b(){if(j){return;}a.prototype.constructor.call(this);this._$LP=-1;this._$d0=0;this._$Yo=0;this._$JP=null;this._$5P=null;this._$BP=null;this._$Eo=null;this._$Qi=null;this._$6s=b._$ms;this.culling=true;this.gl_cacheImage=null;this.instanceNo=b._$42++;}b.prototype=new a();b._$42=0;b._$Os=30;b._$ms=0;b._$ns=1;b._$_s=2;b._$gT=new Array();b.prototype._$_S=function(aH){this._$LP=aH;};b.prototype.getTextureNo=function(){return this._$LP;};b.prototype._$ZL=function(){return this._$Qi;};b.prototype._$H2=function(){return this._$JP;};b.prototype.getNumPoints=function(){return this._$d0;};b.prototype.getType=function(){return a._$wb;};b.prototype._$B2=function(aL,aH,aO){var aM=aH;var aN=(aM._$hr!=null)?aM._$hr:aM._$Cr;var aK=aw._$do;switch(aK){default:case aw._$Ms:throw new Error("_$L _$ro ");case aw._$Qs:for(var aJ=this._$d0-1;aJ>=0;--aJ){var aI=aJ*aw._$No;aN[aI+4]=aO;}break;}};b.prototype._$zP=function(){this._$GS=new g();this._$GS._$zP();};b.prototype._$F0=function(aK){a.prototype._$F0.call(this,aK);this._$LP=aK._$6L();this._$d0=aK._$6L();this._$Yo=aK._$6L();var aH=aK._$nP();this._$BP=new Int16Array(this._$Yo*3);for(var aJ=this._$Yo*3-1;aJ>=0;--aJ){this._$BP[aJ]=aH[aJ];}this._$Eo=aK._$nP();this._$Qi=aK._$nP();if(aK.getFormatVersion()>=ay._$s7){this._$JP=aK._$6L();if(this._$JP!=0){if((this._$JP&1)!=0){var aI=aK._$6L();if(this._$5P==null){this._$5P=new Object();}this._$5P._$Hb=parseInt(aI);}if((this._$JP&b._$Os)!=0){this._$6s=(this._$JP&b._$Os)>>1;}else{this._$6s=b._$ms;}if((this._$JP&32)!=0){this.culling=false;}}}else{this._$JP=0;}};b.prototype.init=function(aL){var aN=new ag(this);var aI=this._$d0*aw._$No;var aH=this._$32();if(aN._$Cr!=null){aN._$Cr=null;}aN._$Cr=new Float32Array(aI);if(aN._$hr!=null){aN._$hr=null;}aN._$hr=aH?new Float32Array(aI):null;var aM=aw._$do;switch(aM){default:case aw._$Ms:if(aw._$Ls){for(var aJ=this._$d0-1;aJ>=0;--aJ){var aO=aJ<<1;this._$Qi[aO+1]=1-this._$Qi[aO+1];}}break;case aw._$Qs:for(var aJ=this._$d0-1;aJ>=0;--aJ){var aO=aJ<<1;var aK=aJ*aw._$No;var aQ=this._$Qi[aO];var aP=this._$Qi[aO+1];aN._$Cr[aK]=aQ;aN._$Cr[aK+1]=aP;aN._$Cr[aK+4]=0;if(aH){aN._$hr[aK]=aQ;aN._$hr[aK+1]=aP;aN._$hr[aK+4]=0;}}break;}return aN;};b.prototype._$Nr=function(aJ,aH){var aK=aH;if(!((this==aK._$GT()))){console.log("### assert!! ### ");}if(!this._$GS._$Ur(aJ)){return;}a.prototype._$Nr.call(this,aJ,aK);if(aK._$IS[0]){return;}var aI=b._$gT;aI[0]=false;aG._$Vr(aJ,this._$GS,aI,this._$d0,this._$Eo,aK._$Cr,aw._$i2,aw._$No);};b.prototype._$2b=function(aK,aI){try{if(!((this==aI._$GT()))){console.log("### assert!! ### ");}var aL=false;if(aI._$IS[0]){aL=true;}var aM=aI;if(!aL){a.prototype._$2b.call(this,aK);if(this._$32()){var aH=this.getTargetBaseDataID();if(aM._$8r==a._$ur){aM._$8r=aK.getBaseDataIndex(aH);}if(aM._$8r<0){if(Q._$so){q._$li("_$L _$0P _$G :: %s",aH);}}else{var aO=aK.getBaseData(aM._$8r);var aJ=aK._$q2(aM._$8r);if(aO!=null&&!aJ._$x2()){aO._$nb(aK,aJ,aM._$Cr,aM._$hr,this._$d0,aw._$i2,aw._$No);aM._$AT=true;}else{aM._$AT=false;}aM.baseOpacity=aJ.getTotalOpacity();}}}}catch(aN){throw aN;}};b.prototype.draw=function(aN,aK,aI){if(!((this==aI._$GT()))){console.log("### assert!! ### ");}if(aI._$IS[0]){return;}var aL=aI;var aJ=this._$LP;if(aJ<0){aJ=1;}var aH=this.getOpacity(aK,aL)*aI._$VS*aI.baseOpacity;var aM=(aL._$hr!=null)?aL._$hr:aL._$Cr;aN.setClipBufPre_clipContextForDraw(aI.clipBufPre_clipContext);aN._$WP(this.culling);aN._$Uo(aJ,3*this._$Yo,this._$BP,aM,this._$Qi,aH,this._$6s,aL);};b.prototype.dump=function(){console.log("  _$yi( %d ) , _$d0( %d ) , _$Yo( %d ) \n",this._$LP,this._$d0,this._$Yo);console.log("  _$Oi _$di = { ");for(var aJ=0;aJ<this._$BP.length;aJ++){console.log("%5d ,",this._$BP[aJ]);}console.log("\n  _$5i _$30");for(var aJ=0;aJ<this._$Eo.length;aJ++){console.log("\n    _$30[%d] = ",aJ);var aH=this._$Eo[aJ];for(var aI=0;aI<aH.length;aI++){console.log("%6.2f, ",aH[aI]);}}console.log("\n");};b.prototype._$72=function(aH){if(this._$5P==null){return null;}return this._$5P[aH];};b.prototype.getIndexArray=function(){return this._$BP;};function ag(aH){aB.prototype.constructor.call(this,aH);this._$8r=a._$ur;this._$Cr=null;this._$hr=null;}ag.prototype=new aB();ag.prototype.getTransformedPoints=function(){return(this._$hr!=null)?this._$hr:this._$Cr;};function k(){if(j){return;}this.x=null;this.y=null;}k.prototype._$HT=function(aH){this.x=aH.x;this.y=aH.y;};k.prototype._$HT=function(aH,aI){this.x=aH;this.y=aI;};function l(aH){if(j){return;}aa.prototype.constructor.call(this);this.drawParamWebGL=new C(aH);this.drawParamWebGL.setGL(Q.getGL(aH));}l.prototype=new aa();l.loadModel=function(aI){var aH=new l();aa._$62(aH,aI);return aH;};l.loadModel=function(aI,aK){var aJ=aK||0;var aH=new l(aJ);aa._$62(aH,aI);return aH;};l._$to=function(){var aH=new l();return aH;};l._$er=function(aM){var aJ=new _$5("../_$_r/_$t0/_$Ri/_$_P._$d");if(aJ.exists()==false){throw new _$ls("_$t0 _$_ _$6 _$Ui :: "+aJ._$PL());}var aH=["../_$_r/_$t0/_$Ri/_$_P.512/_$CP._$1","../_$_r/_$t0/_$Ri/_$_P.512/_$vP._$1","../_$_r/_$t0/_$Ri/_$_P.512/_$EP._$1","../_$_r/_$t0/_$Ri/_$_P.512/_$pP._$1"];var aK=l.loadModel(aJ._$3b());for(var aI=0;aI<aH.length;aI++){var aL=new _$5(aH[aI]);if(aL.exists()==false){throw new _$ls("_$t0 _$_ _$6 _$Ui :: "+aL._$PL());}aK.setTexture(aI,_$nL._$_o(aM,aL._$3b()));}return aK;};l.prototype.setGL=function(aH){Q.setGL(aH);};l.prototype.setTransform=function(aH){this.drawParamWebGL.setTransform(aH);};l.prototype.update=function(){this._$5S.update();this._$5S.preDraw(this.drawParamWebGL);};l.prototype.draw=function(){this._$5S.draw(this.drawParamWebGL);};l.prototype._$K2=function(){this.drawParamWebGL._$K2();};l.prototype.setTexture=function(aI,aH){if(this.drawParamWebGL==null){q._$li("_$Yi for QT _$ki / _$XS() is _$6 _$ui!!");}this.drawParamWebGL.setTexture(aI,aH);};l.prototype.setTexture=function(aI,aH){if(this.drawParamWebGL==null){q._$li("_$Yi for QT _$ki / _$XS() is _$6 _$ui!!");}this.drawParamWebGL.setTexture(aI,aH);};l.prototype._$Rs=function(){return this.drawParamWebGL._$Rs();};l.prototype._$Ds=function(aH){this.drawParamWebGL._$Ds(aH);};l.prototype.getDrawParam=function(){return this.drawParamWebGL;};l.prototype.setMatrix=function(aH){this.drawParamWebGL.setMatrix(aH);};l.prototype.setPremultipliedAlpha=function(aH){this.drawParamWebGL.setPremultipliedAlpha(aH);};l.prototype.isPremultipliedAlpha=function(){return this.drawParamWebGL.isPremultipliedAlpha();};l.prototype.setAnisotropy=function(aH){this.drawParamWebGL.setAnisotropy(aH);};l.prototype.getAnisotropy=function(){return this.drawParamWebGL.getAnisotropy();};function V(){if(j){return;}this.motions=null;this._$eb=false;this.motions=new Array();}V.prototype._$tb=function(){return this.motions;};V.prototype.startMotion=function(aJ,aI){var aM=null;var aL=null;var aH=this.motions.length;for(var aK=0;aK<aH;++aK){aL=this.motions[aK];if(aL==null){continue;}aL._$qS(aL._$w0.getFadeOut());if(this._$eb){q._$Ji("MotionQueueManager[size:%2d]->startMotion() / start _$K _$3 (m%d)\n",aH,aL._$sr);}}if(aJ==null){return -1;}aL=new M();aL._$w0=aJ;this.motions.push(aL);var aN=aL._$sr;if(this._$eb){q._$Ji("MotionQueueManager[size:%2d]->startMotion() / new _$w0 (m%d)\n",aH,aN);}return aN;};V.prototype.updateParam=function(aJ){try{var aI=false;for(var aK=0;aK<this.motions.length;aK++){var aL=this.motions[aK];if(aL==null){this.motions.splice(aK,1);aK--;continue;}var aH=aL._$w0;if(aH==null){this.motions=this.motions.splice(aK,1);aK--;continue;}aH.updateParam(aJ,aL);aI=true;if(aL.isFinished()){if(this._$eb){q._$Ji("MotionQueueManager[size:%2d]->updateParam() / _$T0 _$w0 (m%d)\n",this.motions.length-1,aL._$sr);}this.motions.splice(aK,1);aK--;}else{}}return aI;}catch(aM){q._$li(aM);return true;}};V.prototype.isFinished=function(aK){if(arguments.length>=1){for(var aI=0;aI<this.motions.length;aI++){var aJ=this.motions[aI];if(aJ==null){continue;}if(aJ._$sr==aK&&!aJ.isFinished()){return false;}}return true;}else{for(var aI=0;aI<this.motions.length;aI++){var aJ=this.motions[aI];if(aJ==null){this.motions.splice(aI,1);aI--;continue;}var aH=aJ._$w0;if(aH==null){this.motions.splice(aI,1);aI--;continue;}if(!aJ.isFinished()){return false;}}return true;}};V.prototype.stopAllMotions=function(){for(var aI=0;aI<this.motions.length;aI++){var aJ=this.motions[aI];if(aJ==null){this.motions.splice(aI,1);aI--;continue;}var aH=aJ._$w0;if(aH==null){this.motions.splice(aI,1);aI--;continue;}if(true){this.motions.splice(aI,1);aI--;}}};V.prototype._$Zr=function(aH){this._$eb=aH;};V.prototype._$e=function(){console.log("-- _$R --\n");for(var aH=0;aH<this.motions.length;aH++){var aI=this.motions[aH];var aJ=aI._$w0;console.log("MotionQueueEnt[%d] :: %s\n",this.motions.length,aJ.toString());}};function M(){this._$w0=null;this._$AT=true;this._$9L=false;this._$z2=-1;this._$bs=-1;this._$Do=-1;this._$sr=null;this._$sr=M._$Gs++;}M._$Gs=0;M.prototype.isFinished=function(){return this._$9L;};M.prototype._$qS=function(aJ){var aI=P.getUserTimeMSec();var aH=aI+aJ;if(this._$Do<0||aH<this._$Do){this._$Do=aH;}};M.prototype._$Bs=function(){return this._$sr;};function am(){this.m=new Array(1,0,0,0,1,0,0,0,1);}am.prototype.setContext=function(aI){var aH=this.m;aI.transform(aH[0],aH[1],aH[3],aH[4],aH[6],aH[7]);};am.prototype.toString=function(){var aI="LDTransform { ";for(var aH=0;aH<9;aH++){aI+=this.m[aH].toFixed(2)+" ,";}aI+=" }";return aI;};am.prototype.identity=function(){var aH=this.m;aH[0]=aH[4]=aH[8]=1;aH[1]=aH[2]=aH[3]=aH[5]=aH[6]=aH[7]=0;};am.prototype._$PS=function(aI,aK,aJ){if(aJ==null){aJ=new Array(0,0);}var aH=this.m;aJ[0]=aH[0]*aI+aH[3]*aK+aH[6];aJ[1]=aH[1]*aI+aH[4]*aK+aH[7];return aJ;};am.prototype._$P2=function(aK){if(!aK){aK=new am();}var aI=this.m;var aT=aI[0];var aS=aI[1];var aR=aI[2];var aQ=aI[3];var aP=aI[4];var aO=aI[5];var aN=aI[6];var aM=aI[7];var aL=aI[8];var aJ=aT*aP*aL+aS*aO*aN+aR*aQ*aM-aT*aO*aM-aR*aP*aN-aS*aQ*aL;if(aJ==0){return null;}else{var aH=1/aJ;aK.m[0]=aH*(aP*aL-aM*aO);aK.m[1]=aH*(aM*aR-aS*aL);aK.m[2]=aH*(aS*aO-aP*aR);aK.m[3]=aH*(aN*aO-aQ*aL);aK.m[4]=aH*(aT*aL-aN*aR);aK.m[5]=aH*(aQ*aR-aT*aO);aK.m[6]=aH*(aQ*aM-aN*aP);aK.m[7]=aH*(aN*aS-aT*aM);aK.m[8]=aH*(aT*aP-aQ*aS);return aK;}};am.prototype.transform=function(aI,aK,aJ){if(aJ==null){aJ=new Array(0,0);}var aH=this.m;aJ[0]=aH[0]*aI+aH[3]*aK+aH[6];aJ[1]=aH[1]*aI+aH[4]*aK+aH[7];return aJ;};am.prototype.translate=function(aI,aJ){var aH=this.m;aH[6]=aH[0]*aI+aH[3]*aJ+aH[6];aH[7]=aH[1]*aI+aH[4]*aJ+aH[7];aH[8]=aH[2]*aI+aH[5]*aJ+aH[8];};am.prototype.scale=function(aJ,aI){var aH=this.m;aH[0]*=aJ;aH[1]*=aJ;aH[2]*=aJ;aH[3]*=aI;aH[4]*=aI;aH[5]*=aI;};am.prototype.shear=function(aM,aL){var aH=this.m;var aK=aH[0]+aH[3]*aL;var aJ=aH[1]+aH[4]*aL;var aI=aH[2]+aH[5]*aL;aH[3]=aH[0]*aM+aH[3];aH[4]=aH[1]*aM+aH[4];aH[5]=aH[2]*aM+aH[5];aH[0]=aK;aH[1]=aJ;aH[2]=aI;};am.prototype.rotate=function(aM){var aH=this.m;var aN=Math.cos(aM);var aL=Math.sin(aM);var aK=aH[0]*aN+aH[3]*aL;var aJ=aH[1]*aN+aH[4]*aL;var aI=aH[2]*aN+aH[5]*aL;aH[3]=-aH[0]*aL+aH[3]*aN;aH[4]=-aH[1]*aL+aH[4]*aN;aH[5]=-aH[2]*aL+aH[5]*aN;aH[0]=aK;aH[1]=aJ;aH[2]=aI;};am.prototype.concatenate=function(aL){var aO=this.m;var aM=aL.m;var aS=aO[0]*aM[0]+aO[3]*aM[1]+aO[6]*aM[2];var aR=aO[1]*aM[0]+aO[4]*aM[1]+aO[7]*aM[2];var aQ=aO[2]*aM[0]+aO[5]*aM[1]+aO[8]*aM[2];var aP=aO[0]*aM[3]+aO[3]*aM[4]+aO[6]*aM[5];var aN=aO[1]*aM[3]+aO[4]*aM[4]+aO[7]*aM[5];var aK=aO[2]*aM[3]+aO[5]*aM[4]+aO[8]*aM[5];var aJ=aO[0]*aM[6]+aO[3]*aM[7]+aO[6]*aM[8];var aI=aO[1]*aM[6]+aO[4]*aM[7]+aO[7]*aM[8];var aH=aO[2]*aM[6]+aO[5]*aM[7]+aO[8]*aM[8];m[0]=aS;m[1]=aR;m[2]=aQ;m[3]=aP;m[4]=aN;m[5]=aK;m[6]=aJ;m[7]=aI;m[8]=aH;};function n(aH){if(j){return;}ak.prototype.constructor.call(this,aH);}n.prototype=new ak();n._$eT=null;n._$tP=new Object();n._$2o=function(){if(n._$eT==null){n._$eT=n.getID("DST_BASE");}return n._$eT;};n._$27=function(){n._$tP.clear();n._$eT=null;};n.getID=function(aH){var aI=n._$tP[aH];if(aI==null){aI=new n(aH);n._$tP[aH]=aI;}return aI;};n.prototype._$3s=function(){return new n();};function C(aH){if(j){return;}ax.prototype.constructor.call(this);this.textures=new Array();this.transform=null;this.gl=null;this.glno=aH;this.firstDraw=true;this.anisotropyExt=null;this.maxAnisotropy=0;this._$As=32;this._$Gr=false;this._$NT=null;this._$vS=null;this._$no=null;this.vertShader=null;this.fragShader=null;this.vertShaderOff=null;this.fragShaderOff=null;}C.prototype=new ax();C._$9r=function(aH){var aI=new Float32Array(aH);return aI;};C._$vb=function(aH){var aI=new Int16Array(aH);return aI;};C._$cr=function(aI,aH){if(aI==null||aI._$yL()<aH.length){aI=C._$9r(aH.length*2);aI.put(aH);aI._$oT(0);}else{aI.clear();aI.put(aH);aI._$oT(0);}return aI;};C._$mb=function(aI,aH){if(aI==null||aI._$yL()<aH.length){aI=C._$vb(aH.length*2);aI.put(aH);aI._$oT(0);}else{aI.clear();aI.put(aH);aI._$oT(0);}return aI;};C._$Hs=function(){return this._$Gr;};C._$as=function(aH){this._$Gr=aH;};C.prototype.getGL=function(){return this.gl;};C.prototype.setGL=function(aH){this.gl=aH;};C.prototype.setTransform=function(aH){this.transform=aH;};C.prototype._$ZT=function(){var aH=this.gl;if(this.firstDraw){this.initShader();this.firstDraw=false;this.anisotropyExt=aH.getExtension("EXT_texture_filter_anisotropic")||aH.getExtension("WEBKIT_EXT_texture_filter_anisotropic")||aH.getExtension("MOZ_EXT_texture_filter_anisotropic");if(this.anisotropyExt){this.maxAnisotropy=aH.getParameter(this.anisotropyExt.MAX_TEXTURE_MAX_ANISOTROPY_EXT);}}aH.disable(aH.SCISSOR_TEST);aH.disable(aH.STENCIL_TEST);aH.disable(aH.DEPTH_TEST);aH.frontFace(aH.CW);aH.enable(aH.BLEND);aH.colorMask(1,1,1,1);aH.bindBuffer(aH.ARRAY_BUFFER,null);aH.bindBuffer(aH.ELEMENT_ARRAY_BUFFER,null);};C.prototype._$Uo=function(aS,aT,aL,aU,aV,aN,aM,aO){if(aN<0.01&&this.clipBufPre_clipContextMask==null){return;}var aH=aN>0.9?Q.EXPAND_W:0;var a0=this.gl;if(this.gl==null){throw new Error("gl is null");}var a1=false;var aQ=1;var aP=1;var a3=1;var aZ=1;var aW=this._$C0*aP*aN;var a2=this._$tT*a3*aN;var a5=this._$WL*aZ*aN;var a7=this._$lT*aN;if(this.clipBufPre_clipContextMask!=null){a0.frontFace(a0.CCW);a0.useProgram(this.shaderProgram);this._$vS=T(a0,this._$vS,aU);this._$no=L(a0,this._$no,aL);a0.enableVertexAttribArray(this.a_position_Loc);a0.vertexAttribPointer(this.a_position_Loc,2,a0.FLOAT,false,0,0);this._$NT=T(a0,this._$NT,aV);a0.activeTexture(a0.TEXTURE1);a0.bindTexture(a0.TEXTURE_2D,this.textures[aS]);a0.uniform1i(this.s_texture0_Loc,1);a0.enableVertexAttribArray(this.a_texCoord_Loc);a0.vertexAttribPointer(this.a_texCoord_Loc,2,a0.FLOAT,false,0,0);a0.uniformMatrix4fv(this.u_matrix_Loc,false,this.getClipBufPre_clipContextMask().matrixForMask);var aY=this.getClipBufPre_clipContextMask().layoutChannelNo;var a4=this.getChannelFlagAsColor(aY);a0.uniform4f(this.u_channelFlag,a4.r,a4.g,a4.b,a4.a);var aI=this.getClipBufPre_clipContextMask().layoutBounds;a0.uniform4f(this.u_baseColor_Loc,aI.x*2-1,aI.y*2-1,aI._$EL()*2-1,aI._$5T()*2-1);a0.uniform1i(this.u_maskFlag_Loc,true);}else{a1=this.getClipBufPre_clipContextDraw()!=null;if(a1){a0.useProgram(this.shaderProgramOff);this._$vS=T(a0,this._$vS,aU);this._$no=L(a0,this._$no,aL);a0.enableVertexAttribArray(this.a_position_Loc_Off);a0.vertexAttribPointer(this.a_position_Loc_Off,2,a0.FLOAT,false,0,0);this._$NT=T(a0,this._$NT,aV);a0.activeTexture(a0.TEXTURE1);a0.bindTexture(a0.TEXTURE_2D,this.textures[aS]);a0.uniform1i(this.s_texture0_Loc_Off,1);a0.enableVertexAttribArray(this.a_texCoord_Loc_Off);a0.vertexAttribPointer(this.a_texCoord_Loc_Off,2,a0.FLOAT,false,0,0);a0.uniformMatrix4fv(this.u_clipMatrix_Loc_Off,false,this.getClipBufPre_clipContextDraw().matrixForDraw);a0.uniformMatrix4fv(this.u_matrix_Loc_Off,false,this.matrix4x4);a0.activeTexture(a0.TEXTURE2);a0.bindTexture(a0.TEXTURE_2D,Q.fTexture[this.glno]);a0.uniform1i(this.s_texture1_Loc_Off,2);var aY=this.getClipBufPre_clipContextDraw().layoutChannelNo;var a4=this.getChannelFlagAsColor(aY);a0.uniform4f(this.u_channelFlag_Loc_Off,a4.r,a4.g,a4.b,a4.a);a0.uniform4f(this.u_baseColor_Loc_Off,aW,a2,a5,a7);}else{a0.useProgram(this.shaderProgram);this._$vS=T(a0,this._$vS,aU);this._$no=L(a0,this._$no,aL);a0.enableVertexAttribArray(this.a_position_Loc);a0.vertexAttribPointer(this.a_position_Loc,2,a0.FLOAT,false,0,0);this._$NT=T(a0,this._$NT,aV);a0.activeTexture(a0.TEXTURE1);a0.bindTexture(a0.TEXTURE_2D,this.textures[aS]);a0.uniform1i(this.s_texture0_Loc,1);a0.enableVertexAttribArray(this.a_texCoord_Loc);a0.vertexAttribPointer(this.a_texCoord_Loc,2,a0.FLOAT,false,0,0);a0.uniformMatrix4fv(this.u_matrix_Loc,false,this.matrix4x4);a0.uniform4f(this.u_baseColor_Loc,aW,a2,a5,a7);a0.uniform1i(this.u_maskFlag_Loc,false);}}if(this.culling){this.gl.enable(a0.CULL_FACE);}else{this.gl.disable(a0.CULL_FACE);}this.gl.enable(a0.BLEND);var a6;var aX;var aR;var aK;if(this.clipBufPre_clipContextMask!=null){a6=a0.ONE;aX=a0.ONE_MINUS_SRC_ALPHA;aR=a0.ONE;aK=a0.ONE_MINUS_SRC_ALPHA;}else{switch(aM){case b._$ms:a6=a0.ONE;aX=a0.ONE_MINUS_SRC_ALPHA;aR=a0.ONE;aK=a0.ONE_MINUS_SRC_ALPHA;break;case b._$ns:a6=a0.ONE;aX=a0.ONE;aR=a0.ZERO;aK=a0.ONE;break;case b._$_s:a6=a0.DST_COLOR;aX=a0.ONE_MINUS_SRC_ALPHA;aR=a0.ZERO;aK=a0.ONE;break;}}a0.blendEquationSeparate(a0.FUNC_ADD,a0.FUNC_ADD);a0.blendFuncSeparate(a6,aX,aR,aK);if(this.anisotropyExt){a0.texParameteri(a0.TEXTURE_2D,this.anisotropyExt.TEXTURE_MAX_ANISOTROPY_EXT,this.maxAnisotropy);}var aJ=aL.length;a0.drawElements(a0.TRIANGLES,aJ,a0.UNSIGNED_SHORT,0);a0.bindTexture(a0.TEXTURE_2D,null);};function T(aJ,aH,aI){if(aH==null){aH=aJ.createBuffer();}aJ.bindBuffer(aJ.ARRAY_BUFFER,aH);aJ.bufferData(aJ.ARRAY_BUFFER,aI,aJ.DYNAMIC_DRAW);return aH;}function L(aJ,aH,aI){if(aH==null){aH=aJ.createBuffer();}aJ.bindBuffer(aJ.ELEMENT_ARRAY_BUFFER,aH);aJ.bufferData(aJ.ELEMENT_ARRAY_BUFFER,aI,aJ.DYNAMIC_DRAW);return aH;}C.prototype._$Rs=function(){throw new Error("_$Rs");};C.prototype._$Ds=function(aH){throw new Error("_$Ds");};C.prototype._$K2=function(){for(var aH=0;aH<this.textures.length;aH++){var aI=this.textures[aH];if(aI!=0){this.gl._$K2(1,this.textures,aH);this.textures[aH]=null;}}};C.prototype.setTexture=function(aH,aI){this.textures[aH]=aI;};C.prototype.initShader=function(){var aH=this.gl;this.loadShaders2();this.a_position_Loc=aH.getAttribLocation(this.shaderProgram,"a_position");this.a_texCoord_Loc=aH.getAttribLocation(this.shaderProgram,"a_texCoord");this.u_matrix_Loc=aH.getUniformLocation(this.shaderProgram,"u_mvpMatrix");this.s_texture0_Loc=aH.getUniformLocation(this.shaderProgram,"s_texture0");this.u_channelFlag=aH.getUniformLocation(this.shaderProgram,"u_channelFlag");this.u_baseColor_Loc=aH.getUniformLocation(this.shaderProgram,"u_baseColor");this.u_maskFlag_Loc=aH.getUniformLocation(this.shaderProgram,"u_maskFlag");this.a_position_Loc_Off=aH.getAttribLocation(this.shaderProgramOff,"a_position");this.a_texCoord_Loc_Off=aH.getAttribLocation(this.shaderProgramOff,"a_texCoord");this.u_matrix_Loc_Off=aH.getUniformLocation(this.shaderProgramOff,"u_mvpMatrix");this.u_clipMatrix_Loc_Off=aH.getUniformLocation(this.shaderProgramOff,"u_ClipMatrix");this.s_texture0_Loc_Off=aH.getUniformLocation(this.shaderProgramOff,"s_texture0");this.s_texture1_Loc_Off=aH.getUniformLocation(this.shaderProgramOff,"s_texture1");this.u_channelFlag_Loc_Off=aH.getUniformLocation(this.shaderProgramOff,"u_channelFlag");this.u_baseColor_Loc_Off=aH.getUniformLocation(this.shaderProgramOff,"u_baseColor");};C.prototype.disposeShader=function(){var aH=this.gl;if(this.shaderProgram){aH.deleteProgram(this.shaderProgram);this.shaderProgram=null;}if(this.shaderProgramOff){aH.deleteProgram(this.shaderProgramOff);this.shaderProgramOff=null;}};C.prototype.compileShader=function(aJ,aN){var aM=this.gl;var aH;var aL=aN;var aK=aM.createShader(aJ);if(aK==null){q._$Ji("_$L0 to create shader");return null;}aM.shaderSource(aK,aL);aM.compileShader(aK);var aH=aM.getShaderParameter(aK,aM.COMPILE_STATUS);if(!aH){var aI=aM.getShaderInfoLog(aK);q._$Ji("_$L0 to compile shader : "+aI);aM.deleteShader(aK);return null;}return aK;};C.prototype.loadShaders2=function(){var aN=this.gl;this.shaderProgram=aN.createProgram();if(!this.shaderProgram){return false;}this.shaderProgramOff=aN.createProgram();if(!this.shaderProgramOff){return false;}var aK="attribute vec4     a_position;attribute vec2     a_texCoord;varying vec2       v_texCoord;varying vec4       v_ClipPos;uniform mat4       u_mvpMatrix;void main(){    gl_Position = u_mvpMatrix * a_position;    v_ClipPos = u_mvpMatrix * a_position;    v_texCoord = a_texCoord;}";var aM="precision mediump float;varying vec2       v_texCoord;varying vec4       v_ClipPos;uniform sampler2D  s_texture0;uniform vec4       u_channelFlag;uniform vec4       u_baseColor;uniform bool       u_maskFlag;void main(){    vec4 smpColor;     if(u_maskFlag){        float isInside =             step(u_baseColor.x, v_ClipPos.x/v_ClipPos.w)          * step(u_baseColor.y, v_ClipPos.y/v_ClipPos.w)          * step(v_ClipPos.x/v_ClipPos.w, u_baseColor.z)          * step(v_ClipPos.y/v_ClipPos.w, u_baseColor.w);        smpColor = u_channelFlag * texture2D(s_texture0 , v_texCoord).a * isInside;    }else{        smpColor = texture2D(s_texture0 , v_texCoord) * u_baseColor;    }    gl_FragColor = smpColor;}";var aL="attribute vec4     a_position;attribute vec2     a_texCoord;varying vec2       v_texCoord;varying vec4       v_ClipPos;uniform mat4       u_mvpMatrix;uniform mat4       u_ClipMatrix;void main(){    gl_Position = u_mvpMatrix * a_position;    v_ClipPos = u_ClipMatrix * a_position;    v_texCoord = a_texCoord ;}";var aJ="precision mediump float ;varying vec2       v_texCoord;varying vec4       v_ClipPos;uniform sampler2D  s_texture0;uniform sampler2D  s_texture1;uniform vec4       u_channelFlag;uniform vec4       u_baseColor ;void main(){    vec4 col_formask = texture2D(s_texture0, v_texCoord) * u_baseColor;    vec4 clipMask = texture2D(s_texture1, v_ClipPos.xy / v_ClipPos.w) * u_channelFlag;    float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;    col_formask = col_formask * maskVal;    gl_FragColor = col_formask;}";this.vertShader=this.compileShader(aN.VERTEX_SHADER,aK);if(!this.vertShader){q._$Ji("Vertex shader compile _$li!");return false;}this.vertShaderOff=this.compileShader(aN.VERTEX_SHADER,aL);if(!this.vertShaderOff){q._$Ji("OffVertex shader compile _$li!");return false;}this.fragShader=this.compileShader(aN.FRAGMENT_SHADER,aM);if(!this.fragShader){q._$Ji("Fragment shader compile _$li!");return false;}this.fragShaderOff=this.compileShader(aN.FRAGMENT_SHADER,aJ);if(!this.fragShaderOff){q._$Ji("OffFragment shader compile _$li!");return false;}aN.attachShader(this.shaderProgram,this.vertShader);aN.attachShader(this.shaderProgram,this.fragShader);aN.attachShader(this.shaderProgramOff,this.vertShaderOff);aN.attachShader(this.shaderProgramOff,this.fragShaderOff);aN.linkProgram(this.shaderProgram);aN.linkProgram(this.shaderProgramOff);var aH=aN.getProgramParameter(this.shaderProgram,aN.LINK_STATUS);if(!aH){var aI=aN.getProgramInfoLog(this.shaderProgram);q._$Ji("_$L0 to link program: "+aI);if(this.vertShader){aN.deleteShader(this.vertShader);this.vertShader=0;}if(this.fragShader){aN.deleteShader(this.fragShader);this.fragShader=0;}if(this.shaderProgram){aN.deleteProgram(this.shaderProgram);this.shaderProgram=0;}if(this.vertShaderOff){aN.deleteShader(this.vertShaderOff);this.vertShaderOff=0;}if(this.fragShaderOff){aN.deleteShader(this.fragShaderOff);this.fragShaderOff=0;}if(this.shaderProgramOff){aN.deleteProgram(this.shaderProgramOff);this.shaderProgramOff=0;}return false;}return true;};C.prototype.createFramebuffer=function(){var aL=this.gl;var aK=Q.clippingMaskBufferSize;var aJ=aL.createFramebuffer();aL.bindFramebuffer(aL.FRAMEBUFFER,aJ);var aH=aL.createRenderbuffer();aL.bindRenderbuffer(aL.RENDERBUFFER,aH);aL.renderbufferStorage(aL.RENDERBUFFER,aL.RGBA4,aK,aK);aL.framebufferRenderbuffer(aL.FRAMEBUFFER,aL.COLOR_ATTACHMENT0,aL.RENDERBUFFER,aH);var aI=aL.createTexture();aL.bindTexture(aL.TEXTURE_2D,aI);aL.texImage2D(aL.TEXTURE_2D,0,aL.RGBA,aK,aK,0,aL.RGBA,aL.UNSIGNED_BYTE,null);aL.texParameteri(aL.TEXTURE_2D,aL.TEXTURE_MIN_FILTER,aL.LINEAR);aL.texParameteri(aL.TEXTURE_2D,aL.TEXTURE_MAG_FILTER,aL.LINEAR);aL.texParameteri(aL.TEXTURE_2D,aL.TEXTURE_WRAP_S,aL.CLAMP_TO_EDGE);aL.texParameteri(aL.TEXTURE_2D,aL.TEXTURE_WRAP_T,aL.CLAMP_TO_EDGE);aL.framebufferTexture2D(aL.FRAMEBUFFER,aL.COLOR_ATTACHMENT0,aL.TEXTURE_2D,aI,0);aL.bindTexture(aL.TEXTURE_2D,null);aL.bindRenderbuffer(aL.RENDERBUFFER,null);aL.bindFramebuffer(aL.FRAMEBUFFER,null);Q.fTexture[this.glno]=aI;return{framebuffer:aJ,renderbuffer:aH,texture:Q.fTexture[this.glno]};};function K(aH){if(j){return;}this._$P=new Int8Array(8);this._$R0=new DataView(this._$P.buffer);this._$3i=new Int8Array(1000);this._$hL=0;this._$v0=0;this._$S2=0;this._$Ko=new Array();this._$T=aH;this._$F=0;}K.prototype._$fP=function(){var aK=this._$ST();var aJ,aI,aH;if((aK&128)==0){return aK&255;}else{if(((aJ=this._$ST())&128)==0){return((aK&127)<<7)|(aJ&127);}else{if(((aI=this._$ST())&128)==0){return((aK&127)<<14)|((aJ&127)<<7)|(aI&255);}else{if(((aH=this._$ST())&128)==0){return((aK&127)<<21)|((aJ&127)<<14)|((aI&127)<<7)|(aH&255);}else{throw new J("_$L _$0P  _");}}}}};K.prototype.getFormatVersion=function(){return this._$S2;};K.prototype._$gr=function(aH){this._$S2=aH;};K.prototype._$3L=function(){return this._$fP();};K.prototype._$mP=function(){this._$zT();this._$F+=8;return this._$T.getFloat64(this._$F-8);};K.prototype._$_T=function(){this._$zT();this._$F+=4;return this._$T.getFloat32(this._$F-4);};K.prototype._$6L=function(){this._$zT();this._$F+=4;return this._$T.getInt32(this._$F-4);};K.prototype._$ST=function(){this._$zT();return this._$T.getInt8(this._$F++);};K.prototype._$9T=function(){this._$zT();this._$F+=2;return this._$T.getInt16(this._$F-2);};K.prototype._$2T=function(){this._$zT();this._$F+=8;throw new J("_$L _$q read long");};K.prototype._$po=function(){this._$zT();return this._$T.getInt8(this._$F++)!=0;};var O=true;K.prototype._$bT=function(){this._$zT();var aH=this._$3L();var aK=null;if(O){try{var aM=new ArrayBuffer(aH*2);aK=new Uint16Array(aM);for(var aJ=0;aJ<aH;++aJ){aK[aJ]=this._$T.getUint8(this._$F++);}return String.fromCharCode.apply(null,aK);}catch(aL){O=false;}}try{var aI=new Array();if(aK==null){for(var aJ=0;aJ<aH;++aJ){aI[aJ]=this._$T.getUint8(this._$F++);}}else{for(var aJ=0;aJ<aH;++aJ){aI[aJ]=aK[aJ];}}return String.fromCharCode.apply(null,aI);}catch(aL){console.log("read utf8 / _$rT _$L0 !! : "+aL);}};K.prototype._$cS=function(){this._$zT();var aI=this._$3L();var aH=new Int32Array(aI);for(var aJ=0;aJ<aI;aJ++){aH[aJ]=this._$T.getInt32(this._$F);this._$F+=4;}return aH;};K.prototype._$Tb=function(){this._$zT();var aI=this._$3L();var aH=new Float32Array(aI);for(var aJ=0;aJ<aI;aJ++){aH[aJ]=this._$T.getFloat32(this._$F);this._$F+=4;}return aH;};K.prototype._$5b=function(){this._$zT();var aI=this._$3L();var aH=new Float64Array(aI);for(var aJ=0;aJ<aI;aJ++){aH[aJ]=this._$T.getFloat64(this._$F);this._$F+=8;}return aH;};K.prototype._$nP=function(){return this._$Jb(-1);};K.prototype._$Jb=function(aJ){this._$zT();if(aJ<0){aJ=this._$3L();}if(aJ==ay._$7P){var aH=this._$6L();if(0<=aH&&aH<this._$Ko.length){return this._$Ko[aH];}else{throw new J("_$sL _$4i @_$m0");}}else{var aI=this._$4b(aJ);this._$Ko.push(aI);return aI;}};K.prototype._$4b=function(aN){if(aN==0){return null;}if(aN==50){var aK=this._$bT();var aI=Z.getID(aK);return aI;}else{if(aN==51){var aK=this._$bT();var aI=n.getID(aK);return aI;}else{if(aN==134){var aK=this._$bT();var aI=i.getID(aK);return aI;}else{if(aN==60){var aK=this._$bT();var aI=z.getID(aK);return aI;}}}}if(aN>=48){var aL=ay._$9o(aN);if(aL!=null){aL._$F0(this);return aL;}else{return null;}}switch(aN){case 1:return this._$bT();case 10:var aM=this._$6L();return new I(aM,true);case 11:return new av(this._$mP(),this._$mP(),this._$mP(),this._$mP());case 12:return new av(this._$_T(),this._$_T(),this._$_T(),this._$_T());case 13:return new e(this._$mP(),this._$mP());case 14:return new e(this._$_T(),this._$_T());case 15:var aH=this._$3L();var aI=new Array(aH);for(var aJ=0;aJ<aH;aJ++){aI[aJ]=this._$nP();}return aI;case 17:var aI=new aD(this._$mP(),this._$mP(),this._$mP(),this._$mP(),this._$mP(),this._$mP());return aI;case 21:return new F(this._$6L(),this._$6L(),this._$6L(),this._$6L());case 22:return new k(this._$6L(),this._$6L());case 23:throw new Error("_$L _$ro ");case 16:case 25:return this._$cS();case 26:return this._$5b();case 27:return this._$Tb();case 2:case 3:case 4:case 5:case 6:case 7:case 8:case 9:case 18:case 19:case 20:case 24:case 28:throw new J("_$6 _$q : _$nP() of 2-9 ,18,19,20,24,28 : "+aN);default:throw new J("_$6 _$q : _$nP() NO _$i : "+aN);}};K.prototype._$8L=function(){if(this._$hL==0){this._$v0=this._$ST();}else{if(this._$hL==8){this._$v0=this._$ST();this._$hL=0;}}return((this._$v0>>(7-this._$hL++))&1)==1;};K.prototype._$zT=function(){if(this._$hL!=0){this._$hL=0;}};function ai(){}ai.prototype._$wP=function(aM,aI,aK){for(var aL=0;aL<aK;aL++){for(var aH=0;aH<aI;aH++){var aJ=2*(aH+aL*aI);console.log("(% 7.3f , % 7.3f) , ",aM[aJ],aM[aJ+1]);}console.log("\n");}console.log("\n");};function aC(){}aC._$2S=Math.PI/180;aC._$bS=(Math.PI/180);aC._$wS=180/Math.PI;aC._$NS=(180/Math.PI);aC.PI_F=Math.PI;aC._$kT=[0,0.012368,0.024734,0.037097,0.049454,0.061803,0.074143,0.086471,0.098786,0.111087,0.12337,0.135634,0.147877,0.160098,0.172295,0.184465,0.196606,0.208718,0.220798,0.232844,0.244854,0.256827,0.268761,0.280654,0.292503,0.304308,0.316066,0.327776,0.339436,0.351044,0.362598,0.374097,0.385538,0.396921,0.408243,0.419502,0.430697,0.441826,0.452888,0.463881,0.474802,0.485651,0.496425,0.507124,0.517745,0.528287,0.538748,0.549126,0.559421,0.56963,0.579752,0.589785,0.599728,0.609579,0.619337,0.629,0.638567,0.648036,0.657406,0.666676,0.675843,0.684908,0.693867,0.70272,0.711466,0.720103,0.72863,0.737045,0.745348,0.753536,0.76161,0.769566,0.777405,0.785125,0.792725,0.800204,0.807561,0.814793,0.821901,0.828884,0.835739,0.842467,0.849066,0.855535,0.861873,0.868079,0.874153,0.880093,0.885898,0.891567,0.897101,0.902497,0.907754,0.912873,0.917853,0.922692,0.92739,0.931946,0.936359,0.940629,0.944755,0.948737,0.952574,0.956265,0.959809,0.963207,0.966457,0.96956,0.972514,0.97532,0.977976,0.980482,0.982839,0.985045,0.987101,0.989006,0.990759,0.992361,0.993811,0.995109,0.996254,0.997248,0.998088,0.998776,0.999312,0.999694,0.999924,1];aC._$92=function(aK,aI){var aH=Math.atan2(aK[1],aK[0]);var aJ=Math.atan2(aI[1],aI[0]);return aC._$tS(aH,aJ);};aC._$tS=function(aI,aH){var aJ=aI-aH;while(aJ<-Math.PI){aJ+=2*Math.PI;}while(aJ>Math.PI){aJ-=2*Math.PI;}return aJ;};aC._$9=function(aH){return Math.sin(aH);};aC.fcos=function(aH){return Math.cos(aH);};function aB(aH){if(j){return;}this._$e0=null;this._$IP=null;this._$Us=null;this._$7s=null;this._$IS=[false];this._$VS=null;this._$AT=true;this.baseOpacity=1;this.clipBufPre_clipContext=null;this._$e0=aH;}aB.prototype._$u2=function(){return this._$IS[0];};aB.prototype._$yo=function(){return this._$AT&&!this._$IS[0];};aB.prototype._$GT=function(){return this._$e0;};function r(){}r._$W2=0;r.SYSTEM_INFO=null;r.USER_AGENT=navigator.userAgent;r.isIPhone=function(){if(!r.SYSTEM_INFO){r.setup();}return r.SYSTEM_INFO._isIPhone;};r.isIOS=function(){if(!r.SYSTEM_INFO){r.setup();}return r.SYSTEM_INFO._isIPhone||r.SYSTEM_INFO._isIPad;};r.isAndroid=function(){if(!r.SYSTEM_INFO){r.setup();}return r.SYSTEM_INFO._isAndroid;};r.getOSVersion=function(){if(!r.SYSTEM_INFO){r.setup();}return r.SYSTEM_INFO.version;};r.getOS=function(){if(!r.SYSTEM_INFO){r.setup();}if(r.SYSTEM_INFO._isIPhone||r.SYSTEM_INFO._isIPad){return"iOS";}if(r.SYSTEM_INFO._isAndroid){return"Android";}else{return"_$Q0 OS";}};r.setup=function(){var aK=r.USER_AGENT;function aI(aO,aR){var aN=aO.substring(aR).split(/[ _,;\.]/);var aQ=0;for(var aM=0;aM<=2;aM++){if(isNaN(aN[aM])){break;}var aP=parseInt(aN[aM]);if(aP<0||aP>999){q._$li("err : "+aP+" @UtHtml5.setup()");aQ=0;break;}aQ+=aP*Math.pow(1000,(2-aM));}return aQ;}var aL;var aH;var aJ=r.SYSTEM_INFO={userAgent:aK};if((aL=aK.indexOf("iPhone OS "))>=0){aJ.os="iPhone";aJ._isIPhone=true;aJ.version=aI(aK,aL+"iPhone OS ".length);}else{if((aL=aK.indexOf("iPad"))>=0){aL=aK.indexOf("CPU OS");if(aL<0){q._$li(" err : "+aK+" @UtHtml5.setup()");return;}aJ.os="iPad";aJ._isIPad=true;aJ.version=aI(aK,aL+"CPU OS ".length);}else{if((aL=aK.indexOf("Android"))>=0){aJ.os="Android";aJ._isAndroid=true;aJ.version=aI(aK,aL+"Android ".length);}else{aJ.os="-";aJ.version=-1;}}}};window.UtSystem=P;window.UtDebug=q;window.LDTransform=am;window.LDGL=au;window.Live2D=Q;window.Live2DModelWebGL=l;window.Live2DModelJS=v;window.Live2DMotion=ao;window.MotionQueueManager=V;window.PhysicsHair=u;window.AMotion=ah;window.PartsDataID=i;window.DrawDataID=Z;window.BaseDataID=n;window.ParamID=z;Q.init();var j=false;})();
\ No newline at end of file
diff --git a/bins/ayaka-gui/public/live2dcubismcore.min.js b/bins/ayaka-gui/public/live2dcubismcore.min.js
new file mode 100644
index 00000000..805594d3
--- /dev/null
+++ b/bins/ayaka-gui/public/live2dcubismcore.min.js
@@ -0,0 +1,9 @@
+/**
+ * Live2D Cubism Core
+ * (C) 2019 Live2D Inc. All rights reserved.
+ *
+ * This file is licensed pursuant to the license agreement below.
+ * This file corresponds to the "Redistributable Code" in the agreement.
+ * https://www.live2d.com/eula/live2d-proprietary-software-license-agreement_en.html
+ */
+var Live2DCubismCore;!function(Live2DCubismCore){var _csm=function(){function _csm(){}return _csm.getVersion=function(){return _em.ccall("csmGetVersion","number",[],[])},_csm.getLatestMocVersion=function(){return _em.ccall("csmGetLatestMocVersion","number",[],[])},_csm.getMocVersion=function(moc,mocSize){return _em.ccall("csmGetMocVersion","number",["number","number"],[moc,mocSize])},_csm.getSizeofModel=function(moc){return _em.ccall("csmGetSizeofModel","number",["number"],[moc])},_csm.reviveMocInPlace=function(memory,mocSize){return _em.ccall("csmReviveMocInPlace","number",["number","number"],[memory,mocSize])},_csm.initializeModelInPlace=function(moc,memory,modelSize){return _em.ccall("csmInitializeModelInPlace","number",["number","number","number"],[moc,memory,modelSize])},_csm.getParameterCount=function(model){return _em.ccall("csmGetParameterCount","number",["number"],[model])},_csm.getParameterIds=function(model){return _em.ccall("csmGetParameterIds","number",["number"],[model])},_csm.getParameterMinimumValues=function(model){return _em.ccall("csmGetParameterMinimumValues","number",["number"],[model])},_csm.getParameterTypes=function(model){return _em.ccall("csmGetParameterTypes","number",["number"],[model])},_csm.getParameterMaximumValues=function(model){return _em.ccall("csmGetParameterMaximumValues","number",["number"],[model])},_csm.getParameterDefaultValues=function(model){return _em.ccall("csmGetParameterDefaultValues","number",["number"],[model])},_csm.getParameterValues=function(model){return _em.ccall("csmGetParameterValues","number",["number"],[model])},_csm.getParameterKeyCounts=function(model){return _em.ccall("csmGetParameterKeyCounts","number",["number"],[model])},_csm.getParameterKeyValues=function(model){return _em.ccall("csmGetParameterKeyValues","number",["number"],[model])},_csm.getPartCount=function(model){return _em.ccall("csmGetPartCount","number",["number"],[model])},_csm.getPartIds=function(model){return _em.ccall("csmGetPartIds","number",["number"],[model])},_csm.getPartOpacities=function(model){return _em.ccall("csmGetPartOpacities","number",["number"],[model])},_csm.getPartParentPartIndices=function(model){return _em.ccall("csmGetPartParentPartIndices","number",["number"],[model])},_csm.getDrawableCount=function(model){return _em.ccall("csmGetDrawableCount","number",["number"],[model])},_csm.getDrawableIds=function(model){return _em.ccall("csmGetDrawableIds","number",["number"],[model])},_csm.getDrawableConstantFlags=function(model){return _em.ccall("csmGetDrawableConstantFlags","number",["number"],[model])},_csm.getDrawableDynamicFlags=function(model){return _em.ccall("csmGetDrawableDynamicFlags","number",["number"],[model])},_csm.getDrawableTextureIndices=function(model){return _em.ccall("csmGetDrawableTextureIndices","number",["number"],[model])},_csm.getDrawableDrawOrders=function(model){return _em.ccall("csmGetDrawableDrawOrders","number",["number"],[model])},_csm.getDrawableRenderOrders=function(model){return _em.ccall("csmGetDrawableRenderOrders","number",["number"],[model])},_csm.getDrawableOpacities=function(model){return _em.ccall("csmGetDrawableOpacities","number",["number"],[model])},_csm.getDrawableMaskCounts=function(model){return _em.ccall("csmGetDrawableMaskCounts","number",["number"],[model])},_csm.getDrawableMasks=function(model){return _em.ccall("csmGetDrawableMasks","number",["number"],[model])},_csm.getDrawableVertexCounts=function(model){return _em.ccall("csmGetDrawableVertexCounts","number",["number"],[model])},_csm.getDrawableVertexPositions=function(model){return _em.ccall("csmGetDrawableVertexPositions","number",["number"],[model])},_csm.getDrawableVertexUvs=function(model){return _em.ccall("csmGetDrawableVertexUvs","number",["number"],[model])},_csm.getDrawableIndexCounts=function(model){return _em.ccall("csmGetDrawableIndexCounts","number",["number"],[model])},_csm.getDrawableIndices=function(model){return _em.ccall("csmGetDrawableIndices","number",["number"],[model])},_csm.getDrawableMultiplyColors=function(model){return _em.ccall("csmGetDrawableMultiplyColors","number",["number"],[model])},_csm.getDrawableScreenColors=function(model){return _em.ccall("csmGetDrawableScreenColors","number",["number"],[model])},_csm.getDrawableParentPartIndices=function(model){return _em.ccall("csmGetDrawableParentPartIndices","number",["number"],[model])},_csm.mallocMoc=function(mocSize){return _em.ccall("csmMallocMoc","number",["number"],[mocSize])},_csm.mallocModelAndInitialize=function(moc){return _em.ccall("csmMallocModelAndInitialize","number",["number"],[moc])},_csm.malloc=function(size){return _em.ccall("csmMalloc","number",["number"],[size])},_csm.setLogFunction=function(handler){_em.ccall("csmSetLogFunction",null,["number"],[handler])},_csm.updateModel=function(model){_em.ccall("csmUpdateModel",null,["number"],[model])},_csm.readCanvasInfo=function(model,outSizeInPixels,outOriginInPixels,outPixelsPerUnit){_em.ccall("csmReadCanvasInfo",null,["number","number","number","number"],[model,outSizeInPixels,outOriginInPixels,outPixelsPerUnit])},_csm.resetDrawableDynamicFlags=function(model){_em.ccall("csmResetDrawableDynamicFlags",null,["number"],[model])},_csm.free=function(memory){_em.ccall("csmFree",null,["number"],[memory])},_csm}();Live2DCubismCore.AlignofMoc=64,Live2DCubismCore.AlignofModel=16,Live2DCubismCore.MocVersion_Unknown=0,Live2DCubismCore.MocVersion_30=1,Live2DCubismCore.MocVersion_33=2,Live2DCubismCore.MocVersion_40=3,Live2DCubismCore.MocVersion_42=4,Live2DCubismCore.ParameterType_Normal=0,Live2DCubismCore.ParameterType_BlendShape=1;var Utils=function(){function Version(){}return Version.csmGetVersion=function(){return _csm.getVersion()},Version.csmGetLatestMocVersion=function(){return _csm.getLatestMocVersion()},Version.csmGetMocVersion=function(moc){return _csm.getMocVersion(moc._ptr)},Version}();Live2DCubismCore.Version=Utils;Utils=function(){function Logging(){}return Logging.csmSetLogFunction=function(pointer){Logging.logFunction=pointer;pointer=_em.addFunction(Logging.wrapLogFunction,"vi");_csm.setLogFunction(pointer)},Logging.csmGetLogFunction=function(){return Logging.logFunction},Logging.wrapLogFunction=function(messageStr){messageStr=_em.UTF8ToString(messageStr);Logging.logFunction(messageStr)},Logging}();Live2DCubismCore.Logging=Utils;Utils=function(){function Moc(mocBytes){var memory=_csm.mallocMoc(mocBytes.byteLength);memory&&(new Uint8Array(_em.HEAPU8.buffer,memory,mocBytes.byteLength).set(new Uint8Array(mocBytes)),this._ptr=_csm.reviveMocInPlace(memory,mocBytes.byteLength),this._ptr||_csm.free(memory))}return Moc.fromArrayBuffer=function(moc){if(!moc)return null;moc=new Moc(moc);return moc._ptr?moc:null},Moc.prototype._release=function(){_csm.free(this._ptr),this._ptr=0},Moc}();Live2DCubismCore.Moc=Utils;Utils=function(){function Model(moc){this._ptr=_csm.mallocModelAndInitialize(moc._ptr),this._ptr&&(this.parameters=new Parameters(this._ptr),this.parts=new Parts(this._ptr),this.drawables=new Drawables(this._ptr),this.canvasinfo=new CanvasInfo(this._ptr))}return Model.fromMoc=function(model){model=new Model(model);return model._ptr?model:null},Model.prototype.update=function(){_csm.updateModel(this._ptr)},Model.prototype.release=function(){_csm.free(this._ptr),this._ptr=0},Model}();Live2DCubismCore.Model=Utils;var CanvasInfo=function(modelPtr){var _canvasSize_data,_canvasSize_dataHeap,_canvasOrigin_data,_canvasOrigin_dataHeap,_canvasPPU_data,_canvasPPU_dataPtr,_canvasPPU_dataHeap;modelPtr&&(_canvasPPU_data=(_canvasSize_data=new Float32Array(2)).length*_canvasSize_data.BYTES_PER_ELEMENT,_canvasOrigin_dataHeap=_csm.malloc(_canvasPPU_data),(_canvasSize_dataHeap=new Uint8Array(_em.HEAPU8.buffer,_canvasOrigin_dataHeap,_canvasPPU_data)).set(new Uint8Array(_canvasSize_data.buffer)),_canvasPPU_dataPtr=(_canvasOrigin_data=new Float32Array(2)).length*_canvasOrigin_data.BYTES_PER_ELEMENT,_canvasPPU_dataHeap=_csm.malloc(_canvasPPU_dataPtr),(_canvasOrigin_dataHeap=new Uint8Array(_em.HEAPU8.buffer,_canvasPPU_dataHeap,_canvasPPU_dataPtr)).set(new Uint8Array(_canvasOrigin_data.buffer)),_canvasPPU_dataHeap=(_canvasPPU_data=new Float32Array(1)).length*_canvasPPU_data.BYTES_PER_ELEMENT,_canvasPPU_dataPtr=_csm.malloc(_canvasPPU_dataHeap),(_canvasPPU_dataHeap=new Uint8Array(_em.HEAPU8.buffer,_canvasPPU_dataPtr,_canvasPPU_dataHeap)).set(new Uint8Array(_canvasPPU_data.buffer)),_csm.readCanvasInfo(modelPtr,_canvasSize_dataHeap.byteOffset,_canvasOrigin_dataHeap.byteOffset,_canvasPPU_dataHeap.byteOffset),_canvasSize_data=new Float32Array(_canvasSize_dataHeap.buffer,_canvasSize_dataHeap.byteOffset,_canvasSize_dataHeap.length),_canvasOrigin_data=new Float32Array(_canvasOrigin_dataHeap.buffer,_canvasOrigin_dataHeap.byteOffset,_canvasOrigin_dataHeap.length),_canvasPPU_data=new Float32Array(_canvasPPU_dataHeap.buffer,_canvasPPU_dataHeap.byteOffset,_canvasPPU_dataHeap.length),this.CanvasWidth=_canvasSize_data[0],this.CanvasHeight=_canvasSize_data[1],this.CanvasOriginX=_canvasOrigin_data[0],this.CanvasOriginY=_canvasOrigin_data[1],this.PixelsPerUnit=_canvasPPU_data[0],_csm.free(_canvasSize_dataHeap.byteOffset),_csm.free(_canvasOrigin_dataHeap.byteOffset),_csm.free(_canvasPPU_dataHeap.byteOffset))};Live2DCubismCore.CanvasInfo=CanvasInfo;var Parameters=function(modelPtr){var length,length2;this.count=_csm.getParameterCount(modelPtr),length=_csm.getParameterCount(modelPtr),this.ids=new Array(length);for(var _ids=new Uint32Array(_em.HEAPU32.buffer,_csm.getParameterIds(modelPtr),length),i=0;i<_ids.length;i++)this.ids[i]=_em.UTF8ToString(_ids[i]);length=_csm.getParameterCount(modelPtr),this.minimumValues=new Float32Array(_em.HEAPF32.buffer,_csm.getParameterMinimumValues(modelPtr),length),length=_csm.getParameterCount(modelPtr),this.types=new Int32Array(_em.HEAP32.buffer,_csm.getParameterTypes(modelPtr),length),length=_csm.getParameterCount(modelPtr),this.maximumValues=new Float32Array(_em.HEAPF32.buffer,_csm.getParameterMaximumValues(modelPtr),length),length=_csm.getParameterCount(modelPtr),this.defaultValues=new Float32Array(_em.HEAPF32.buffer,_csm.getParameterDefaultValues(modelPtr),length),length=_csm.getParameterCount(modelPtr),this.values=new Float32Array(_em.HEAPF32.buffer,_csm.getParameterValues(modelPtr),length),length=_csm.getParameterCount(modelPtr),this.keyCounts=new Int32Array(_em.HEAP32.buffer,_csm.getParameterKeyCounts(modelPtr),length),length=_csm.getParameterCount(modelPtr),length2=new Int32Array(_em.HEAP32.buffer,_csm.getParameterKeyCounts(modelPtr),length),this.keyValues=new Array(length);for(var _keyValues=new Uint32Array(_em.HEAPU32.buffer,_csm.getParameterKeyValues(modelPtr),length),i=0;i<_keyValues.length;i++)this.keyValues[i]=new Float32Array(_em.HEAPF32.buffer,_keyValues[i],length2[i])};Live2DCubismCore.Parameters=Parameters;var Parts=function(modelPtr){var length;this.count=_csm.getPartCount(modelPtr),length=_csm.getPartCount(modelPtr),this.ids=new Array(length);for(var _ids=new Uint32Array(_em.HEAPU32.buffer,_csm.getPartIds(modelPtr),length),i=0;i<_ids.length;i++)this.ids[i]=_em.UTF8ToString(_ids[i]);length=_csm.getPartCount(modelPtr),this.opacities=new Float32Array(_em.HEAPF32.buffer,_csm.getPartOpacities(modelPtr),length),length=_csm.getPartCount(modelPtr),this.parentIndices=new Int32Array(_em.HEAP32.buffer,_csm.getPartParentPartIndices(modelPtr),length)};Live2DCubismCore.Parts=Parts;var Drawables=function(){function Drawables(modelPtr){this._modelPtr=modelPtr;var length,length2=null;this.count=_csm.getDrawableCount(modelPtr),length=_csm.getDrawableCount(modelPtr),this.ids=new Array(length);for(var _ids=new Uint32Array(_em.HEAPU32.buffer,_csm.getDrawableIds(modelPtr),length),i=0;i<_ids.length;i++)this.ids[i]=_em.UTF8ToString(_ids[i]);length=_csm.getDrawableCount(modelPtr),this.constantFlags=new Uint8Array(_em.HEAPU8.buffer,_csm.getDrawableConstantFlags(modelPtr),length),length=_csm.getDrawableCount(modelPtr),this.dynamicFlags=new Uint8Array(_em.HEAPU8.buffer,_csm.getDrawableDynamicFlags(modelPtr),length),length=_csm.getDrawableCount(modelPtr),this.textureIndices=new Int32Array(_em.HEAP32.buffer,_csm.getDrawableTextureIndices(modelPtr),length),length=_csm.getDrawableCount(modelPtr),this.drawOrders=new Int32Array(_em.HEAP32.buffer,_csm.getDrawableDrawOrders(modelPtr),length),length=_csm.getDrawableCount(modelPtr),this.renderOrders=new Int32Array(_em.HEAP32.buffer,_csm.getDrawableRenderOrders(modelPtr),length),length=_csm.getDrawableCount(modelPtr),this.opacities=new Float32Array(_em.HEAPF32.buffer,_csm.getDrawableOpacities(modelPtr),length),length=_csm.getDrawableCount(modelPtr),this.maskCounts=new Int32Array(_em.HEAP32.buffer,_csm.getDrawableMaskCounts(modelPtr),length),length=_csm.getDrawableCount(modelPtr),this.vertexCounts=new Int32Array(_em.HEAP32.buffer,_csm.getDrawableVertexCounts(modelPtr),length),length=_csm.getDrawableCount(modelPtr),this.indexCounts=new Int32Array(_em.HEAP32.buffer,_csm.getDrawableIndexCounts(modelPtr),length),length=_csm.getDrawableCount(modelPtr),this.multiplyColors=new Float32Array(_em.HEAPF32.buffer,_csm.getDrawableMultiplyColors(modelPtr),4*length),length=_csm.getDrawableCount(modelPtr),this.screenColors=new Float32Array(_em.HEAPF32.buffer,_csm.getDrawableScreenColors(modelPtr),4*length),length=_csm.getDrawableCount(modelPtr),this.parentPartIndices=new Int32Array(_em.HEAP32.buffer,_csm.getDrawableParentPartIndices(modelPtr),length),length=_csm.getDrawableCount(modelPtr),length2=new Int32Array(_em.HEAP32.buffer,_csm.getDrawableMaskCounts(modelPtr),length),this.masks=new Array(length);for(var _masks=new Uint32Array(_em.HEAPU32.buffer,_csm.getDrawableMasks(modelPtr),length),i=0;i<_masks.length;i++)this.masks[i]=new Int32Array(_em.HEAP32.buffer,_masks[i],length2[i]);length=_csm.getDrawableCount(modelPtr),length2=new Int32Array(_em.HEAP32.buffer,_csm.getDrawableVertexCounts(modelPtr),length),this.vertexPositions=new Array(length);for(var _vertexPositions=new Uint32Array(_em.HEAPU32.buffer,_csm.getDrawableVertexPositions(modelPtr),length),i=0;i<_vertexPositions.length;i++)this.vertexPositions[i]=new Float32Array(_em.HEAPF32.buffer,_vertexPositions[i],2*length2[i]);length=_csm.getDrawableCount(modelPtr),length2=new Int32Array(_em.HEAP32.buffer,_csm.getDrawableVertexCounts(modelPtr),length),this.vertexUvs=new Array(length);for(var _vertexUvs=new Uint32Array(_em.HEAPU32.buffer,_csm.getDrawableVertexUvs(modelPtr),length),i=0;i<_vertexUvs.length;i++)this.vertexUvs[i]=new Float32Array(_em.HEAPF32.buffer,_vertexUvs[i],2*length2[i]);length=_csm.getDrawableCount(modelPtr),length2=new Int32Array(_em.HEAP32.buffer,_csm.getDrawableIndexCounts(modelPtr),length),this.indices=new Array(length);for(var _indices=new Uint32Array(_em.HEAPU32.buffer,_csm.getDrawableIndices(modelPtr),length),i=0;i<_indices.length;i++)this.indices[i]=new Uint16Array(_em.HEAPU16.buffer,_indices[i],length2[i])}return Drawables.prototype.resetDynamicFlags=function(){_csm.resetDrawableDynamicFlags(this._modelPtr)},Drawables}();Live2DCubismCore.Drawables=Drawables;Utils=function(){function Utils(){}return Utils.hasBlendAdditiveBit=function(bitfield){return 1==(1&bitfield)},Utils.hasBlendMultiplicativeBit=function(bitfield){return 2==(2&bitfield)},Utils.hasIsDoubleSidedBit=function(bitfield){return 4==(4&bitfield)},Utils.hasIsInvertedMaskBit=function(bitfield){return 8==(8&bitfield)},Utils.hasIsVisibleBit=function(bitfield){return 1==(1&bitfield)},Utils.hasVisibilityDidChangeBit=function(bitfield){return 2==(2&bitfield)},Utils.hasOpacityDidChangeBit=function(bitfield){return 4==(4&bitfield)},Utils.hasDrawOrderDidChangeBit=function(bitfield){return 8==(8&bitfield)},Utils.hasRenderOrderDidChangeBit=function(bitfield){return 16==(16&bitfield)},Utils.hasVertexPositionsDidChangeBit=function(bitfield){return 32==(32&bitfield)},Utils.hasBlendColorDidChangeBit=function(bitfield){return 64==(64&bitfield)},Utils}();Live2DCubismCore.Utils=Utils;var _scriptDir,_em_module=(_scriptDir="undefined"!=typeof document&&document.currentScript?document.currentScript.src:void 0,function(_em_module){_em_module=_em_module||{};var b,m,e={};for(m in b=b||(void 0!==_em_module?_em_module:{}))b.hasOwnProperty(m)&&(e[m]=b[m]);var w,z,A,v,x,Aa=!1,r=!1,n="object"==typeof window,Aa="function"==typeof importScripts,r="object"==typeof process&&"object"==typeof process.versions&&"string"==typeof process.versions.node&&!n&&!Aa,t=!n&&!r&&!Aa,u="";r?(u=__dirname+"/",v=function(a,c){var d=B(a);return d||(z=z||require("fs"),a=(A=A||require("path")).normalize(a),d=z.readFileSync(a)),c?d:d.toString()},x=function(a){return assert((a=(a=v(a,!0)).buffer?a:new Uint8Array(a)).buffer),a},1<process.argv.length&&process.argv[1].replace(/\\/g,"/"),process.argv.slice(2),process.on("uncaughtException",function(a){throw a}),process.on("unhandledRejection",C),b.inspect=function(){return"[Emscripten Module object]"}):t?("undefined"!=typeof read&&(v=function(a){var c=B(a);return c?D(c):read(a)}),x=function(a){var c;return(c=B(a))?c:"function"==typeof readbuffer?new Uint8Array(readbuffer(a)):(assert("object"==typeof(c=read(a,"binary"))),c)},"undefined"!=typeof print&&("undefined"==typeof console&&(console={}),console.log=print,console.warn=console.error="undefined"!=typeof printErr?printErr:print)):(n||Aa)&&(Aa?u=self.location.href:document.currentScript&&(u=document.currentScript.src),u=0!==(u=_scriptDir||u).indexOf("blob:")?u.substr(0,u.lastIndexOf("/")+1):"",v=function(a){try{var c=new XMLHttpRequest;return c.open("GET",a,!1),c.send(null),c.responseText}catch(d){if(a=B(a))return D(a);throw d}},Aa&&(x=function(a){try{var c=new XMLHttpRequest;return c.open("GET",a,!1),c.responseType="arraybuffer",c.send(null),new Uint8Array(c.response)}catch(d){if(a=B(a))return a;throw d}}),w=function(a){var c=E,d=F,f=new XMLHttpRequest;f.open("GET",c,!0),f.responseType="arraybuffer",f.onload=function(){var g;200==f.status||0==f.status&&f.response?d(f.response):(g=B(c))?d(g.buffer):a()},f.onerror=a,f.send(null)});var G=b.print||console.log.bind(console),H=b.printErr||console.warn.bind(console);for(m in e)e.hasOwnProperty(m)&&(b[m]=e[m]);var e=null,I=Array(1),J=0,K=!1;function assert(a,c){a||C("Assertion failed: "+c)}var buffer,N,M,O,L="undefined"!=typeof TextDecoder?new TextDecoder("utf8"):void 0;function ca(a,c,d){var f=c+d;for(d=c;a[d]&&!(f<=d);)++d;if(16<d-c&&a.subarray&&L)return L.decode(a.subarray(c,d));for(f="";c<d;){var h,p,g=a[c++];128&g?(h=63&a[c++],192==(224&g)?f+=String.fromCharCode((31&g)<<6|h):(p=63&a[c++],(g=224==(240&g)?(15&g)<<12|h<<6|p:(7&g)<<18|h<<12|p<<6|63&a[c++])<65536?f+=String.fromCharCode(g):(g-=65536,f+=String.fromCharCode(55296|g>>10,56320|1023&g)))):f+=String.fromCharCode(g)}return f}function da(a,c){return a?ca(M,a,c):""}function ea(a){return 0<a%16777216&&(a+=16777216-a%16777216),a}function fa(a){buffer=a,b.HEAP8=N=new Int8Array(a),b.HEAP16=new Int16Array(a),b.HEAP32=O=new Int32Array(a),b.HEAPU8=M=new Uint8Array(a),b.HEAPU16=new Uint16Array(a),b.HEAPU32=new Uint32Array(a),b.HEAPF32=new Float32Array(a),b.HEAPF64=new Float64Array(a)}function P(a){for(;0<a.length;){var d,c=a.shift();"function"==typeof c?c():"number"==typeof(d=c.C)?void 0===c.w?b.dynCall_v(d):b.dynCall_vi(d,c.w):d(void 0===c.w?null:c.w)}}"undefined"!=typeof TextDecoder&&new TextDecoder("utf-16le"),Aa=b.TOTAL_MEMORY||16777216,Aa=(buffer=b.buffer||new ArrayBuffer(Aa)).byteLength,fa(buffer),O[1052]=5247296;var ia=[],ja=[],ka=[],la=[];Math.imul&&-5===Math.imul(4294967295,5)||(Math.imul=function(a,c){var d=65535&a,f=65535&c;return d*f+((a>>>16)*f+d*(c>>>16)<<16)|0}),Math.clz32||(Math.clz32=function(a){var c=32,d=a>>16;return d&&(c-=16,a=d),(d=a>>8)&&(c-=8,a=d),(d=a>>4)&&(c-=4,a=d),(d=a>>2)&&(c-=2,a=d),a>>1?c-2:c-a}),Math.trunc||(Math.trunc=function(a){return a<0?Math.ceil(a):Math.floor(a)});var Q=0,S=null,T=null;function C(a){throw b.onAbort&&b.onAbort(a),G(a),H(a),K=!0,"abort("+a+"). Build with -s ASSERTIONS=1 for more info."}b.preloadedImages={},b.preloadedAudios={};var E=null,U="data:application/octet-stream;base64,";function na(a){return a.replace(/\b__Z[\w\d_]+/g,function(a){return a==a?a:a+" ["+a+"]"})}function oa(){var a=Error();if(!a.stack){try{throw Error(0)}catch(c){a=c}if(!a.stack)return"(no stack trace available)"}return a.stack.toString()}var V=[null,[],[]];function W(a,c){var d=V[a];0===c||10===c?((1===a?G:H)(ca(d,0)),d.length=0):d.push(c)}function pa(a,c,d,f){try{for(var g=0,h=0;h<d;h++){for(var p=O[c+8*h>>2],k=O[c+(8*h+4)>>2],y=0;y<k;y++)W(a,M[p+y]);g+=k}return O[f>>2]=g,0}catch(R){return"undefined"!=typeof FS&&R instanceof FS.A||C(R),R.B}}function qa(){return N.length}function ra(a){try{var c=new ArrayBuffer(a);if(c.byteLength==a)return new Int8Array(c).set(N),sa(c),fa(c),1}catch(d){}}var ta=!(E="data:application/octet-stream;base64,AAAAAAAAAAARAAoAERERAAAAAAUAAAAAAAAJAAAAAAsAAAAAAAAAABEADwoREREDCgcAARMJCwsAAAkGCwAACwAGEQAAABEREQAAAAAAAAAAAAAAAAAAAAALAAAAAAAAAAARAAoKERERAAoAAAIACQsAAAAJAAsAAAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAADAAAAAAMAAAAAAkMAAAAAAAMAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAA0AAAAEDQAAAAAJDgAAAAAADgAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAPAAAAAA8AAAAACRAAAAAAABAAABAAABIAAAASEhIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAABISEgAAAAAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAAAAAAAAoAAAAACgAAAAAJCwAAAAAACwAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAwAAAAACQwAAAAAAAwAAAwAADAxMjM0NTY3ODlBQkNERUYFAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAgAAABgKAAAABAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAK/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBbiBlcnJvciBvY2N1cnJlZCBpbiB0aGUgaW50ZXJwb2xhdGlvbiBmb3IgYmxlbmQgc2hhcGVzLiBDb21iaW5hdGlvbkNvdW50IGlzICVkLgBbQ1NNXSBbRV1XYXJwRGVmb3JtZXI6OlRyYW5zZm9ybVRhcmdldCgpIGVycm9yLiBbJWRdIHAwMT0oJS40ZiAsICUuNGYpCgBbQ1NNXSBbRV1Jbml0aWFsaXplRGVmb3JtZXJzKCk6IFVua25vd24gRGVmb3JtZXIgVHlwZS4KAExpdmUyRCBDdWJpc20gU0RLIENvcmUgVmVyc2lvbiAlZC4lZC4lZABNT0MzAFtDU01dIFtFXWNzbVJldml2ZU1vY0luUGxhY2UgaXMgZmFpbGVkLiBDb3JydXB0ZWQgIG1vYzMgZmlsZS4KAFtDU01dIFtFXWNzbVJldml2ZU1vY0luUGxhY2UgaXMgZmFpbGVkLiBUaGUgQ29yZSB1bnN1cHBvcnQgbGF0ZXIgdGhhbiBtb2MzIHZlcjpbJWRdLiBUaGlzIG1vYzMgdmVyIGlzIFslZF0uCgBbQ1NNXSBbRV1jc21HZXRNb2NWZXJzaW9uIGlzIGZhaWxlZC4gQ29ycnVwdGVkIG1vYzMgZmlsZS4KAFtDU01dIFtFXSVzOiAlcwoAY3NtR2V0TW9jVmVyc2lvbgAiYWRkcmVzcyIgaXMgbnVsbC4AY3NtUmV2aXZlTW9jSW5QbGFjZQAiYWRkcmVzcyIgYWxpZ25tZW50IGlzIGludmFsaWQuACJzaXplIiBpcyBpbnZhbGlkLgBjc21SZWFkQ2FudmFzSW5mbwAibW9kZWwiIGlzIGludmFsaWQuACJvdXRTaXplSW5QaXhlbHMiIGlzIG51bGwuACJvdXRPcmlnaW5JblBpeGVscyIgaXMgbnVsbC4AIm91dFBpeGVsc1BlclVuaXQiIGlzIG51bGwuAGNzbUdldFNpemVvZk1vZGVsACJtb2MiIGlzIGludmFsaWQuAGNzbUluaXRpYWxpemVNb2RlbEluUGxhY2UAInNpemUiIGlzIGludmFsaWQAY3NtVXBkYXRlTW9kZWwAY3NtR2V0UGFyYW1ldGVyQ291bnQAY3NtR2V0UGFyYW1ldGVySWRzAGNzbUdldFBhcmFtZXRlclR5cGVzAGNzbUdldFBhcmFtZXRlck1pbmltdW1WYWx1ZXMAY3NtR2V0UGFyYW1ldGVyTWF4aW11bVZhbHVlcwBjc21HZXRQYXJhbWV0ZXJEZWZhdWx0VmFsdWVzAGNzbUdldFBhcmFtZXRlclZhbHVlcwBjc21HZXRQYXJ0Q291bnQAY3NtR2V0UGFydElkcwBjc21HZXRQYXJ0T3BhY2l0aWVzAGNzbUdldFBhcnRQYXJlbnRQYXJ0SW5kaWNlcwBjc21HZXREcmF3YWJsZUNvdW50AGNzbUdldERyYXdhYmxlSWRzAGNzbUdldERyYXdhYmxlQ29uc3RhbnRGbGFncwBjc21HZXREcmF3YWJsZUR5bmFtaWNGbGFncwBjc21HZXREcmF3YWJsZVRleHR1cmVJbmRpY2VzAGNzbUdldERyYXdhYmxlRHJhd09yZGVycwBjc21HZXREcmF3YWJsZVJlbmRlck9yZGVycwBjc21HZXREcmF3YWJsZU9wYWNpdGllcwBjc21HZXREcmF3YWJsZU1hc2tDb3VudHMAY3NtR2V0RHJhd2FibGVNYXNrcwBjc21HZXREcmF3YWJsZVZlcnRleENvdW50cwBjc21HZXREcmF3YWJsZVZlcnRleFBvc2l0aW9ucwBjc21HZXREcmF3YWJsZVZlcnRleFV2cwBjc21HZXREcmF3YWJsZUluZGV4Q291bnRzAGNzbUdldERyYXdhYmxlSW5kaWNlcwBjc21HZXREcmF3YWJsZU11bHRpcGx5Q29sb3JzAGNzbUdldERyYXdhYmxlU2NyZWVuQ29sb3JzAGNzbUdldERyYXdhYmxlUGFyZW50UGFydEluZGljZXMAY3NtUmVzZXREcmF3YWJsZUR5bmFtaWNGbGFncwBjc21HZXRQYXJhbWV0ZXJLZXlDb3VudHMAY3NtR2V0UGFyYW1ldGVyS2V5VmFsdWVzAFtDU01dIFtXXVJvdGF0aW9uRGVmb3JtZXI6IE5vdCBmb3VuZCB0cmFuc2Zvcm1lZCBEaXJlY3Rpb24uCgBbQ1NNXSBbRV1VcGRhdGVEZWZvcm1lckhpZXJhcmNoeSgpOiBVbmtub3duIERlZm9ybWVyIFR5cGUuCgAlcwoALSsgICAwWDB4AChudWxsKQAtMFgrMFggMFgtMHgrMHggMHgAaW5mAElORgBuYW4ATkFOAC4=");function D(a){for(var c=[],d=0;d<a.length;d++){var f=a[d];255<f&&(ta&&assert(!1,"Character code "+f+" ("+String.fromCharCode(f)+")  at offset "+d+" not in 0x00-0xFF."),f&=255),c.push(String.fromCharCode(f))}return c.join("")}var ua="function"==typeof atob?atob:function(a){var c="",d=0;a=a.replace(/[^A-Za-z0-9\+\/=]/g,"");do{var f="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(a.charAt(d++)),g="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(a.charAt(d++)),h="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(a.charAt(d++)),p="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(a.charAt(d++)),f=f<<2|g>>4,g=(15&g)<<4|h>>2,k=(3&h)<<6|p}while(c+=String.fromCharCode(f),64!==h&&(c+=String.fromCharCode(g)),64!==p&&(c+=String.fromCharCode(k)),d<a.length);return c};function B(a){if(String.prototype.startsWith?a.startsWith(U):0===a.indexOf(U)){if(a=a.slice(U.length),"boolean"==typeof r&&r){try{var c=Buffer.from(a,"base64")}catch(h){c=new Buffer(a,"base64")}var d=new Uint8Array(c.buffer,c.byteOffset,c.byteLength)}else try{for(var f=ua(a),g=new Uint8Array(f.length),c=0;c<f.length;++c)g[c]=f.charCodeAt(c);d=g}catch(h){throw Error("Converting base64 string to bytes failed.")}return d}}Aa=function(global,env,buffer){var a=new global.Int8Array(buffer),b=new global.Int16Array(buffer),c=new global.Int32Array(buffer),d=new global.Uint8Array(buffer),e=new global.Uint16Array(buffer),f=new global.Float32Array(buffer),g=new global.Float64Array(buffer),h=0|env.v,q=global.Math.floor,r=global.Math.pow,s=global.Math.cos,t=global.Math.sin,u=global.Math.atan2,v=global.Math.imul,w=global.Math.clz32,x=env.a,y=env.b,z=env.c,A=env.d,B=env.e,C=env.f,D=env.g,E=env.h,F=env.i,G=env.j,H=env.k,I=env.l,J=env.m,S=4416;function ea(a){var b,d,g,h,i,j,n,o,p,q,r,s,t,u,v,w,x,y,m,k=0,l=0;if(!((0|(m=0|c[500+(a|=0)>>2]))<=0)){n=0|c[a+504>>2],o=0|c[a+444>>2],d=0|c[a+536>>2],l=0;do{if(g=0|c[n+(24*l|0)+12>>2],h=0|c[o+(c[n+(24*l|0)+4>>2]<<2)>>2],i=0|c[o+(c[n+(24*l|0)+8>>2]<<2)>>2],j=0|c[n+(24*l|0)+16>>2],a=0|c[n+(24*l|0)+20>>2],b=+f[d+(l<<2)>>2],0<(0|g))for(k=0;x=+f[j+(k<<2)>>2],s=+f[j+((p=1|k)<<2)>>2],w=(0|e[a+(k<<1)>>1])<<1&65534,v=+f[(y=h+(w<<2)|0)>>2],r=+f[(w=h+((1|w)<<2)|0)>>2],p=(0|e[a+(p<<1)>>1])<<1&65534,u=+f[(t=i+(p<<2)|0)>>2],q=+f[(p=i+((1|p)<<2)|0)>>2],f[y>>2]=v+x*(u-v)*b,f[w>>2]=r+x*(q-r)*b,f[t>>2]=u+s*(v-u)*b,f[p>>2]=q+s*(r-q)*b,(0|(k=k+2|0))<(0|g););}while((0|(l=l+1|0))!=(0|m))}}function fa(a){var b=0|c[(a|=0)>>2];(0|d[4+b>>0])<4||ga(a,0|c[a+596>>2],0|c[a+600>>2],0|c[984+b>>2],0|c[a+152>>2],0|c[796+b>>2])}function ga(a,b,d,e,g,h){a|=0,e|=0,g|=0,h|=0;var l,o,p,q,r,s,t,u,w,i=0,j=0,k=0,m=0,n=0,v=S;if(S=S+16|0,u=v+8|0,t=v,s=(d|=0)+(12*(b|=0)|0)|0,(0|b)<=0)S=v;else{do{b=0|c[d>>2],o=0|c[g+(b<<2)>>2],q=(b=0|c[h+(b<<2)>>2])<<1,n=0|c[d+4>>2],i=0|c[d+8>>2],p=0|c[1028+(0|c[a>>2])>>2],r=i+(48*n|0)|0;a:do{if(0<(0|n)){if((0|b)<=0)for(;;)if(3<=(b=0|c[i+8>>2])>>>0&&(c[u>>2]=b,ia(0,784,u)),r>>>0<=(i=i+48|0)>>>0)break a;do{j=e+(c[i+4>>2]<<2)|0,b=0|c[i+8>>2];b:do{if(0|b)switch(n=p+(c[j+(c[i+12>>2]<<2)>>2]<<2)|0,0|b){case 1:for(j=i+20|0,b=i+44|0,k=0;f[(m=o+(k<<2)|0)>>2]=+f[m>>2]+ +f[b>>2]*(+f[n+(k<<2)>>2]*+f[j>>2]),(0|(k=k+1|0))!=(0|q););break;case 2:for(j=p+(c[j+(c[i+16>>2]<<2)>>2]<<2)|0,k=i+20|0,l=i+24|0,b=i+44|0,m=0;f[(w=o+(m<<2)|0)>>2]=+f[w>>2]+ +f[b>>2]*(+f[n+(m<<2)>>2]*+f[k>>2]+ +f[j+(m<<2)>>2]*+f[l>>2]),(0|(m=m+1|0))!=(0|q););break;default:c[t>>2]=b,ia(0,784,t);break b}}while(0)}while((i=i+48|0)>>>0<r>>>0)}}while(0)}while((d=d+12|0)>>>0
>>0);S=v}}function ha(a){var b=0|c[(a|=0)>>2];(0|d[4+b>>0])<4||ga(a,0|c[a+604>>2],0|c[a+608>>2],0|c[1024+b>>2],0|c[a+444>>2],0|c[892+b>>2])}function ia(a,b,d){a|=0,b|=0,d|=0;var e,f,g=S;S=S+272|0,a=g+16|0,f=g,(e=0|c[904])&&(c[f>>2]=d,bc(a,b,f),Z[1&e](a)),S=g}function ma(b,d,e){e|=0;var m,f=0,g=0,h=0,i=0,j=0,k=0,l=0,n=0,o=0,p=0,o=0|a[4+(b|=0)>>0];if(c[(d|=0)>>2]=628,p=0|c[(n=b+704|0)>>2],0<(0|(j=0|c[p>>2]))){for(f=0|c[b+1048>>2],g=0|c[b+720>>2],i=h=0;i=(1<<c[f+(c[g+(h<<2)>>2]<<2)>>2])+i|0,(0|(h=h+1|0))!=(0|j););f=i<<2}else f=0;if(c[d+4>>2]=12*j,c[d+8>>2]=c[p>>2]<<2,c[d+12>>2]=c[p>>2]<<2,c[d+16>>2]=c[p>>2]<<2,c[d+20>>2]=c[p>>2]<<2,c[d+24>>2]=c[p>>2]<<2,c[d+28>>2]=f,c[d+32>>2]=c[p>>2]<<2,c[d+36>>2]=f,c[d+40>>2]=f,c[d+44>>2]=c[(m=p+4|0)>>2]<<5,c[d+48>>2]=c[m>>2]<<2,c[d+52>>2]=c[m>>2]<<2,c[d+56>>2]=c[m>>2]<<2,c[d+60>>2]=c[m>>2]<<4,c[d+64>>2]=c[m>>2]<<4,0<(0|(l=0|c[(m=p+8|0)>>2]))){for(g=0|c[b+796>>2],h=0|c[b+1048>>2],i=0|c[b+780>>2],f=k=j=0;f=(15+(c[g+(j<<2)>>2]<<3)&-16)+f|0,k=(1<<c[h+(c[i+(j<<2)>>2]<<2)>>2])+k|0,(0|(j=j+1|0))!=(0|l););g=k<<2}else f=g=0;if(c[d+68>>2]=24*l,c[d+72>>2]=c[m>>2]<<2,c[d+76>>2]=c[m>>2]<<2,c[d+80>>2]=c[m>>2]<<2,c[d+84>>2]=f,c[d+88>>2]=c[m>>2]<<4,c[d+92>>2]=c[m>>2]<<4,c[d+96>>2]=c[m>>2]<<2,c[d+100>>2]=g,c[d+104>>2]=c[m>>2]<<2,c[d+108>>2]=g,c[d+112>>2]=g,c[d+116>>2]=g,c[d+120>>2]=g,c[d+124>>2]=g,c[d+128>>2]=g,c[d+132>>2]=g,c[d+136>>2]=g,c[d+140>>2]=g,c[d+144>>2]=c[m>>2]<<2,c[d+148>>2]=c[m>>2]<<2,c[d+152>>2]=c[m>>2]<<2,c[d+156>>2]=c[m>>2]<<2,c[d+160>>2]=c[m>>2]<<2,c[d+164>>2]=c[m>>2]<<2,0<(0|(j=0|c[(k=p+12|0)>>2]))){for(f=0|c[b+1048>>2],g=0|c[b+812>>2],i=h=0;i=(1<<c[f+(c[g+(h<<2)>>2]<<2)>>2])+i|0,(0|(h=h+1|0))!=(0|j););f=i<<2}else f=0;if(c[d+168>>2]=12*j,c[d+172>>2]=c[k>>2]<<2,c[d+176>>2]=c[k>>2]<<2,c[d+180>>2]=c[k>>2]<<2,c[d+184>>2]=c[k>>2]<<2,c[d+188>>2]=c[k>>2]<<2,c[d+192>>2]=c[k>>2]<<2,c[d+196>>2]=c[k>>2]<<2,c[d+200>>2]=c[k>>2]<<2,c[d+204>>2]=c[k>>2]<<4,c[d+208>>2]=c[k>>2]<<4,c[d+212>>2]=c[k>>2]<<2,c[d+216>>2]=f,c[d+220>>2]=c[k>>2]<<2,c[d+224>>2]=f,c[d+228>>2]=f,c[d+232>>2]=f,c[d+236>>2]=f,c[d+240>>2]=f,c[d+244>>2]=f,c[d+248>>2]=f,c[d+252>>2]=f,c[d+256>>2]=f,c[d+260>>2]=f,c[d+264>>2]=f,c[d+268>>2]=f,c[d+272>>2]=c[k>>2]<<2,c[d+276>>2]=c[k>>2]<<2,c[d+280>>2]=c[k>>2]<<2,c[d+284>>2]=c[k>>2]<<2,c[d+288>>2]=c[k>>2]<<2,c[d+292>>2]=c[k>>2]<<2,0<(0|(l=0|c[(m=p+16|0)>>2]))){for(g=0|c[b+892>>2],h=0|c[b+1048>>2],i=0|c[b+852>>2],f=k=j=0;f=(15+(c[g+(j<<2)>>2]<<3)&-16)+f|0,k=(1<<c[h+(c[i+(j<<2)>>2]<<2)>>2])+k|0,(0|(j=j+1|0))!=(0|l););g=k<<2}else f=g=0;if(c[d+296>>2]=20*l,c[d+300>>2]=c[m>>2]<<2,c[d+304>>2]=c[m>>2],c[d+308>>2]=c[m>>2]<<2,c[d+312>>2]=c[m>>2]<<2,c[d+316>>2]=c[m>>2]<<2,c[d+320>>2]=f,c[d+324>>2]=c[m>>2]<<2,c[d+328>>2]=c[m>>2]<<4,c[d+332>>2]=c[m>>2]<<4,c[d+336>>2]=c[m>>2]<<2,c[d+340>>2]=c[m>>2]<<2,c[d+344>>2]=c[m>>2]<<2,c[d+348>>2]=c[m>>2]<<4,c[d+352>>2]=c[m>>2]<<4,c[d+356>>2]=c[m>>2]<<2,c[d+360>>2]=g,c[d+364>>2]=c[m>>2]<<2,c[d+368>>2]=g,c[d+372>>2]=g,c[d+376>>2]=g,c[d+380>>2]=g,c[d+384>>2]=g,c[d+388>>2]=g,c[d+392>>2]=g,c[d+396>>2]=g,c[d+400>>2]=g,c[d+404>>2]=g,c[d+408>>2]=c[m>>2]<<2,c[d+412>>2]=c[m>>2]<<2,c[d+416>>2]=c[m>>2]<<2,c[d+420>>2]=c[m>>2]<<2,c[d+424>>2]=c[m>>2]<<2,c[d+428>>2]=c[m>>2]<<2,n=0|c[n>>2],c[d+432>>2]=52*(0|c[(g=n+20|0)>>2]),f=(m=3<(255&o))?0:c[g>>2]<<2,c[d+436>>2]=f,c[d+440>>2]=c[g>>2]<<2,c[d+444>>2]=28*(0|c[n+52>>2]),0<(0|(j=0|c[p+48>>2]))){for(f=0|c[b+1048>>2],i=h=g=0;h=(o=0|c[f+(g<<2)>>2])+h|0,i=(1<<o)+i|0,(0|(g=g+1|0))!=(0|j););g=h<<2,f=i<<2}else f=g=0;if(c[d+448>>2]=36*j,c[d+452>>2]=g,c[d+456>>2]=f,c[d+460>>2]=f,c[d+488>>2]=28*(0|c[(g=p+72|0)>>2]),0<(0|(g=0|c[g>>2]))){for(h=0|c[b+1152>>2],i=0|c[b+1160>>2],f=0|c[b+1164>>2],l=k=j=0;k=(0|k)<(0|(o=0|c[h+(j<<2)>>2]))?o:k,l=(0|(o=(0|c[i+(j<<2)>>2])-(0|c[f+(j<<2)>>2])|0))<(0|l)?l:o+1|0,(0|(j=j+1|0))!=(0|g););g=k<<2,f=l<<2}else f=g=0;if(c[d+492>>2]=c[p+76>>2]<<4,c[d+496>>2]=f,c[d+500>>2]=g,c[d+504>>2]=f,0<(0|(j=0|c[(k=p+80|0)>>2]))){for(f=0|c[b+1048>>2],g=0|c[b+1188>>2],i=h=0;i=(1<<c[f+(c[g+(h<<2)>>2]<<2)>>2])+i|0,(0|(h=h+1|0))!=(0|j););f=i<<2}else f=0;if(c[d+508>>2]=24*j,c[d+512>>2]=c[k>>2]<<2,c[d+516>>2]=c[k>>2]<<2,c[d+520>>2]=f,c[d+524>>2]=c[k>>2]<<2,c[d+528>>2]=f,c[d+532>>2]=f,m){if(c[d+464>>2]=20*(0|c[n+120>>2]),c[d+468>>2]=28*(0|c[n+100>>2]),0<(0|(i=0|c[p+104>>2]))){for(f=0|c[b+1080>>2],h=g=0;h=(0|c[f+(g<<2)>>2])+h|0,(0|(g=g+1|0))!=(0|i););f=h<<2}else f=0;c[d+472>>2]=48*i,c[d+476>>2]=f,c[d+480>>2]=12*(0|c[n+108>>2]),c[d+484>>2]=12*(0|c[n+112>>2]),f=g=c[d+540>>2]=0}else{if(0<(0|(m=0|c[(n=p+20|0)>>2]))){k=0|c[b+948>>2],l=0|c[b+952>>2],i=0|c[b+1036>>2],f=j=0;do{if(b=0|c[l+(j<<2)>>2],h=(g=i+(c[k+(j<<2)>>2]<<2)|0)+(b<<2)|0,0<(0|b))for(;f=(0|c[g>>2])+f|0,(g=g+4|0)>>>0<h>>>0;);}while((0|(j=j+1|0))!=(0|m))}else f=0;c[d+540>>2]=m<<2,g=f<<2,f=c[n>>2]<<2}for(c[d+536>>2]=f,c[d+544>>2]=g,g=f=0;g=(b=15+(0|c[(p=d+(f<<2)|0)>>2])&-16)+(c[p>>2]=g)|0,137!=(0|(f=f+1|0)););c[e>>2]=g}function na(b,e,g){b|=0,e|=0,g|=0;var C,D,G,J,M,V,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,E=0,F=0,H=0,I=0,K=0,L=0,N=0,O=0,P=0,Q=0,R=0,T=0,U=0,W=0,X=0,Y=0,Z=0,_=S;if(S=S+560|0,H=_+552|0,h=(p=_)+556|0,Vc(0|p,0,548),ma(b,p,h),g>>>0<(h=0|c[h>>2])>>>0)return S=_,(Z=0)|Z;if(Vc(0|e,0,0|h),Z=e+(0|c[p>>2])|0,c[(D=Z+8|0)>>2]=e+(0|c[p+4>>2]),c[Z+40>>2]=e+(0|c[p+8>>2]),c[Z+44>>2]=e+(0|c[p+12>>2]),c[Z+48>>2]=e+(0|c[p+16>>2]),c[(E=Z+52|0)>>2]=e+(0|c[p+20>>2]),c[(F=Z+16|0)>>2]=e+(0|c[p+24>>2]),c[Z+24>>2]=e+(0|c[p+28>>2]),c[Z+28>>2]=e+(0|c[p+32>>2]),c[Z+32>>2]=e+(0|c[p+36>>2]),c[Z+36>>2]=e+(0|c[p+40>>2]),j=0|c[(Y=b+704|0)>>2],c[(G=Z+308|0)>>2]=e+(0|c[p+44>>2]),c[Z+312>>2]=e+(0|c[p+48>>2]),c[Z+316>>2]=e+(0|c[p+52>>2]),c[Z+320>>2]=e+(0|c[p+56>>2]),c[Z+324>>2]=e+(0|c[p+60>>2]),c[Z+328>>2]=e+(0|c[p+64>>2]),c[(L=Z+60|0)>>2]=e+(0|c[p+68>>2]),c[Z+144>>2]=e+(0|c[p+72>>2]),c[Z+148>>2]=e+(0|c[p+76>>2]),h=e+(0|c[p+80>>2])|0,c[(k=Z+152|0)>>2]=h,0<(0|(j=0|c[j+8>>2]))&&(l=e+(0|c[p+84>>2])|0,m=b+796|0,c[h>>2]=l,1!=(0|j)))for(h=0,i=1,g=l;g=g+(15+(c[(0|c[m>>2])+(h<<2)>>2]<<3)&-16)|0,c[(0|c[k>>2])+(i<<2)>>2]=g,!((0|j)<=(0|(h=i+1|0)));)W=i,i=h,h=W;if(c[Z+156>>2]=e+(0|c[p+88>>2]),c[Z+160>>2]=e+(0|c[p+92>>2]),c[(I=Z+68|0)>>2]=e+(0|c[p+96>>2]),c[Z+76>>2]=e+(0|c[p+100>>2]),c[Z+80>>2]=e+(0|c[p+104>>2]),c[Z+84>>2]=e+(0|c[p+108>>2]),c[Z+88>>2]=e+(0|c[p+112>>2]),c[Z+92>>2]=e+(0|c[p+116>>2]),c[Z+96>>2]=e+(0|c[p+120>>2]),c[Z+100>>2]=e+(0|c[p+124>>2]),c[Z+104>>2]=e+(0|c[p+128>>2]),c[Z+108>>2]=e+(0|c[p+132>>2]),c[Z+112>>2]=e+(0|c[p+136>>2]),c[Z+116>>2]=e+(0|c[p+140>>2]),c[Z+120>>2]=e+(0|c[p+144>>2]),c[Z+124>>2]=e+(0|c[p+148>>2]),c[Z+128>>2]=e+(0|c[p+152>>2]),c[Z+132>>2]=e+(0|c[p+156>>2]),c[Z+136>>2]=e+(0|c[p+160>>2]),c[Z+140>>2]=e+(0|c[p+164>>2]),c[(J=Z+168|0)>>2]=e+(0|c[p+168>>2]),c[Z+264>>2]=e+(0|c[p+172>>2]),c[Z+268>>2]=e+(0|c[p+176>>2]),c[Z+272>>2]=e+(0|c[p+180>>2]),c[Z+276>>2]=e+(0|c[p+184>>2]),c[Z+280>>2]=e+(0|c[p+188>>2]),c[Z+284>>2]=e+(0|c[p+192>>2]),c[Z+288>>2]=e+(0|c[p+196>>2]),c[Z+292>>2]=e+(0|c[p+200>>2]),c[Z+296>>2]=e+(0|c[p+204>>2]),c[Z+300>>2]=e+(0|c[p+208>>2]),c[(K=Z+176|0)>>2]=e+(0|c[p+212>>2]),c[Z+184>>2]=e+(0|c[p+216>>2]),c[Z+188>>2]=e+(0|c[p+220>>2]),c[Z+192>>2]=e+(0|c[p+224>>2]),c[Z+196>>2]=e+(0|c[p+228>>2]),c[Z+200>>2]=e+(0|c[p+232>>2]),c[Z+204>>2]=e+(0|c[p+236>>2]),c[Z+208>>2]=e+(0|c[p+240>>2]),c[Z+212>>2]=e+(0|c[p+244>>2]),c[Z+216>>2]=e+(0|c[p+248>>2]),c[Z+220>>2]=e+(0|c[p+252>>2]),c[Z+224>>2]=e+(0|c[p+256>>2]),c[Z+228>>2]=e+(0|c[p+260>>2]),c[Z+232>>2]=e+(0|c[p+264>>2]),c[Z+236>>2]=e+(0|c[p+268>>2]),c[Z+240>>2]=e+(0|c[p+272>>2]),c[Z+244>>2]=e+(0|c[p+276>>2]),c[Z+248>>2]=e+(0|c[p+280>>2]),c[Z+252>>2]=e+(0|c[p+284>>2]),c[Z+256>>2]=e+(0|c[p+288>>2]),c[Z+260>>2]=e+(0|c[p+292>>2]),j=0|c[Y>>2],c[(O=Z+336|0)>>2]=e+(0|c[p+296>>2]),c[Z+424>>2]=e+(0|c[p+300>>2]),c[Z+432>>2]=e+(0|c[p+304>>2]),c[Z+436>>2]=e+(0|c[p+308>>2]),c[Z+440>>2]=e+(0|c[p+312>>2]),h=e+(0|c[p+316>>2])|0,c[(k=Z+444|0)>>2]=h,0<(0|(j=0|c[j+16>>2]))&&(n=e+(0|c[p+320>>2])|0,o=b+892|0,c[h>>2]=n,1!=(0|j)))for(h=0,i=1,g=n;g=g+(15+(c[(0|c[o>>2])+(h<<2)>>2]<<3)&-16)|0,c[(0|c[k>>2])+(i<<2)>>2]=g,!((0|j)<=(0|(h=i+1|0)));)W=i,i=h,h=W;if(c[Z+448>>2]=e+(0|c[p+324>>2]),c[(P=Z+452|0)>>2]=e+(0|c[p+328>>2]),c[(Q=Z+456|0)>>2]=e+(0|c[p+332>>2]),c[Z+460>>2]=e+(0|c[p+336>>2]),c[Z+464>>2]=e+(0|c[p+340>>2]),c[Z+468>>2]=e+(0|c[p+344>>2]),c[Z+472>>2]=e+(0|c[p+348>>2]),c[Z+476>>2]=e+(0|c[p+352>>2]),c[(N=Z+344|0)>>2]=e+(0|c[p+356>>2]),c[Z+352>>2]=e+(0|c[p+360>>2]),c[Z+356>>2]=e+(0|c[p+364>>2]),c[Z+360>>2]=e+(0|c[p+368>>2]),c[Z+364>>2]=e+(0|c[p+372>>2]),c[Z+368>>2]=e+(0|c[p+376>>2]),c[Z+372>>2]=e+(0|c[p+380>>2]),c[Z+376>>2]=e+(0|c[p+384>>2]),c[Z+380>>2]=e+(0|c[p+388>>2]),c[Z+384>>2]=e+(0|c[p+392>>2]),c[Z+388>>2]=e+(0|c[p+396>>2]),c[Z+392>>2]=e+(0|c[p+400>>2]),c[Z+396>>2]=e+(0|c[p+404>>2]),c[Z+400>>2]=e+(0|c[p+408>>2]),c[Z+404>>2]=e+(0|c[p+412>>2]),c[Z+408>>2]=e+(0|c[p+416>>2]),c[Z+412>>2]=e+(0|c[p+420>>2]),c[Z+416>>2]=e+(0|c[p+424>>2]),c[Z+420>>2]=e+(0|c[p+428>>2]),A=0|c[p+436>>2],C=0|c[p+440>>2],c[(W=Z+544|0)>>2]=e+(0|c[p+432>>2]),c[(B=Z+548|0)>>2]=e+A,c[(A=Z+552|0)>>2]=e+C,c[(C=Z+560|0)>>2]=e+(0|c[p+444>>2]),h=0|c[Y>>2],j=e+(0|c[p+448>>2])|0,c[(U=Z+568|0)>>2]=j,0<(0|(h=0|c[h+48>>2])))for(g=0|c[b+1048>>2],k=e+(0|c[p+452>>2])|0,m=e+((l=0)|c[p+456>>2])|0,o=e+(0|c[p+460>>2])|0;c[j+(36*l|0)>>2]=k,c[j+(36*l|0)+16>>2]=m,c[j+(36*l|0)+20>>2]=o,n=1<<(i=0|c[g+(l<<2)>>2]),(0|(l=l+1|0))!=(0|h);)k=k+(i<<2)|0,m=m+(n<<2)|0,o=o+(n<<2)|0;if(h=0|c[Y>>2],i=e+(0|c[p+488>>2])|0,c[(M=Z+484|0)>>2]=i,0<(0|(h=0|c[h+72>>2])))for(g=0|c[b+1152>>2],k=e+((j=0)|c[p+492>>2])|0;k=(c[i+(28*j|0)+12>>2]=k)+(c[g+(j<<2)>>2]<<4)|0,(0|(j=j+1|0))!=(0|h););if(c[Z+488>>2]=e+(0|c[p+496>>2]),c[Z+492>>2]=e+(0|c[p+500>>2]),c[Z+496>>2]=e+(0|c[p+504>>2]),c[(R=Z+504|0)>>2]=e+(0|c[p+508>>2]),c[Z+536>>2]=e+(0|c[p+512>>2]),c[(T=Z+512|0)>>2]=e+(0|c[p+516>>2]),c[Z+520>>2]=e+(0|c[p+520>>2]),c[Z+524>>2]=e+(0|c[p+524>>2]),c[Z+528>>2]=e+(0|c[p+528>>2]),c[Z+532>>2]=e+(0|c[p+532>>2]),z=3<(0|d[(V=b+4|0)>>0])){if(c[Z+576>>2]=e+(0|c[p+464>>2]),c[Z+584>>2]=e+(0|c[p+468>>2]),h=0|c[p+476>>2],j=0|c[Y>>2],l=e+(0|c[p+472>>2])|0,c[Z+592>>2]=l,0<(0|(j=0|c[j+104>>2])))for(k=0|c[b+1080>>2],h=e+h|0,g=0;c[l+(48*g|0)+40>>2]=h,(0|(i=g+1|0))!=(0|j);)h=h+(c[k+(g<<2)>>2]<<2)|0,g=i;c[Z+600>>2]=e+(0|c[p+480>>2]),c[Z+608>>2]=e+(0|c[p+484>>2]),g=0|c[Y>>2],h=0|c[g+20>>2]}else if(g=0|c[p+536>>2],i=0|c[p+544>>2],c[Z+616>>2]=e+(0|c[p+540>>2]),c[(p=Z+612|0)>>2]=e+g,g=0|c[Y>>2],0<(0|(h=0|c[g+20>>2])))for(m=b+948|0,n=b+952|0,l=b+1036|0,k=e+i|(o=0);;){if(h=0|c[(0|c[m>>2])+(o<<2)>>2],i=(y=0|c[(0|c[n>>2])+(o<<2)>>2])+h|0,0<(0|y)){for(g=0|c[l>>2],j=0;j=(0|c[g+(h<<2)>>2])+j|0,(0|(h=h+1|0))<(0|i););h=(0|c[p>>2])+(o<<2)|0,j?(g=k,i=j):X=27}else h=(0|c[p>>2])+(o<<2)|0,X=27;if(27==(0|X)&&(i=g=X=0),c[h>>2]=g,g=0|c[Y>>2],(0|(h=0|c[g+20>>2]))<=(0|(o=o+1|0)))break;k=k+(i<<2)|0}c[Z>>2]=b,c[Z+620>>2]=1,c[Z+624>>2]=1&a[20+(0|c[b+708>>2])>>0],k=(c[Z+540>>2]=h)+-1|0;a:do{if(0<(0|h)){if(e=0|c[W>>2],q=0|c[b+928>>2],s=0|c[b+924>>2],u=0|c[b+936>>2],v=0|c[b+932>>2],w=0|c[b+940>>2],x=0|c[b+952>>2],y=b+948|0,p=0|c[A>>2],o=Z+584|0,n=b+956|0,!z)for(;;){if(c[e+(52*k|0)>>2]=0,c[e+(52*k|0)+4>>2]=c[(i=q+(k<<2)|0)>>2],c[e+(52*k|0)+8>>2]=c[(A=s+(k<<2)|0)>>2],f[e+(52*k|0)+12>>2]=+f[A>>2]-+f[i>>2],c[e+(52*k|0)+16>>2]=c[u+(k<<2)>>2],c[e+(52*k|0)+44>>2]=c[(i=v+(k<<2)|0)>>2],t=+r(.10000000149011612,+ +(0|c[w+(k<<2)>>2])),f[e+(52*k|0)+20>>2]=t,f[e+(52*k|0)+24>>2]=1.5*t,A=0|c[x+(k<<2)>>2],j=(c[e+(52*k|0)+32>>2]=A)?(0|c[C>>2])+(28*(0|c[(0|c[y>>2])+(k<<2)>>2])|0)|0:0,c[e+(52*k|0)+28>>2]=j,c[e+(52*k|0)+48>>2]=1,c[p+(k<<2)>>2]=c[i>>2],!(0<(0|k)))break a;k=k+-1|0}for(l=0|c[b+944>>2],m=0|c[b+960>>2];c[e+(52*k|0)>>2]=c[l+(k<<2)>>2],c[e+(52*k|0)+4>>2]=c[(j=q+(k<<2)|0)>>2],c[e+(52*k|0)+8>>2]=c[(A=s+(k<<2)|0)>>2],f[e+(52*k|0)+12>>2]=+f[A>>2]-+f[j>>2],c[e+(52*k|0)+16>>2]=c[u+(k<<2)>>2],c[e+(52*k|0)+44>>2]=c[(j=v+(k<<2)|0)>>2],t=+r(.10000000149011612,+ +(0|c[w+(k<<2)>>2])),f[e+(52*k|0)+20>>2]=t,f[e+(52*k|0)+24>>2]=1.5*t,A=0|c[x+(k<<2)>>2],i=(c[e+(52*k|0)+32>>2]=A)?(0|c[C>>2])+(28*(0|c[(0|c[y>>2])+(k<<2)>>2])|0)|0:0,c[e+(52*k|0)+28>>2]=i,A=0|c[m+(k<<2)>>2],i=(c[e+(52*k|0)+40>>2]=A)?(0|c[o>>2])+(28*(0|c[(0|c[n>>2])+(k<<2)>>2])|0)|0:0,c[e+(52*k|0)+36>>2]=i,c[e+(52*k|0)+48>>2]=1,c[p+(k<<2)>>2]=c[j>>2],0<(0|k);)k=k+-1|0}}while(0);if(z?(c[B>>2]=c[b+944>>2],l=g,m=b):(Vc(0|c[B>>2],0,h<<2|0),m=0|c[Z>>2],l=0|c[m+704>>2]),h=0|c[l+52>>2],0<(0|(c[Z+556>>2]=h)))for(g=0|c[C>>2],i=0|c[m+1036>>2],j=0|c[m+1132>>2],k=0|c[m+1032>>2];c[g+(28*(h=(B=h)+-1|0)|0)>>2]=c[i+(h<<2)>>2],c[g+(28*h|0)+4>>2]=j+(c[k+(h<<2)>>2]<<2),c[g+(28*h|0)+8>>2]=0,f[g+(28*h|0)+12>>2]=0,c[g+(28*h|0)+16>>2]=0,c[g+(28*h|0)+20>>2]=1,(c[g+(28*h|0)+24>>2]=1)<(0|B););if(h=0|c[l+48>>2],0<(0|(c[Z+564>>2]=h))){n=m+1048|0,o=m+1040|0,m=m+1044|0;do{if(l=h,g=0|c[U>>2],i=0|c[(0|c[n>>2])+((h=h+-1|0)<<2)>>2],0<(0|(c[g+(36*h|0)+4>>2]=i)))for(j=g+(36*h|0)|0,k=0;c[(0|c[j>>2])+(k<<2)>>2]=(0|c[C>>2])+(28*(0|c[(0|c[o>>2])+((0|c[(0|c[m>>2])+(h<<2)>>2])+k<<2)>>2])|0),(0|(k=k+1|0))!=(0|i););}while(c[g+(36*h|0)+8>>2]=1<<i,c[g+(36*h|0)+24>>2]=1,(c[g+(36*h|0)+28>>2]=1)<(0|l));q=0|c[Z>>2],l=0|c[q+704>>2]}else q=m;if(g=0|c[l>>2],0<(0|(c[(e=Z+4|0)>>2]=g))){for(j=0|c[D>>2],o=0|c[U>>2],p=0|c[q+720>>2],k=0|c[q+740>>2],m=0|c[q+736>>2],n=0|c[q+732>>2],h=0|c[E>>2],i=g;c[j+(12*(i=(E=i)+-1|0)|0)>>2]=o+(36*(0|c[p+(i<<2)>>2])|0),c[j+(12*i|0)+4>>2]=c[k+(i<<2)>>2],c[j+(12*i|0)+8>>2]=c[m+(i<<2)>>2],f[h+(i<<2)>>2]=0==(0|c[n+(i<<2)>>2])?0:1,1<(0|E););for(i=0|c[F>>2],h=0;E=0|c[o+(36*(0|c[p+((g=(F=g)+-1|0)<<2)>>2])|0)+8>>2],h=(c[i+(g<<2)>>2]=E)+h|0,1<(0|F););g=0|c[e>>2]}else h=0;if(c[Z+20>>2]=h,c[Z+12>>2]=g,h=0|c[l+4>>2],0<(0|(c[Z+304>>2]=h))){m=q+752|0,o=q+764|0,n=q+768|0,l=q+772|0,p=q+776|0,k=q+760|0;do{switch(j=h,g=0|c[G>>2],c[g+((h=h+-1|0)<<5)>>2]=(0|c[U>>2])+(36*(0|c[(0|c[m>>2])+(h<<2)>>2])|0),c[g+(h<<5)+4>>2]=c[(0|c[o>>2])+(h<<2)>>2],c[g+(h<<5)+8>>2]=c[(0|c[n>>2])+(h<<2)>>2],F=0|c[(0|c[l>>2])+(h<<2)>>2],c[g+(h<<5)+12>>2]=F,i=0|c[(0|c[p>>2])+(h<<2)>>2],c[g+(h<<5)+16>>2]=i,c[g+(h<<5)+28>>2]=c[(0|c[k>>2])+(h<<2)>>2],0|F){case 0:c[(0|c[L>>2])+(24*i|0)+20>>2]=h,c[g+(h<<5)+20>>2]=2,c[g+(h<<5)+24>>2]=2;break;case 1:c[(0|c[J>>2])+(12*i|0)+8>>2]=h,c[g+(h<<5)+20>>2]=3,c[g+(h<<5)+24>>2]=3;break;default:ia(0,937,H)}}while(1<(0|j));B=0|c[Z>>2],z=0|c[B+704>>2]}else z=l,B=q;if(i=0|c[z+8>>2],h=(c[(e=Z+56|0)>>2]=i)+-1|0,p=0<(0|i))if(j=0|c[L>>2],k=0|c[U>>2],l=0|c[B+780>>2],m=0|c[B+800>>2],n=0|c[B+804>>2],o=0|c[B+796>>2],1<(0|d[B+4>>0]))for(g=0|c[B+808>>2];c[j+(24*h|0)>>2]=k+(36*(0|c[l+(h<<2)>>2])|0),c[j+(24*h|0)+4>>2]=c[m+(h<<2)>>2],c[j+(24*h|0)+8>>2]=c[n+(h<<2)>>2],c[j+(24*h|0)+16>>2]=c[o+(h<<2)>>2],c[j+(24*h|0)+12>>2]=c[g+(h<<2)>>2],0<(0|h);)h=h+-1|0;else for(;c[j+(24*h|0)>>2]=k+(36*(0|c[l+(h<<2)>>2])|0),c[j+(24*h|0)+4>>2]=c[m+(h<<2)>>2],c[j+(24*h|0)+8>>2]=c[n+(h<<2)>>2],c[j+(24*h|0)+16>>2]=c[o+(h<<2)>>2],(c[j+(24*h|0)+12>>2]=0)<(0|h);)h=h+-1|0;if(g=0|c[z+12>>2],0<(0|(c[(n=Z+164|0)>>2]=g)))for(h=0|c[J>>2],j=0|c[U>>2],k=0|c[B+812>>2],l=0|c[B+828>>2],m=g;c[h+(12*(m=(H=m)+-1|0)|0)>>2]=j+(36*(0|c[k+(m<<2)>>2])|0),c[h+(12*m|0)+4>>2]=c[l+(m<<2)>>2],1<(0|H););if(p){for(j=0|c[L>>2],g=0|c[I>>2],h=0;I=0|c[8+(0|c[j+(24*(i=(L=i)+-1|0)|0)>>2])>>2],h=(c[g+(i<<2)>>2]=I)+h|0,1<(0|L););i=0|c[e>>2],g=0|c[n>>2]}else h=0;if(c[Z+72>>2]=h,c[Z+64>>2]=i,0<(0|g)){for(j=0|c[J>>2],i=0|c[K>>2],h=0;K=0|c[8+(0|c[j+(12*(g=(L=g)+-1|0)|0)>>2])>>2],h=(c[i+(g<<2)>>2]=K)+h|0,1<(0|L););g=0|c[n>>2]}else h=0;if(c[Z+180>>2]=h,c[Z+172>>2]=g,A=B+704|0,h=0|c[z+16>>2],0<(0|(c[(p=Z+332|0)>>2]=h))){for(g=0|c[O>>2],n=0|c[U>>2],o=0|c[B+852>>2],i=0|c[B+876>>2],j=0|c[B+880>>2],k=0|c[B+892>>2],l=0|c[B+872>>2],m=h;c[g+(20*(m=(O=m)+-1|0)|0)>>2]=n+(36*(0|c[o+(m<<2)>>2])|0),c[g+(20*m|0)+4>>2]=c[i+(m<<2)>>2],c[g+(20*m|0)+8>>2]=c[j+(m<<2)>>2],c[g+(20*m|0)+16>>2]=c[k+(m<<2)>>2],c[g+(20*m|0)+12>>2]=c[l+(m<<2)>>2],1<(0|O););for(g=0|c[N>>2],i=0;N=0|c[n+(36*(0|c[o+((h=(O=h)+-1|0)<<2)>>2])|0)+8>>2],i=(c[g+(h<<2)>>2]=N)+i|0,1<(0|O););if(h=0|c[p>>2],c[Z+348>>2]=i,0<(0|(c[Z+340>>2]=h)))for(j=0|c[P>>2],g=0|c[Q>>2],i=h<<2;f[j+((i=(Q=i)+-4|0)<<2)>>2]=1,f[j+((O=Q+-3|0)<<2)>>2]=1,f[j+((P=Q+-2|0)<<2)>>2]=1,f[j+((Q=Q+-1|0)<<2)>>2]=1,f[g+(i<<2)>>2]=0,f[g+(O<<2)>>2]=0,!(((f[g+(P<<2)>>2]=0)|h)<=(f[g+(Q<<2)>>2]=1));)h=h+-1|0}else c[Z+348>>2]=0,c[Z+340>>2]=h;if(y=0|c[z+72>>2],0<(0|(c[Z+480>>2]=y))){h=0|c[M>>2],g=0|c[B+1152>>2],i=0|c[B+1156>>2],j=0|c[B+1160>>2],k=0|c[B+1164>>2],l=0|c[B+1148>>2],s=B+1172|0,v=B+1168|0,u=B+1176|0,w=0;do{if(m=0|c[g+(w<<2)>>2],c[h+(28*w|0)+4>>2]=m,c[h+(28*w|0)>>2]=c[i+(w<<2)>>2],Q=0|c[j+(w<<2)>>2],c[h+(28*w|0)+16>>2]=Q,n=0|c[k+(w<<2)>>2],c[h+(28*w|0)+20>>2]=n,c[h+(28*w|0)+24>>2]=Q+1-n,n=(c[h+(28*w|0)+8>>2]=0)|c[l+(w<<2)>>2],0<(0|m))for(o=0|c[h+(28*w|0)+12>>2],p=0|c[s>>2],e=0|c[v>>2],q=0|c[u>>2],x=0;c[o+(x<<4)+4>>2]=c[p+((Q=x+n|0)<<2)>>2],c[o+(x<<4)>>2]=c[e+(Q<<2)>>2],c[o+(x<<4)+8>>2]=c[q+(Q<<2)>>2],(0|(x=x+1|(c[o+(x<<4)+12>>2]=0)))!=(0|m););}while((0|(w=w+1|0))!=(0|y))}g=0|c[z+80>>2],c[(e=Z+500|0)>>2]=g;do{if(0<(0|g)){for(n=0|c[R>>2],o=0|c[U>>2],p=0|c[B+1188>>2],h=0|c[B+1200>>2],i=0|c[B+1204>>2],j=0|c[B+1212>>2],k=0|c[B+1216>>2],l=0|c[B+1208>>2],m=0|c[B+1220>>2];c[n+(24*(g=(U=g)+-1|0)|0)>>2]=o+(36*(0|c[p+(g<<2)>>2])|0),c[n+(24*g|0)+4>>2]=c[h+(g<<2)>>2],c[n+(24*g|0)+8>>2]=c[i+(g<<2)>>2],c[n+(24*g|0)+12>>2]=c[j+(g<<2)>>2],R=0|c[l+(g<<2)>>2],c[n+(24*g|0)+16>>2]=k+(R<<2),c[n+(24*g|0)+20>>2]=m+(R<<1),1<(0|U););if((0|(g=0|c[e>>2]))<=0){h=0;break}for(i=0|c[T>>2],h=0;T=0|c[o+(36*(0|c[p+((g=(U=g)+-1|0)<<2)>>2])|0)+8>>2],h=(c[i+(g<<2)>>2]=T)+h|0,1<(0|U););g=0|c[e>>2]}else h=0}while(0);c[Z+516>>2]=h,c[Z+508>>2]=g;do{if(3<(0|d[V>>0])){if((255&(h=0|a[B+4>>0]))<4)break;if(g=0|c[z+120>>2],0<(0|(c[Z+572>>2]=g)))for(o=0|c[Z+576>>2],i=0|c[W>>2],j=0|c[B+1112>>2],k=0|c[B+1124>>2],l=0|c[B+1116>>2],m=0|c[B+1128>>2],n=0|c[B+1120>>2];c[o+(20*(g=(X=g)+-1|0)|0)>>2]=i+(52*(0|c[j+(g<<2)>>2])|0),W=0|c[l+(g<<2)>>2],c[o+(20*g|0)+4>>2]=k+(W<<2),c[o+(20*g|0)+8>>2]=m+(W<<2),c[o+(20*g|0)+12>>2]=c[n+(g<<2)>>2],1<(0|X););if(g=0|c[z+100>>2],0<(0|(c[Z+580>>2]=g)))for(i=0|c[Z+584>>2],j=0|c[B+1056>>2],k=0|c[B+1132>>2],l=0|c[B+1052>>2],m=0|c[B+1060>>2];c[i+(28*(g=(X=g)+-1|0)|0)>>2]=c[j+(g<<2)>>2],c[i+(28*g|0)+4>>2]=k+(c[l+(g<<2)>>2]<<2),c[i+(28*g|0)+8>>2]=c[m+(g<<2)>>2],c[i+(28*g|0)+12>>2]=0,f[i+(28*g|0)+16>>2]=0,c[i+(28*g|0)+20>>2]=1,(c[i+(28*g|0)+24>>2]=1)<(0|X););if(g=0|c[z+104>>2],0<(0|(c[Z+588>>2]=g))){p=Z+592|0,q=Z+584|0,o=B+1064|0,s=B+1068|0,m=B+1080|0,e=Z+576|0,n=B+1108|0,l=B+1076|0;do{if(k=g,h=0|c[p>>2],c[h+(48*(g=g+-1|0)|0)>>2]=(0|c[q>>2])+(28*(0|c[(0|c[o>>2])+(g<<2)>>2])|0),c[h+(48*g|0)+4>>2]=c[(0|c[s>>2])+(g<<2)>>2],c[h+(48*g|0)+8>>2]=0,c[h+(48*g|0)+28>>2]=1,c[h+(48*g|0)+32>>2]=1,j=0|c[(0|c[m>>2])+(g<<2)>>2],0<(0|(c[h+(48*g|0)+36>>2]=j)))for(h=h+(48*g|0)+40|0,i=0;c[(0|c[h>>2])+(i<<2)>>2]=(0|c[e>>2])+(20*(0|c[(0|c[n>>2])+((0|c[(0|c[l>>2])+(g<<2)>>2])+i<<2)>>2])|0),(0|(i=i+1|0))!=(0|j););}while(1<(0|k));o=0|c[Z>>2],h=0|a[o+4>>0]}else o=B;if(n=0|c[Y>>2],g=0|c[n+108>>2],(255&h)<4)break;if(0<(0|(c[Z+596>>2]=g)))for(i=0|c[Z+600>>2],j=0|c[b+1084>>2],k=0|c[b+1092>>2],l=0|c[Z+592>>2],m=0|c[b+1088>>2],h=g;c[i+(12*(h=(Y=h)+-1|0)|0)>>2]=c[j+(h<<2)>>2],c[i+(12*h|0)+4>>2]=c[k+(h<<2)>>2],c[i+(12*h|0)+8>>2]=l+(48*(0|c[m+(h<<2)>>2])|0),1<(0|Y););if(h=0|c[n+112>>2],0<(0|(c[Z+604>>2]=h)))for(i=0|c[Z+608>>2],j=0|c[b+1096>>2],k=0|c[b+1104>>2],l=0|c[Z+592>>2],g=0|c[b+1100>>2];c[i+(12*(h=(b=h)+-1|0)|0)>>2]=c[j+(h<<2)>>2],c[i+(12*h|0)+4>>2]=c[k+(h<<2)>>2],c[i+(12*h|0)+8>>2]=l+(48*(0|c[g+(h<<2)>>2])|0),1<(0|b););if(i=0|c[o+1132>>2],j=0|c[20+(0|c[o+704>>2])>>2],k=Z+612|0,c[Z+616>>2]=c[o+972>>2],h=0|c[o+964>>2],c[k>>2]=h,(0|j)<=0)break;if(c[h>>2]=i+(c[c[(g=o+968|0)>>2]>>2]<<2),1==(0|j))break;for(h=1;c[(0|c[k>>2])+(h<<2)>>2]=i+(c[(0|c[g>>2])+(h<<2)>>2]<<2),(0|(h=h+1|0))!=(0|j););}else{if((0|c[z+20>>2])<=0)break;y=B+948|0,z=B+952|0,v=Z+612|0,w=B+1032|0,x=B+1036|0,q=B+1132|0,s=Z+616|0,u=0;do{if(h=0|c[(0|c[y>>2])+(u<<2)>>2],p=(b=0|c[(0|c[z>>2])+(u<<2)>>2])+h|0,e=0|c[(0|c[v>>2])+(u<<2)>>2],0<(0|b)){n=0|c[w>>2],o=0|c[x>>2],m=h,h=0;do{if(g=0|c[n+(m<<2)>>2],l=(b=0|c[o+(m<<2)>>2])+g|0,0<(0|b)){k=0|c[q>>2];do{t=+f[k+(g<<2)>>2],i=e+(h<<2)|0;b:do{if(0<(0|h))for(j=e;;){if(+f[j>>2]==t)break b;if(i>>>0<=(j=j+4|0)>>>0){X=146;break}}else X=146}while(0)}while(146==(0|X)&&(X=0,f[i>>2]=t,h=h+1|0),(0|(g=g+1|0))<(0|l))}}while((0|(m=m+1|0))<(0|p))}else h=0;!function(a,b){a|=0;var h,j,k,m,d=0,e=0,f=0,g=0,i=0,l=0;S=(m=S)+208|0,f=(b|=0)<<2,c[(i=k=(j=m)+192|0)>>2]=1,c[i+4>>2]=0;a:do{if(0|f){for(c[j+4>>2]=4,d=b=c[j>>2]=4,e=2;(c[j+(e<<2)>>2]=b=b+4+d|0)>>>0<f>>>0;)i=d,d=b,e=e+1|0,b=i;if(a>>>0<(g=a+f+-4|0)>>>0){h=g,i=4+k|0,d=a,e=b=1;do{do{if(3!=(3&b|0)){if((0|c[j+((f=e+-1|0)<<2)>>2])>>>0<(h-d|0)>>>0?wc(d,e,j):yc(d,b,0|c[i>>2],e,0,j),1==(0|e)){zc(k,1),e=0;break}zc(k,f),e=1;break}}while(wc(d,e,j),xc(k,2),e=e+2|0,0)}while(b=1|c[k>>2],c[k>>2]=b,(d=d+4|0)>>>0<g>>>0);f=0|c[(g=i)>>2]}else g=4+k|0,f=0,d=a,e=b=1;for(yc(d,b,f,e,0,j),f=4+k|0;;){if(1==(0|e)&1==(0|b)){if(!(0|c[f>>2]))break a;l=21}else(0|e)<2?l=21:(zc(k,2),a=e+-2|0,c[k>>2]=7^c[k>>2],xc(k,1),yc(d+(0-(0|c[j+(a<<2)>>2]))+-4|0,0|c[k>>2],0|c[g>>2],e+-1|0,1,j),zc(k,1),b=1|c[k>>2],yc(d=d+-4|0,c[k>>2]=b,0|c[g>>2],a,1,j),e=a);21==(0|l)&&(xc(k,a=(l=0)|Ac(k)),b=0|c[k>>2],d=d+-4|0,e=a+e|0)}}}while(0);S=m}(e,h),c[(0|c[s>>2])+(u<<2)>>2]=h,u=u+1|0}while((0|u)<(0|c[20+(0|c[A>>2])>>2]))}}while(0);return Gb(Z),S=_,0|Z}function oa(a,b){var c,d;return 0|((d=+f[(a|=0)>>2])<(c=+f[(b|=0)>>2])?-1:c<d&1)}function pa(b){var d=0|a[4+(b|=0)>>0];c[b+704>>2]=b+(0|c[b+64>>2]),c[b+708>>2]=b+(0|c[b+68>>2]),c[b+712>>2]=b+(0|c[b+72>>2]),c[b+716>>2]=b+(0|c[b+76>>2]),c[b+720>>2]=b+(0|c[b+80>>2]),c[b+724>>2]=b+(0|c[b+84>>2]),c[b+728>>2]=b+(0|c[b+88>>2]),c[b+732>>2]=b+(0|c[b+92>>2]),c[b+736>>2]=b+(0|c[b+96>>2]),c[b+740>>2]=b+(0|c[b+100>>2]),c[b+744>>2]=b+(0|c[b+104>>2]),c[b+748>>2]=b+(0|c[b+108>>2]),c[b+752>>2]=b+(0|c[b+112>>2]),c[b+756>>2]=b+(0|c[b+116>>2]),c[b+760>>2]=b+(0|c[b+120>>2]),c[b+764>>2]=b+(0|c[b+124>>2]),c[b+768>>2]=b+(0|c[b+128>>2]),c[b+772>>2]=b+(0|c[b+132>>2]),c[b+776>>2]=b+(0|c[b+136>>2]),c[b+780>>2]=b+(0|c[b+140>>2]),c[b+784>>2]=b+(0|c[b+144>>2]),c[b+788>>2]=b+(0|c[b+148>>2]),c[b+796>>2]=b+(0|c[b+152>>2]),c[b+800>>2]=b+(0|c[b+156>>2]),c[b+804>>2]=b+(0|c[b+160>>2]),c[b+812>>2]=b+(0|c[b+164>>2]),c[b+816>>2]=b+(0|c[b+168>>2]),c[b+820>>2]=b+(0|c[b+172>>2]),c[b+828>>2]=b+(0|c[b+176>>2]),c[b+832>>2]=b+(0|c[b+180>>2]),c[b+836>>2]=b+(0|c[b+184>>2]),c[b+840>>2]=b+(0|c[b+188>>2]),c[b+844>>2]=b+(0|c[b+192>>2]),c[b+848>>2]=b+(0|c[b+196>>2]),c[b+852>>2]=b+(0|c[b+200>>2]),c[b+856>>2]=b+(0|c[b+204>>2]),c[b+860>>2]=b+(0|c[b+208>>2]),c[b+868>>2]=b+(0|c[b+212>>2]),c[b+872>>2]=b+(0|c[b+216>>2]),c[b+876>>2]=b+(0|c[b+220>>2]),c[b+880>>2]=b+(0|c[b+224>>2]),c[b+884>>2]=b+(0|c[b+228>>2]),c[b+888>>2]=b+(0|c[b+232>>2]),c[b+892>>2]=b+(0|c[b+236>>2]),c[b+896>>2]=b+(0|c[b+240>>2]),c[b+900>>2]=b+(0|c[b+244>>2]),c[b+904>>2]=b+(0|c[b+248>>2]),c[b+908>>2]=b+(0|c[b+252>>2]),c[b+912>>2]=b+(0|c[b+256>>2]),c[b+916>>2]=b+(0|c[b+260>>2]),c[b+920>>2]=b+(0|c[b+264>>2]),c[b+924>>2]=b+(0|c[b+268>>2]),c[b+928>>2]=b+(0|c[b+272>>2]),c[b+932>>2]=b+(0|c[b+276>>2]),c[b+936>>2]=b+(0|c[b+280>>2]),c[b+940>>2]=b+(0|c[b+284>>2]),c[b+948>>2]=b+(0|c[b+288>>2]),c[b+952>>2]=b+(0|c[b+292>>2]),c[b+976>>2]=b+(0|c[b+296>>2]),c[b+980>>2]=b+(0|c[b+300>>2]),c[b+984>>2]=b+(0|c[b+304>>2]),c[b+988>>2]=b+(0|c[b+308>>2]),c[b+992>>2]=b+(0|c[b+312>>2]),c[b+996>>2]=b+(0|c[b+316>>2]),c[b+1e3>>2]=b+(0|c[b+320>>2]),c[b+1004>>2]=b+(0|c[b+324>>2]),c[b+1008>>2]=b+(0|c[b+328>>2]),c[b+1012>>2]=b+(0|c[b+332>>2]),c[b+1016>>2]=b+(0|c[b+336>>2]),c[b+1020>>2]=b+(0|c[b+340>>2]),c[b+1024>>2]=b+(0|c[b+344>>2]),c[b+1028>>2]=b+(0|c[b+348>>2]),c[b+1040>>2]=b+(0|c[b+352>>2]),c[b+1044>>2]=b+(0|c[b+356>>2]),c[b+1048>>2]=b+(0|c[b+360>>2]),c[b+1032>>2]=b+(0|c[b+364>>2]),c[b+1036>>2]=b+(0|c[b+368>>2]),c[b+1132>>2]=b+(0|c[b+372>>2]),c[b+1136>>2]=b+(0|c[b+376>>2]),c[b+1140>>2]=b+(0|c[b+380>>2]),c[b+1144>>2]=b+(0|c[b+384>>2]),c[b+1148>>2]=b+(0|c[b+388>>2]),c[b+1152>>2]=b+(0|c[b+392>>2]),c[b+1156>>2]=b+(0|c[b+396>>2]),c[b+1160>>2]=b+(0|c[b+400>>2]),c[b+1164>>2]=b+(0|c[b+404>>2]),c[b+1168>>2]=b+(0|c[b+408>>2]),c[b+1172>>2]=b+(0|c[b+412>>2]),c[b+1176>>2]=b+(0|c[b+416>>2]),c[b+1180>>2]=b+(0|c[b+420>>2]),c[b+1184>>2]=b+(0|c[b+424>>2]),c[b+1188>>2]=b+(0|c[b+428>>2]),c[b+1192>>2]=b+(0|c[b+432>>2]),c[b+1196>>2]=b+(0|c[b+436>>2]),c[b+1200>>2]=b+(0|c[b+440>>2]),c[b+1204>>2]=b+(0|c[b+444>>2]),c[b+1208>>2]=b+(0|c[b+448>>2]),c[b+1212>>2]=b+(0|c[b+452>>2]),c[b+1216>>2]=b+(0|c[b+456>>2]),c[b+1220>>2]=b+(0|c[b+460>>2]),c[b+1224>>2]=b+(0|c[b+464>>2]),(255&d)<=1||(c[b+808>>2]=b+(0|c[b+468>>2]),(255&d)<=3||(c[b+964>>2]=b+(0|c[b+472>>2]),c[b+968>>2]=b+(0|c[b+476>>2]),c[b+972>>2]=b+(0|c[b+480>>2]),c[b+792>>2]=b+(0|c[b+484>>2]),c[b+824>>2]=b+(0|c[b+488>>2]),c[b+864>>2]=b+(0|c[b+492>>2]),c[b+1228>>2]=b+(0|c[b+496>>2]),c[b+1232>>2]=b+(0|c[b+500>>2]),c[b+1236>>2]=b+(0|c[b+504>>2]),c[b+1240>>2]=b+(0|c[b+508>>2]),c[b+1244>>2]=b+(0|c[b+512>>2]),c[b+1248>>2]=b+(0|c[b+516>>2]),c[b+944>>2]=b+(0|c[b+520>>2]),c[b+956>>2]=b+(0|c[b+524>>2]),c[b+960>>2]=b+(0|c[b+528>>2]),c[b+1052>>2]=b+(0|c[b+532>>2]),c[b+1056>>2]=b+(0|c[b+536>>2]),c[b+1060>>2]=b+(0|c[b+540>>2]),c[b+1064>>2]=b+(0|c[b+544>>2]),c[b+1068>>2]=b+(0|c[b+548>>2]),c[b+1072>>2]=b+(0|c[b+552>>2]),c[b+1076>>2]=b+(0|c[b+556>>2]),c[b+1080>>2]=b+(0|c[b+560>>2]),c[b+1084>>2]=b+(0|c[b+564>>2]),c[b+1088>>2]=b+(0|c[b+568>>2]),c[b+1092>>2]=b+(0|c[b+572>>2]),c[b+1096>>2]=b+(0|c[b+576>>2]),c[b+1100>>2]=b+(0|c[b+580>>2]),c[b+1104>>2]=b+(0|c[b+584>>2]),c[b+1108>>2]=b+(0|c[b+588>>2]),c[b+1112>>2]=b+(0|c[b+592>>2]),c[b+1116>>2]=b+(0|c[b+596>>2]),c[b+1120>>2]=b+(0|c[b+600>>2]),c[b+1124>>2]=b+(0|c[b+604>>2]),c[b+1128>>2]=b+(0|c[b+608>>2])))}function qa(d){d|=0;var n,o,p,e=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,q=0,r=0,s=0,t=S;if(S=S+32|0,g=t+24|0,c[(s=t)>>2]=4,c[s+4>>2]=2,c[s+8>>2]=2,function(a,b){var d,e;S=(a=S)+272|0,d=a+16|0,c[(e=a)>>2]=b|=0,bc(d,993,e),function(a){var b,d;S=(b=S)+16|0,c[(d=b)>>2]=a|=0,function(a,b,d){S=(b=S)+16|0,c[(a=b)>>2]=d|=0,cc(496,2518,a),S=b}(0,0,d),S=b}(d),S=a}(0,s),0|$b(d))return ia(0,1038,t+16|0),S=t,(s=0)|s;if(4<(255&(e=0|a[(h=d+4|0)>>0])))return c[g>>2]=4,c[g+4>>2]=255&e,ia(0,1101,g),S=t,(s=0)|s;if(0|a[(e=d+5|0)>>0]?(pb(h,1),qb(d+64|0,4,160),a[e>>0]=0,pa(d),e=0|a[h>>0],qb(0|c[(g=d+704|0)>>2],4,32),pb(0|c[(s=d+708|0)>>2],4),pb(4+(0|c[s>>2])|0,4),pb(8+(0|c[s>>2])|0,4),pb(12+(0|c[s>>2])|0,4),pb(16+(0|c[s>>2])|0,4),pb(20+(0|c[s>>2])|0,1),qb(0|c[d+720>>2],4,0|c[c[g>>2]>>2]),qb(0|c[d+724>>2],4,0|c[c[g>>2]>>2]),qb(0|c[d+728>>2],4,0|c[c[g>>2]>>2]),qb(0|c[d+732>>2],4,0|c[c[g>>2]>>2]),qb(0|c[d+736>>2],4,0|c[c[g>>2]>>2]),qb(0|c[d+740>>2],4,0|c[c[g>>2]>>2]),qb(0|c[d+752>>2],4,0|c[4+(0|c[g>>2])>>2]),qb(0|c[d+756>>2],4,0|c[4+(0|c[g>>2])>>2]),qb(0|c[d+760>>2],4,0|c[4+(0|c[g>>2])>>2]),qb(0|c[d+764>>2],4,0|c[4+(0|c[g>>2])>>2]),qb(0|c[d+768>>2],4,0|c[4+(0|c[g>>2])>>2]),qb(0|c[d+772>>2],4,0|c[4+(0|c[g>>2])>>2]),qb(0|c[d+776>>2],4,0|c[4+(0|c[g>>2])>>2]),qb(0|c[d+780>>2],4,0|c[8+(0|c[g>>2])>>2]),qb(0|c[d+784>>2],4,0|c[8+(0|c[g>>2])>>2]),qb(0|c[d+788>>2],4,0|c[8+(0|c[g>>2])>>2]),qb(0|c[d+796>>2],4,0|c[8+(0|c[g>>2])>>2]),qb(0|c[d+800>>2],4,0|c[8+(0|c[g>>2])>>2]),qb(0|c[d+804>>2],4,0|c[8+(0|c[g>>2])>>2]),qb(0|c[d+812>>2],4,0|c[12+(0|c[g>>2])>>2]),qb(0|c[d+816>>2],4,0|c[12+(0|c[g>>2])>>2]),qb(0|c[d+820>>2],4,0|c[12+(0|c[g>>2])>>2]),qb(0|c[d+828>>2],4,0|c[12+(0|c[g>>2])>>2]),qb(0|c[d+852>>2],4,0|c[16+(0|c[g>>2])>>2]),qb(0|c[d+856>>2],4,0|c[16+(0|c[g>>2])>>2]),qb(0|c[d+860>>2],4,0|c[16+(0|c[g>>2])>>2]),qb(0|c[d+868>>2],4,0|c[16+(0|c[g>>2])>>2]),qb(0|c[d+872>>2],4,0|c[16+(0|c[g>>2])>>2]),qb(0|c[d+876>>2],4,0|c[16+(0|c[g>>2])>>2]),qb(0|c[d+880>>2],4,0|c[16+(0|c[g>>2])>>2]),qb(0|c[d+884>>2],4,0|c[16+(0|c[g>>2])>>2]),qb(0|c[d+888>>2],1,0|c[16+(0|c[g>>2])>>2]),qb(0|c[d+892>>2],4,0|c[16+(0|c[g>>2])>>2]),qb(0|c[d+896>>2],4,0|c[16+(0|c[g>>2])>>2]),qb(0|c[d+900>>2],4,0|c[16+(0|c[g>>2])>>2]),qb(0|c[d+904>>2],4,0|c[16+(0|c[g>>2])>>2]),qb(0|c[d+908>>2],4,0|c[16+(0|c[g>>2])>>2]),qb(0|c[d+912>>2],4,0|c[16+(0|c[g>>2])>>2]),qb(0|c[d+924>>2],4,0|c[20+(0|c[g>>2])>>2]),qb(0|c[d+928>>2],4,0|c[20+(0|c[g>>2])>>2]),qb(0|c[d+932>>2],4,0|c[20+(0|c[g>>2])>>2]),qb(0|c[d+936>>2],4,0|c[20+(0|c[g>>2])>>2]),qb(0|c[d+940>>2],4,0|c[20+(0|c[g>>2])>>2]),qb(0|c[d+948>>2],4,0|c[20+(0|c[g>>2])>>2]),qb(0|c[d+952>>2],4,0|c[20+(0|c[g>>2])>>2]),qb(0|c[d+976>>2],4,0|c[24+(0|c[g>>2])>>2]),qb(0|c[d+980>>2],4,0|c[28+(0|c[g>>2])>>2]),qb(0|c[d+984>>2],4,0|c[28+(0|c[g>>2])>>2]),qb(0|c[d+988>>2],4,0|c[32+(0|c[g>>2])>>2]),qb(0|c[d+992>>2],4,0|c[32+(0|c[g>>2])>>2]),qb(0|c[d+996>>2],4,0|c[32+(0|c[g>>2])>>2]),qb(0|c[d+1e3>>2],4,0|c[32+(0|c[g>>2])>>2]),qb(0|c[d+1004>>2],4,0|c[32+(0|c[g>>2])>>2]),qb(0|c[d+1008>>2],4,0|c[32+(0|c[g>>2])>>2]),qb(0|c[d+1012>>2],4,0|c[32+(0|c[g>>2])>>2]),qb(0|c[d+1016>>2],4,0|c[36+(0|c[g>>2])>>2]),qb(0|c[d+1020>>2],4,0|c[36+(0|c[g>>2])>>2]),qb(0|c[d+1024>>2],4,0|c[36+(0|c[g>>2])>>2]),qb(0|c[d+1028>>2],4,0|c[40+(0|c[g>>2])>>2]),qb(0|c[d+1040>>2],4,0|c[44+(0|c[g>>2])>>2]),qb(0|c[d+1044>>2],4,0|c[48+(0|c[g>>2])>>2]),qb(0|c[d+1048>>2],4,0|c[48+(0|c[g>>2])>>2]),qb(0|c[d+1032>>2],4,0|c[52+(0|c[g>>2])>>2]),qb(0|c[d+1036>>2],4,0|c[52+(0|c[g>>2])>>2]),qb(0|c[d+1132>>2],4,0|c[56+(0|c[g>>2])>>2]),qb(0|c[d+1136>>2],4,0|c[60+(0|c[g>>2])>>2]),qb(0|c[d+1140>>2],2,0|c[64+(0|c[g>>2])>>2]),qb(0|c[d+1144>>2],4,0|c[68+(0|c[g>>2])>>2]),qb(0|c[d+1148>>2],4,0|c[72+(0|c[g>>2])>>2]),qb(0|c[d+1152>>2],4,0|c[72+(0|c[g>>2])>>2]),qb(0|c[d+1156>>2],4,0|c[72+(0|c[g>>2])>>2]),qb(0|c[d+1160>>2],4,0|c[72+(0|c[g>>2])>>2]),qb(0|c[d+1164>>2],4,0|c[72+(0|c[g>>2])>>2]),qb(0|c[d+1168>>2],4,0|c[76+(0|c[g>>2])>>2]),qb(0|c[d+1172>>2],4,0|c[76+(0|c[g>>2])>>2]),qb(0|c[d+1176>>2],4,0|c[76+(0|c[g>>2])>>2]),qb(0|c[d+1188>>2],4,0|c[80+(0|c[g>>2])>>2]),qb(0|c[d+1192>>2],4,0|c[80+(0|c[g>>2])>>2]),qb(0|c[d+1196>>2],4,0|c[80+(0|c[g>>2])>>2]),qb(0|c[d+1200>>2],4,0|c[80+(0|c[g>>2])>>2]),qb(0|c[d+1204>>2],4,0|c[80+(0|c[g>>2])>>2]),qb(0|c[d+1208>>2],4,0|c[80+(0|c[g>>2])>>2]),qb(0|c[d+1212>>2],4,0|c[80+(0|c[g>>2])>>2]),qb(0|c[d+1216>>2],4,0|c[84+(0|c[g>>2])>>2]),qb(0|c[d+1220>>2],2,0|c[84+(0|c[g>>2])>>2]),qb(0|c[d+1224>>2],4,0|c[88+(0|c[g>>2])>>2]),1<(255&e)&&(qb(0|c[d+808>>2],4,0|c[8+(0|c[g>>2])>>2]),3<(255&e))&&(qb(0|c[d+968>>2],4,0|c[20+(0|c[g>>2])>>2]),qb(0|c[d+972>>2],4,0|c[20+(0|c[g>>2])>>2]),qb(0|c[d+792>>2],4,0|c[8+(0|c[g>>2])>>2]),qb(0|c[d+824>>2],4,0|c[12+(0|c[g>>2])>>2]),qb(0|c[d+864>>2],4,0|c[16+(0|c[g>>2])>>2]),qb(0|c[d+1228>>2],4,0|c[92+(0|c[g>>2])>>2]),qb(0|c[d+1232>>2],4,0|c[92+(0|c[g>>2])>>2]),qb(0|c[d+1236>>2],4,0|c[92+(0|c[g>>2])>>2]),qb(0|c[d+1240>>2],4,0|c[96+(0|c[g>>2])>>2]),qb(0|c[d+1244>>2],4,0|c[96+(0|c[g>>2])>>2]),qb(0|c[d+1248>>2],4,0|c[96+(0|c[g>>2])>>2]),qb(0|c[d+944>>2],4,0|c[20+(0|c[g>>2])>>2]),qb(0|c[d+956>>2],4,0|c[20+(0|c[g>>2])>>2]),qb(0|c[d+960>>2],4,0|c[20+(0|c[g>>2])>>2]),qb(0|c[d+1052>>2],4,0|c[100+(0|c[g>>2])>>2]),qb(0|c[d+1056>>2],4,0|c[100+(0|c[g>>2])>>2]),qb(0|c[d+1060>>2],4,0|c[100+(0|c[g>>2])>>2]),qb(0|c[d+1064>>2],4,0|c[104+(0|c[g>>2])>>2]),qb(0|c[d+1068>>2],4,0|c[104+(0|c[g>>2])>>2]),qb(0|c[d+1072>>2],4,0|c[104+(0|c[g>>2])>>2]),qb(0|c[d+1076>>2],4,0|c[104+(0|c[g>>2])>>2]),qb(0|c[d+1080>>2],4,0|c[104+(0|c[g>>2])>>2]),qb(0|c[d+1084>>2],4,0|c[108+(0|c[g>>2])>>2]),qb(0|c[d+1088>>2],4,0|c[108+(0|c[g>>2])>>2]),qb(0|c[d+1092>>2],4,0|c[108+(0|c[g>>2])>>2]),qb(0|c[d+1096>>2],4,0|c[112+(0|c[g>>2])>>2]),qb(0|c[d+1100>>2],4,0|c[112+(0|c[g>>2])>>2]),qb(0|c[d+1104>>2],4,0|c[112+(0|c[g>>2])>>2]),qb(0|c[d+1108>>2],4,0|c[116+(0|c[g>>2])>>2]),qb(0|c[d+1112>>2],4,0|c[120+(0|c[g>>2])>>2]),qb(0|c[d+1116>>2],4,0|c[120+(0|c[g>>2])>>2]),qb(0|c[d+1120>>2],4,0|c[120+(0|c[g>>2])>>2]),qb(0|c[d+1124>>2],4,0|c[124+(0|c[g>>2])>>2]),qb(0|c[d+1128>>2],4,0|c[124+(0|c[g>>2])>>2]))):(pa(d),g=d+704|0),0|c[905]||(c[905]=1),e=0|c[g>>2],0<(0|c[e>>2]))for(h=d+716|0,i=d+712|0,j=0;c[(0|c[i>>2])+(j<<2)>>2]=(0|c[h>>2])+(j<<6),e=0|c[g>>2],(0|(j=j+1|0))<(0|c[e>>2]););if(0<(0|c[e+4>>2]))for(h=d+748|0,i=d+744|0,j=0;c[(0|c[i>>2])+(j<<2)>>2]=(0|c[h>>2])+(j<<6),e=0|c[g>>2],(0|(j=j+1|0))<(0|c[e+4>>2]););if(0<(0|c[e+16>>2]))for(k=d+848|0,l=d+832|0,r=d+1136|0,p=d+896|0,q=d+836|0,m=d+1140|0,n=d+900|0,o=d+840|0,h=d+1144|0,i=d+908|0,j=d+844|0,s=0;c[(0|c[l>>2])+(s<<2)>>2]=(0|c[k>>2])+(s<<6),c[(0|c[q>>2])+(s<<2)>>2]=(0|c[r>>2])+(c[(0|c[p>>2])+(s<<2)>>2]<<2),c[(0|c[o>>2])+(s<<2)>>2]=(0|c[m>>2])+(c[(0|c[n>>2])+(s<<2)>>2]<<1),c[(0|c[j>>2])+(s<<2)>>2]=(0|c[h>>2])+(c[(0|c[i>>2])+(s<<2)>>2]<<2),e=0|c[g>>2],(0|(s=s+1|0))<(0|c[e+16>>2]););if(0<(0|c[e+20>>2]))for(h=d+920|0,i=d+916|0,j=0;c[(0|c[i>>2])+(j<<2)>>2]=(0|c[h>>2])+(j<<6),e=0|c[g>>2],(0|(j=j+1|0))<(0|c[e+20>>2]););if(0<(0|c[e+80>>2]))for(h=d+1184|0,i=d+1180|0,j=0;c[(0|c[i>>2])+(j<<2)>>2]=(0|c[h>>2])+(j<<6),e=0|c[g>>2],(0|(j=j+1|0))<(0|c[e+80>>2]););if(1&a[20+(0|c[d+708>>2])>>0])return S=t,0|d;if((0|(m=0|c[e+16>>2]))<=0)return S=t,0|d;e=0|c[d+1140>>2],g=0|c[d+900>>2],h=0|c[d+904>>2],j=0;do{if(i=e+(c[g+(j<<2)>>2]<<1)|0,l=(s=0|c[h+(j<<2)>>2])-1|0,1<(0|s))for(k=0;r=0|b[(q=i+(k<<1)|0)>>1],b[q>>1]=0|b[(s=i+(k+2<<1)|0)>>1],b[s>>1]=r,(0|(k=k+3|0))<(0|l););}while((0|(j=j+1|0))!=(0|m));g=0|c[d+1136>>2],h=0|c[d+896>>2],i=0|c[d+892>>2],k=0;do{if(j=(e=g+(c[h+(k<<2)>>2]<<2)|0)+((s=0|c[i+(k<<2)>>2])<<1<<2)|0,0<(0|s))for(e=e+4|0;f[e>>2]=1-+f[e>>2],(e=e+8|0)>>>0<j>>>0;);}while((0|(k=k+1|0))!=(0|m));return S=t,0|d}function ra(a){var b=S;return S=S+16|0,0|$b(a|=0)?(ia(0,1210,b),S=b,(a=0)|a):(a=0|d[a+4>>0],S=b,0|a)}function ta(a){var j,k,l,m,b=0,e=0,f=0,g=0,h=0,i=0,e=64+(a|=0)|0,b=a+144|0;if(xa(e,0|c[a+88>>2],0|c[a+148>>2],0|c[b>>2]),za(e,0|c[a+92>>2],0|c[a+152>>2],0|c[796+(0|c[a>>2])>>2],2,0|c[b>>2]),!((0|d[4+(0|c[a>>2])>>0])<4||(xa(e,0|c[a+96>>2],0|c[(m=a+120|0)>>2],0|c[b>>2]),xa(e,0|c[a+100>>2],0|c[(f=a+124|0)>>2],0|c[b>>2]),xa(e,0|c[a+104>>2],0|c[(g=a+128|0)>>2],0|c[b>>2]),xa(e,0|c[a+108>>2],0|c[(j=a+132|0)>>2],0|c[b>>2]),xa(e,0|c[a+112>>2],0|c[(k=a+136|0)>>2],0|c[b>>2]),xa(e,0|c[a+116>>2],0|c[(l=a+140|0)>>2],0|c[b>>2]),b=0|c[a+156>>2],e=0|c[m>>2],f=0|c[f>>2],g=0|c[g>>2],(0|(m=0|c[a+56>>2]))<=0))){for(i=h=0;c[b+(h<<2)>>2]=c[e+(i<<2)>>2],c[b+((1|h)<<2)>>2]=c[f+(i<<2)>>2],c[b+((2|h)<<2)>>2]=c[g+(i<<2)>>2],(0|(i=i+1|0))!=(0|m);)h=h+4|0;for(i=0|c[a+160>>2],h=0|c[j>>2],g=0|c[k>>2],b=0|c[l>>2],f=e=0;c[i+(e<<2)>>2]=c[h+(f<<2)>>2],c[i+((1|e)<<2)>>2]=c[g+(f<<2)>>2],c[i+((2|e)<<2)>>2]=c[b+(f<<2)>>2],(0|(f=f+1|0))!=(0|m);)e=e+4|0}}function ua(a){var j,k,l,m,b=0,e=0,f=0,g=0,h=0,i=0,e=172+(a|=0)|0,b=a+264|0;if(xa(e,0|c[a+196>>2],0|c[a+268>>2],0|c[b>>2]),xa(e,0|c[a+200>>2],0|c[a+284>>2],0|c[b>>2]),xa(e,0|c[a+204>>2],0|c[a+276>>2],0|c[b>>2]),xa(e,0|c[a+208>>2],0|c[a+280>>2],0|c[b>>2]),xa(e,0|c[a+212>>2],0|c[a+272>>2],0|c[b>>2]),!((0|d[4+(0|c[a>>2])>>0])<4||(xa(e,0|c[a+216>>2],0|c[(m=a+240|0)>>2],0|c[b>>2]),xa(e,0|c[a+220>>2],0|c[(f=a+244|0)>>2],0|c[b>>2]),xa(e,0|c[a+224>>2],0|c[(g=a+248|0)>>2],0|c[b>>2]),xa(e,0|c[a+228>>2],0|c[(j=a+252|0)>>2],0|c[b>>2]),xa(e,0|c[a+232>>2],0|c[(k=a+256|0)>>2],0|c[b>>2]),xa(e,0|c[a+236>>2],0|c[(l=a+260|0)>>2],0|c[b>>2]),b=0|c[a+296>>2],e=0|c[m>>2],f=0|c[f>>2],g=0|c[g>>2],(0|(m=0|c[a+164>>2]))<=0))){for(i=h=0;c[b+(h<<2)>>2]=c[e+(i<<2)>>2],c[b+((1|h)<<2)>>2]=c[f+(i<<2)>>2],c[b+((2|h)<<2)>>2]=c[g+(i<<2)>>2],(0|(i=i+1|0))!=(0|m);)h=h+4|0;for(i=0|c[a+300>>2],h=0|c[j>>2],g=0|c[k>>2],b=0|c[l>>2],f=e=0;c[i+(e<<2)>>2]=c[h+(f<<2)>>2],c[i+((1|e)<<2)>>2]=c[g+(f<<2)>>2],c[i+((2|e)<<2)>>2]=c[b+(f<<2)>>2],(0|(f=f+1|0))!=(0|m);)e=e+4|0}}function va(a){var j,k,l,m,b=0,e=0,f=0,g=0,h=0,i=0,e=340+(a|=0)|0,b=a+424|0;if(xa(e,0|c[a+364>>2],0|c[a+448>>2],0|c[b>>2]),ya(e,0|c[a+368>>2],0|c[a+440>>2],0|c[b>>2]),za(e,0|c[a+372>>2],0|c[a+444>>2],0|c[892+(0|c[a>>2])>>2],2,0|c[b>>2]),!((0|d[4+(0|c[a>>2])>>0])<4||(xa(e,0|c[a+376>>2],0|c[(m=a+400|0)>>2],0|c[b>>2]),xa(e,0|c[a+380>>2],0|c[(f=a+404|0)>>2],0|c[b>>2]),xa(e,0|c[a+384>>2],0|c[(g=a+408|0)>>2],0|c[b>>2]),xa(e,0|c[a+388>>2],0|c[(j=a+412|0)>>2],0|c[b>>2]),xa(e,0|c[a+392>>2],0|c[(k=a+416|0)>>2],0|c[b>>2]),xa(e,0|c[a+396>>2],0|c[(l=a+420|0)>>2],0|c[b>>2]),b=0|c[a+452>>2],e=0|c[m>>2],f=0|c[f>>2],g=0|c[g>>2],(0|(m=0|c[a+332>>2]))<=0))){for(i=h=0;c[b+(h<<2)>>2]=c[e+(i<<2)>>2],c[b+((1|h)<<2)>>2]=c[f+(i<<2)>>2],c[b+((2|h)<<2)>>2]=c[g+(i<<2)>>2],(0|(i=i+1|0))!=(0|m);)h=h+4|0;for(i=0|c[a+456>>2],h=0|c[j>>2],g=0|c[k>>2],b=0|c[l>>2],f=e=0;c[i+(e<<2)>>2]=c[h+(f<<2)>>2],c[i+((1|e)<<2)>>2]=c[g+(f<<2)>>2],c[i+((2|e)<<2)>>2]=c[b+(f<<2)>>2],(0|(f=f+1|0))!=(0|m);)e=e+4|0}}function xa(a,b,d,e){b|=0,d|=0,e|=0;var m,n,o,g=0,h=0,i=0,j=0,k=0,l=0;if(0<(0|(g=0|c[8+(a|=0)>>2])))for(h=0|c[a+20>>2],i=0|c[a+12>>2],j=0;f[i+(j<<2)>>2]=+f[b+(j<<2)>>2]*+f[h+(j<<2)>>2],(0|(j=j+1|0))!=(0|g););if(!((0|(n=0|c[a>>2]))<=0))if(l=a+16|0,o=0|c[a+4>>2],m=a+12|0,e)for(b=j=0;;){if(0|c[e>>2]){if(h=(a=0|c[(0|c[l>>2])+(b<<2)>>2])+j|0,0<(0|a))for(g=0|c[m>>2],i=j,k=0;k+=+f[g+(i<<2)>>2],(0|(i=i+1|0))<(0|h););else k=0;f[d+(b<<2)>>2]=k}if((0|(g=b+1|0))==(0|n))break;e=e+4|0,j=(0|c[o+(b<<2)>>2])+j|0,b=g}else for(j=0|c[l>>2],a=b=0;;){if(h=(l=0|c[j+(a<<2)>>2])+b|0,0<(0|l))for(g=0|c[m>>2],i=b,k=0;k+=+f[g+(i<<2)>>2],(0|(i=i+1|0))<(0|h););else k=0;if(f[d+(a<<2)>>2]=k,(0|(g=a+1|0))==(0|n))break;b=(0|c[o+(a<<2)>>2])+b|0,a=g}}function ya(a,b,d,e){b|=0,d|=0,e|=0;var m,n,g=0,h=0,i=0,j=0,k=0,l=0;if(0<(0|(g=0|c[8+(a|=0)>>2])))for(h=0|c[a+20>>2],i=0|c[a+12>>2],j=0;f[i+(j<<2)>>2]=+f[b+(j<<2)>>2]*+f[h+(j<<2)>>2],(0|(j=j+1|0))!=(0|g););if(!((0|(g=0|c[a>>2]))<=0))if(l=a+16|0,m=0|c[a+4>>2],n=a+12|0,e)for(b=j=0;;){if(0|c[e>>2]){if(h=(i=0|c[(0|c[l>>2])+(b<<2)>>2])+j|0,0<(0|i))for(g=0|c[n>>2],i=j,k=0;k+=+f[g+(i<<2)>>2],(0|(i=i+1|0))<(0|h););else k=0;c[d+(b<<2)>>2]=~~(k+.0010000000474974513),g=0|c[a>>2]}if(!((0|(h=b+1|0))<(0|g)))break;e=e+4|0,j=(0|c[m+(b<<2)>>2])+j|0,b=h}else for(j=0|c[l>>2],e=b=0;;){if(h=(l=0|c[j+(e<<2)>>2])+b|0,0<(0|l))for(g=0|c[n>>2],i=b,k=0;k+=+f[g+(i<<2)>>2],(0|(i=i+1|0))<(0|h););else k=0;if(c[d+(e<<2)>>2]=~~(k+.0010000000474974513),!((0|(g=e+1|0))<(0|c[a>>2])))break;b=(0|c[m+(e<<2)>>2])+b|0,e=g}}function za(a,b,d,e,g,h){b|=0,d|=0,e|=0,g|=0,h|=0;var r,s,u,w,x,t,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;if(!((0|(t=0|c[(a|=0)>>2]))<=0))if(w=a+16|0,u=0|c[a+4>>2],s=a+20|0,r=g<<2,h)for(p=o=0;;){if(0|c[h>>2]&&(l=0|c[d+(p<<2)>>2],a=0|c[e+(p<<2)>>2],n=0|v(a,g),m=(i=0|c[(0|c[w>>2])+(p<<2)>>2])+o|0,(k=0<(0|n))&&Vc(0|l,0,0|v(r,a)),0<(0|i)&&(q=0|c[s>>2],k))){i=o;do{for(a=0|c[b+(i<<2)>>2],j=+f[q+(i<<2)>>2],k=0;f[(x=l+(k<<2)|0)>>2]=+f[x>>2]+j*+f[a+(k<<2)>>2],(0|(k=k+1|0))!=(0|n););}while((0|(i=i+1|0))<(0|m))}if((0|(a=p+1|0))==(0|t))break;h=h+4|0,o=(0|c[u+(p<<2)>>2])+o|0,p=a}else for(o=n=0;;){if(k=0|c[d+(o<<2)>>2],a=0|c[e+(o<<2)>>2],m=0|v(a,g),l=(h=0|c[(0|c[w>>2])+(o<<2)>>2])+n|0,(i=0<(0|m))&&Vc(0|k,0,0|v(r,a)),0<(0|h)&&(p=0|c[s>>2],i)){h=n;do{for(a=0|c[b+(h<<2)>>2],j=+f[p+(h<<2)>>2],i=0;f[(q=k+(i<<2)|0)>>2]=+f[q>>2]+j*+f[a+(i<<2)>>2],(0|(i=i+1|0))!=(0|m););}while((0|(h=h+1|0))<(0|l))}if((0|(a=o+1|0))==(0|t))break;n=(0|c[u+(o<<2)>>2])+n|0,o=a}}function Ha(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|function(a){a|=0;var b,e,d=S;return S=S+560|0,b=(e=d)+548|0,Vc(0|e,0,548),ma(a,e,b),S=d,0|c[b>>2]}(a),S=d,0|b):(c[b>>2]=1515,c[b+4>>2]=1533,ia(0,1269,b),S=d,(b=0)|b)}function Ia(a,b,d){b|=0,d|=0;var e,g,f=0,h=0,i=S;return S=S+32|0,h=i+24|0,g=i+16|0,f=i+8|0,e=i,(a|=0)?b?((f=b)+15&-16|0)!=(0|f)?(c[g>>2]=1551,c[4+g>>2]=1342,ia(0,1269,g),S=i,(h=0)|h):(b=0|na(a,b,d))?(S=i,0|b):(c[h>>2]=1551,c[h+4>>2]=1577,ia(0,1269,h),S=i,(h=0)|h):(c[f>>2]=1551,c[f+4>>2]=1303,ia(0,1269,f),S=i,(h=0)|h):(c[e>>2]=1551,c[e+4>>2]=1533,ia(0,1269,e),S=i,(h=0)|h)}function ob(a,b,c,d){if(c=+c,d=+d,(b=+u(+(b=+b),+(a=+a))-+u(+d,+c))<-3.1415927410125732)for(;(b+=6.2831854820251465)<-3.1415927410125732;);if(!(3.1415927410125732<b))return+b;for(;3.1415927410125732<(b+=-6.2831854820251465););return+b}function pb(b,c){var d;if(!((c=(b|=0)+(0|c)-1|0)>>>0<=b>>>0))for(;d=0|a[b>>0],a[b>>0]=0|a[c>>0],b=b+1|0,a[c>>0]=d,b>>>0<(c=c+-1|0)>>>0;);}function qb(b,c,d){b|=0,c|=0;var g,e=0,f=0;if(d|=0)do{if(d=d+-1|0,(f=b)>>>0<(e=(b=b+c|0)-1|0)>>>0)for(;g=0|a[f>>0],a[f>>0]=0|a[e>>0],f=f+1|0,a[e>>0]=g,f>>>0<(e=e+-1|0)>>>0;);}while(0!=(0|d))}function xb(a){var s,l,b=0,e=0,g=0,h=0,i=0,j=0,k=0,n=0,o=0,p=0,q=0,r=0,t=0,u=0,v=0,m=(b=0|c[(l=336+(a|=0)|0)>>2])+(20*(n=0|c[(o=a+332|0)>>2])|0)|0,p=a+424|0,i=0|c[a+48>>2],j=0|c[a+316>>2],k=0|c[a+308>>2];if(0<(0|n))for(n=0|c[p>>2],g=0|c[a+448>>2],h=0|c[a+444>>2];0|c[n>>2]&&(-1!=(0|(e=0|c[b+4>>2]))&&(f[g>>2]=+f[i+(e<<2)>>2]*+f[g>>2]),-1!=(0|(e=0|c[b+8>>2]))&&(f[g>>2]=+f[j+(e<<2)>>2]*+f[g>>2],r=0|c[h>>2],$[3&c[k+(e<<5)+24>>2]](a,e,r,r,0|c[b+16>>2]))),!(m>>>0<=(b=b+20|0)>>>0);)n=n+4|0,g=g+4|0,h=h+4|0;if(!((0|d[4+(0|c[a>>2])>>0])<4||(k=(b=0|c[l>>2])+(20*(r=0|c[o>>2])|0)|0,i=0|c[a+324>>2],j=0|c[a+328>>2],(0|r)<=0)))for(h=0|c[p>>2],e=b,g=0|c[a+452>>2],b=0|c[a+456>>2];0|c[h>>2]&&-1!=(0|(q=0|c[e+8>>2]))&&(t=+f[g>>2]*+f[(o=i+((p=q<<2)<<2)|0)>>2],f[g>>2]=t,u=+f[(r=g+4|0)>>2]*+f[4+o>>2],f[r>>2]=u,v=+f[(a=g+8|0)>>2]*+f[8+o>>2],f[g>>2]=t<0?0:1<t?1:t,f[r>>2]=u<0?0:1<u?1:u,f[a>>2]=v<0?0:1<v?1:v,f[g+12>>2]=1,v=+f[b>>2],u=+f[(p=j+(p<<2)|0)>>2],f[b>>2]=u=v+u-v*u,v=+f[(a=b+4|0)>>2],t=+f[p+4>>2],f[a>>2]=t=v+t-v*t,s=(v=+f[(r=b+8|0)>>2])+(s=+f[p+8>>2])-v*s,f[b>>2]=u<0?0:1<u?1:u,f[a>>2]=t<0?0:1<t?1:t,f[r>>2]=s<0?0:1<s?1:s,f[b+12>>2]=1),!(k>>>0<=(e=e+20|0)>>>0);)h=h+4|0,g=g+16|0,b=b+16|0}function yb(a){var e,b=0|c[332+(a|=0)>>2];0|c[a+428>>2]&&(Uc(0|c[a+460>>2],0|c[a+436>>2],0|(e=b<<2)),Uc(0|c[a+464>>2],0|c[a+440>>2],0|e),Uc(0|c[a+468>>2],0|c[a+448>>2],0|e),(0|d[4+(0|c[a>>2])>>0])<=3||(Uc(0|c[a+472>>2],0|c[a+452>>2],0|(e=b<<4)),Uc(0|c[a+476>>2],0|c[a+456>>2],0|e)))}function zb(b){var j,k,m,n,o,p,q,r,s,t,y,d=0,e=0,g=0,h=0,i=0,l=0,u=0,v=0,x=0,e=0|a[4+(0|c[(b|=0)>>2])>>0],w=0|c[b+332>>2],d=b+428|0;if(0|c[b+620>>2]){if(!(((c[d>>2]=0)|w)<=0))for(h=b+424|0,i=b+432|0,d=b+448|0,e=0;g=0!=(0|c[(0|c[h>>2])+(e<<2)>>2])&&0!=+f[(0|c[d>>2])+(e<<2)>>2]?127:126,a[(0|c[i>>2])+e>>0]=g,(0|(e=e+1|0))!=(0|w););}else if(0|c[d>>2]){if(!(((c[d>>2]=0)|w)<=0))if(m=b+424|0,p=b+432|0,o=b+448|0,r=b+468|0,n=b+440|0,q=b+464|0,t=b+436|0,s=b+460|0,j=b+452|0,l=b+472|0,k=b+456|0,i=b+476|0,(255&e)<=3)for(d=0;l=0==(0|c[(0|c[m>>2])+(d<<2)>>2]),x=+f[(0|c[o>>2])+(d<<2)>>2],v=(0|c[p>>2])+d|0,u=(1&a[v>>0])==(u=0!=x&(1^l)&1)<<24>>24?u:2|u,u=x!=+f[(0|c[r>>2])+(d<<2)>>2]?4|u:u,u=(0|c[(0|c[n>>2])+(d<<2)>>2])==(0|c[(0|c[q>>2])+(d<<2)>>2])?u:8|u,u=(0|c[(0|c[t>>2])+(d<<2)>>2])==(0|c[(0|c[s>>2])+(d<<2)>>2])?u:16|u,a[v>>0]=l?u:32|u,(0|(d=d+1|0))!=(0|w););else for(h=g=0;y=0==(0|c[(0|c[m>>2])+(g<<2)>>2]),x=+f[(0|c[o>>2])+(g<<2)>>2],e=(0|c[p>>2])+g|0,d=(1&a[e>>0])==(d=0!=x&(1^y)&1)<<24>>24?d:2|d,d=x!=+f[(0|c[r>>2])+(g<<2)>>2]?4|d:d,d=(0|c[(0|c[n>>2])+(g<<2)>>2])==(0|c[(0|c[q>>2])+(g<<2)>>2])?d:8|d,d=(0|c[(0|c[t>>2])+(g<<2)>>2])==(0|c[(0|c[s>>2])+(g<<2)>>2])?d:16|d,d=y?d:32|d,y=(0|c[j>>2])+(h<<2)|0,b=(0|c[l>>2])+(h<<2)|0,+f[y>>2]==+f[b>>2]&&+f[4+y>>2]==+f[b+4>>2]&&+f[8+y>>2]==+f[b+8>>2]&&+f[12+y>>2]==+f[b+12>>2]&&(u=(0|c[k>>2])+(h<<2)|0,v=(0|c[i>>2])+(h<<2)|0,+f[u>>2]==+f[v>>2])&&+f[u+4>>2]==+f[v+4>>2]&&+f[u+8>>2]==+f[v+8>>2]&&+f[u+12>>2]==+f[v+12>>2]||(d|=64),a[e>>0]=d,(0|(g=g+1|0))!=(0|w);)h=h+4|0}else if(!((0|w)<=0))for(g=b+424|0,h=b+432|0,d=b+448|0,e=0;0!=(0|c[(0|c[g>>2])+(e<<2)>>2])&&0!=+f[(0|c[d>>2])+(e<<2)>>2]?(v=(0|c[h>>2])+e|0,a[v>>0]=1|a[v>>0]):(v=(0|c[h>>2])+e|0,a[v>>0]=-2&a[v>>0]),(0|(e=e+1|0))!=(0|w););}function Bb(a){var C,D,E,F,G,b=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,H=0,I=0,J=0,K=0,k=0|c[(A=60+(a|=0)|0)>>2],b=0|c[a>>2],l=0|c[b+784>>2],m=0|c[(B=a+56|0)>>2],n=0|c[b+1028>>2];if(0<(0|m)){for(s=a+80|0,v=a+92|0,u=a+88|0,w=a+84|0,t=b+984|0,h=b+980|0,j=i=0;;){if(g=0|c[k+(24*i|0)>>2],15==(0|(z=0!=(0|c[(b=g+24|0)>>2])||0|c[g+28>>2]?15:z))&&(c[((z=0)|c[s>>2])+(i<<2)>>2]=c[(r=g+12|0)>>2],0|c[b>>2])&&(o=0|c[l+(i<<2)>>2],x=(p=0|c[g+16>>2])+((H=0|c[r>>2])<<2)|0,0<(0|H)))for(b=p,e=(0|c[u>>2])+(j<<2)|0,f=(0|c[v>>2])+(j<<2)|0;H=(0|c[b>>2])+o|0,c[f>>2]=n+(c[(0|c[t>>2])+(H<<2)>>2]<<2),c[e>>2]=c[(0|c[h>>2])+(H<<2)>>2],!(x>>>0<=(b=b+4|0)>>>0);)e=e+4|0,f=f+4|0;if(0|c[g+28>>2]&&(y=(q=0|c[g+20>>2])+((H=0|c[g+12>>2])<<2)|0,0<(0|H)))for(b=(0|c[w>>2])+(j<<2)|0,e=q;c[b>>2]=c[e>>2],!(y>>>0<=(e=e+4|0)>>>0);)b=b+4|0;if((0|(i=i+1|0))==(0|m))break;j=(0|c[g+8>>2])+j|0}b=0|c[a>>2]}if(!((0|d[b+4>>0])<4||(G=0|c[A>>2],H=0|c[b+792>>2],(0|(A=0|c[B>>2]))<=0)))for(D=a+96|0,C=a+100|0,B=a+104|0,F=a+108|0,E=a+112|0,z=a+116|0,x=b+1228|0,v=b+1232|0,u=b+1236|0,y=b+1240|0,w=b+1244|0,k=b+1248|0,m=l=0;;){if(b=0|c[G+(24*l|0)>>2],0|c[b+24>>2]&&(I=0|c[H+(l<<2)>>2],K=(J=0|c[b+16>>2])+((a=0|c[b+12>>2])<<2)|0,0<(0|a)))for(e=0|c[x>>2],f=0|c[v>>2],g=0|c[u>>2],h=0|c[y>>2],i=0|c[w>>2],j=0|c[k>>2],n=J,o=(0|c[B>>2])+(m<<2)|0,p=(0|c[C>>2])+(m<<2)|0,q=(0|c[D>>2])+(m<<2)|0,r=(0|c[z>>2])+(m<<2)|0,s=(0|c[E>>2])+(m<<2)|0,t=(0|c[F>>2])+(m<<2)|0;a=(0|c[n>>2])+I|0,c[q>>2]=c[e+(a<<2)>>2],c[p>>2]=c[f+(a<<2)>>2],c[o>>2]=c[g+(a<<2)>>2],c[t>>2]=c[h+(a<<2)>>2],c[s>>2]=c[i+(a<<2)>>2],c[r>>2]=c[j+(a<<2)>>2],!(K>>>0<=(n=n+4|0)>>>0);)o=o+4|0,p=p+4|0,q=q+4|0,r=r+4|0,s=s+4|0,t=t+4|0;if((0|(l=l+1|0))==(0|A))break;m=(0|c[b+8>>2])+m|0}}function Cb(a){var H,I,J,K,L,Q,b=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,M=0,N=0,O=0,P=0,T=0,U=0,V=0,W=0,S=0|c[168+(a|=0)>>2],R=0|c[a>>2],r=0|c[816+R>>2];if(0<(0|(s=0|c[(Q=a+164|0)>>2])))for(A=a+188|0,w=a+200|0,E=a+204|0,G=a+208|0,K=a+212|0,B=a+196|0,L=a+192|0,v=992+R|0,D=996+R|0,F=1e3+R|0,J=1004+R|0,C=988+R|0,H=1008+R|0,x=a+288|0,I=1012+R|0,y=a+292|0,O=N=0;;){if(t=0|c[S+(12*N|0)>>2],14==(0|(P=0!=(0|c[(b=t+24|0)>>2])||0|c[t+28>>2]?14:P))&&(c[((P=0)|c[A>>2])+(N<<2)>>2]=c[(z=t+12|0)>>2],0|c[b>>2])){if(b=0|c[r+(N<<2)>>2],k=(e=0|c[t+16>>2])+((q=0|c[z>>2])<<2)|0,0<(0|q))for(f=0|c[v>>2],g=0|c[D>>2],h=0|c[F>>2],i=0|c[J>>2],j=0|c[C>>2],l=(0|c[w>>2])+(O<<2)|0,m=e,n=(0|c[B>>2])+(O<<2)|0,o=(0|c[E>>2])+(O<<2)|0,p=(0|c[G>>2])+(O<<2)|0,q=(0|c[K>>2])+(O<<2)|0;W=(0|c[m>>2])+b|0,c[l>>2]=c[f+(W<<2)>>2],c[o>>2]=c[g+(W<<2)>>2],c[p>>2]=c[h+(W<<2)>>2],c[q>>2]=c[i+(W<<2)>>2],c[n>>2]=c[j+(W<<2)>>2],!(k>>>0<=(m=m+4|0)>>>0);)l=l+4|0,n=n+4|0,o=o+4|0,p=p+4|0,q=q+4|0;W=(0|c[e>>2])+b|0,c[(0|c[x>>2])+(N<<2)>>2]=c[(0|c[H>>2])+(W<<2)>>2],c[(0|c[y>>2])+(N<<2)>>2]=c[(0|c[I>>2])+(W<<2)>>2]}if(0|c[t+28>>2]&&(M=(u=0|c[t+20>>2])+((W=0|c[t+12>>2])<<2)|0,0<(0|W)))for(b=(0|c[L>>2])+(O<<2)|0,e=u;c[b>>2]=c[e>>2],!(M>>>0<=(e=e+4|0)>>>0);)b=b+4|0;if((0|(N=N+1|0))==(0|s))break;O=(0|c[t+8>>2])+O|0}if(!((0|d[4+R>>0])<4||(G=0|c[824+R>>2],(0|(A=0|c[Q>>2]))<=0)))for(D=a+216|0,C=a+220|0,B=a+224|0,F=a+228|0,E=a+232|0,z=a+236|0,x=1228+R|0,v=1232+R|0,u=1236+R|0,y=1240+R|0,w=1244+R|0,k=1248+R|0,m=l=0;;){if(j=0|c[S+(12*l|0)>>2],0|c[j+24>>2]&&(U=0|c[G+(l<<2)>>2],V=(T=0|c[j+16>>2])+((W=0|c[j+12>>2])<<2)|0,0<(0|W)))for(b=0|c[x>>2],e=0|c[v>>2],f=0|c[u>>2],g=0|c[y>>2],h=0|c[w>>2],i=0|c[k>>2],n=T,o=(0|c[B>>2])+(m<<2)|0,p=(0|c[C>>2])+(m<<2)|0,q=(0|c[D>>2])+(m<<2)|0,r=(0|c[z>>2])+(m<<2)|0,s=(0|c[E>>2])+(m<<2)|0,t=(0|c[F>>2])+(m<<2)|0;W=(0|c[n>>2])+U|0,c[q>>2]=c[b+(W<<2)>>2],c[p>>2]=c[e+(W<<2)>>2],c[o>>2]=c[f+(W<<2)>>2],c[t>>2]=c[g+(W<<2)>>2],c[s>>2]=c[h+(W<<2)>>2],c[r>>2]=c[i+(W<<2)>>2],!(V>>>0<=(n=n+4|0)>>>0);)o=o+4|0,p=p+4|0,q=q+4|0,r=r+4|0,s=s+4|0,t=t+4|0;if((0|(l=l+1|0))==(0|A))break;m=(0|c[j+8>>2])+m|0}}function Db(a){var F,G,b=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,H=0,I=0,J=0,K=0,l=0|c[(D=336+(a|=0)|0)>>2],b=0|c[a>>2],m=0|c[b+856>>2],n=0|c[(E=a+332|0)>>2],o=0|c[b+1028>>2];if(0<(0|n)){for(t=a+356|0,y=a+372|0,w=a+364|0,u=a+368|0,z=a+360|0,v=b+1024|0,x=b+1016|0,i=b+1020|0,k=j=0;;){if(h=0|c[l+(20*j|0)>>2],15==(0|(C=0!=(0|c[(b=h+24|0)>>2])||0|c[h+28>>2]?15:C))&&(c[((C=0)|c[t>>2])+(j<<2)>>2]=c[(s=h+12|0)>>2],0|c[b>>2])&&(p=0|c[m+(j<<2)>>2],A=(q=0|c[h+16>>2])+((H=0|c[s>>2])<<2)|0,0<(0|H)))for(b=(0|c[u>>2])+(k<<2)|0,e=q,f=(0|c[w>>2])+(k<<2)|0,g=(0|c[y>>2])+(k<<2)|0;H=(0|c[e>>2])+p|0,c[g>>2]=o+(c[(0|c[v>>2])+(H<<2)>>2]<<2),c[f>>2]=c[(0|c[x>>2])+(H<<2)>>2],c[b>>2]=c[(0|c[i>>2])+(H<<2)>>2],!(A>>>0<=(e=e+4|0)>>>0);)b=b+4|0,f=f+4|0,g=g+4|0;if(0|c[h+28>>2]&&(B=(r=0|c[h+20>>2])+((H=0|c[h+12>>2])<<2)|0,0<(0|H)))for(b=(0|c[z>>2])+(k<<2)|0,e=r;c[b>>2]=c[e>>2],!(B>>>0<=(e=e+4|0)>>>0);)b=b+4|0;if((0|(j=j+1|0))==(0|n))break;k=(0|c[h+8>>2])+k|0}b=0|c[a>>2]}if(!((0|d[b+4>>0])<4||(G=0|c[D>>2],H=0|c[b+864>>2],(0|(A=0|c[E>>2]))<=0)))for(D=a+376|0,C=a+380|0,B=a+384|0,F=a+388|0,E=a+392|0,z=a+396|0,x=b+1228|0,v=b+1232|0,u=b+1236|0,y=b+1240|0,w=b+1244|0,k=b+1248|0,m=l=0;;){if(b=0|c[G+(20*l|0)>>2],0|c[b+24>>2]&&(I=0|c[H+(l<<2)>>2],K=(J=0|c[b+16>>2])+((a=0|c[b+12>>2])<<2)|0,0<(0|a)))for(e=0|c[x>>2],f=0|c[v>>2],g=0|c[u>>2],h=0|c[y>>2],i=0|c[w>>2],j=0|c[k>>2],n=J,o=(0|c[B>>2])+(m<<2)|0,p=(0|c[C>>2])+(m<<2)|0,q=(0|c[D>>2])+(m<<2)|0,r=(0|c[z>>2])+(m<<2)|0,s=(0|c[E>>2])+(m<<2)|0,t=(0|c[F>>2])+(m<<2)|0;a=(0|c[n>>2])+I|0,c[q>>2]=c[e+(a<<2)>>2],c[p>>2]=c[f+(a<<2)>>2],c[o>>2]=c[g+(a<<2)>>2],c[t>>2]=c[h+(a<<2)>>2],c[s>>2]=c[i+(a<<2)>>2],c[r>>2]=c[j+(a<<2)>>2],!(K>>>0<=(n=n+4|0)>>>0);)o=o+4|0,p=p+4|0,q=q+4|0,r=r+4|0,s=s+4|0,t=t+4|0;if((0|(l=l+1|0))==(0|A))break;m=(0|c[b+8>>2])+m|0}}function Gb(a){var d,e,g,b=0;if(yb(a|=0),function(a){var e,g,b=0,d=0,h=0,j=0,k=0,i=(b=0|c[4+(a|=0)>>2])+(52*(h=0|c[a>>2])|0)|0;if(!((0|h)<=0))for(h=0|c[a+12>>2];d=+f[h>>2],a=b+4|0,d=(g=0==(0|c[b+16>>2]))?(k=+f[a>>2],j=+f[b+8>>2],d<k?k:j<d?j:d):(k=+f[b+12>>2],(j=+f[a>>2])+k*((d=(d-j)/k)-(0|~~+q(+d)))),a=b+48|0,+f[(e=b+44|0)>>2]!=d?(c[a>>2]=1,f[e>>2]=d):c[a>>2]=0,g&&(f[h>>2]=d),!(i>>>0<=(b=b+52|0)>>>0);)h=h+4|0}(a+540|0),function(a){var b=0,d=0,e=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,t=0,u=0,s=(b=0|c[544+(a|=0)>>2])+(52*(n=0|c[a+540>>2])|0)|0;if(!((0|n)<=0)){n=0==(0|c[a+620>>2]);do{a:do{if(0==(0|c[b>>2])&&(o=+f[b+44>>2],p=+f[b+20>>2],q=+f[b+24>>2],t=(r=0|c[b+28>>2])+(28*(l=0|c[b+32>>2])|0)|0,0<(0|l))){if(!n)for(l=r;;){h=0|c[l>>2];do{if(1<=(0|h)){if(g=0|c[l+4>>2],d=(e=+f[g>>2])-p,1==(0|h)){h=!(o<p+e)|!(d<o),d=a=0,m=41;break}if(o<d){g=l+16|0,i=1,d=a=0,m=43;break}if(o<p+e)d=a=h=0,m=41;else{for(a=1;!(o<p+(d=+f[g+(a<<2)>>2]));){if(!((0|(a=a+1|0))<(0|h))){m=40;break}e=d}if(40==(0|m)){g=l+16|0,a=h+-(i=1)|0,d=0,m=43;break}d=d-p<o?h=0:(a=a+-1|0,(d-=e)<q?h=0:(h=0,(o-e)/d)),m=41}}else d=a=h=0,m=41}while(0);if(41==(0|m)&&(h|(m=0)==(0|c[(g=l+16|0)>>2])?(i=1&h,m=43):(c[l+24>>2]=1,c[l+20>>2]=1,k=l+8|0,j=l+12|0,h=0)),43==(0|m)&&(e=+f[(j=l+12|(m=0))>>2],h=1&((0|c[(k=l+8|0)>>2])!=(0|a)|(u=e!=d)&(0==d|0==e)),c[l+24>>2]=1&u,c[l+20>>2]=h,h=i),f[j>>2]=d,c[k>>2]=a,c[g>>2]=h,t>>>0<=(l=l+28|0)>>>0)break a}if(!(0|c[b+48>>2]))for(a=r;;)if(c[a+24>>2]=0,t>>>(c[a+20>>2]=0)<=(a=a+28|0)>>>0)break a;l=r;do{h=0|c[l>>2];do{if(1<=(0|h)){if(g=0|c[l+4>>2],d=(e=+f[g>>2])-p,1==(0|h)){h=!(o<p+e)|!(d<o),d=a=0,m=24;break}if(o<d){g=l+16|0,i=1,d=a=0,m=26;break}if(o<p+e)d=a=h=0,m=24;else{for(a=1;!(o<p+(d=+f[g+(a<<2)>>2]));){if(!((0|(a=a+1|0))<(0|h))){m=21;break}e=d}if(21==(0|m)){g=l+16|0,a=h+-(i=1)|0,d=0,m=26;break}d=d-p<o?h=0:(a=a+-1|0,(d-=e)<q?h=0:(h=0,(o-e)/d)),m=24}}else d=a=h=0,m=24}while(0)}while(24==(0|m)&&(h|(m=0)==(0|c[(g=l+16|0)>>2])?(i=1&h,m=26):(c[l+24>>2]=1,c[l+20>>2]=1,k=l+8|0,j=l+12|0,h=0)),26==(0|m)&&(e=+f[(j=l+12|(m=0))>>2],h=1&((0|c[(k=l+8|0)>>2])!=(0|a)|(u=e!=d)&(0==d|0==e)),c[l+24>>2]=1&u,c[l+20>>2]=h,h=i),f[j>>2]=d,c[k>>2]=a,c[g>>2]=h,(l=l+28|0)>>>0<t>>>0)}}while(0)}while((b=b+52|0)>>>0
>>0)}}(a),Nb(a),function(a){var l,o,y,z,b=0,d=0,e=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,p=0,q=0,r=0,s=0,u=0,w=0,x=0,t=(b=0|c[568+(a|=0)>>2])+(36*(p=0|c[a+564>>2])|0)|0;if(!((0|p)<=0)){p=0==(0|c[a+620>>2]);do{o=0|c[b+4>>2];a:do{if(0<(0|o))for(i=0|c[b>>2],e=a=d=j=0;;){if(g=0|c[i+(j<<2)>>2],0|c[g+16>>2]){e=1,a=d=0;break a}if(e=e||0|c[g+24>>2],a=a||0|c[g+20>>2],d=d+(0!=+f[g+12>>2]&1)|0,(0|o)<=(0|(j=j+1|0))){i=d,x=11;break}}else e=a=i=0,x=11}while(0);b:do{if(11==(0|x))if(d=p?a:1,(x=0)!=((a=p?e:1)|d|0)&&(c[b+12>>2]=w=1<<i,q=0|c[b>>2],r=0|c[b+16>>2],s=0|c[b+20>>2],u=r+(w<<2)|0,31!=(0|i))){for(Vc(0|r,0,((e=r+4|0)>>>0<u>>>0?u:e)+~r+4&-4|0),e=s+(w<<2)|0,g=s;f[g>>2]=1,(g=g+4|0)>>>0<e>>>0;);if(1<=(0|o)){if(!i)for(i=0,k=1;;){if(g=0|c[q+(i<<2)>>2],j=0|v(0|c[g+8>>2],k),0==(h=+f[g+12>>2]))for(e=0;c[(n=r+(e<<2)|0)>>2]=(0|c[n>>2])+j,(0|(e=e+1|0))!=(0|w););else c[r>>2]=(0|c[r>>2])+j,f[s>>2]=(1-h)*+f[s>>2];if(k=0|v(0|c[g>>2],k),(0|(i=i+1|0))==(0|o)){e=0;break b}}m=0,n=e=1;do{if(l=0|c[q+(m<<2)>>2],g=0|c[8+l>>2],k=0|v(g,n),0==(h=+f[(j=12+l|0)>>2]))for(g=0;c[(j=r+(g<<2)|0)>>2]=(0|c[j>>2])+k,(0|(g=g+1|0))!=(0|w););else{for(i=0|v(g+1|0,n),c[r>>2]=(0|c[r>>2])+k,f[s>>2]=(1-h)*+f[s>>2],g=1;h=+f[j>>2],c[(y=r+(g<<2)|0)>>2]=((z=0!=(g&e|0))?i:k)+(0|c[y>>2]),f[(y=s+(g<<2)|0)>>2]=(z?h:1-h)*+f[y>>2],(0|(g=g+1|0))!=(0|w););e<<=1}}while(n=0|v(0|c[l>>2],n),(0|(m=m+1|0))!=(0|o));e=0}else e=0}else e=0}while(0)}while(c[b+28>>2]=a,c[b+24>>2]=d,c[b+32>>2]=e,(b=b+36|0)>>>0<t>>>0)}}(a),Ob(a),e=0|c[a+4>>2],d=(b=0|c[a+52>>2])+(e<<2)|0,0<(0|e))for(;g=+f[b>>2],f[b>>2]=g<0?0:1<g?1:g,(b=b+4|0)>>>0<d>>>0;);!function(a,b,d){d|=0;var e=0,f=(b|=0)+(12*(a|=0)|0)|0;if(!((0|a)<=0))for(e=d;;){do{if(0|c[b+8>>2]){if(-1!=(0|(a=0|c[b+4>>2]))&&0==(0|c[d+(a<<2)>>2])){a=0;break}a=0==(0|c[32+(0|c[b>>2])>>2])}else a=0}while(0);if(c[e>>2]=1&a,f>>>0<=(b=b+12|0)>>>0)break;e=e+4|0}}(e,0|c[a+8>>2],0|c[a+40>>2]),function(a){var e,f,i,q,r,n,b=0,d=0,g=0,h=0,k=0,l=0,o=0,p=0,s=0,t=0,u=0,j=0|c[8+(a|=0)>>2],b=0|c[a>>2],m=0|c[b+724>>2];if(!((0|(n=0|c[a+4>>2]))<=0))for(q=a+28|0,r=a+36|0,i=a+32|0,f=b+976|0,h=g=0;;){if(e=0|c[j+(12*g|0)>>2],6==(0|(u=0!=(0|c[(a=24+e|0)>>2])||0|c[28+e>>2]?6:u))&&(c[((u=0)|c[q>>2])+(g<<2)>>2]=c[(p=12+e|0)>>2],0|c[a>>2])&&(o=0|c[m+(g<<2)>>2],s=(k=0|c[16+e>>2])+((d=0|c[p>>2])<<2)|0,0<(0|d)))for(a=0|c[f>>2],b=(0|c[r>>2])+(h<<2)|0,d=k;c[b>>2]=c[a+((0|c[d>>2])+o<<2)>>2],!(s>>>0<=(d=d+4|0)>>>0);)b=b+4|0;if(0|c[28+e>>2]&&(t=(l=0|c[20+e>>2])+((d=0|c[12+e>>2])<<2)|0,0<(0|d)))for(a=(0|c[i>>2])+(h<<2)|0,b=l;c[a>>2]=c[b>>2],!(t>>>0<=(b=b+4|0)>>>0);)a=a+4|0;if((0|(g=g+1|0))==(0|n))break;h=(0|c[8+e>>2])+h|0}}(a),function(a){ya(12+(a|=0)|0,0|c[36+a>>2],0|c[44+a>>2],0|c[40+a>>2])}(a),function(a){var d,f,g,h,i,j,k,b=0,e=0;if(S=(k=S)+16|0,j=k,i=(b=0|c[308+(a|=0)>>2])+((e=0|c[a+304>>2])<<5)|0,f=0|c[a+40>>2],g=0|c[a+312>>2],h=0|c[a+144>>2],d=0|c[a+264>>2],(0|e)<=0)S=k;else{for(e=g;;){do{if(0|c[b+28>>2]){if(-1!=(0|(a=0|c[b+4>>2]))&&0==(0|c[f+(a<<2)>>2])){a=0;break}if(-1!=(0|(a=0|c[b+8>>2]))&&0==(0|c[g+(a<<2)>>2])){a=0;break}a=0==(0|c[32+(0|c[b>>2])>>2])}else a=0}while(0);switch(a&=1,c[e>>2]=a,0|c[b+12>>2]){case 0:c[h+(c[b+16>>2]<<2)>>2]=a;break;case 1:c[d+(c[b+16>>2]<<2)>>2]=a;break;default:ia(0,2458,j)}if(i>>>0<=(b=b+32|0)>>>0)break;e=e+4|0}S=k}}(a),Bb(a),Cb(a),ta(a),ua(a),function(a){var b=0,d=0,g=(b=0|c[336+(a|=0)>>2])+(20*(d=0|c[a+332>>2])|0)|0,e=0|c[a+40>>2],f=0|c[a+312>>2];if(!((0|d)<=0))for(d=0|c[a+424>>2];;){do{if(0|c[b+12>>2]){if(-1!=(0|(a=0|c[b+4>>2]))&&0==(0|c[e+(a<<2)>>2])){a=0;break}if(-1!=(0|(a=0|c[b+8>>2]))&&0==(0|c[f+(a<<2)>>2])){a=0;break}a=0==(0|c[32+(0|c[b>>2])>>2])}else a=0}while(0);if(c[d>>2]=1&a,g>>>0<=(b=b+20|0)>>>0)break;d=d+4|0}}(a),Db(a),va(a),function(a){var e,f,i,q,r,n,b=0,d=0,g=0,h=0,k=0,l=0,o=0,p=0,s=0,t=0,u=0,j=0|c[504+(a|=0)>>2],b=0|c[a>>2],m=0|c[b+1192>>2];if(!((0|(n=0|c[a+500>>2]))<=0))for(q=a+524|0,r=a+532|0,i=a+528|0,f=b+1224|0,h=g=0;;){if(e=0|c[j+(24*g|0)>>2],6==(0|(u=0!=(0|c[(a=24+e|0)>>2])||0|c[28+e>>2]?6:u))&&(c[((u=0)|c[q>>2])+(g<<2)>>2]=c[(p=12+e|0)>>2],0|c[a>>2])&&(o=0|c[m+(g<<2)>>2],s=(k=0|c[16+e>>2])+((d=0|c[p>>2])<<2)|0,0<(0|d)))for(a=0|c[f>>2],b=(0|c[r>>2])+(h<<2)|0,d=k;c[b>>2]=c[a+((0|c[d>>2])+o<<2)>>2],!(s>>>0<=(d=d+4|0)>>>0);)b=b+4|0;if(0|c[28+e>>2]&&(t=(l=0|c[20+e>>2])+((d=0|c[12+e>>2])<<2)|0,0<(0|d)))for(a=(0|c[i>>2])+(h<<2)|0,b=l;c[a>>2]=c[b>>2],!(t>>>0<=(b=b+4|0)>>>0);)a=a+4|0;if((0|(g=g+1|0))==(0|n))break;h=(0|c[8+e>>2])+h|0}}(a),function(a){xa(508+(a|=0)|0,0|c[532+a>>2],0|c[536+a>>2],0)}(a),fa(a),ha(a),function(a){var b=0,d=0,g=0,h=0,j=0,i=(b=0|c[8+(a|=0)>>2])+(12*(j=0|c[a+4>>2])|0)|0,e=0|c[a+48>>2];if(!((0|j)<=0))for(j=0|c[a+40>>2],d=e,a=0|c[a+52>>2];0|c[j>>2]&&(g=+f[a>>2],f[d>>2]=g,-1!=(0|(h=0|c[b+4>>2])))&&(f[d>>2]=g*+f[e+(h<<2)>>2]),!(i>>>0<=(b=b+12|0)>>>0);)j=j+4|0,d=d+4|0,a=a+4|0}(a),function(a){var b,d=0,e=0,f=0;if(!((0|(b=0|c[304+(a|=0)>>2]))<=0))for(d=0|c[312+a>>2],e=0|c[308+a>>2],f=0;0|c[d>>2]&&_[3&c[e+20>>2]](a,f),(0|(f=f+1|0))!=(0|b);)d=d+4|0,e=e+32|0}(a),xb(a),ea(a),function(a){var g,j,b=0,d=0,e=0,h=0,i=0;if(!(0|c[(a|=0)+624>>2]||(g=(b=0|c[a+336>>2])+(20*(h=0|c[a+332>>2])|0)|0,(0|h)<=0)))for(h=0|c[a+424>>2],a=0|c[a+444>>2];;){if(0|c[h>>2]&&(e=0|c[a>>2],i=(d=0|c[b+16>>2])<<1,0<(0|d)))for(d=1;f[(j=e+(d<<2)|0)>>2]=-+f[j>>2],(0|(d=d+2|0))<(0|i););if(g>>>0<=(b=b+20|0)>>>0)break;h=h+4|0,a=a+4|0}}(a),function(a){var n,b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,o=0,p=0,r=0,q=0|c[480+(a|=0)>>2],j=(r=0|c[a+484>>2])+(28*q|0)|0,b=0|c[a+440>>2],d=0|c[a+44>>2],e=0|c[a+40>>2],f=0|c[a+424>>2];if(!((0|q)<=0)){k=r;do{if(0<(0|(g=0|c[k+4>>2])))for(h=0|c[k+12>>2],i=k+20|0,l=0;p=0|c[h+(l<<4)+4>>2],o=1==(0|c[h+(l<<4)>>2]),c[h+(l<<4)+12>>2]=c[(0==(0|c[(o?e:f)+(p<<2)>>2])?i:(o?d:b)+(p<<2)|0)>>2],(0|(l=l+1|0))!=(0|g););}while((k=k+28|0)>>>0<j>>>0);n=0|c[a+436>>2],o=a+488|0,p=a+492|0,l=a+496|0,m=0;do{if(0<(0|c[(a=r+(28*m|0)+24|0)>>2])){for(b=0|c[o>>2],e=0;c[b+(e<<2)>>2]=-1,(0|(e=e+1|0))<(0|(d=0|c[a>>2])););if(0<(0|d))for(b=0|c[l>>2],d=0;c[b+(d<<2)>>2]=-1,(0|(d=d+1|0))<(0|c[a>>2]););}if(0<(0|c[(k=r+(28*m|0)+4|0)>>2])){for(j=0|c[p>>2],d=0;c[j+(d<<2)>>2]=-1,(0|(d=d+1|0))<(0|(b=0|c[k>>2])););if(0<(0|b))for(e=0|c[r+(28*m|0)+12>>2],g=r+(28*m|0)+20|0,f=0|c[l>>2],i=0;d=(0|c[e+(i<<4)+12>>2])-(0|c[g>>2])|0,b=-1==(0|(b=0|c[(h=f+(d<<2)|0)>>2]))?(0|c[o>>2])+(d<<2)|0:j+(b<<2)|0,c[b>>2]=i,(0|(i=(c[h>>2]=i)+1|0))<(0|c[k>>2]););}if(0<(0|(b=0|c[a>>2]))){i=0|c[o>>2],j=r+(28*m|0)+12|0,d=(h=0)|c[r+(28*m|0)+8>>2];do{if(-1!=(0|(e=0|c[i+(h<<2)>>2]))){for(f=0|c[j>>2],g=0|c[p>>2];d=(b=1==(0|c[f+(e<<4)>>2])?(b=0|c[f+(e<<4)+8>>2],c[r+(28*b|0)+8>>2]=d,0|c[r+(28*b|0)>>2]):(c[n+(c[f+(e<<4)+4>>2]<<2)>>2]=d,1))+d|0,!((0|(e=0|c[g+((k=e)<<2)>>2]))<=(0|k)|-1==(0|e)););b=0|c[a>>2]}}while((0|(h=h+1|0))<(0|b))}}while((0|(m=m+1|0))!=(0|q))}}(a),zb(a),c[a+620>>2]=0}function Nb(a){var l,s,b=0,e=0,g=0,h=0,i=0,j=0,k=0,m=0,n=0,o=0,p=0,q=0,r=0,t=0,u=0;if(!((0|d[4+(0|c[(a|=0)>>2])>>0])<4||(s=(b=0|c[a+544>>2])+(52*(l=0|c[a+540>>2])|0)|0,(0|l)<=0))){l=0==(0|c[a+620>>2]);do{a:do{if(1==(0|c[b>>2])&&(q=+f[b+44>>2],t=(r=0|c[b+36>>2])+(28*(k=0|c[b+40>>2])|0)|0,0<(0|k))){if(!l)for(j=r;;){g=0|c[j>>2];do{if(2<=(0|g)&&(o=0|c[j+4>>2],!(q<=(p=+f[o>>2])))){for(h=1,i=p;;){if(a=h+1|0,q<(e=+f[o+(h<<2)>>2])){k=25;break}if(!((0|a)<(0|g))){k=26;break}h=a,i=e}if(25==(0|k)){a=h+-1|0,e=(q-i)/(e-i);break}if(26==(0|k)){a=g+-1|0,e=0;break}}else e=a=0}while(0);if(i=+f[(h=j+16|0)>>2],g=1&((0|c[(k=j+12|0)>>2])!=(0|a)|(u=i!=e)&(0==e|0==i)),c[j+24>>2]=1&u,c[j+20>>2]=g,f[h>>2]=e,c[k>>2]=a,t>>>0<=(j=j+28|0)>>>0)break a}if(!(0|c[b+48>>2]))for(a=r;;)if(c[a+24>>2]=0,t>>>(c[a+20>>2]=0)<=(a=a+28|0)>>>0)break a;j=r;do{g=0|c[j>>2];do{if(2<=(0|g)&&(m=0|c[j+4>>2],!(q<=(n=+f[m>>2])))){for(h=1,i=n;;){if(a=h+1|0,q<(e=+f[m+(h<<2)>>2])){k=17;break}if(!((0|a)<(0|g))){k=18;break}h=a,i=e}if(17==(0|k)){a=h+-1|0,e=(q-i)/(e-i);break}if(18==(0|k)){a=g+-1|0,e=0;break}}else e=a=0}while(0)}while(i=+f[(k=j+16|0)>>2],h=1&((0|c[(u=j+12|0)>>2])!=(0|a)|(g=i!=e)&(0==e|0==i)),c[j+24>>2]=1&g,c[j+20>>2]=h,f[k>>2]=e,c[u>>2]=a,(j=j+28|0)>>>0<t>>>0)}}while(0)}while((b=b+52|0)>>>0
>>0)}}function Ob(a){var q,r,s,t,b=0,e=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;if(!((0|d[4+(0|c[(a|=0)>>2])>>0])<4||(t=(b=0|c[a+592>>2])+(48*(s=0|c[a+588>>2])|0)|0,(0|s)<=0))){s=0==(0|c[a+620>>2]);do{if(a=0|c[b>>2],g=s?0|c[a+24>>2]:1,(l=s?0|c[a+20>>2]:1)|g){k=0|c[a+12>>2],e=+f[a+16>>2],j=(0|k)==(0|(a=0|c[a+8>>2]));do{if(0!=e){if(i=k+1|0,j){e=(g=a=c[b+8>>2]=1)-e,j=11;break}a=(0|i)==(0|a)?1:2,j=10;break}}while(a=1&(1^j),j=10,0);10==(0|j)&&(j=0,c[b+8>>2]=a,g?(i=k,a=l,j=11):(i=k,a=l,g=0)),11==(0|j)&&(f[b+20>>2]=1-e,f[b+24>>2]=e),a?(c[b+12>>2]=i,c[b+16>>2]=i+1):a=0}else a=l;q=0|c[b+36>>2];a:do{if(0<(0|q)){if(r=0|c[b+40>>2],!s)for(p=0,e=1;;){o=0|c[r+(p<<2)>>2],j=0|c[o+4>>2],k=0|c[o+8>>2],l=0|c[o+12>>2],n=+f[44+(0|c[o>>2])>>2];do{if(1<=(0|l)){if(1==(0|l)){h=+f[k>>2];break}if(n<=(h=+f[j>>2])){h=+f[k>>2];break}for(i=1;;){if(n<(m=+f[j+(i<<2)>>2])){j=40;break}if(!((0|(i=i+1|0))<(0|l))){j=41;break}h=m}if(40==(0|j)){h=(1-(h=(n-h)/(m-h)))*+f[k+(i+-1<<2)>>2]+h*+f[k+(i<<2)>>2];break}if(41==(0|j)){h=+f[k+(l+-1<<2)>>2];break}}else h=1}while(0);if(e=e<(f[o+16>>2]=h)?e:h,(0|(p=p+1|0))==(0|q))break a}p=0,e=1;do{if(o=0|c[r+(p<<2)>>2],i=0|c[o>>2],0|c[i+48>>2]){j=0|c[o+4>>2],k=0|c[o+8>>2],l=0|c[o+12>>2],n=+f[i+44>>2];do{if(1<=(0|l)){if(1==(0|l)){h=+f[k>>2];break}if(n<=(h=+f[j>>2])){h=+f[k>>2];break}for(i=1;;){if(n<(m=+f[j+(i<<2)>>2])){j=28;break}if(!((0|(i=i+1|0))<(0|l))){j=27;break}h=m}if(27==(0|j)){h=+f[k+(l+-1<<2)>>2];break}if(28==(0|j)){h=(1-(h=(n-h)/(m-h)))*+f[k+(i+-1<<2)>>2]+h*+f[k+(i<<2)>>2];break}}else h=1}while(0);f[o+16>>2]=h}else h=+f[o+16>>2]}while(e=e<h?e:h,(0|(p=p+1|0))!=(0|q))}else e=1}while(0)}while(f[b+44>>2]=e,c[b+28>>2]=a,c[b+32>>2]=g,(b=b+48|0)>>>0<t>>>0)}}function _b(a,b){b|=0;var e,f,d=0;switch(g[h>>3]=a=+a,f=0|Rc(0|(d=0|c[h>>2]),0|(e=0|c[h+4>>2]),52),z(),2047&f){case 0:d=0!=a?(a=+_b(0x10000000000000000*a,b),(0|c[b>>2])-64|0):0,c[b>>2]=d;break;case 2047:break;default:c[b>>2]=(2047&f)-1022,c[h>>2]=d,c[h+4>>2]=-2146435073&e|1071644672,a=+g[h>>3]}return+a}function $b(b){var g,c=0,e=0,f=0,c=0|a[(b|=0)>>0];a:do{if(c<<24>>24)for(e=b,f=4,b=1033;;){if(!(c<<24>>24==(g=0|a[b>>0])<<24>>24&0!=(0|(f=f+-1|0))&g<<24>>24!=0))break a;if(b=b+1|0,!((c=0|a[(e=e+1|0)>>0])<<24>>24)){c=0;break}}else c=0,b=1033}while(0);return(255&c)-(0|d[b>>0])|0}function ac(a){return((0|a)-48|0)>>>0<10|0}function bc(b,d,e){b|=0,d|=0,e|=0;var f,i,j,h=0,g=S;S=S+144|0,Uc(0|(i=g),640,144),c[i+48>>2]=h=(h=-2-b|0)>>>0<256?h:256,c[(f=i+20|0)>>2]=b,j=(c[i+44>>2]=b)+h|0,c[(b=i+16|0)>>2]=j,c[i+28>>2]=j,cc(i,d,e),0|h&&(j=0|c[f>>2],a[j+(((0|j)==(0|c[b>>2]))<<31>>31)>>0]=0),S=g}function cc(a,b,c){fc(a|=0,b|=0,c|=0)}function dc(b,e,f,g,h,i){b|=0,e=+e,f|=0,g|=0,h|=0,i|=0;var C,B,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,w=0,x=0,y=0,A=0,D=0,E=0,F=0,G=0,H=S;S=S+560|0,m=H+32|0,E=12+(l=(F=G=H)+540|0)|(c[(t=H+536|0)>>2]=0),tc(e),B=(0|(j=0|z()))<0?(tc(e=-e),j=0|z(),D=1,2539):(D=0!=(2049&h|0)&1,0==(2048&h|0)?0==(1&h|0)?2540:2545:2542);do{if(!0&2146435072==(2146435072&j|0))G=0!=(32&i|0),oc(b,32,f,j=D+3|0,-65537&h),hc(b,B,D),hc(b,e!=e|!1?G?2566:2570:G?2558:2562,3),oc(b,32,f,j,8192^h);else{if((j=0!=(q=2*+_b(e,t)))&&(c[t>>2]=(0|c[t>>2])-1),97==(0|(w=32|i))){r=0==(0|(o=32&i))?B:9+B|0,p=2|D,j=12-g|0;do{if(!(11<g>>>0|0==(0|j))){for(e=8;e*=16,0!=(0|(j=j+-1|0)););if(45==(0|a[r>>0])){e=-(e+(-q-e));break}e=q+e-e;break}}while(e=q,0);for((0|(j=0|mc(j=(0|(k=0|c[t>>2]))<0?0-k|0:k,((0|j)<0)<<31>>31,E)))==(0|E)&&(a[(j=l+11|0)>>0]=48),a[j+-1>>0]=43+(k>>31&2),a[(n=j+-2|0)>>0]=i+15,k=(0|g)<1,l=0==(8&h|0),j=G;m=j+1|0,a[j>>0]=o|d[480+(D=~~e)>>0],e=16*(e-(0|D)),1!=(m-F|0)||l&k&0==e||(a[m>>0]=46,m=j+2|0),0!=e;)j=m;oc(b,32,f,E=(j=0!=(0|g)&&(-2-F+m|0)<(0|g)?g+2+(k=E)-(l=n)|0:(k=E)-F-(l=n)+m|0)+p|0,h),hc(b,r,p),oc(b,48,f,E,65536^h),hc(b,G,F=m-F|0),oc(b,48,j-(F+(G=k-l|0))|0,0,0),hc(b,n,G),oc(b,32,f,E,8192^h),j=E;break}for(k=(0|g)<0?6:g,e=j?(l=(0|c[t>>2])-28|0,c[t>>2]=l,268435456*q):(l=0|c[t>>2],q),m=C=(0|l)<0?m:m+288|0;c[m>>2]=y=~~e>>>0,m=m+4|0,0!=(e=1e9*(e-(y>>>0))););if(y=C,0<(0|l)){j=C;do{if(o=(0|l)<29?l:29,j>>>0<=(l=m+-4|0)>>>0){for(n=0;s=0|Mc(0|(s=0|Sc(0|c[l>>2],0,0|o)),0|z(),0|n,0),x=0|Mc(0|s,0|(u=0|z()),0|(x=0|Lc(0|(n=0|Qc(0|s,0|u,1e9,0)),0|z(),-1e9,-1)),0|z()),z(),c[l>>2]=x,j>>>0<=(l=l+-4|0)>>>0;);n&&(c[(j=j+-4|0)>>2]=n)}a:do{if(j>>>0<m>>>0)for(;;){if(0|c[(l=m+-4|0)>>2])break a;if(!(j>>>0<l>>>0)){m=l;break}m=l}}while(0)}while(l=(0|c[t>>2])-o|0,0<(0|(c[t>>2]=l)))}else j=C;if((0|l)<0){g=1+((k+25|0)/9|0)|0,s=102==(0|w);do{if(r=(0|(r=0-l|0))<9?r:9,j>>>0<m>>>0){for(o=(1<<r)-1|0,n=r?1e9>>>r:1e9,p=0,l=j;x=0|c[l>>2],c[l>>2]=(r?x>>>r:x)+p,p=0|v(x&o,n),(l=l+4|0)>>>0<m>>>0;);j=0==(0|c[j>>2])?j+4|0:j,p&&(c[m>>2]=p,m=m+4|0)}else j=0==(0|c[j>>2])?j+4|0:j}while(m=(0|g)<((x=m-(l=s?C:j)|0)>>2|0)?l+(g<<2)|0:m,l=(0|c[t>>2])+r|0,(0|(c[t>>2]=l))<0);s=m}else s=m;if(j>>>0
>>0){if(l=9*((y-j|0)>>2)|0,10<=(n=0|c[j>>2])>>>0)for(m=10;l=l+1|0,(m=10*m|0)>>>0<=n>>>0;);}else l=0;if((0|(m=k-(102==(0|w)?0:l)+(((u=0!=(0|k))&(t=103==(0|w)))<<31>>31)|0))<((9*((x=s-y|0)>>2)|0)-9|0)){if(g=C+4+((m=(0|(x=m+9216|0))/9|0)-1024<<2)|0,(0|(m=x+(0|v(m,-9))|0))<8)for(n=10;n=10*n|0,(0|m)<7;)m=m+1|0;else n=10;if((p=(g+4|0)==(0|s))&0==(0|(o=(o=0|c[g>>2])-(r=0|v(m=(o>>>0)/(n>>>0)|0,n))|0)))m=g;else if(q=0==(1&m|0)?9007199254740992:9007199254740994,e=o>>>0<(x=n>>>1)>>>0?.5:p&(0|o)==(0|x)?1:1.5,D&&(q=(x=45==(0|a[B>>0]))?-q:q,e=x?-e:e),c[g>>2]=r,q+e!=q){if(999999999<(c[g>>2]=x=r+n|0)>>>0)for(l=g;(m=l+-4|0)>>>(c[l>>2]=0)<j>>>0&&(c[(j=j+-4|0)>>2]=0),x=1+(0|c[m>>2])|0,999999999<(c[m>>2]=x)>>>0;)l=m;else m=g;if(l=9*((y-j|0)>>2)|0,10<=(o=0|c[j>>2])>>>0)for(n=10;l=l+1|0,(n=10*n|0)>>>0<=o>>>0;);}else m=g;x=j,j=(w=m+4|0)>>>0
>>0?w:s}else x=j,j=s;r=0-l|0;b:do{if(x>>>0<j>>>0)for(;;){if(0|c[(m=j+-4|0)>>2]){s=1,w=j;break b}if(!(x>>>0<m>>>0)){s=0,w=m;break}j=m}else s=0,w=j}while(0);do{if(t){if(n=(0|l)<(0|(j=k+(1&(1^u))|0))&-5<(0|l)?(k=j+-1-l|0,i+-1|0):(k=j+-1|0,i+-2|0),!(8&h)){if(s&&0!=(0|(A=0|c[w+-4>>2])))if((A>>>0)%10|0)m=0;else for(j=10,m=0;m=m+1|0,!((A>>>0)%((j=10*j|0)>>>0)|0););else m=9;if(j=(9*((w-y|0)>>2)|0)-9|0,102==(32|n)){k=(0|k)<(0|(i=0<(0|(i=j-m|0))?i:0))?k:i;break}k=(0|k)<(0|(i=0<(0|(i=j+l-m|0))?i:0))?k:i;break}}else n=i}while(0);if(o=(g=0!=(0|k))?1:h>>>3&1,p=102==(32|n))j=(u=0)<(0|l)?l:0;else{if(((m=E)-(j=0|mc(j=(0|l)<0?r:l,((0|j)<0)<<31>>31,E))|0)<2)for(;a[(j=j+-1|0)>>0]=48,(m-j|0)<2;);a[j+-1>>0]=43+(l>>31&2),a[(j=j+-2|0)>>0]=n,j=m-(u=j)|0}if(oc(b,32,f,j=D+1+k+o+j|0,h),hc(b,B,D),oc(b,48,f,j,65536^h),p){p=r=G+9|0,n=G+8|0,m=o=C>>>0<x>>>0?C:x;do{if(l=0|mc(0|c[m>>2],0,r),(0|m)==(0|o))(0|l)==(0|r)&&(a[n>>0]=48,l=n);else if(G>>>0<l>>>0)for(Vc(0|G,48,l-F|0);G>>>0<(l=l+-1|0)>>>0;);}while(hc(b,l,p-l|0),(m=m+4|0)>>>0<=C>>>0);if(0==(8&h|0)&(1^g)||hc(b,2574,1),m>>>0<w>>>0&0<(0|k))for(;;){if(G>>>0<(l=0|mc(0|c[m>>2],0,r))>>>0)for(Vc(0|G,48,l-F|0);G>>>0<(l=l+-1|0)>>>0;);if(hc(b,l,(0|k)<9?k:9),l=k+-9|0,!((m=m+4|0)>>>0<w>>>0&9<(0|k))){k=l;break}k=l}oc(b,48,k+9|0,9,0)}else{if(x>>>0<(g=s?w:x+4|0)>>>0&-1<(0|k)){t=0==(8&h|0),s=r=G+9|0,n=0-F|0,p=G+8|0,o=x;do{(0|(l=0|mc(0|c[o>>2],0,r)))==(0|r)&&(a[p>>0]=48,l=p);do{if((0|o)==(0|x)){if(m=l+1|0,hc(b,l,1),t&(0|k)<1){l=m;break}hc(b,2574,1),l=m}else{if(l>>>0<=G>>>0)break;for(Vc(0|G,48,l+n|0);G>>>0<(l=l+-1|0)>>>0;);}}while(0)}while(hc(b,l,(0|(F=s-l|0))<(0|k)?F:k),(o=o+4|0)>>>0<g>>>0&-1<(0|(k=k-F|0)))}oc(b,48,k+18|0,18,0),hc(b,u,E-u|0)}oc(b,32,f,j,8192^h)}}while(0);return S=H,0|((0|j)<(0|f)?f:j)}function fc(b,d,e){b|=0,d|=0,e|=0;var h,i,j,k,l,m,n,o,f=0,g=0,p=S;for(S=S+224|0,l=p+208|0,n=p+80|0,g=40+(f=o=(m=p)+160|0)|0;(0|(f=f+4|(c[f>>2]=0)))<(0|g););c[l>>2]=c[e>>2],0<=(0|gc(0,d,l,n,o))&&(k=32&(e=0|c[b>>2]),(0|a[b+74>>0])<1&&(c[b>>2]=-33&e),0|c[(g=b+48|0)>>2]?gc(b,d,l,n,o):(e=0|c[(f=b+44|0)>>2],c[f>>2]=m,c[(h=b+28|0)>>2]=m,c[(j=b+20|0)>>2]=m,c[g>>2]=80,c[(i=b+16|0)>>2]=m+80,gc(b,d,l,n,o),0|e&&(X[3&c[b+36>>2]](b,0,0),c[f>>2]=e,c[g>>2]=0,c[i>>2]=0,c[h>>2]=0,c[j>>2]=0)),c[b>>2]=c[b>>2]|k),S=p}function gc(d,e,f,h,i){d|=0,f|=0,h|=0,i|=0;var v,w,x,y,A,B,C,D,E,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,G=0,F=S;S=S+64|0,B=F+40|0,E=(w=F)+48|0,C=F+60|0,c[(D=F+56|0)>>2]=e|=0,A=0!=(0|d),y=v=w+40|0,w=w+39|0,x=4+E|0,m=j=e=0;a:for(;;){do{do{if(-1<(0|e)){if((2147483647-e|0)<(0|j)){c[922]=61,e=-1;break}e=j+e|0;break}}while(0);if(p=0|c[D>>2],!((j=0|a[p>>0])<<24>>24)){u=91;break a}k=p;b:for(;;){switch(j<<24>>24){case 37:u=10;break b;case 0:j=k;break b}c[D>>2]=t=k+1|0,j=0|a[t>>0],k=t}c:do{if(10==(0|u)){u=0,j=l=k;do{if(37!=(0|a[l+1>>0]))break c}while(j=j+1|0,c[D>>2]=l=l+2|0,37==(0|a[l>>0]))}}while(0)}while(j=j-p|0,A&&hc(d,p,j),0!=(0|j));if(l=0|c[D>>2],o=0|ac(j=0|a[l+1>>0])?(k=(o=36==(0|a[l+2>>0]))?3:1,r=o?j+-48|0:-1,o?1:m):(r=-(k=1),m),c[D>>2]=k=l+k|0,31<(l=((j=0|a[k>>0])<<24>>24)-32|0)>>>0|0==(1<<l&75913|0))n=0;else for(j=0;;){if(m=1<<l|j,c[D>>2]=k=k+1|0,31<(l=((j=0|a[k>>0])<<24>>24)-32|0)>>>0|0==(1<<l&75913|0)){n=m;break}j=m}if(j<<24>>24==42){if(0!=(0|ac(j=0|a[(l=k+1|0)>>0]))&&36==(0|a[k+2>>0]))c[i+(j+-48<<2)>>2]=10,m=1,j=k+3|0,k=0|c[h+((0|a[l>>0])-48<<3)>>2];else{if(0|o){e=-1;break}A?(m=3+(0|c[f>>2])&-4,k=0|c[m>>2],c[f>>2]=m+4,m=0,j=l):(j=l,k=m=0)}l=c[D>>2]=j,q=(s=(0|k)<0)?8192|n:n,t=m,s=s?0-k|0:k}else{if((0|(j=0|ic(D)))<0){e=-1;break}l=0|c[D>>2],q=n,t=o,s=j}do{if(46==(0|a[l>>0])){if(42!=(0|a[(j=l+1|0)>>0])){c[D>>2]=j,n=0|ic(D),j=0|c[D>>2];break}if(0|ac(k=0|a[(j=l+2|0)>>0])&&36==(0|a[l+3>>0])){c[i+(k+-48<<2)>>2]=10,n=0|c[h+((0|a[j>>0])-48<<3)>>2],c[D>>2]=j=l+4|0;break}if(0|t){e=-1;break a}A?(o=3+(0|c[f>>2])&-4,k=0|c[o>>2],c[f>>2]=o+4):k=0,c[D>>2]=j,n=k}else j=l,n=-1}while(0);for(o=0;;){if(57<((0|a[j>>0])-65|0)>>>0){e=-1;break a}if(c[D>>2]=k=j+1|0,!(((m=255&(l=0|a[(0|a[j>>0])-65+(16+(58*o|0))>>0]))-1|0)>>>0<8))break;j=k,o=m}if(!(l<<24>>24)){e=-1;break}k=-1<(0|r);do{if(l<<24>>24==19){if(k){e=-1;break a}u=52}else{if(k){c[i+(r<<2)>>2]=m,r=0|c[4+(m=h+(r<<3)|0)>>2],c[(u=B)>>2]=c[m>>2],c[u+4>>2]=r,u=52;break}if(!A){e=0;break a}jc(B,m,f),u=53}}while(0);52==(0|u)&&(u=0,A?u=53:j=0);d:do{if(53==(0|u)){l=(u=0)!=(0|o)&3==(15&(l=0|a[j>>0])|0)?-33&l:l,j=-65537&q,r=0==(8192&q|0)?q:j;e:do{switch(0|l){case 110:switch((255&o)<<24>>24){case 0:case 1:c[c[B>>2]>>2]=e,j=0;break d;case 2:j=0|c[B>>2],c[j>>2]=e,c[j+4>>2]=((0|e)<0)<<31>>31,j=0;break d;case 3:b[c[B>>2]>>1]=e,j=0;break d;case 4:a[c[B>>2]>>0]=e,j=0;break d;case 6:c[c[B>>2]>>2]=e,j=0;break d;case 7:j=0|c[B>>2],c[j>>2]=e,c[j+4>>2]=((0|e)<0)<<31>>31,j=0;break d;default:j=0;break d}case 112:j=8|r,k=8<n>>>0?n:8,m=120,u=65;break;case 88:case 120:j=r,k=n,m=l,u=65;break;case 111:n=0==(8&(j=r)|0)|(0|(l=y-(o=0|function(b,c,d){if(d|=0,!(0==(0|(b|=0))&0==(0|(c|=0))))for(;a[(d=d+-1|0)>>0]=7&b|48,!(0==(0|(b=0|Rc(0|b,0|c,3)))&0==(0|(c=0|z()))););return 0|d}(p=0|c[(q=B)>>2],q=0|c[q+4>>2],v))|0))<(0|n)?n:l+1|0,l=0,k=2522,u=71;break;case 105:case 100:if(j=0|c[(k=B)>>2],(0|(k=0|c[k+4>>2]))<0){j=0|Nc(0,0,0|j,0|k),k=0|z(),c[(l=B)>>2]=j,c[l+4>>2]=k,l=1,m=2522,u=70;break e}l=0!=(2049&r|0)&1,m=0==(2048&r|0)?0==(1&r|0)?2522:2524:2523,u=70;break e;case 117:j=0|c[(k=B)>>2],k=0|c[k+4>>2],l=0,m=2522,u=70;break;case 99:a[w>>0]=c[B>>2],p=w,o=j,m=1,l=0,k=2522,j=y;break;case 115:p=q=0==(0|(q=0|c[B>>2]))?2532:q,o=j,m=(G=0==(0|(r=0|function(b,d){b|=0;var e=0,f=0,e=0!=(0|(d|=0));a:do{if(e&0!=(3&b|0))for(;;){if(!(0|a[b>>0]))break a;if(!((e=0!=(0|(d=d+-1|0)))&0!=(3&(b=b+1|0)|0))){f=5;break}}else f=5}while(0);b:do{if(5==(0|f)){do{if(e){if(!(0|a[b>>0])){if(d)break b;break}c:do{if(3<d>>>0)for(;;){if((-2139062144&(e=0|c[b>>2])^-2139062144)&e+-16843009|0)break c;if(b=b+4|0,(d=d+-4|0)>>>0<=3){f=11;break}}else f=11}while(0);if(11==(0|f)&&!d)break;for(;;){if(!(0|a[b>>0]))break b;if(!(d=d+-1|0))break;b=b+1|0}}}while(0);b=0}}while(0);return 0|b}(q,n))))?n:r-q|0,l=0,k=2522,j=G?q+n|0:r;break;case 67:c[E>>2]=c[B>>2],c[x>>2]=0,l=c[B>>2]=E,n=-1,u=78;break;case 83:if(n){l=0|c[B>>2],u=78;break e}oc(d,32,s,0,r),j=0,u=88;break e;case 65:case 71:case 70:case 69:case 97:case 103:case 102:case 101:j=0|dc(d,+g[B>>3],s,n,r,l);break d;default:o=r,m=n,l=0,k=2522,j=y}}while(0);f:do{if(65==(0|u))o=0|kc(p=0|c[(q=B)>>2],q=0|c[q+4>>2],v,32&m),n=k,l=(G=0==(8&j|0)|0==(0|p)&0==(0|q))?0:2,k=G?2522:2522+(m>>>4)|0,u=71;else if(70==(0|u))o=0|mc(p=j,q=k,v),j=r,k=m,u=71;else if(78==(0|u)){for(j=u=0,o=l;k=0|c[o>>2];){if((m=(0|(k=0|pc(C,k)))<0)|(n-j|0)>>>0<k>>>0){u=82;break}if(!((j=k+j|0)>>>0<n>>>0))break;o=o+4|0}if(82==(0|u)&&(u=0,m)){e=-1;break a}if(oc(d,32,s,j,r),j)for(m=0;;){if(!(k=0|c[l>>2])){u=88;break f}if((0|j)<(0|(m=(k=0|pc(C,k))+m|0))){u=88;break f}if(hc(d,C,k),j>>>0<=m>>>0){u=88;break}l=l+4|0}else j=0,u=88}}while(0);if(71==(0|u))G=(u=0)!=(0|n)|(m=0!=(0|p)|0!=(0|q)),m=y-o+(1&(1^m))|0,p=G?o:v,o=-1<(0|n)?-65537&j:j,m=G?(0|m)<(0|n)?n:m:0,j=y;else if(88==(0|u)){u=0,oc(d,32,s,j,8192^r),j=(0|j)<(0|s)?s:j;break}oc(d,32,j=(0|s)<(0|(G=(q=(0|m)<(0|(r=j-p|0))?r:m)+l|0))?G:s,G,o),hc(d,k,l),oc(d,48,j,G,65536^o),oc(d,48,q,r,0),hc(d,p,r),oc(d,32,j,G,8192^o)}}while(0);m=t}g:do{if(91==(0|u)&&!d)if(m){for(e=1;j=0|c[i+(e<<2)>>2];)if(jc(h+(e<<3)|0,j,f),10<=(e=e+1|0)>>>0){e=1;break g}for(j=0;;){if(e=e+1|0,0|j){e=-1;break g}if(10<=e>>>0){e=1;break g}j=0|c[i+(e<<2)>>2]}}else e=0}while(0);return S=F,0|e}function hc(a,b,d){b|=0,d|=0,32&c[(a|=0)>>2]||rc(b,d,a)}function ic(b){var d=0,e=0,f=0,e=0|c[(b|=0)>>2];if(0|ac((d=0|a[e>>0])<<24>>24))for(f=d,d=0;d=(10*d|0)-48+(f<<24>>24)|0,c[b>>2]=e=e+1|0,0!=(0|ac((f=0|a[e>>0])<<24>>24)););else d=0;return 0|d}function jc(a,b,d){a|=0,b|=0,d|=0;var h,e=0,f=0;a:do{if(b>>>0<=20)switch(0|b){case 9:e=3+(0|c[d>>2])&-4,b=0|c[e>>2],c[d>>2]=e+4,c[a>>2]=b;break a;case 10:e=3+(0|c[d>>2])&-4,b=0|c[e>>2],c[d>>2]=e+4,c[(e=a)>>2]=b,c[e+4>>2]=((0|b)<0)<<31>>31;break a;case 11:e=3+(0|c[d>>2])&-4,b=0|c[e>>2],c[d>>2]=e+4,c[(e=a)>>2]=b,c[e+4>>2]=0;break a;case 12:e=7+(0|c[d>>2])&-8,f=0|c[(b=e)>>2],b=0|c[b+4>>2],c[d>>2]=e+8,c[(e=a)>>2]=f,c[e+4>>2]=b;break a;case 13:f=3+(0|c[d>>2])&-4,e=0|c[f>>2],c[d>>2]=f+4,c[(f=a)>>2]=e=(65535&e)<<16>>16,c[f+4>>2]=((0|e)<0)<<31>>31;break a;case 14:f=3+(0|c[d>>2])&-4,e=0|c[f>>2],c[d>>2]=f+4,c[(f=a)>>2]=65535&e,c[f+4>>2]=0;break a;case 15:f=3+(0|c[d>>2])&-4,e=0|c[f>>2],c[d>>2]=f+4,c[(f=a)>>2]=e=(255&e)<<24>>24,c[f+4>>2]=((0|e)<0)<<31>>31;break a;case 16:f=3+(0|c[d>>2])&-4,e=0|c[f>>2],c[d>>2]=f+4,c[(f=a)>>2]=255&e,c[f+4>>2]=0;break a;case 17:f=7+(0|c[d>>2])&-8,h=+g[f>>3],c[d>>2]=f+8,g[a>>3]=h;break a;case 18:!function(a,b){a|=0;var e=7+(0|c[(b|=0)>>2])&-8,d=+g[e>>3];c[b>>2]=8+e,g[a>>3]=d}(a,d);break a;default:break a}}while(0)}function kc(b,c,e,f){if(e|=0,f|=0,!(0==(0|(b|=0))&0==(0|(c|=0))))for(;a[(e=e+-1|0)>>0]=0|d[480+(15&b)>>0]|f,!(0==(0|(b=0|Rc(0|b,0|c,4)))&0==(0|(c=0|z()))););return 0|e}function mc(b,c,d){d|=0;var e,f=0,g=0;if(0<(c|=0)>>>0|0==(0|c)&4294967295<(b|=0)>>>0)for(;g=0|Mc(0|(e=b),0|(f=c),0|(g=0|Lc(0|(b=0|Qc(0|b,0|c,10,0)),0|(c=0|z()),-10,-1)),0|z()),z(),a[(d=d+-1|0)>>0]=255&g|48,9<f>>>0|9==(0|f)&4294967295<e>>>0;);if(b)for(;f=255&((g=b)+(0|v(b=(b>>>0)/10|0,-10))|48),a[(d=d+-1|0)>>0]=f,10<=g>>>0;);return 0|d}function oc(a,b,c,d,e){a|=0,b|=0;var f,g=S;if(S=S+256|0,f=g,(0|(d|=0))<(0|(c|=0))&0==(73728&(e|=0)|0)){if(Vc(0|f,b<<24>>24|0,0|((e=c-d|0)>>>0<256?e:256)),255<e>>>0){for(d=e;hc(a,f,256),255<(d=d+-256|0)>>>0;);e&=255}hc(a,f,e)}S=g}function pc(a,b){return b|=0,0|((a|=0)?0|qc(a,b):0)}function qc(b,d){b|=0,d|=0;do{if(b){if(d>>>0<128){a[b>>0]=d,b=1;break}if(!(0|c[916])){if(57216==(-128&d|0)){a[b>>0]=d,b=1;break}c[922]=25,b=-1;break}if(d>>>0<2048){a[b>>0]=d>>>6|192,a[b+1>>0]=63&d|128,b=2;break}if(d>>>0<55296|57344==(-8192&d|0)){a[b>>0]=d>>>12|224,a[b+1>>0]=d>>>6&63|128,a[b+2>>0]=63&d|128,b=3;break}if((d+-65536|0)>>>0<1048576){a[b>>0]=d>>>18|240,a[b+1>>0]=d>>>12&63|128,a[b+2>>0]=d>>>6&63|128,a[b+3>>0]=63&d|128,b=4;break}c[922]=25,b=-1;break}}while(b=1,0);return 0|b}function rc(b,d,e){b|=0,d|=0;var i,f=0,g=0,h=0;(f=0|c[(g=16+(e|=0)|0)>>2])?h=5:0|function(b){var d=0,e=0|a[(d=74+(b|=0)|0)>>0];return a[d>>0]=255+e|e,0|(d=8&(d=0|c[b>>2])?(c[b>>2]=32|d,-1):(c[8+b>>2]=0,d=(c[4+b>>2]=0)|c[44+b>>2],c[28+b>>2]=d,c[20+b>>2]=d,c[16+b>>2]=d+(0|c[48+b>>2]),0))}(e)||(f=0|c[g>>2],h=5);a:do{if(5==(0|h)){if((f-(g=h=0|c[(i=e+20|0)>>2])|0)>>>0<d>>>0){X[3&c[e+36>>2]](e,b,d);break}b:do{if((0|a[e+75>>0])<0|0==(0|d))f=d;else{for(h=d;10!=(0|a[b+(f=h+-1|0)>>0]);){if(!f){f=d;break b}h=f}if((0|X[3&c[e+36>>2]](e,b,h))>>>0<h>>>0)break a;g=0|c[i>>2],f=d-h|0,b=b+h|0}}while(0);Uc(0|g,0|b,0|f),c[i>>2]=(0|c[i>>2])+f}}while(0)}function tc(b){return g[h>>3]=b=+b,b=0|c[h>>2],y(0|c[h+4>>2]),0|b}function wc(a,b,d){b|=0,d|=0;var g,h,i,e=0,f=0,j=S;S=S+240|0,c[(i=j)>>2]=a|=0;a:do{if(1<(0|b))for(f=e=a,a=1;;){if(-1<(0|oa(e,g=(f=f+-4|0)+(0-(0|c[d+((h=b+-2|0)<<2)>>2]))|0))&&-1<(0|oa(e,f)))break a;if(e=i+(a<<2)|0,a=a+1|0,(0|(b=-1<(0|oa(g,f))?(f=c[e>>2]=g,b+-1|0):(c[e>>2]=f,h)))<=1)break a;e=0|c[i>>2]}else a=1}while(0);Cc(i,a),S=j}function xc(a,b){var d=0,e=0,f=4+(a|=0)|0;31<(b|=0)>>>0?(d=0|c[f>>2],c[a>>2]=d,b=b+-32|(e=c[f>>2]=0)):(d=0|c[a>>2],e=0|c[f>>2]),c[a>>2]=e<<32-b|(b?d>>>b:d),c[f>>2]=b?e>>>b:e}function yc(a,b,d,e,f,g){a|=0,d|=0,e|=0,f|=0,g|=0;var j,k,l,h=0,i=0,m=S;S=S+240|0,c[(k=(l=m)+232|0)>>2]=b|=0,c[(j=4+k|0)>>2]=d,c[l>>2]=a;a:do{if(1!=(0|b)|0!=(0|d)&&1<=(0|oa(h=a+(0-(0|c[g+(e<<2)>>2]))|0,a)))for(b=h,i=1,h=0==(0|f);;){if(h&1<(0|e)){if(-1<(0|oa(h=a+-4|0,b))){b=a,h=i,d=10;break a}if(-1<(0|oa(h+(0-(0|c[g+(e+-2<<2)>>2]))|0,b))){b=a,h=i,d=10;break a}}if(d=i+1|0,c[l+(i<<2)>>2]=b,xc(k,f=0|Ac(k)),e=f+e|0,!(1!=(0|c[k>>2])|0!=(0|c[j>>2]))){h=d,d=10;break a}if((0|oa(h=b+(0-(0|c[g+(e<<2)>>2]))|0,0|c[l>>2]))<1){h=d,d=10;break}a=b,b=h,i=d,h=1}else d=9}while(0);9==(0|d)&&0==(0|f)&&(b=a,h=1,d=10),10==(0|d)&&(Cc(l,h),wc(b,e,g)),S=m}function zc(a,b){var d=0,e=0,g=4+(a|=0)|0;31<(b|=0)>>>0?(d=0|c[a>>2],c[g>>2]=d,b=b+-32|(e=c[a>>2]=0)):(d=0|c[g>>2],e=0|c[a>>2]),c[g>>2]=((g=32-b|0)?e>>>g:e)|d<<b,c[a>>2]=e<<b}function Ac(a){var b;return(b=0|Bc((0|c[(a|=0)>>2])-1|0))?0|b:0|(0==(0|(a=0|Bc(0|c[a+4>>2])))?0:a+32|0)}function Bc(a){var b=0;if(a|=0)if(1&a)b=0;else for(b=0;b=b+1|0,!(2&a);)a>>>=1;else b=32;return 0|b}function Cc(a,b){a|=0;var f,d=0,e=S;if(S=S+256|0,d=e,2<=(0|(b|=0)))for(Uc(0|(c[a+(b<<2)>>2]=d),0|c[a>>2],4),d=0;Uc(0|c[(f=a+(d<<2)|0)>>2],0|c[a+((d=d+1|0)<<2)>>2],4),c[f>>2]=4+(0|c[f>>2]),(0|d)!=(0|b););S=e}function Ec(a){a|=0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=S;S=S+16|0,n=w;do{if(a>>>0<245){if(m=0|c[923],3&(d=(a=(k=a>>>0<11?16:a+11&-8)>>>3)?m>>>a:m)|0)return a=0|c[(b=8+(f=3732+((e=(1&d^1)+a|0)<<1<<2)|0)|0)>>2],(0|(d=0|c[(g=a+8|0)>>2]))==(0|f)?c[923]=m&~(1<<e):(c[d+12>>2]=f,c[b>>2]=d),c[a+4>>2]=3|(v=e<<3),c[(v=a+v+4|0)>>2]=1|c[v>>2],S=w,0|g;if((l=0|c[925])>>>0<k>>>0){if(0|d)return g=0|c[(b=8+(d=3732+((e=((a=(e=(i=(e=((e=d<<a&((e=2<<a)|0-e))&0-e)-1|0)>>>12&16)?e>>>i:e)>>>5&8)|i|(g=(e=a?e>>>a:e)>>>2&4)|(b=(e=g?e>>>g:e)>>>1&2)|(d=(e=b?e>>>b:e)>>>1&1))+(d?e>>>d:e)|0)<<1<<2)|0)|0)>>2],(0|(a=0|c[(i=g+8|0)>>2]))==(0|d)?c[923]=a=m&~(1<<e):(c[a+12>>2]=d,c[b>>2]=a,a=m),h=(v=e<<3)-k|0,c[g+4>>2]=3|k,c[4+(f=g+k|0)>>2]=1|h,c[g+v>>2]=h,0|l&&(e=0|c[928],d=3732+((b=l>>>3)<<1<<2)|0,a=a&(b=1<<b)?0|c[(b=a=d+8|0)>>2]:(c[923]=a|b,b=d+8|0,d),c[b>>2]=e,c[a+12>>2]=e,c[e+8>>2]=a,c[e+12>>2]=d),c[925]=h,c[928]=f,S=w,0|i;if(g=0|c[924]){for(j=0|c[3996+(((e=(j=(f=(j=(g&0-g)-1|0)>>>12&16)?j>>>f:j)>>>5&8)|f|(h=(j=e?j>>>e:j)>>>2&4)|(d=(j=h?j>>>h:j)>>>1&2)|(i=(j=d?j>>>d:j)>>>1&1))+(i?j>>>i:j)<<2)>>2],i=(-8&c[j+4>>2])-k|0,d=j;(a=0|c[d+16>>2])||(a=0|c[d+20>>2]);)i=(h=(d=(-8&c[a+4>>2])-k|0)>>>0<i>>>0)?d:i,d=a,j=h?a:j;if(j>>>0<(h=j+k|0)>>>0){f=0|c[j+24>>2],b=0|c[j+12>>2];do{if((0|b)==(0|j)){if(!(b=0|c[(a=j+20|0)>>2])&&!(b=0|c[(a=j+16|0)>>2])){d=0;break}for(;;)if(d=0|c[(e=b+20|0)>>2])b=d,a=e;else{if(!(d=0|c[(e=b+16|0)>>2]))break;b=d,a=e}c[a>>2]=0,d=b}else d=0|c[j+8>>2],c[d+12>>2]=b,c[b+8>>2]=d,d=b}while(0);do{if(0|f){if(b=0|c[j+28>>2],(0|j)==(0|c[(a=3996+(b<<2)|0)>>2])){if(!(c[a>>2]=d)){c[924]=g&~(1<<b);break}}else if(!(c[((0|c[(v=f+16|0)>>2])==(0|j)?v:f+20|0)>>2]=d))break;c[d+24>>2]=f,0|(b=0|c[j+16>>2])&&(c[d+16>>2]=b,c[b+24>>2]=d),0|(b=0|c[j+20>>2])&&(c[d+20>>2]=b,c[b+24>>2]=d)}}while(0);return i>>>0<16?(c[j+4>>2]=3|(v=i+k|0),c[(v=j+v+4|0)>>2]=1|c[v>>2]):(c[j+4>>2]=3|k,c[h+4>>2]=1|i,c[h+i>>2]=i,0|l&&(e=0|c[928],d=3732+((b=l>>>3)<<1<<2)|0,a=(b=1<<b)&m?0|c[(b=a=d+8|0)>>2]:(c[923]=b|m,b=d+8|0,d),c[b>>2]=e,c[a+12>>2]=e,c[e+8>>2]=a,c[e+12>>2]=d),c[925]=i,c[928]=h),S=w,j+8|0}m=k}else m=k}else m=k}else if(a>>>0<=4294967231)if(k=-8&(a=a+11|0),e=0|c[924]){d=0-k|0,j=(a>>>=8)?16777215<k>>>0?31:1&((r=7+(j=14-((i=(520192+(j=a<<(m=(a+1048320|0)>>>16&8))|0)>>>16&4)|m|(r=(245760+(j<<=i)|0)>>>16&2))+(j<<r>>>15)|0)|0)?k>>>r:k)|j<<1:0,a=0|c[3996+(j<<2)>>2];a:do{if(a)for(h=k<<(31==((f=0)|j)?0:25-(j>>>1)|0),i=a,a=0;;){if((g=(-8&c[i+4>>2])-k|0)>>>0<d>>>0){if(!g){d=0,a=f=i,r=65;break a}d=g,a=i}if(f=0==(0|(r=0|c[i+20>>2]))|(0|r)==(0|(i=0|c[i+16+(h>>>31<<2)>>2]))?f:r,!i){r=61;break}h<<=1}else a=f=0,r=61}while(0);if(61==(0|r)){if(0==(0|f)&0==(0|a)){if(!(a=((a=2<<j)|0-a)&e)){m=k;break}f=0|c[3996+(((h=(f=(i=(f=(a&0-a)-1|0)>>>12&16)?f>>>i:f)>>>5&8)|i|(j=(f=h?f>>>h:f)>>>2&4)|(m=(f=j?f>>>j:f)>>>1&2)|(a=(f=m?f>>>m:f)>>>1&1))+(a?f>>>a:f)<<2)>>2],a=0}f?r=65:(i=d,g=a)}if(65==(0|r))for(;;){if(d=(g=(m=(-8&c[f+4>>2])-k|0)>>>0<d>>>0)?m:d,g=g?f:a,!(a=(a=0|c[f+16>>2])||0|c[f+20>>2])){i=d;break}f=a,a=g}if(0!=(0|g)&&i>>>0<((0|c[925])-k|0)>>>0&&g>>>0<(l=g+k|0)>>>0){h=0|c[g+24>>2],b=0|c[g+12>>2];do{if((0|b)==(0|g)){if(!(b=0|c[(a=g+20|0)>>2])&&!(b=0|c[(a=g+16|0)>>2])){b=0;break}for(;;)if(d=0|c[(f=b+20|0)>>2])b=d,a=f;else{if(!(d=0|c[(f=b+16|0)>>2]))break;b=d,a=f}c[a>>2]=0}else v=0|c[g+8>>2],c[v+12>>2]=b,c[b+8>>2]=v}while(0);do{if(h){if(a=0|c[g+28>>2],(0|g)==(0|c[(d=3996+(a<<2)|0)>>2])){if(!(c[d>>2]=b)){e&=~(1<<a),c[924]=e;break}}else if(!(c[((0|c[(v=h+16|0)>>2])==(0|g)?v:h+20|0)>>2]=b))break;c[b+24>>2]=h,0|(a=0|c[g+16>>2])&&(c[b+16>>2]=a,c[a+24>>2]=b),(a=0|c[g+20>>2])&&(c[b+20>>2]=a,c[a+24>>2]=b)}}while(0);b:do{if(i>>>0<16)c[g+4>>2]=3|(v=i+k|0),c[(v=g+v+4|0)>>2]=1|c[v>>2];else{if(c[g+4>>2]=3|k,c[l+4>>2]=1|i,b=(c[l+i>>2]=i)>>>3,i>>>0<256){d=3732+(b<<1<<2)|0,a=(a=0|c[923])&(b=1<<b)?0|c[(b=a=d+8|0)>>2]:(c[923]=a|b,b=d+8|0,d),c[b>>2]=l,c[a+12>>2]=l,c[l+8>>2]=a,c[l+12>>2]=d;break}if(b=3996+((d=(b=i>>>8)?16777215<i>>>0?31:1&((v=7+(d=14-((t=(520192+(d=b<<(u=(b+1048320|0)>>>16&8))|0)>>>16&4)|u|(v=(245760+(d<<=t)|0)>>>16&2))+(d<<v>>>15)|0)|0)?i>>>v:i)|d<<1:0)<<2)|0,c[l+28>>2]=d,c[4+(a=l+16|0)>>2]=0,c[a>>2]=0,!(e&(a=1<<d))){c[924]=e|a,c[b>>2]=l,c[l+24>>2]=b,c[l+12>>2]=l,c[l+8>>2]=l;break}b=0|c[b>>2];c:do{if((-8&c[b+4>>2]|0)!=(0|i)){for(e=i<<(31==(0|d)?0:25-(d>>>1)|0);a=0|c[(d=b+16+(e>>>31<<2)|0)>>2];){if((-8&c[a+4>>2]|0)==(0|i)){b=a;break c}e<<=1,b=a}c[d>>2]=l,c[l+24>>2]=b,c[l+12>>2]=l,c[l+8>>2]=l;break b}}while(0);v=0|c[(u=b+8|0)>>2],c[v+12>>2]=l,c[u>>2]=l,c[l+8>>2]=v,c[l+12>>2]=b,c[l+24>>2]=0}}while(0);return S=w,g+8|0}m=k}else m=k;else m=-1}while(0);if(m>>>0<=(d=0|c[925])>>>0)return b=0|c[928],15<(a=d-m|0)>>>0?(c[928]=v=b+m|0,c[925]=a,c[v+4>>2]=1|a,c[b+d>>2]=a,c[b+4>>2]=3|m):(c[925]=0,c[928]=0,c[b+4>>2]=3|d,c[(v=b+d+4|0)>>2]=1|c[v>>2]),S=w,b+8|0;if(m>>>0<(h=0|c[926])>>>0)return c[926]=t=h-m|0,v=0|c[929],c[929]=u=v+m|0,c[u+4>>2]=1|t,c[v+4>>2]=3|m,S=w,v+8|0;if(i=m+48|0,(k=(g=(a=0|c[1041]?0|c[1043]:(c[1043]=4096,c[1042]=4096,c[1044]=-1,c[1045]=-1,c[1046]=0,c[1034]=0,c[1041]=-16&n^1431655768,4096))+(j=m+47|0)|0)&(e=0-a|0))>>>0<=m>>>0)return S=w,(v=0)|v;if(0|(a=0|c[1033])&&(n=(l=0|c[1031])+k|0)>>>0<=l>>>0|a>>>0<n>>>0)return S=w,(v=0)|v;d:do{if(4&c[1034])b=0,r=143;else{d=0|c[929];e:do{if(d){for(f=4140;!((a=0|c[f>>2])>>>0<=d>>>0&&(a+(0|c[(q=f+4|0)>>2])|0)>>>0>d>>>0);){if(!(a=0|c[f+8>>2])){r=128;break e}f=a}if((b=g-h&e)>>>0<2147483647)if((0|(a=0|Jc(b)))==((0|c[f>>2])+(0|c[q>>2])|0)){if(-1!=(0|a)){h=a,g=b,r=145;break d}}else e=a,r=136;else b=0}else r=128}while(0);do{if(128==(0|r))if(-1!=(0|(d=0|Jc(0)))&&(b=d,p=(b=(0==((p=(o=0|c[1042])-1|0)&b|0)?0:(p+b&0-o)-b|0)+k|0)+(o=0|c[1031])|0,m>>>0<b>>>0&b>>>0<2147483647)){if(0|(q=0|c[1033])&&p>>>0<=o>>>0|q>>>0<p>>>0){b=0;break}if((0|(a=0|Jc(b)))==(0|d)){h=d,g=b,r=145;break d}e=a,r=136}else b=0}while(0);do{if(136==(0|r)){if(d=0-b|0,!(b>>>0<i>>>0&b>>>0<2147483647&-1!=(0|e))){if(-1==(0|e)){b=0;break}h=e,g=b,r=145;break d}if(2147483647<=(a=j-b+(a=0|c[1043])&0-a)>>>0){h=e,g=b,r=145;break d}if(-1==(0|Jc(a))){Jc(d),b=0;break}h=e,g=a+b|0,r=145;break d}}while(0);c[1034]=4|c[1034],r=143}}while(0);if(143==(0|r)&&k>>>0<2147483647&&!(-1==(0|(s=0|Jc(k)))|1^(t=(m+40|0)>>>0<(u=(q=0|Jc(0))-s|0)>>>0)|s>>>0<q>>>0&-1!=(0|s)&-1!=(0|q)^1)&&(h=s,g=t?u:b,r=145),145==(0|r)){b=(0|c[1031])+g|0,(c[1031]=b)>>>0>(0|c[1032])>>>0&&(c[1032]=b),j=0|c[929];f:do{if(j){for(f=4140;;){if((0|h)==((b=0|c[f>>2])+(a=0|c[(e=f+4|0)>>2])|0)){r=154;break}if(!(d=0|c[f+8>>2]))break;f=d}if(154==(0|r)&&0==(8&c[f+12>>2]|0)&&j>>>0<h>>>0&b>>>0<=j>>>0){c[e>>2]=a+g,u=j+(t=0==(7&(t=j+8|0)|0)?0:0-t&7)|0,t=(v=(0|c[926])+g|0)-t|0,c[929]=u,c[926]=t,c[u+4>>2]=1|t,c[j+v+4>>2]=40,c[930]=c[1045];break}for(h>>>0<(0|c[927])>>>0&&(c[927]=h),d=h+g|0,a=4140;;){if((0|c[a>>2])==(0|d)){r=162;break}if(!(b=0|c[a+8>>2]))break;a=b}if(162==(0|r)&&0==(8&c[a+12>>2]|0)){c[a>>2]=h,c[(l=a+4|0)>>2]=(0|c[l>>2])+g,k=(l=h+(0==(7&(l=h+8|0)|0)?0:0-l&7)|0)+m|0,i=(b=d+(0==(7&(b=d+8|0)|0)?0:0-b&7)|0)-l-m|0,c[l+4>>2]=3|m;g:do{if((0|j)==(0|b))v=(0|c[926])+i|0,c[926]=v,c[929]=k,c[k+4>>2]=1|v;else{if((0|c[928])==(0|b)){v=(0|c[925])+i|0,c[925]=v,c[928]=k,c[k+4>>2]=1|v,c[k+v>>2]=v;break}if(1==(3&(a=0|c[b+4>>2])|0)){h=-8&a,e=a>>>3;h:do{if(a>>>0<256){if(a=0|c[b+8>>2],(0|(d=0|c[b+12>>2]))==(0|a)){c[923]=c[923]&~(1<<e);break}c[a+12>>2]=d,c[d+8>>2]=a;break}g=0|c[b+24>>2],a=0|c[b+12>>2];do{if((0|a)==(0|b)){if(!(a=0|c[(d=4+(e=b+16|0)|0)>>2])){if(!(a=0|c[e>>2])){a=0;break}d=e}for(;;)if(e=0|c[(f=a+20|0)>>2])a=e,d=f;else{if(!(e=0|c[(f=a+16|0)>>2]))break;a=e,d=f}c[d>>2]=0}else v=0|c[b+8>>2],c[v+12>>2]=a,c[a+8>>2]=v}while(0);if(!g)break;e=3996+((d=0|c[b+28>>2])<<2)|0;do{if((0|c[e>>2])==(0|b)){if(0|(c[e>>2]=a))break;c[924]=c[924]&~(1<<d);break h}if(!(c[((0|c[(v=g+16|0)>>2])==(0|b)?v:g+20|0)>>2]=a))break h}while(0)}while(c[a+24>>2]=g,0|(d=0|c[(e=b+16|0)>>2])&&(c[a+16>>2]=d,c[d+24>>2]=a),(d=0|c[e+4>>2])&&(c[a+20>>2]=d,c[d+24>>2]=a,0));b=b+h|0,f=h+i|0}else f=i;if(c[(b=b+4|0)>>2]=-2&c[b>>2],c[k+4>>2]=1|f,b=(c[k+f>>2]=f)>>>3,f>>>0<256){d=3732+(b<<1<<2)|0,a=(a=0|c[923])&(b=1<<b)?0|c[(b=a=d+8|0)>>2]:(c[923]=a|b,b=d+8|0,d),c[b>>2]=k,c[a+12>>2]=k,c[k+8>>2]=a,c[k+12>>2]=d;break}b=f>>>8;do{if(b){if(16777215<f>>>0){e=31;break}e=1&((v=7+(e=14-((t=(520192+(e=b<<(u=(b+1048320|0)>>>16&8))|0)>>>16&4)|u|(v=(245760+(e<<=t)|0)>>>16&2))+(e<<v>>>15)|0)|0)?f>>>v:f)|e<<1}else e=0}while(0);if(a=3996+(e<<2)|0,c[k+28>>2]=e,c[4+(b=k+16|0)>>2]=0,!((b=(c[b>>2]=0)|c[924])&(d=1<<e))){c[924]=b|d,c[a>>2]=k,c[k+24>>2]=a,c[k+12>>2]=k,c[k+8>>2]=k;break}b=0|c[a>>2];i:do{if((-8&c[b+4>>2]|0)!=(0|f)){for(e=f<<(31==(0|e)?0:25-(e>>>1)|0);a=0|c[(d=b+16+(e>>>31<<2)|0)>>2];){if((-8&c[a+4>>2]|0)==(0|f)){b=a;break i}e<<=1,b=a}c[d>>2]=k,c[k+24>>2]=b,c[k+12>>2]=k,c[k+8>>2]=k;break g}}while(0);v=0|c[(u=b+8|0)>>2],c[v+12>>2]=k,c[u>>2]=k,c[k+8>>2]=v,c[k+12>>2]=b,c[k+24>>2]=0}}while(0);return S=w,l+8|0}for(a=4140;!((b=0|c[a>>2])>>>0<=j>>>0&&j>>>0<(v=b+(0|c[a+4>>2])|0)>>>0);)a=0|c[a+8>>2];for(b=(a=(a=(f=v+-47|0)+(0==(7&(a=f+8|0)|0)?0:0-a&7)|0)>>>0<(f=j+16|0)>>>0?j:a)+8|0,u=h+(t=0==(7&(t=h+8|0)|0)?0:0-t&7)|0,t=(d=g+-40|0)-t|0,c[929]=u,c[926]=t,c[u+4>>2]=1|t,c[h+d+4>>2]=40,c[930]=c[1045],c[(d=a+4|0)>>2]=27,c[b>>2]=c[1035],c[b+4>>2]=c[1036],c[b+8>>2]=c[1037],c[b+12>>2]=c[1038],c[1035]=h,c[1036]=g,c[1038]=0,c[1037]=b,b=a+24|0;c[(b=(u=b)+4|0)>>2]=7,(u+8|0)>>>0<v>>>0;);if((0|a)!=(0|j)){if(g=a-j|0,c[d>>2]=-2&c[d>>2],c[j+4>>2]=1|g,b=(c[a>>2]=g)>>>3,g>>>0<256){d=3732+(b<<1<<2)|0,a=(a=0|c[923])&(b=1<<b)?0|c[(b=a=d+8|0)>>2]:(c[923]=a|b,b=d+8|0,d),c[b>>2]=j,c[a+12>>2]=j,c[j+8>>2]=a,c[j+12>>2]=d;break}if(d=3996+((e=(b=g>>>8)?16777215<g>>>0?31:1&((v=7+(e=14-((t=(520192+(e=b<<(u=(b+1048320|0)>>>16&8))|0)>>>16&4)|u|(v=(245760+(e<<=t)|0)>>>16&2))+(e<<v>>>15)|0)|0)?g>>>v:g)|e<<1:0)<<2)|0,c[j+28>>2]=e,c[j+20>>2]=0,!((b=(c[f>>2]=0)|c[924])&(a=1<<e))){c[924]=b|a,c[d>>2]=j,c[j+24>>2]=d,c[j+12>>2]=j,c[j+8>>2]=j;break}b=0|c[d>>2];j:do{if((-8&c[b+4>>2]|0)!=(0|g)){for(e=g<<(31==(0|e)?0:25-(e>>>1)|0);a=0|c[(d=b+16+(e>>>31<<2)|0)>>2];){if((-8&c[a+4>>2]|0)==(0|g)){b=a;break j}e<<=1,b=a}c[d>>2]=j,c[j+24>>2]=b,c[j+12>>2]=j,c[j+8>>2]=j;break f}}while(0);v=0|c[(u=b+8|0)>>2],c[v+12>>2]=j,c[u>>2]=j,c[j+8>>2]=v,c[j+12>>2]=b,c[j+24>>2]=0}}else 0==(0|(v=0|c[927]))|h>>>0<v>>>0&&(c[927]=h),c[1035]=h,c[1036]=g,c[1038]=0,c[932]=c[1041],c[931]=-1,c[936]=3732,c[935]=3732,c[938]=3740,c[937]=3740,c[940]=3748,c[939]=3748,c[942]=3756,c[941]=3756,c[944]=3764,c[943]=3764,c[946]=3772,c[945]=3772,c[948]=3780,c[947]=3780,c[950]=3788,c[949]=3788,c[952]=3796,c[951]=3796,c[954]=3804,c[953]=3804,c[956]=3812,c[955]=3812,c[958]=3820,c[957]=3820,c[960]=3828,c[959]=3828,c[962]=3836,c[961]=3836,c[964]=3844,c[963]=3844,c[966]=3852,c[965]=3852,c[968]=3860,c[967]=3860,c[970]=3868,c[969]=3868,c[972]=3876,c[971]=3876,c[974]=3884,c[973]=3884,c[976]=3892,c[975]=3892,c[978]=3900,c[977]=3900,c[980]=3908,c[979]=3908,c[982]=3916,c[981]=3916,c[984]=3924,c[983]=3924,c[986]=3932,c[985]=3932,c[988]=3940,c[987]=3940,c[990]=3948,c[989]=3948,c[992]=3956,c[991]=3956,c[994]=3964,c[993]=3964,c[996]=3972,c[995]=3972,c[998]=3980,c[997]=3980,u=h+(t=0==(7&(t=h+8|0)|0)?0:0-t&7)|0,t=(v=g+-40|0)-t|0,c[929]=u,c[926]=t,c[u+4>>2]=1|t,c[h+v+4>>2]=40,c[930]=c[1045]}while(0);if(m>>>0<(b=0|c[926])>>>0)return c[926]=t=b-m|0,v=0|c[929],c[929]=u=v+m|0,c[u+4>>2]=1|t,c[v+4>>2]=3|m,S=w,v+8|0}return c[922]=48,S=w,(v=0)|v}function Fc(a){var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;if(a|=0){e=0|c[927],k=(d=a+-8|0)+(b=-8&(a=0|c[a+-4>>2]))|0;do{if(1&a)j=i=d;else{if(f=0|c[d>>2],!(3&a))return;if(h=f+b|0,(g=d+(0-f)|0)>>>0<e>>>0)return;if((0|c[928])==(0|g)){if(3==(3&(a=0|c[(b=k+4|0)>>2])|0))return c[925]=h,c[b>>2]=-2&a,c[g+4>>2]=1|h,void(c[g+h>>2]=h);j=i=g,b=h;break}if(d=f>>>3,f>>>0<256){if(a=0|c[g+8>>2],(0|(b=0|c[g+12>>2]))==(0|a)){c[923]=c[923]&~(1<<d),j=i=g,b=h;break}c[a+12>>2]=b,c[b+8>>2]=a,j=i=g,b=h;break}f=0|c[g+24>>2],a=0|c[g+12>>2];do{if((0|a)==(0|g)){if(!(a=0|c[(b=4+(d=g+16|0)|0)>>2])){if(!(a=0|c[d>>2])){d=0;break}b=d}for(;;)if(d=0|c[(e=a+20|0)>>2])a=d,b=e;else{if(!(d=0|c[(e=a+16|0)>>2]))break;a=d,b=e}c[b>>2]=0,d=a}else d=0|c[g+8>>2],c[d+12>>2]=a,c[a+8>>2]=d,d=a}while(0);if(f){if(a=0|c[g+28>>2],(0|c[(b=3996+(a<<2)|0)>>2])==(0|g)){if(!(c[b>>2]=d)){c[924]=c[924]&~(1<<a),j=i=g,b=h;break}}else if(!(c[((0|c[(j=f+16|0)>>2])==(0|g)?j:f+20|0)>>2]=d)){j=i=g,b=h;break}c[d+24>>2]=f,0|(a=0|c[(b=g+16|0)>>2])&&(c[d+16>>2]=a,c[a+24>>2]=d),(a=0|c[b+4>>2])&&(c[d+20>>2]=a,c[a+24>>2]=d),j=i=g,b=h}else j=i=g,b=h}}while(0);if(!(k>>>0<=i>>>0)&&1&(d=0|c[(a=k+4|0)>>2])){if(2&d)c[a>>2]=-2&d,c[j+4>>2]=1|b,f=c[i+b>>2]=b;else{if((0|c[929])==(0|k))return k=(0|c[926])+b|0,c[926]=k,c[929]=j,c[j+4>>2]=1|k,(0|j)!=(0|c[928])?void 0:(c[928]=0,void(c[925]=0));if((0|c[928])==(0|k))return k=(0|c[925])+b|0,c[925]=k,c[928]=i,c[j+4>>2]=1|k,void(c[i+k>>2]=k);f=(-8&d)+b|0,e=d>>>3;do{if(d>>>0<256){if(b=0|c[k+8>>2],(0|(a=0|c[k+12>>2]))==(0|b)){c[923]=c[923]&~(1<<e);break}c[b+12>>2]=a,c[a+8>>2]=b;break}g=0|c[k+24>>2],a=0|c[k+12>>2];do{if((0|a)==(0|k)){if(!(a=0|c[(b=4+(d=k+16|0)|0)>>2])){if(!(a=0|c[d>>2])){d=0;break}b=d}for(;;)if(d=0|c[(e=a+20|0)>>2])a=d,b=e;else{if(!(d=0|c[(e=a+16|0)>>2]))break;a=d,b=e}c[b>>2]=0,d=a}else d=0|c[k+8>>2],c[d+12>>2]=a,c[a+8>>2]=d,d=a}while(0);if(0|g){if(a=0|c[k+28>>2],(0|c[(b=3996+(a<<2)|0)>>2])==(0|k)){if(!(c[b>>2]=d)){c[924]=c[924]&~(1<<a);break}}else if(!(c[((0|c[(h=g+16|0)>>2])==(0|k)?h:g+20|0)>>2]=d))break;c[d+24>>2]=g,0|(a=0|c[(b=k+16|0)>>2])&&(c[d+16>>2]=a,c[a+24>>2]=d),0|(a=0|c[b+4>>2])&&(c[d+20>>2]=a,c[a+24>>2]=d)}}while(0);if(c[j+4>>2]=1|f,c[i+f>>2]=f,(0|j)==(0|c[928]))return void(c[925]=f)}if(a=f>>>3,f>>>0<256)return d=3732+(a<<1<<2)|0,b=(b=0|c[923])&(a=1<<a)?0|c[(a=b=d+8|0)>>2]:(c[923]=b|a,a=d+8|0,d),c[a>>2]=j,c[b+12>>2]=j,c[j+8>>2]=b,void(c[j+12>>2]=d);b=3996+((e=(a=f>>>8)?16777215<f>>>0?31:1&((k=7+(e=14-((h=(520192+(e=a<<(i=(a+1048320|0)>>>16&8))|0)>>>16&4)|i|(k=(245760+(e<<=h)|0)>>>16&2))+(e<<k>>>15)|0)|0)?f>>>k:f)|e<<1:0)<<2)|0,c[j+28>>2]=e,c[j+20>>2]=0,a=(c[j+16>>2]=0)|c[924],d=1<<e;a:do{if(a&d){a=0|c[b>>2];b:do{if((-8&c[a+4>>2]|0)!=(0|f)){for(e=f<<(31==(0|e)?0:25-(e>>>1)|0);b=0|c[(d=a+16+(e>>>31<<2)|0)>>2];){if((-8&c[b+4>>2]|0)==(0|f)){a=b;break b}e<<=1,a=b}c[d>>2]=j,c[j+24>>2]=a,c[j+12>>2]=j,c[j+8>>2]=j;break a}}while(0);k=0|c[(i=a+8|0)>>2],c[k+12>>2]=j,c[i>>2]=j,c[j+8>>2]=k,c[j+12>>2]=a,c[j+24>>2]=0}else c[924]=a|d,c[b>>2]=j,c[j+24>>2]=b,c[j+12>>2]=j,c[j+8>>2]=j}while(0);if(k=(0|c[931])-1|0,!(0|(c[931]=k))){for(a=4148;a=0|c[a>>2];)a=a+8|0;c[931]=-1}}}}function Gc(a,b){var d=0,e=0,f=0,g=0,h=0,i=0,j=0,j=(a|=0)+(b|=0)|0,d=0|c[a+4>>2];do{if(1&d)i=a,a=b;else{if(e=0|c[a>>2],!(3&d))return;if(h=e+b|0,(0|c[928])==(0|(g=a+(0-e)|0))){if(3==(3&(d=0|c[(a=j+4|0)>>2])|0))return c[925]=h,c[a>>2]=-2&d,c[g+4>>2]=1|h,c[j>>2]=h,0;i=g,a=h;break}if(b=e>>>3,e>>>0<256){if(d=0|c[g+8>>2],(0|(a=0|c[g+12>>2]))==(0|d)){c[923]=c[923]&~(1<<b),i=g,a=h;break}c[d+12>>2]=a,c[a+8>>2]=d,i=g,a=h;break}f=0|c[g+24>>2],d=0|c[g+12>>2];do{if((0|d)==(0|g)){if(!(d=0|c[(a=4+(b=g+16|0)|0)>>2])){if(!(d=0|c[b>>2])){b=0;break}a=b}for(;;)if(b=0|c[(e=d+20|0)>>2])d=b,a=e;else{if(!(b=0|c[(e=d+16|0)>>2]))break;d=b,a=e}c[a>>2]=0,b=d}else b=0|c[g+8>>2],c[b+12>>2]=d,c[d+8>>2]=b,b=d}while(0);if(f){if(d=0|c[g+28>>2],(0|c[(a=3996+(d<<2)|0)>>2])==(0|g)){if(!(c[a>>2]=b)){c[924]=c[924]&~(1<<d),i=g,a=h;break}}else if(!(c[((0|c[(i=f+16|0)>>2])==(0|g)?i:f+20|0)>>2]=b)){i=g,a=h;break}c[b+24>>2]=f,0|(d=0|c[(a=g+16|0)>>2])&&(c[b+16>>2]=d,c[d+24>>2]=b),(d=0|c[a+4>>2])&&(c[b+20>>2]=d,c[d+24>>2]=b),i=g,a=h}else i=g,a=h}}while(0);if(2&(b=0|c[(d=j+4|0)>>2]))c[d>>2]=-2&b,c[i+4>>2]=1|a,c[i+a>>2]=a;else{if((0|c[929])==(0|j))return j=(0|c[926])+a|0,c[926]=j,c[929]=i,c[i+4>>2]=1|j,(0|i)==(0|c[928])&&(c[928]=0,void(c[925]=0));if((0|c[928])==(0|j))return j=(0|c[925])+a|0,c[925]=j,c[928]=i,c[i+4>>2]=1|j,c[i+j>>2]=j,0;g=(-8&b)+a|0,e=b>>>3;do{if(b>>>0<256){if(a=0|c[j+8>>2],(0|(d=0|c[j+12>>2]))==(0|a)){c[923]=c[923]&~(1<<e);break}c[a+12>>2]=d,c[d+8>>2]=a;break}f=0|c[j+24>>2],d=0|c[j+12>>2];do{if((0|d)==(0|j)){if(!(d=0|c[(a=4+(b=j+16|0)|0)>>2])){if(!(d=0|c[b>>2])){b=0;break}a=b}for(;;)if(b=0|c[(e=d+20|0)>>2])d=b,a=e;else{if(!(b=0|c[(e=d+16|0)>>2]))break;d=b,a=e}c[a>>2]=0,b=d}else b=0|c[j+8>>2],c[b+12>>2]=d,c[d+8>>2]=b,b=d}while(0);if(0|f){if(d=0|c[j+28>>2],(0|c[(a=3996+(d<<2)|0)>>2])==(0|j)){if(!(c[a>>2]=b)){c[924]=c[924]&~(1<<d);break}}else if(!(c[((0|c[(h=f+16|0)>>2])==(0|j)?h:f+20|0)>>2]=b))break;c[b+24>>2]=f,0|(d=0|c[(a=j+16|0)>>2])&&(c[b+16>>2]=d,c[d+24>>2]=b),0|(d=0|c[a+4>>2])&&(c[b+20>>2]=d,c[d+24>>2]=b)}}while(0);if(c[i+4>>2]=1|g,c[i+g>>2]=g,(0|i)==(0|c[928]))return c[925]=g,0;a=g}if(d=a>>>3,a>>>0<256)return b=3732+(d<<1<<2)|0,a=(a=0|c[923])&(d=1<<d)?0|c[(d=a=b+8|0)>>2]:(c[923]=a|d,d=b+8|0,b),c[d>>2]=i,c[a+12>>2]=i,c[i+8>>2]=a,c[i+12>>2]=b,0;if(b=3996+((f=(d=a>>>8)?16777215<a>>>0?31:1&((j=7+(f=14-((g=(520192+(f=d<<(h=(d+1048320|0)>>>16&8))|0)>>>16&4)|h|(j=(245760+(f<<=g)|0)>>>16&2))+(f<<j>>>15)|0)|0)?a>>>j:a)|f<<1:0)<<2)|0,c[i+28>>2]=f,c[i+20>>2]=0,!((d=(c[i+16>>2]=0)|c[924])&(e=1<<f)))return c[924]=d|e,c[b>>2]=i,c[i+24>>2]=b,c[i+12>>2]=i,c[i+8>>2]=i,0;d=0|c[b>>2];a:do{if((-8&c[d+4>>2]|0)!=(0|a)){for(f=a<<(31==(0|f)?0:25-(f>>>1)|0);b=0|c[(e=d+16+(f>>>31<<2)|0)>>2];){if((-8&c[b+4>>2]|0)==(0|a)){d=b;break a}f<<=1,d=b}return c[e>>2]=i,c[i+24>>2]=d,c[i+12>>2]=i,c[i+8>>2]=i,0}}while(0);j=0|c[(h=d+8|0)>>2],c[j+12>>2]=i,c[h>>2]=i,c[i+8>>2]=j,c[i+12>>2]=d,c[i+24>>2]=0}function Ic(a,b,d){a|=0;var e;return 0!=(3&(b|=0)|0)|0==(0|(e=b>>>2))||1073741823+e&e|0?28:(-64-b|0)>>>0<(d|=0)>>>0||!(b=0|function(a,b){b|=0;var g,d=0,e=0,f=0,h=0,i=0;if((d=16<(a|=0)>>>0?a:16)+-1&d)for(a=16;a>>>0<d>>>0;)a<<=1;else a=d;if((-64-a|0)>>>0<=b>>>0)return c[922]=48,(h=0)|h;if(!(d=0|Ec(12+(g=b>>>0<11?16:b+11&-8)+a|0)))return(h=0)|h;f=d+-8|0;do{if(a+-1&d){if(e=15<((e=(d+a+-1&0-a)-8|0)-(b=f)|0)>>>0?e:e+a|0,d=(-8&(i=0|c[(a=d+-4|0)>>2]))-(b=e-b|0)|0,3&i){c[(i=e+4|0)>>2]=d|1&c[i>>2]|2,c[(d=e+d+4|0)>>2]=1|c[d>>2],c[a>>2]=b|1&c[a>>2]|2,c[i>>2]=1|c[i>>2],Gc(f,b),a=b=e;break}c[e>>2]=(0|c[f>>2])+b,c[e+4>>2]=d,a=b=e;break}}while(a=b=f,0);return 3&(a=0|c[(d=a+4|0)>>2])|0&&(16+g|0)>>>0<(h=-8&a)>>>0&&(i=h-g|0,f=b+g|0,c[d>>2]=g|1&a|2,c[f+4>>2]=3|i,c[(h=b+h+4|0)>>2]=1|c[h>>2],Gc(f,i)),b+8|0}(16<b>>>0?b:16,d))?48:(c[a>>2]=b,(a=0)|a)}function Jc(a){var b,d=0;return(a=(b=0|c[(d=4208)>>2])+(0|a)|0)>>>0>(0|H())>>>0&&0==(0|J(0|a))?(c[922]=48,-1):(c[d>>2]=a,0|b)}function Lc(a,b,c,d){b|=0,d|=0;var e,f;return c=0|function(a,b){var c,d,e,f;return a=((c=0|v(e=65535&(b|=0),f=65535&(a|=0)))>>>16)+(0|v(e,d=a>>>16))|0,b=0|v(e=b>>>16,f),0|(y((a>>>16)+(0|v(e,d))+(((65535&a)+b|0)>>>16)|0),a+b<<16|65535&c|0)}(e=a|=0,f=c|=0),a=0|z(),0|(y((0|v(b,f))+(0|v(d,e))+a|0&a|0),0|c)}function Mc(a,b,c,d){return 0|(y((b|=0)+(d|=0)+((c=(a|=0)+(0|c)>>>0)>>>0<a>>>0|0)>>>0|0),0|c)}function Nc(a,b,c,d){return 0|(y(0|(d=(b|=0)-(d|=0)-((a|=0)>>>0<(c|=0)>>>0|0)>>>0)),a-c>>>0|0)}function Oc(a){return 0|((a|=0)?31-(0|w(a^a-1))|0:32)}function Pc(a,b,d,e,f){f|=0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,l=a|=0,h=d|=0,i=n=e|=0;if(!(k=j=b|=0))return g=0!=(0|f),i?(g&&(c[f>>2]=0|a,c[f+4>>2]=0&b),(f=n=0)|(y(0|n),f)):(g&&(c[f>>2]=(l>>>0)%(h>>>0),c[f+4>>2]=0),f=(l>>>(n=0))/(h>>>0)>>>0,0|(y(0|n),f));g=0==(0|i);do{if(h){if(!g){if((g=(0|w(0|i))-(0|w(0|k))|0)>>>0<=31){a=l>>>((h=m=g+1|0)>>>0)&(b=g-31>>31)|k<<(i=31-g|0),b&=k>>>(m>>>0),g=0,i=l<<i;break}return f&&(c[f>>2]=0|a,c[f+4>>2]=j|0&b),(f=n=0)|(y(0|n),f)}if((g=h-1|0)&h|0){a=(m=32-(i=33+(0|w(0|h))-(0|w(0|k))|0)|0)-1>>31&k>>>((o=i-32|0)>>>0)|(k<<m|l>>>((h=i)>>>0))&(b=o>>31),b&=k>>>(i>>>0),g=l<<(p=64-i|0)&(j=m>>31),i=(k<<p|l>>>(o>>>0))&j|l<<m&i-33>>31;break}return 0|f&&(c[f>>2]=g&l,c[f+4>>2]=0),1==(0|h)?(p=0|a,0|(y(0|(o=j|0&b)),p)):(o=k>>>((p=0|Oc(0|h))>>>0)|0,p=k<<32-p|l>>>(p>>>0)|0,0|(y(0|o),p))}if(g)return 0|f&&(c[f>>2]=(k>>>0)%(h>>>0),c[f+4>>2]=0),p=(k>>>(o=0))/(h>>>0)>>>0,0|(y(0|o),p);if(!l)return 0|f&&(c[f>>2]=0,c[f+4>>2]=(k>>>0)%(i>>>0)),p=(k>>>(o=0))/(i>>>0)>>>0,0|(y(0|o),p);if(!((g=i-1|0)&i))return 0|f&&(c[f>>2]=0|a,c[f+4>>2]=g&k|0&b),p=k>>>(((o=0)|Oc(0|i))>>>0),0|(y(0|o),p);if((g=(0|w(0|i))-(0|w(0|k))|0)>>>0<=30){a=k<<(i=31-g|0)|l>>>((h=b=g+1|0)>>>0),b=k>>>(b>>>0),g=0,i=l<<i;break}return f&&(c[f>>2]=0|a,c[f+4>>2]=j|0&b),(p=o=0)|(y(0|o),p)}while(0);if(h){for(k=0|Mc(0|(m=0|d),0|(l=n|0&e),-1,-1),d=0|z(),j=i,i=0;j=g>>>31|(e=j)<<1,g=i|g<<1,Nc(0|k,0|d,0|(e=a<<1|e>>>31|0),0|(n=a>>>31|b<<1|0)),i=1&(o=(p=0|z())>>31|((0|p)<0?-1:0)<<1),a=0|Nc(0|e,0|n,o&m|0,(((0|p)<0?-1:0)>>31|((0|p)<0?-1:0)<<1)&l|0),b=0|z(),0!=(0|(h=h-1|0)););k=j,j=0}else k=i,i=j=0;return(h=0)|f&&(c[f>>2]=a,c[f+4>>2]=b),p=-2&(g<<1|0)|i,0|(y(0|(o=(0|g)>>>31|(k|h)<<1|0&(h<<1|g>>>31)|j)),p)}function Qc(a,b,c,d){return 0|Pc(a|=0,b|=0,c|=0,d|=0,0)}function Rc(a,b,c){return a|=0,b|=0,(0|(c|=0))<32?(y(b>>>c|0),a>>>c|(b&(1<<c)-1)<<32-c):(y(0),b>>>c-32|0)}function Sc(a,b,c){return a|=0,b|=0,(0|(c|=0))<32?(y(b<<c|(a&(1<<c)-1<<32-c)>>>32-c|0),a<<c):(y(a<<c-32|0),0)}function Uc(b,d,e){var f,g,h;if(b|=0,d|=0,8192<=(0|(e|=0)))return I(0|b,0|d,0|e),0|b;if(h=0|b,g=b+e|0,(3&b)==(3&d)){for(;3&b;){if(!e)return 0|h;a[b>>0]=0|a[d>>0],b=b+1|0,d=d+1|0,e=e-1|0}for(f=(e=-4&g|0)-64|0;(0|b)<=(0|f);)c[b>>2]=c[d>>2],c[b+4>>2]=c[d+4>>2],c[b+8>>2]=c[d+8>>2],c[b+12>>2]=c[d+12>>2],c[b+16>>2]=c[d+16>>2],c[b+20>>2]=c[d+20>>2],c[b+24>>2]=c[d+24>>2],c[b+28>>2]=c[d+28>>2],c[b+32>>2]=c[d+32>>2],c[b+36>>2]=c[d+36>>2],c[b+40>>2]=c[d+40>>2],c[b+44>>2]=c[d+44>>2],c[b+48>>2]=c[d+48>>2],c[b+52>>2]=c[d+52>>2],c[b+56>>2]=c[d+56>>2],c[b+60>>2]=c[d+60>>2],b=b+64|0,d=d+64|0;for(;(0|b)<(0|e);)c[b>>2]=c[d>>2],b=b+4|0,d=d+4|0}else for(e=g-4|0;(0|b)<(0|e);)a[b>>0]=0|a[d>>0],a[b+1>>0]=0|a[d+1>>0],a[b+2>>0]=0|a[d+2>>0],a[b+3>>0]=0|a[d+3>>0],b=b+4|0,d=d+4|0;for(;(0|b)<(0|g);)a[b>>0]=0|a[d>>0],b=b+1|0,d=d+1|0;return 0|h}function Vc(b,d,e){d|=0;var f,g,i,h=(b|=0)+(e|=0)|0;if(d&=255,67<=(0|e)){for(;3&b;)a[b>>0]=d,b=b+1|0;for(i=d|d<<8|d<<16|d<<24,g=(f=-4&h|0)-64|0;(0|b)<=(0|g);)c[b>>2]=i,c[b+4>>2]=i,c[b+8>>2]=i,c[b+12>>2]=i,c[b+16>>2]=i,c[b+20>>2]=i,c[b+24>>2]=i,c[b+28>>2]=i,c[b+32>>2]=i,c[b+36>>2]=i,c[b+40>>2]=i,c[b+44>>2]=i,c[b+48>>2]=i,c[b+52>>2]=i,c[b+56>>2]=i,c[b+60>>2]=i,b=b+64|0;for(;(0|b)<(0|f);)c[b>>2]=i,b=b+4|0}for(;(0|b)<(0|h);)a[b>>0]=d,b=b+1|0;return h-e|0}function gd(a){return x(0),0}function id(a,b,c,d){return x(2),0}var W=[gd,function(a){return 0|A(0,0|(a|=0))},function(a){return 0},gd],X=[function(a,b,c){return x(1),0},function(a,b,c){return 0|B(0,0|(a|=0),0|(b|=0),0|(c|=0))},function(a,b,d){b|=0,d|=0;var e,i,j,k,m,n,o,f=0,g=0,h=0,p=0,l=S;for(S=S+32|0,i=(g=l)+16|0,f=0|c[(j=28+(a|=0)|0)>>2],c[g>>2]=f,f=(0|c[(k=a+20|0)>>2])-f|0,c[g+4>>2]=f,c[g+8>>2]=b,e=a+60|0,f=f+(c[g+12>>(h=2)]=d)|0;;){if((0|f)==(0|(b=0|function(a){return 0|(a=(a|=0)<<16>>16?(c[922]=65535&a,-1):0)}(0|G(0|c[e>>2],0|g,0|h,0|i))?c[i>>2]=-1:0|c[i>>2]))){b=6;break}if((0|b)<0){b=8;break}p=0|c[g+4>>2],c[(n=(m=p>>>0<b>>>0)?g+8|0:g)>>2]=(0|c[n>>2])+(p=b-(m?p:0)|0),c[(o=n+4|0)>>2]=(0|c[o>>2])-p,g=n,h=h+(m<<31>>31)|0,f=f-b|0}return 6==(0|b)?(p=0|c[a+44>>2],c[a+16>>2]=p+(0|c[a+48>>2]),c[j>>2]=p,c[k>>2]=p):8==(0|b)&&(c[a+16>>2]=0,c[j>>2]=0,c[k>>2]=0,c[a>>2]=32|c[a>>2],d=2==(0|h)?0:d-(0|c[g+4>>2])|0),S=l,0|d},function(a,b,d){var e,f;return Uc(0|(f=0|c[(e=20+(a|=0)|0)>>2]),0|(b|=0),0|(a=(d|=0)>>>0<(a=(0|c[a+16>>2])-f|0)>>>0?d:a)),c[e>>2]=(0|c[e>>2])+a,0|d}],Y=[id,function(a,b,c,d){return 0|C(0,0|(a|=0),0|(b|=0),0|(c|=0),0|(d|=0))},function(a,b,c,d){return y(0),0},id],Z=[function(a){x(3)},function(a){D(0,0|(a|=0))}],_=[function(a,b){x(4)},function(a,b){E(0,0|(a|=0),0|(b|=0))},function(p,b){var j,e=0,g=0,h=0,o=0,k=0,l=0,m=0,n=0,e=0|c[(j=308+(p|=0)|0)>>2],g=0|c[p+316>>2],h=0|c[p+320>>2];-1==(0|(o=0|c[(k=e+((b|=0)<<5)+8|0)>>2]))?(c[g+(b<<2)>>2]=c[(0|c[p+148>>2])+(c[e+(b<<5)+16>>2]<<2)>>2],f[h+(b<<2)>>2]=1):(m=0|c[(l=e+(b<<5)+16|0)>>2],n=0|c[(0|c[p+152>>2])+(m<<2)>>2],$[3&c[e+(o<<5)+24>>2]](p,o,n,n,0|c[(0|c[p+60>>2])+(24*m|0)+16>>2]),k=0|c[k>>2],f[g+(b<<2)>>2]=+f[(0|c[p+148>>2])+(c[l>>2]<<2)>>2]*+f[g+(k<<2)>>2],c[h+(b<<2)>>2]=c[h+(k<<2)>>2]),(0|d[4+(0|c[p>>2])>>0])<4||(e=0|c[j>>2],g=0|c[p+324>>2],j=0|c[p+328>>2],h=b<<2,o=c[e+(b<<5)+16>>2]<<2,-1==(0|(e=0|c[e+(b<<5)+8>>2]))?(e=0|c[p+156>>2],c[g+(h<<2)>>2]=c[e+(o<<2)>>2],c[g+((b=1|h)<<2)>>2]=c[e+((k=1|o)<<2)>>2],c[g+((n=2|h)<<2)>>2]=c[e+((m=2|o)<<2)>>2],f[g+((e=3|h)<<2)>>2]=1,l=0|c[p+160>>2],c[j+(h<<2)>>2]=c[l+(o<<2)>>2],c[j+(b<<2)>>2]=c[l+(k<<2)>>2],c[j+(n<<2)>>2]=c[l+(m<<2)>>2]):(m=e<<2,l=(0|c[p+156>>2])+(o<<2)|0,f[(e=g+(h<<2)|0)>>2]=+f[l>>2]*+f[(n=g+(m<<2)|0)>>2],f[e+4>>2]=+f[l+4>>2]*+f[n+4>>2],f[e+8>>2]=+f[l+8>>2]*+f[n+8>>2],f[g+((e=3|h)<<2)>>2]=1,l=(0|c[p+160>>2])+(o<<2)|0,p=+f[l>>2],o=+f[(m=j+(m<<2)|0)>>2],f[(n=j+(h<<2)|0)>>2]=p+o-p*o,o=+f[l+4>>2],p=+f[m+4>>2],f[n+4>>2]=o+p-o*p,p=+f[l+8>>2],o=+f[m+8>>2],f[n+8>>2]=p+o-p*o),f[j+(e<<2)>>2]=1)},function(a,b){var n,p,q,r,s,t,u,v,w,x,y,z,A,B,C,e=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,o=0,D=0,E=0,F=0,G=0,H=S;if(S=S+48|0,u=H+8|0,s=H+40|0,r=H+32|0,q=(t=H)+24|0,F=H+16|0,e=0|c[(y=308+(a|=0)|0)>>2],w=0|c[a+316>>2],x=0|c[a+320>>2],-1==(0|(p=0|c[(B=e+((b|=0)<<5)+8|0)>>2])))G=0|c[e+(b<<5)+16>>2],c[w+(b<<2)>>2]=c[(0|c[a+268>>2])+(G<<2)>>2],c[x+(b<<2)>>2]=c[(0|c[a+272>>2])+(G<<2)>>2];else{for(v=0|c[(C=e+(b<<5)+16|0)>>2],j=0|c[(0|c[(z=a+276|0)>>2])+(v<<2)>>2],c[F>>2]=j,v=0|c[(0|c[(A=a+280|0)>>2])+(v<<2)>>2],c[(D=F+4|0)>>2]=v,E=1==(0|c[e+(p<<5)+12>>2])?-10:-.10000000149011612,c[s>>2]=j,c[(j=4+s|0)>>2]=v,$[3&c[(v=e+(p<<5)+24|0)>>2]](a,p,s,r,1),h=4+q|0,e=4+r|0,g=t+4|0,i=9,o=1;f[q>>2]=(m=0*o)+ +f[s>>2],f[h>>2]=(n=E*o)+ +f[j>>2],$[3&c[v>>2]](a,p,q,t,1),l=+f[t>>2]-+f[r>>2],f[t>>2]=l,k=+f[g>>2]-+f[e>>2],!(0!=l|0!=(f[g>>2]=k));){if(f[q>>2]=+f[s>>2]-m,f[h>>2]=+f[j>>2]-n,$[3&c[v>>2]](a,p,q,t,1),k=+f[t>>2]-+f[r>>2],f[t>>2]=k,m=+f[g>>2]-+f[e>>2],0!=k|0!=(f[g>>2]=m)){G=6;break}if(!i){G=8;break}i=i+-1|0,o*=.10000000149011612}6==(0|G)?(l=-k,k=-m):8==(0|G)&&(ia(0,2397,u),k=l=0),E=180*+ob(0,E,l,k)/3.1415927410125732,$[3&c[v>>2]](a,0|c[B>>2],F,F,1),G=0|c[C>>2],c[(0|c[z>>2])+(G<<2)>>2]=c[F>>2],c[(0|c[A>>2])+(G<<2)>>2]=c[D>>2],F=(0|c[a+284>>2])+(G<<2)|0,f[F>>2]=+f[F>>2]-E,F=0|c[B>>2],f[w+(b<<2)>>2]=+f[(0|c[a+268>>2])+(G<<2)>>2]*+f[w+(F<<2)>>2],G=(0|c[a+272>>2])+(G<<2)|0,E=+f[G>>2]*+f[x+(F<<2)>>2],f[x+(b<<2)>>2]=E,f[G>>2]=E}(0|d[4+(0|c[a>>2])>>0])<4||(e=0|c[y>>2],g=0|c[a+324>>2],j=0|c[a+328>>2],h=b<<2,i=c[e+(b<<5)+16>>2]<<2,-1==(0|(e=0|c[e+(b<<5)+8>>2]))?(e=0|c[a+296>>2],c[g+(h<<2)>>2]=c[e+(i<<2)>>2],c[g+((F=1|h)<<2)>>2]=c[e+((D=1|i)<<2)>>2],c[g+((b=2|h)<<2)>>2]=c[e+((G=2|i)<<2)>>2],f[g+((e=3|h)<<2)>>2]=1,a=0|c[a+300>>2],c[j+(h<<2)>>2]=c[a+(i<<2)>>2],c[j+(F<<2)>>2]=c[a+(D<<2)>>2],c[j+(b<<2)>>2]=c[a+(G<<2)>>2]):(F=e<<2,G=(0|c[a+296>>2])+(i<<2)|0,f[(e=g+(h<<2)|0)>>2]=+f[G>>2]*+f[(b=g+(F<<2)|0)>>2],f[e+4>>2]=+f[G+4>>2]*+f[b+4>>2],f[e+8>>2]=+f[G+8>>2]*+f[b+8>>2],f[g+((e=3|h)<<2)>>2]=1,G=(0|c[a+300>>2])+(i<<2)|0,o=+f[G>>2],E=+f[(a=j+(F<<2)|0)>>2],f[(b=j+(h<<2)|0)>>2]=o+E-o*E,E=+f[G+4>>2],o=+f[a+4>>2],f[b+4>>2]=E+o-E*o,o=+f[G+8>>2],E=+f[a+8>>2],f[b+8>>2]=o+E-o*E),f[j+(e<<2)>>2]=1),S=H}],$=[function(a,b,c,d,e){x(5)},function(a,b,c,d,e){F(0,0|(a|=0),0|(b|=0),0|(c|=0),0|(d|=0),0|(e|=0))},function(a,b,d,e,h){d|=0,e|=0;var B,F,G,H,I,J,K,L,N,O,P,Q,R,T,U,V,W,X,Y,$,ca,da,aa,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,w=0,x=0,y=0,z=0,A=0,C=0,D=0,E=0,M=0,_=0,Z=S;if(S=S+32|0,Y=Z,b=0|c[(0|c[308+(a|=0)>>2])+((b|=0)<<5)+16>>2],i=0|c[a+60>>2],R=0|c[(0|c[a+152>>2])+(b<<2)>>2],T=0|c[i+(24*b|0)+8>>2],U=0|c[i+(24*b|0)+4>>2],V=1+T|0,(0|(h|=0))<=0)S=Z;else{W=+(0|T),X=+(0|U),Q=0==(0|c[i+(24*b|0)+12>>2]),F=R+(T<<3)|0,G=R+((N=0|v(U,V))<<3)|0,H=R+((L=N+T|0)<<3)|0,I=4+R|0,J=R+(T<<3)+4|0,K=R+(N<<3)+4|0,L=R+(L<<3)+4|0,P=T-1|0,O=U-1|0,t=u=w=x=j=k=s=r=q=p=E=D=o=n=m=l=M=A=0;do{y=(B=+f[d+(M<<3)>>2])*W,C=(z=+f[d+(M<<3)+4>>2])*X,a=!(1<=B),i=!(1<=z);do{if(i&a&!(B<0)&!(z<0)){if(a=~~y,b=(0|v(V,i=~~C))+a|0,k=y-(0|a),j=C-(0|i),!Q){f[e+(M<<3)>>2]=(y=1-j)*((z=1-k)*+f[R+(b<<3)>>2])+y*(k*+f[R+((_=b+1|0)<<3)>>2])+j*(z*+f[R+((a=b+V|0)<<3)>>2])+j*(k*+f[R+((i=a+1|0)<<3)>>2]),z=y*(z*+f[R+(b<<3)+4>>2])+y*(k*+f[R+(_<<3)+4>>2])+j*(z*+f[R+(a<<3)+4>>2]),y=j*(k*+f[R+(i<<3)+4>>2]);break}if(k+j<=1){f[e+(M<<3)>>2]=(z=1-k-j)*+f[R+(b<<3)>>2]+k*+f[R+((i=b+1|0)<<3)>>2]+j*+f[R+((_=b+V|0)<<3)>>2],z=z*+f[R+(b<<3)+4>>2]+k*+f[R+(i<<3)+4>>2],y=j*+f[R+(_<<3)+4>>2];break}f[e+(M<<3)>>2]=(C=k+-1+j)*+f[R+((a=1+(i=b+V|0)|0)<<3)>>2]+(z=1-k)*+f[R+(i<<3)>>2]+(y=1-j)*+f[R+((_=b+1|0)<<3)>>2],z=C*+f[R+(a<<3)+4>>2]+z*+f[R+(i<<3)+4>>2],y*=+f[R+(_<<3)+4>>2];break}if(A||(aa=+f[R>>2],da=+f[F>>2],ca=+f[G>>2],D=+f[H>>2],$=+f[I>>2],t=(w=+f[J>>2])-(x=+f[K>>2]),A=1,D=.25*(aa+da+ca+D)-.5*(aa=D-aa),E=.25*($+w+x+(E=+f[L>>2]))-.5*($=E-$),x=.5*((u=da-ca)+aa),w=.5*(t+$),u=.5*(aa-u),t=.5*($-t)),!(z<3&-2<B&B<3&-2<z)){f[e+(M<<3)>>2]=z*u+(B*x+D),z*=t,y=B*w+E;break}do{if(B<=0){if(z<=0){l=D-(n=2*u),m=E-(o=2*t),n=(r=D-2*x)-n,o=(s=E-2*w)-o,p=+f[R>>2],q=+f[I>>2],k=.5*(2+B),j=.5*(z+2);break}if(i){o=(j=+(0|(i=(0|U)==(0|(i=~~C))?O:i)))/X,k=(0|(_=i+1|0))/X,i=0|v(i,V),_=0|v(_,V),l=+f[R+(i<<3)>>2],m=+f[R+(i<<3)+4>>2],n=o*u+(r=D-2*x),o=o*t+(s=E-2*w),p=+f[R+(_<<3)>>2],q=+f[R+(_<<3)+4>>2],r=k*u+r,s=k*t+s,k=.5*(2+B),j=C-j;break}l=+f[G>>2],m=+f[K>>2],n=u+(r=D-2*x),o=t+(s=E-2*w),p=(j=3*u)+D,q=(k=3*t)+E,r=j+r,s=k+s,k=.5*(2+B),j=.5*(z+-1);break}if(b=z<=0,a){if(b){l=(m=(0|(i=(_=(0|T)==(0|(_=~~y))?P:_)+1|0))/W)*x+D-(n=2*u),m=m*w+E-(o=2*t),n=(p=(k=+(0|_))/W)*x+D-n,o=p*w+E-o,p=+f[R+(i<<3)>>2],q=+f[R+(i<<3)+4>>2],r=+f[R+(_<<3)>>2],s=+f[R+(_<<3)+4>>2],k=y-k,j=.5*(z+2);break}if(i){c[Y>>2]=M,g[Y+8>>3]=B,g[Y+16>>3]=z,ia(0,865,Y);break}k=+(0|(_=(0|T)==(0|(_=~~y))?P:_)),q=(0|(i=_+1|0))/W,l=+f[R+((i=i+N|0)<<3)>>2],m=+f[R+(i<<3)+4>>2],n=+f[R+((_=_+N|0)<<3)>>2],o=+f[R+(_<<3)+4>>2],p=(r=3*u)+(q*x+D),q=(j=3*t)+(q*w+E),r+=(s=k/W)*x+D,s=j+(s*w+E),k=y-k,j=.5*(z+-1);break}if(b){l=(p=3*x+D)-(n=2*u),m=(q=3*w+E)-(o=2*t),n=x+D-n,o=w+E-o,r=+f[F>>2],s=+f[J>>2],k=.5*(B-1),j=.5*(z+2);break}if(i){m=(j=+(0|(i=(0|U)==(0|(i=~~C))?O:i)))/X,r=(0|(_=i+1|0))/X,i=(0|v(i,V))+T|0,_=(0|v(_,V))+T|0,l=m*u+(p=3*x+D),m=m*t+(q=3*w+E),n=+f[R+(i<<3)>>2],o=+f[R+(i<<3)+4>>2],p=r*u+p,q=r*t+q,r=+f[R+(_<<3)>>2],s=+f[R+(_<<3)+4>>2],k=.5*(B-1),j=C-j;break}l=u+(p=3*x+D),m=t+(q=3*w+E),n=+f[H>>2],o=+f[L>>2],p=(r=3*u)+p,q=(s=3*t)+q,r+=x+D,s+=w+E,k=.5*(B-1),j=.5*(z+-1);break}while(0);if(k+j<=1){f[e+(M<<3)>>2]=n+(l-n)*k+(r-n)*j,z=o+(m-o)*k,y=(s-o)*j;break}f[e+(M<<3)>>2]=p+(r-p)*(z=1-k)+(l-p)*(y=1-j),z=q+(s-q)*z,y*=m-q;break}while(0)}while(f[e+(M<<3)+4>>2]=z+y,(0|(M=M+1|0))!=(0|h));S=Z}},function(a,b,d,e,g){d|=0,e|=0,g|=0;var i,k,n,o,h,j,l,m;if(b=0|c[(0|c[308+(a|=0)>>2])+((b|=0)<<5)+16>>2],j=3.1415927410125732*(+f[(0|c[a+168>>2])+(12*b|0)+4>>2]+ +f[(0|c[a+284>>2])+(b<<2)>>2])/180,h=+t(+j),j=+s(+j),k=(j*=i=+f[(0|c[a+272>>2])+(b<<2)>>2])*(l=0==(0|c[(0|c[a+288>>2])+(b<<2)>>2])?1:-1),i=(h*=i)*(m=0==(0|c[(0|c[a+292>>2])+(b<<2)>>2])?1:-1),l*=h,m*=j,j=+f[(0|c[a+276>>2])+(b<<2)>>2],h=+f[(0|c[a+280>>2])+(b<<2)>>2],!((0|g)<=0))for(b=0;o=+f[d+(b<<3)>>2],n=+f[d+(b<<3)+4>>2],f[e+(b<<3)>>2]=k*o-i*n+j,f[e+(b<<3)+4>>2]=l*o+m*n+h,(0|(b=b+1|0))!=(0|g););}];return{___errno_location:function(){return 3688},___muldi3:Lc,___udivdi3:Qc,_bitshift64Lshr:Rc,_bitshift64Shl:Sc,_csmFree:function(a){Fc(a|=0)},_csmGetDrawableConstantFlags:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[888+(0|c[a>>2])>>2],S=d,0|b):(c[b>>2]=1896,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetDrawableCount:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[a+332>>2],S=d,0|b):(c[b>>2]=1858,c[b+4>>2]=1411,ia(0,1269,b),S=d,-1)},_csmGetDrawableDrawOrders:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[a+440>>2],S=d,0|b):(c[b>>2]=1980,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetDrawableDynamicFlags:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[a+432>>2],S=d,0|b):(c[b>>2]=1924,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetDrawableIds:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[832+(0|c[a>>2])>>2],S=d,0|b):(c[b>>2]=1878,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetDrawableIndexCounts:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[904+(0|c[a>>2])>>2],S=d,0|b):(c[b>>2]=2182,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetDrawableIndices:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[840+(0|c[a>>2])>>2],S=d,0|b):(c[b>>2]=2208,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetDrawableMaskCounts:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[912+(0|c[a>>2])>>2],S=d,0|b):(c[b>>2]=2056,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetDrawableMasks:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[844+(0|c[a>>2])>>2],S=d,0|b):(c[b>>2]=2081,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetDrawableMultiplyColors:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[a+452>>2],S=d,0|b):(c[b>>2]=2230,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetDrawableOpacities:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[a+448>>2],S=d,0|b):(c[b>>2]=2032,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetDrawableParentPartIndices:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[876+(0|c[a>>2])>>2],S=d,0|b):(c[b>>2]=2286,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetDrawableRenderOrders:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[a+436>>2],S=d,0|b):(c[b>>2]=2005,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetDrawableScreenColors:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[a+456>>2],S=d,0|b):(c[b>>2]=2259,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetDrawableTextureIndices:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[884+(0|c[a>>2])>>2],S=d,0|b):(c[b>>2]=1951,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetDrawableVertexCounts:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[892+(0|c[a>>2])>>2],S=d,0|b):(c[b>>2]=2101,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetDrawableVertexPositions:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[a+444>>2],S=d,0|b):(c[b>>2]=2128,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetDrawableVertexUvs:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[836+(0|c[a>>2])>>2],S=d,0|b):(c[b>>2]=2158,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetLatestMocVersion:function(){return 4},_csmGetMocVersion:function(a,b){b|=0;var d=S;return S=S+16|0,b=d,(a|=0)?(a=0|ra(a),S=d,0|a):(c[b>>2]=1286,c[b+4>>2]=1303,ia(0,1269,b),S=d,(a=0)|a)},_csmGetParameterCount:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[a+540>>2],S=d,0|b):(c[b>>2]=1610,c[b+4>>2]=1411,ia(0,1269,b),S=d,-1)},_csmGetParameterDefaultValues:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[932+(0|c[a>>2])>>2],S=d,0|b):(c[b>>2]=1729,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetParameterIds:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[916+(0|c[a>>2])>>2],S=d,0|b):(c[b>>2]=1631,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetParameterKeyCounts:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[a+616>>2],S=d,0|b):(c[b>>2]=2347,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetParameterKeyValues:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[a+612>>2],S=d,0|b):(c[b>>2]=2372,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetParameterMaximumValues:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[924+(0|c[a>>2])>>2],S=d,0|b):(c[b>>2]=1700,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetParameterMinimumValues:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[928+(0|c[a>>2])>>2],S=d,0|b):(c[b>>2]=1671,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetParameterTypes:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[a+548>>2],S=d,0|b):(c[b>>2]=1650,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetParameterValues:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[a+552>>2],S=d,0|b):(c[b>>2]=1758,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetPartCount:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[a+4>>2],S=d,0|b):(c[b>>2]=1780,c[b+4>>2]=1411,ia(0,1269,b),S=d,-1)},_csmGetPartIds:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[712+(0|c[a>>2])>>2],S=d,0|b):(c[b>>2]=1796,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetPartOpacities:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[a+52>>2],S=d,0|b):(c[b>>2]=1810,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetPartParentPartIndices:function(a){var b=0,d=S;return S=S+16|0,b=d,(a|=0)?(b=0|c[740+(0|c[a>>2])>>2],S=d,0|b):(c[b>>2]=1830,c[b+4>>2]=1411,ia(0,1269,b),S=d,(b=0)|b)},_csmGetSizeofModel:Ha,_csmGetVersion:function(){return 67239938},_csmInitializeModelInPlace:Ia,_csmMalloc:function(a){return 0|Ec(a|=0)},_csmMallocMoc:function(a){var b,d=S;return S=S+16|0,Ic(b=d,64,a|=0),S=d,0|c[b>>2]},_csmMallocModelAndInitialize:function(d){var b=0,e=0,f=S;return S=S+16|0,b=f,0!=(0|(d|=0))&&0==(0|Ic(b,16,e=0|Ha(d)))?(b=0|Ia(d,d=0|c[b>>2],e))||(Fc(d),b=0):b=0,S=f,0|b},_csmReadCanvasInfo:function(a,b,d,e){b|=0,d|=0,e|=0;var f,g,h,i=0,j=S;S=S+32|0,g=j+24|0,i=j+16|0,h=j+8|0,f=j,(a|=0)?b?d?e?(i=0|c[708+(0|c[a>>2])>>2],c[b>>2]=c[i+12>>2],c[b+4>>2]=c[i+16>>2],c[d>>2]=c[i+4>>2],c[d+4>>2]=c[i+8>>2],c[e>>2]=c[i>>2]):(c[g>>2]=1393,c[4+g>>2]=1487,ia(0,1269,g)):(c[i>>2]=1393,c[i+4>>2]=1458,ia(0,1269,i)):(c[h>>2]=1393,c[4+h>>2]=1431,ia(0,1269,h)):(c[f>>2]=1393,c[f+4>>2]=1411,ia(0,1269,f)),S=j},_csmResetDrawableDynamicFlags:function(a){var b,d=S;S=S+16|0,b=d,(a|=0)?c[a+428>>2]=1:(c[b>>2]=2318,c[b+4>>2]=1411,ia(0,1269,b)),S=d},_csmReviveMocInPlace:function(a,b){b|=0;var e,d=0,f=0,g=S;return S=S+32|0,f=g+16|0,e=g+8|0,d=g,(a|=0)?((d=a)+63&-64|0)!=(0|d)?(c[e>>2]=1322,c[4+e>>2]=1342,ia(0,1269,e),S=g,(f=0)|f):0|b&&(b+63&-64|0)==(0|b)?(f=0|qa(a),S=g,0|f):(c[f>>2]=1322,c[f+4>>2]=1374,ia(0,1269,f),S=g,(f=0)|f):(c[d>>2]=1322,c[d+4>>2]=1303,ia(0,1269,d),S=g,(f=0)|f)},_csmSetLogFunction:function(a){c[904]=a|=0},_csmUpdateModel:function(a){var b,d=S;S=S+16|0,b=d,(a|=0)?Gb(a):(c[b>>2]=1595,c[b+4>>2]=1411,ia(0,1269,b)),S=d},_emscripten_get_sbrk_ptr:function(){return 4208},_emscripten_replace_memory:function(newBuffer){return a=new Int8Array(newBuffer),d=new Uint8Array(newBuffer),b=new Int16Array(newBuffer),e=new Uint16Array(newBuffer),c=new Int32Array(newBuffer),f=new Float32Array(newBuffer),g=new Float64Array(newBuffer),!0},_free:Fc,_i64Add:Mc,_i64Subtract:Nc,_malloc:Ec,_memcpy:Uc,_memset:Vc,dynCall_ii:function(a,b){return 0|W[3&(a|=0)](0|(b|=0))},dynCall_iiii:function(a,b,c,d){return 0|X[3&(a|=0)](0|(b|=0),0|(c|=0),0|(d|=0))},dynCall_iiiii:function(a,b,c,d,e){return 0|Y[3&(a|=0)](0|(b|=0),0|(c|=0),0|(d|=0),0|(e|=0))},dynCall_vi:function(a,b){Z[1&(a|=0)](0|(b|=0))},dynCall_vii:function(a,b,c){_[3&(a|=0)](0|(b|=0),0|(c|=0))},dynCall_viiiii:function(a,b,c,d,e,f){$[3&(a|=0)](0|(b|=0),0|(c|=0),0|(d|=0),0|(e|=0),0|(f|=0))},establishStackSpace:function(a,b){S=a|=0},stackAlloc:function(a){var b=S;return S=15+(S+(a|=0)|0)&-16,0|b},stackRestore:function(a){S=0|a},stackSave:function(){return 0|S}}}({Math:Math,Int8Array:Int8Array,Int16Array:Int16Array,Int32Array:Int32Array,Uint8Array:Uint8Array,Uint16Array:Uint16Array,Float32Array:Float32Array,Float64Array:Float64Array},{a:C,b:function(a){J=a},c:function(){return J},d:function(a,c){return I[a](c)},e:function(a,c,d,f){return I[a](c,d,f)},f:function(a,c,d,f,g){return I[a](c,d,f,g)},g:function(a,c){I[a](c)},h:function(a,c,d){I[a](c,d)},i:function(a,c,d,f,g,h){I[a](c,d,f,g,h)},j:function(){return pa.apply(null,arguments)},k:qa,l:function(a,c,d){M.set(M.subarray(c,c+d),a)},m:function(a){if(2130706432<a)return!1;for(var c=Math.max(qa(),16777216);c<a;)c=c<=536870912?ea(2*c):Math.min(ea((3*c+2147483648)/4),2130706432);return!!ra(c)},n:pa,o:function(){C("OOM")},p:function(a){return a},q:na,r:ra,s:function(){var a=b._fflush;a&&a(0),V[1].length&&W(1,10),V[2].length&&W(2,10)},t:oa,u:function(){var a=oa();return b.extraStackTrace&&(a+="\n"+b.extraStackTrace()),na(a)},v:4400},buffer),b.___errno_location=Aa.___errno_location,b.___muldi3=Aa.___muldi3,b.___udivdi3=Aa.___udivdi3,b._bitshift64Lshr=Aa._bitshift64Lshr,b._bitshift64Shl=Aa._bitshift64Shl,b._csmFree=Aa._csmFree,b._csmGetDrawableConstantFlags=Aa._csmGetDrawableConstantFlags,b._csmGetDrawableCount=Aa._csmGetDrawableCount,b._csmGetDrawableDrawOrders=Aa._csmGetDrawableDrawOrders,b._csmGetDrawableDynamicFlags=Aa._csmGetDrawableDynamicFlags,b._csmGetDrawableIds=Aa._csmGetDrawableIds,b._csmGetDrawableIndexCounts=Aa._csmGetDrawableIndexCounts,b._csmGetDrawableIndices=Aa._csmGetDrawableIndices,b._csmGetDrawableMaskCounts=Aa._csmGetDrawableMaskCounts,b._csmGetDrawableMasks=Aa._csmGetDrawableMasks,b._csmGetDrawableMultiplyColors=Aa._csmGetDrawableMultiplyColors,b._csmGetDrawableOpacities=Aa._csmGetDrawableOpacities,b._csmGetDrawableParentPartIndices=Aa._csmGetDrawableParentPartIndices,b._csmGetDrawableRenderOrders=Aa._csmGetDrawableRenderOrders,b._csmGetDrawableScreenColors=Aa._csmGetDrawableScreenColors,b._csmGetDrawableTextureIndices=Aa._csmGetDrawableTextureIndices,b._csmGetDrawableVertexCounts=Aa._csmGetDrawableVertexCounts,b._csmGetDrawableVertexPositions=Aa._csmGetDrawableVertexPositions,b._csmGetDrawableVertexUvs=Aa._csmGetDrawableVertexUvs,b._csmGetLatestMocVersion=Aa._csmGetLatestMocVersion,b._csmGetMocVersion=Aa._csmGetMocVersion,b._csmGetParameterCount=Aa._csmGetParameterCount,b._csmGetParameterDefaultValues=Aa._csmGetParameterDefaultValues,b._csmGetParameterIds=Aa._csmGetParameterIds,b._csmGetParameterKeyCounts=Aa._csmGetParameterKeyCounts,b._csmGetParameterKeyValues=Aa._csmGetParameterKeyValues,b._csmGetParameterMaximumValues=Aa._csmGetParameterMaximumValues,b._csmGetParameterMinimumValues=Aa._csmGetParameterMinimumValues,b._csmGetParameterTypes=Aa._csmGetParameterTypes,b._csmGetParameterValues=Aa._csmGetParameterValues,b._csmGetPartCount=Aa._csmGetPartCount,b._csmGetPartIds=Aa._csmGetPartIds,b._csmGetPartOpacities=Aa._csmGetPartOpacities,b._csmGetPartParentPartIndices=Aa._csmGetPartParentPartIndices,b._csmGetSizeofModel=Aa._csmGetSizeofModel,b._csmGetVersion=Aa._csmGetVersion,b._csmInitializeModelInPlace=Aa._csmInitializeModelInPlace,b._csmMalloc=Aa._csmMalloc,b._csmMallocMoc=Aa._csmMallocMoc,b._csmMallocModelAndInitialize=Aa._csmMallocModelAndInitialize,b._csmReadCanvasInfo=Aa._csmReadCanvasInfo,b._csmResetDrawableDynamicFlags=Aa._csmResetDrawableDynamicFlags,b._csmReviveMocInPlace=Aa._csmReviveMocInPlace,b._csmSetLogFunction=Aa._csmSetLogFunction,b._csmUpdateModel=Aa._csmUpdateModel,b._emscripten_get_sbrk_ptr=Aa._emscripten_get_sbrk_ptr;var sa=b._emscripten_replace_memory=Aa._emscripten_replace_memory;b._free=Aa._free,b._i64Add=Aa._i64Add,b._i64Subtract=Aa._i64Subtract,b._malloc=Aa._malloc,b._memcpy=Aa._memcpy,b._memset=Aa._memset,b.establishStackSpace=Aa.establishStackSpace;var F,Ca,Ea,Y,xa=b.stackAlloc=Aa.stackAlloc,ya=b.stackRestore=Aa.stackRestore,za=b.stackSave=Aa.stackSave;function Z(){function a(){if(!Y&&(Y=!0,!K)){if(P(ja),P(ka),b.onRuntimeInitialized&&b.onRuntimeInitialized(),b.postRun)for("function"==typeof b.postRun&&(b.postRun=[b.postRun]);b.postRun.length;){var a=b.postRun.shift();la.unshift(a)}P(la)}}if(!(0<Q)){if(b.preRun)for("function"==typeof b.preRun&&(b.preRun=[b.preRun]);b.preRun.length;)!function(){var a=b.preRun.shift();ia.unshift(a)}();P(ia),0<Q||(b.setStatus?(b.setStatus("Running..."),setTimeout(function(){setTimeout(function(){b.setStatus("")},1),a()},1)):a())}}if(b.dynCall_ii=Aa.dynCall_ii,b.dynCall_iiii=Aa.dynCall_iiii,b.dynCall_iiiii=Aa.dynCall_iiiii,b.dynCall_vi=Aa.dynCall_vi,b.dynCall_vii=Aa.dynCall_vii,b.dynCall_viiiii=Aa.dynCall_viiiii,b.asm=Aa,b.ccall=function(a,c,d,f){var g={string:function(a){var c=0;if(null!=a&&0!==a){var d=1+(a.length<<2),f=c=xa(d),g=M;if(0<d){for(var d=f+d-1,h=0;h<a.length;++h){var l=a.charCodeAt(h);if((l=55296<=l&&l<=57343?65536+((1023&l)<<10)|1023&a.charCodeAt(++h):l)<=127){if(d<=f)break;g[f++]=l}else{if(l<=2047){if(d<=f+1)break;g[f++]=192|l>>6}else{if(l<=65535){if(d<=f+2)break;g[f++]=224|l>>12}else{if(d<=f+3)break;g[f++]=240|l>>18,g[f++]=128|l>>12&63}g[f++]=128|l>>6&63}g[f++]=128|63&l}}g[f]=0}}return c},array:function(a){var c=xa(a.length);return N.set(a,c),c}},h=function(a){var c=b["_"+a];return assert(c,"Cannot call unknown function "+a+", make sure it is exported"),c}(a),p=[];if(a=0,f)for(var k=0;k<f.length;k++){var y=g[d[k]];y?(0===a&&(a=za()),p[k]=y(f[k])):p[k]=f[k]}return d=function(a){return"string"===c?da(a):"boolean"===c?!!a:a}(d=h.apply(null,p)),0!==a&&ya(a),d},b.UTF8ToString=da,b.addFunction=function(a){for(var c=0;c<1;c++)if(!I[c])return I[c]=a,1+c;throw"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS."},E&&((String.prototype.startsWith?E.startsWith(U):0===E.indexOf(U))||(Aa=E,E=b.locateFile?b.locateFile(Aa,u):u+Aa),r||t?(Ea=x(E),M.set(Ea,8)):(Q++,b.monitorRunDependencies&&b.monitorRunDependencies(Q),F=function(a){a.byteLength&&(a=new Uint8Array(a)),M.set(a,8),b.memoryInitializerRequest&&delete b.memoryInitializerRequest.response,Q--,b.monitorRunDependencies&&b.monitorRunDependencies(Q),0==Q&&(null!==S&&(clearInterval(S),S=null),T&&(a=T,T=null,a()))},Ca=function(){w(function(){throw"could not load memory initializer "+E})},(Ea=B(E))?F(Ea.buffer):b.memoryInitializerRequest?(Ea=function(){var a=b.memoryInitializerRequest,c=a.response;if(200!==a.status&&0!==a.status){if(!(c=B(b.memoryInitializerRequestURL)))return console.warn("a problem seems to have happened with Module.memoryInitializerRequest, status: "+a.status+", retrying "+E),void Ca();c=c.buffer}F(c)},b.memoryInitializerRequest.response?setTimeout(Ea,0):b.memoryInitializerRequest.addEventListener("load",Ea)):Ca())),b.then=function(a){var c;return Y?a(b):(c=b.onRuntimeInitialized,b.onRuntimeInitialized=function(){c&&c(),a(b)}),b},T=function Fa(){Y||Z(),Y||(T=Fa)},b.run=Z,b.preInit)for("function"==typeof b.preInit&&(b.preInit=[b.preInit]);0<b.preInit.length;)b.preInit.pop()();return Z(),_em_module});"object"==typeof exports&&"object"==typeof module?module.exports=_em_module:"function"==typeof define&&define.amd?define([],function(){return _em_module}):"object"==typeof exports&&(exports._em_module=_em_module);var _em=_em_module()}(Live2DCubismCore=Live2DCubismCore||{});
\ No newline at end of file
diff --git a/bins/ayaka-gui/src-tauri/Cargo.toml b/bins/ayaka-gui/src-tauri/Cargo.toml
new file mode 100644
index 00000000..c6471061
--- /dev/null
+++ b/bins/ayaka-gui/src-tauri/Cargo.toml
@@ -0,0 +1,20 @@
+[package]
+name = "ayaka-gui"
+version = "0.1.0"
+edition = "2021"
+
+[build-dependencies]
+tauri-build = { version = "1.0", features = [] }
+
+[dependencies]
+ayaka-runtime = { path = "../../../utils/ayaka-runtime" }
+flexi_logger = { version = "0.23", default-features = false, features = ["colors"] }
+serde_json = "1.0"
+serde = { version = "1.0", features = ["derive"] }
+tauri = { version = "1.0", features = ["cli", "protocol-all", "window-all"] }
+tauri-plugin-localhost = "0.1"
+portpicker = "0.1"
+
+[features]
+default = [ "custom-protocol" ]
+custom-protocol = [ "tauri/custom-protocol" ]
diff --git a/bins/ayaka-gui/src-tauri/build.rs b/bins/ayaka-gui/src-tauri/build.rs
new file mode 100644
index 00000000..d860e1e6
--- /dev/null
+++ b/bins/ayaka-gui/src-tauri/build.rs
@@ -0,0 +1,3 @@
+fn main() {
+    tauri_build::build()
+}
diff --git a/bins/ayaka-gui/src-tauri/icons/128x128.png b/bins/ayaka-gui/src-tauri/icons/128x128.png
new file mode 100644
index 00000000..4ef2562d
Binary files /dev/null and b/bins/ayaka-gui/src-tauri/icons/128x128.png differ
diff --git a/bins/ayaka-gui/src-tauri/icons/128x128@2x.png b/bins/ayaka-gui/src-tauri/icons/128x128@2x.png
new file mode 100644
index 00000000..a4a5d400
Binary files /dev/null and b/bins/ayaka-gui/src-tauri/icons/128x128@2x.png differ
diff --git a/bins/ayaka-gui/src-tauri/icons/32x32.png b/bins/ayaka-gui/src-tauri/icons/32x32.png
new file mode 100644
index 00000000..5359f85c
Binary files /dev/null and b/bins/ayaka-gui/src-tauri/icons/32x32.png differ
diff --git a/bins/ayaka-gui/src-tauri/icons/icon.icns b/bins/ayaka-gui/src-tauri/icons/icon.icns
new file mode 100644
index 00000000..a1371c92
Binary files /dev/null and b/bins/ayaka-gui/src-tauri/icons/icon.icns differ
diff --git a/bins/ayaka-gui/src-tauri/icons/icon.ico b/bins/ayaka-gui/src-tauri/icons/icon.ico
new file mode 100644
index 00000000..32fbbff3
Binary files /dev/null and b/bins/ayaka-gui/src-tauri/icons/icon.ico differ
diff --git a/bins/ayaka-gui/src-tauri/src/main.rs b/bins/ayaka-gui/src-tauri/src/main.rs
new file mode 100644
index 00000000..d911e2fc
--- /dev/null
+++ b/bins/ayaka-gui/src-tauri/src/main.rs
@@ -0,0 +1,402 @@
+#![cfg_attr(
+    all(not(debug_assertions), target_os = "windows"),
+    windows_subsystem = "windows"
+)]
+
+use ayaka_runtime::{
+    anyhow::{self, anyhow, Result},
+    log::{debug, info, warn},
+    *,
+};
+use flexi_logger::{FileSpec, LogSpecification, Logger};
+use serde::{Deserialize, Serialize};
+use std::{collections::HashMap, fmt::Display};
+use tauri::{async_runtime::Mutex, command, AppHandle, Manager, State};
+
+type CommandResult<T> = std::result::Result<T, CommandError>;
+
+#[derive(Debug, Default, Serialize)]
+struct CommandError {
+    msg: String,
+}
+
+impl<E: Into<anyhow::Error>> From<E> for CommandError {
+    fn from(e: E) -> Self {
+        Self {
+            msg: e.into().to_string(),
+        }
+    }
+}
+
+impl Display for CommandError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.write_str(&self.msg)
+    }
+}
+
+#[command]
+fn ayaka_version() -> &'static str {
+    ayaka_runtime::version()
+}
+
+#[derive(Debug, Serialize)]
+struct FullSettings {
+    settings: Settings,
+    contexts: Vec<RawContext>,
+}
+
+#[derive(Debug, Clone, Serialize)]
+#[serde(tag = "t", content = "data")]
+enum OpenGameStatus {
+    LoadSettings,
+    LoadProfile(String),
+    CreateRuntime,
+    LoadPlugin(String, usize, usize),
+    LoadGlobalRecords,
+    LoadRecords,
+    Loaded,
+}
+
+fn emit_open_status(
+    handle: &AppHandle,
+    status: OpenGameStatus,
+) -> std::result::Result<(), tauri::Error> {
+    handle.emit_all("ayaka://open_status", status)
+}
+
+#[command]
+async fn open_game(handle: AppHandle, storage: State<'_, Storage>) -> CommandResult<()> {
+    let config = &storage.config;
+    let context = Context::open(config, FrontendType::Html);
+    pin_mut!(context);
+    while let Some(status) = context.next().await {
+        match status {
+            OpenStatus::LoadProfile => {
+                emit_open_status(&handle, OpenGameStatus::LoadProfile(config.clone()))?
+            }
+            OpenStatus::CreateRuntime => emit_open_status(&handle, OpenGameStatus::CreateRuntime)?,
+            OpenStatus::LoadPlugin(name, i, len) => {
+                emit_open_status(&handle, OpenGameStatus::LoadPlugin(name, i, len))?
+            }
+        }
+    }
+    let mut ctx = context.await?;
+
+    let window = handle.get_window("main").unwrap();
+    window.set_title(&ctx.game.title)?;
+    let settings = {
+        emit_open_status(&handle, OpenGameStatus::LoadSettings)?;
+        load_settings(&storage.ident).await.unwrap_or_else(|e| {
+            warn!("Load settings failed: {}", e);
+            Settings::new()
+        })
+    };
+    ctx.set_settings(settings);
+
+    emit_open_status(&handle, OpenGameStatus::LoadGlobalRecords)?;
+    ctx.set_global_record(
+        load_global_record(&storage.ident, &ctx.game.title)
+            .await
+            .unwrap_or_else(|e| {
+                warn!("Load global records failed: {}", e);
+                Default::default()
+            }),
+    );
+
+    emit_open_status(&handle, OpenGameStatus::LoadRecords)?;
+    *storage.records.lock().await = load_records(&storage.ident, &ctx.game.title)
+        .await
+        .unwrap_or_else(|e| {
+            warn!("Load records failed: {}", e);
+            Default::default()
+        });
+    *storage.context.lock().await = Some(ctx);
+
+    emit_open_status(&handle, OpenGameStatus::Loaded)?;
+    Ok(())
+}
+
+#[command]
+async fn get_settings(storage: State<'_, Storage>) -> CommandResult<Option<Settings>> {
+    Ok(storage
+        .context
+        .lock()
+        .await
+        .as_ref()
+        .map(|ctx| ctx.settings())
+        .cloned())
+}
+
+#[command]
+async fn set_settings(settings: Settings, storage: State<'_, Storage>) -> CommandResult<()> {
+    if let Some(context) = storage.context.lock().await.as_mut() {
+        context.set_settings(settings);
+    }
+    Ok(())
+}
+
+#[command]
+async fn get_records(storage: State<'_, Storage>) -> CommandResult<Vec<ActionRecord>> {
+    Ok(storage.records.lock().await.clone())
+}
+
+#[command]
+async fn save_record_to(index: usize, storage: State<'_, Storage>) -> CommandResult<()> {
+    let mut records = storage.records.lock().await;
+    if let Some(record) = storage
+        .context
+        .lock()
+        .await
+        .as_ref()
+        .map(|ctx| ctx.record.clone())
+    {
+        if index >= records.len() {
+            records.push(record);
+        } else {
+            records[index] = record;
+        }
+    }
+    Ok(())
+}
+
+#[command]
+async fn save_all(storage: State<'_, Storage>) -> CommandResult<()> {
+    if let Some(context) = storage.context.lock().await.as_ref() {
+        let game = &context.game.title;
+        save_settings(&storage.ident, context.settings()).await?;
+        save_global_record(&storage.ident, game, context.global_record()).await?;
+        save_records(&storage.ident, game, &storage.records.lock().await).await?;
+    }
+    Ok(())
+}
+
+#[command]
+fn choose_locale(locales: Vec<Locale>) -> CommandResult<Option<Locale>> {
+    let current = Locale::current();
+    debug!("Choose {} from {:?}", current, locales);
+    Ok(current.choose_from(&locales).cloned())
+}
+
+#[derive(Default)]
+struct Storage {
+    ident: String,
+    config: String,
+    records: Mutex<Vec<ActionRecord>>,
+    context: Mutex<Option<Context>>,
+    action: Mutex<Option<Action>>,
+}
+
+impl Storage {
+    pub fn new(ident: impl Into<String>, config: impl Into<String>) -> Self {
+        Self {
+            ident: ident.into(),
+            config: config.into(),
+            ..Default::default()
+        }
+    }
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+struct GameInfo {
+    pub title: String,
+    pub author: String,
+    pub props: HashMap<String, String>,
+}
+
+impl GameInfo {
+    pub fn new(game: &Game) -> Self {
+        Self {
+            title: game.title.clone(),
+            author: game.author.clone(),
+            props: game.props.clone(),
+        }
+    }
+}
+
+#[command]
+async fn info(storage: State<'_, Storage>) -> CommandResult<Option<GameInfo>> {
+    let ctx = storage.context.lock().await;
+    if let Some(ctx) = ctx.as_ref() {
+        Ok(Some(GameInfo::new(&ctx.game)))
+    } else {
+        warn!("Game hasn't been loaded.");
+        Ok(None)
+    }
+}
+
+#[command]
+async fn start_new(locale: Locale, storage: State<'_, Storage>) -> CommandResult<()> {
+    if let Some(ctx) = storage.context.lock().await.as_mut() {
+        ctx.init_new();
+        info!("Init new context with locale {}.", locale);
+    } else {
+        warn!("Game hasn't been loaded.")
+    }
+    Ok(())
+}
+
+#[command]
+async fn start_record(
+    locale: Locale,
+    index: usize,
+    storage: State<'_, Storage>,
+) -> CommandResult<()> {
+    if let Some(ctx) = storage.context.lock().await.as_mut() {
+        let raw_ctx = storage.records.lock().await[index].clone();
+        let last_line = raw_ctx.history.last().unwrap();
+        *storage.action.lock().await = Some(last_line.clone());
+        ctx.init_context(raw_ctx);
+        info!("Init new context with locale {}.", locale);
+    } else {
+        warn!("Game hasn't been loaded.")
+    }
+    Ok(())
+}
+
+#[command]
+async fn next_run(storage: State<'_, Storage>) -> CommandResult<bool> {
+    let mut context = storage.context.lock().await;
+    let action = context.as_mut().and_then(|context| context.next_run());
+    if let Some(action) = action {
+        debug!("Next action: {:?}", action);
+        *storage.action.lock().await = Some(action);
+        Ok(true)
+    } else {
+        debug!("No action left.");
+        *storage.action.lock().await = None;
+        Ok(false)
+    }
+}
+
+#[command]
+async fn next_back_run(storage: State<'_, Storage>) -> CommandResult<bool> {
+    let mut context = storage.context.lock().await;
+    let action = context.as_mut().and_then(|context| context.next_back_run());
+    if let Some(action) = action {
+        debug!("Last action: {:?}", action);
+        *storage.action.lock().await = Some(action);
+        Ok(true)
+    } else {
+        debug!("No action in the history.");
+        Ok(false)
+    }
+}
+
+#[command]
+async fn current_visited(storage: State<'_, Storage>) -> CommandResult<bool> {
+    let action = storage.action.lock().await;
+    let visited = if let Some(action) = action.as_ref() {
+        let context = storage.context.lock().await;
+        context
+            .as_ref()
+            .map(|context| context.visited(action))
+            .unwrap_or_default()
+    } else {
+        false
+    };
+    Ok(visited)
+}
+
+#[command]
+async fn current_run(storage: State<'_, Storage>) -> CommandResult<Option<Action>> {
+    Ok(storage.action.lock().await.as_ref().cloned())
+}
+
+#[command]
+async fn switch(i: usize, storage: State<'_, Storage>) -> CommandResult<RawValue> {
+    debug!("Switch {}", i);
+    let mut context = storage.context.lock().await;
+    let context = context
+        .as_mut()
+        .ok_or_else(|| anyhow!("Context not initialized."))?;
+    let action = storage.action.lock().await;
+    let switch = action
+        .as_ref()
+        .and_then(|action| action.switches.get(i))
+        .ok_or_else(|| anyhow!("Index error: {}", i))?;
+    Ok(context.call(&switch.action))
+}
+
+#[command]
+async fn history(storage: State<'_, Storage>) -> CommandResult<Vec<Action>> {
+    let mut hs = storage
+        .context
+        .lock()
+        .await
+        .as_ref()
+        .map(|context| context.record.history.clone())
+        .unwrap_or_default();
+    hs.reverse();
+    debug!("Get history {:?}", hs);
+    Ok(hs)
+}
+
+fn main() -> Result<()> {
+    let port =
+        portpicker::pick_unused_port().ok_or_else(|| anyhow!("failed to find unused port"))?;
+    info!("Picked port {}", port);
+    tauri::Builder::default()
+        .plugin(tauri_plugin_localhost::Builder::new(port).build())
+        .setup(|app| {
+            let ident = app.config().tauri.bundle.identifier.clone();
+            let log_handle = if cfg!(debug_assertions) {
+                Logger::with(LogSpecification::parse("warn,ayaka=debug,ayalog=debug")?)
+                    .log_to_stdout()
+                    .set_palette("b1;3;2;4;6".to_string())
+                    .use_utc()
+                    .start()?
+            } else {
+                Logger::with(LogSpecification::parse("info,wasmer=warn")?)
+                    .log_to_file(
+                        FileSpec::default()
+                            .directory(app.path_resolver().log_dir().unwrap())
+                            .basename("ayaka-gui"),
+                    )
+                    .use_utc()
+                    .start()?
+            };
+            app.manage(log_handle);
+            #[cfg(debug_assertions)]
+            {
+                let window = app.get_window("main").unwrap();
+                window.open_devtools();
+            }
+            let matches = app.get_cli_matches()?;
+            let config = matches.args["config"]
+                .value
+                .as_str()
+                .map(|s| s.to_string())
+                .unwrap_or_else(|| {
+                    std::env::current_exe()
+                        .unwrap()
+                        .parent()
+                        .unwrap()
+                        .join("config.yaml")
+                        .to_string_lossy()
+                        .into_owned()
+                });
+            app.manage(Storage::new(ident, config));
+            Ok(())
+        })
+        .invoke_handler(tauri::generate_handler![
+            ayaka_version,
+            open_game,
+            get_settings,
+            set_settings,
+            get_records,
+            save_record_to,
+            save_all,
+            choose_locale,
+            info,
+            start_new,
+            start_record,
+            next_run,
+            next_back_run,
+            current_run,
+            current_visited,
+            switch,
+            history,
+        ])
+        .run(tauri::generate_context!())?;
+    Ok(())
+}
diff --git a/bins/ayaka-gui/src-tauri/tauri.conf.json b/bins/ayaka-gui/src-tauri/tauri.conf.json
new file mode 100644
index 00000000..c668ceb2
--- /dev/null
+++ b/bins/ayaka-gui/src-tauri/tauri.conf.json
@@ -0,0 +1,93 @@
+{
+  "$schema": "../node_modules/@tauri-apps/cli/schema.json",
+  "build": {
+    "beforeBuildCommand": "npm run build",
+    "beforeDevCommand": "npm run dev",
+    "devPath": "http://localhost:5173",
+    "distDir": "../dist"
+  },
+  "package": {
+    "productName": "ayaka-gui",
+    "version": "0.1.0"
+  },
+  "tauri": {
+    "allowlist": {
+      "all": false,
+      "window": {
+        "all": true
+      },
+      "protocol": {
+        "all": true,
+        "asset": true,
+        "assetScope": [
+          "**"
+        ]
+      }
+    },
+    "bundle": {
+      "active": true,
+      "category": "RolePlayingGame",
+      "copyright": "",
+      "deb": {
+        "depends": [
+          "libwebkit2gtk-4.0-37"
+        ]
+      },
+      "externalBin": [],
+      "icon": [
+        "icons/32x32.png",
+        "icons/128x128.png",
+        "icons/128x128@2x.png",
+        "icons/icon.icns",
+        "icons/icon.ico"
+      ],
+      "identifier": "com.unigal.ayaka",
+      "longDescription": "",
+      "macOS": {
+        "entitlements": null,
+        "exceptionDomain": "",
+        "frameworks": [],
+        "providerShortName": null,
+        "signingIdentity": null
+      },
+      "resources": [],
+      "shortDescription": "",
+      "targets": [
+        "deb",
+        "msi",
+        "app"
+      ],
+      "windows": {
+        "certificateThumbprint": null,
+        "digestAlgorithm": "sha256",
+        "timestampUrl": ""
+      }
+    },
+    "security": {
+      "csp": null
+    },
+    "updater": {
+      "active": false
+    },
+    "windows": [
+      {
+        "label": "main",
+        "fullscreen": false,
+        "height": 600,
+        "width": 800,
+        "resizable": true,
+        "title": "Ayaka",
+        "center": true
+      }
+    ],
+    "cli": {
+      "args": [
+        {
+          "name": "config",
+          "index": 1,
+          "takesValue": true
+        }
+      ]
+    }
+  }
+}
\ No newline at end of file
diff --git a/bins/ayaka-gui/src/App.vue b/bins/ayaka-gui/src/App.vue
new file mode 100644
index 00000000..c368ef05
--- /dev/null
+++ b/bins/ayaka-gui/src/App.vue
@@ -0,0 +1,52 @@
+<script setup lang="ts">
+import 'bootstrap-dark-5/dist/css/bootstrap-dark.min.css'
+import { appWindow } from "@tauri-apps/api/window"
+import { save_all } from './interop'
+import { Modal } from 'bootstrap'
+</script>
+
+<script lang="ts">
+export default {
+    async created() {
+        appWindow.listen("tauri://close-requested", this.quit)
+    },
+    methods: {
+        quit() {
+            let modal = new Modal(this.$refs.quitModal as HTMLElement)
+            modal.show()
+        },
+        async quit_direct() {
+            await save_all()
+            await appWindow.close()
+        }
+    }
+}
+</script>
+
+<template>
+    <router-view @quit="quit" />
+
+    <div class="modal fade" ref="quitModal" tabindex="-1">
+        <div class="modal-dialog">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h5 class="modal-title">{{ $t("quit") }}</h5>
+                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
+                </div>
+                <div class="modal-body">{{ $t("quitConfirm") }}</div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-primary" data-bs-dismiss="modal">
+                        {{ $t("dialogNo") }}
+                    </button>
+                    <button type="button" class="btn btn-secondary" @click="quit_direct">
+                        {{ $t("dialogYes") }}
+                    </button>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<style>
+@import './assets/base.css';
+</style>
diff --git a/bins/ayaka-gui/src/assets/base.css b/bins/ayaka-gui/src/assets/base.css
new file mode 100644
index 00000000..37a398d1
--- /dev/null
+++ b/bins/ayaka-gui/src/assets/base.css
@@ -0,0 +1,43 @@
+.background {
+    position: fixed;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    max-width: 100%;
+    max-height: 100%;
+}
+
+.content {
+    position: absolute;
+    top: 10%;
+    width: 100%;
+    text-align: center;
+}
+
+.content-full {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+}
+
+.content-below-command {
+    position: absolute;
+    top: 2.5em;
+    left: 0;
+    width: 100%;
+    bottom: 0;
+}
+
+@media(prefers-color-scheme:light) {
+    meta[name="theme-color"] {
+        attr-content: "#111111"
+    }
+}
+
+@media(prefers-color-scheme:dark) {
+    meta[name="theme-color"] {
+        attr-content: "#eeeeee"
+    }
+}
\ No newline at end of file
diff --git a/bins/ayaka-gui/src/assets/logo.png b/bins/ayaka-gui/src/assets/logo.png
new file mode 100644
index 00000000..e134cd98
Binary files /dev/null and b/bins/ayaka-gui/src/assets/logo.png differ
diff --git a/bins/ayaka-gui/src/components/ActionCard.vue b/bins/ayaka-gui/src/components/ActionCard.vue
new file mode 100644
index 00000000..5ac4591f
--- /dev/null
+++ b/bins/ayaka-gui/src/components/ActionCard.vue
@@ -0,0 +1,28 @@
+<script lang="ts">
+export default {
+    props: { ch: String, line: String }
+}
+</script>
+
+<template>
+    <div class="card">
+        <div class="card-header char">
+            <h4 class="card-title">{{ ch }}</h4>
+        </div>
+        <div class="card-body lines">
+            <p class="h4 card-text">
+                <span v-html="line"></span>
+            </p>
+        </div>
+    </div>
+</template>
+
+<style>
+.char {
+    height: 3em;
+}
+
+.lines {
+    height: 8em;
+}
+</style>
diff --git a/bins/ayaka-gui/src/components/IconButton.vue b/bins/ayaka-gui/src/components/IconButton.vue
new file mode 100644
index 00000000..35f95382
--- /dev/null
+++ b/bins/ayaka-gui/src/components/IconButton.vue
@@ -0,0 +1,23 @@
+<script setup lang="ts">
+import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
+</script>
+
+<script lang="ts">
+export default {
+    props: { icon: String, btnclass: String },
+    emits: ["click"]
+}
+</script>
+
+<template>
+    <button :class='`btn btn-primary btn-command ${btnclass}`' @click='$emit("click")'>
+        <FontAwesomeIcon :icon='`fas fa-${icon}`'></FontAwesomeIcon>
+    </button>
+</template>
+
+<style>
+.btn-command {
+    width: 2.5em;
+    height: 2.5em;
+}
+</style>
diff --git a/bins/ayaka-gui/src/components/Live2D.vue b/bins/ayaka-gui/src/components/Live2D.vue
new file mode 100644
index 00000000..912323a6
--- /dev/null
+++ b/bins/ayaka-gui/src/components/Live2D.vue
@@ -0,0 +1,82 @@
+<script setup lang="ts">
+import * as PIXI from 'pixi.js'
+import { Live2DModel } from 'pixi-live2d-display'
+import { Mutex } from 'async-mutex'
+import { conv_src, GameInfo, info } from '../interop';
+</script>
+
+<script lang="ts">
+export default {
+    props: { names: Array<string> },
+    data() {
+        return {
+            game: {} as GameInfo,
+            models: new Map<string, Live2DModel>(),
+            app: undefined as PIXI.Application | undefined,
+            mutex: new Mutex(),
+        }
+    },
+    async created() {
+        this.game = await info()
+    },
+    async mounted() {
+        this.app = new PIXI.Application({
+            view: this.$refs.canvas as HTMLCanvasElement,
+            backgroundAlpha: 0,
+            resizeTo: this.$refs.canvas as HTMLElement,
+        })
+        window.addEventListener("resize", this.onresize)
+    },
+    async updated() {
+        await this.mutex.runExclusive(async () => {
+            if (this.app) {
+                this.app.stage.removeChildren(0)
+                if (this.names) {
+                    for (const name of this.names) {
+                        let m = this.models.get(name)
+                        if (!m) {
+                            const path = conv_src((this.game.props as any)["ch_" + name + "_model"]) ?? ""
+                            m = await Live2DModel.from(path)
+                            m.name = name
+                            console.log("Loaded Live2D model: %O", m);
+                            this.models.set(name, m)
+                        }
+                        this.app.stage.addChild(m)
+                    }
+                    this.onresize()
+                }
+            }
+        })
+    },
+    unmounted() {
+        window.removeEventListener("resize", this.onresize)
+        this.app?.destroy()
+        this.app = undefined
+    },
+    methods: {
+        onresize() {
+            if (this.app) {
+                let canvas_scale = window.innerHeight / 600.0
+                const count = this.app.stage.children.length
+                const width_per_ch = this.app.view.clientWidth / count
+                this.app.stage.children.forEach((c, i) => {
+                    let m = c as Live2DModel;
+                    m.x = width_per_ch * (i as number) + width_per_ch / 2
+                    m.anchor.set(0.5, 0)
+                    m.scale.set(canvas_scale * this.model_scale(m.name))
+                })
+            }
+        },
+        model_scale(key?: string): number {
+            if (key) {
+                return parseFloat((this.game.props as any)["ch_" + key + "_scale"])
+            }
+            return 1
+        }
+    }
+}
+</script>
+
+<template>
+    <canvas class="content-full" ref="canvas"></canvas>
+</template>
diff --git a/bins/ayaka-gui/src/env.d.ts b/bins/ayaka-gui/src/env.d.ts
new file mode 100644
index 00000000..3ba5b8dc
--- /dev/null
+++ b/bins/ayaka-gui/src/env.d.ts
@@ -0,0 +1,13 @@
+/// <reference types="vite/client" />
+
+declare module '*.vue' {
+    import type { DefineComponent } from 'vue'
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
+    const component: DefineComponent<{}, {}, any>
+    export default component
+}
+
+declare module 'timers-promises' {
+    import { setTimeout } from "timers/promises"
+    export { setTimeout }
+}
diff --git a/bins/ayaka-gui/src/interop/index.ts b/bins/ayaka-gui/src/interop/index.ts
new file mode 100644
index 00000000..1701b2cd
--- /dev/null
+++ b/bins/ayaka-gui/src/interop/index.ts
@@ -0,0 +1,162 @@
+import { convertFileSrc, invoke } from "@tauri-apps/api/tauri"
+import { Locale } from 'vue-i18n'
+
+export function conv_src(path?: string): string | undefined {
+    if (path) {
+        return decodeURIComponent(convertFileSrc(path))
+    }
+    return undefined
+}
+
+export interface OpenGameStatus {
+    t: keyof typeof OpenGameStatusType,
+    data?: object,
+}
+
+export enum OpenGameStatusType {
+    LoadProfile,
+    CreateRuntime,
+    LoadPlugin,
+    LoadSettings,
+    LoadGlobalRecords,
+    LoadRecords,
+    Loaded,
+}
+
+export interface Settings {
+    lang: Locale,
+}
+
+export interface RawContext {
+    cur_para: string,
+    cur_act: number,
+    history: Action[],
+    bg?: string,
+    bgm?: string,
+}
+
+export interface GameInfo {
+    title: string,
+    author: string,
+    props: {
+        bg?: string,
+    },
+}
+
+export interface Action {
+    line: ActionLine[],
+    ch_key?: string,
+    character?: string,
+    para_title?: string,
+    switches: Switch[],
+    props: {
+        bg?: string,
+        bgm?: string,
+        efm?: string,
+        voice?: string,
+        video?: string,
+        ch_models_count?: string,
+    },
+}
+
+export interface ActionLine {
+    type: keyof typeof ActionLineType,
+    data: string
+}
+
+export enum ActionLineType {
+    Chars,
+    Block,
+}
+
+export interface Switch {
+    text: string,
+    enabled: boolean,
+}
+
+export function ayaka_version(): Promise<string> {
+    return invoke("ayaka_version")
+}
+
+export function open_game(): Promise<void> {
+    return invoke("open_game")
+}
+
+export function get_settings(): Promise<Settings | undefined> {
+    return invoke("get_settings")
+}
+
+export function set_settings(settings: Settings): Promise<void> {
+    return invoke("set_settings", { settings: settings })
+}
+
+export function get_records(): Promise<RawContext[]> {
+    return invoke("get_records")
+}
+
+export function save_record_to(index: number): Promise<void> {
+    return invoke("save_record_to", { index: index })
+}
+
+export async function set_locale(loc: Locale): Promise<void> {
+    let settings = await get_settings() ?? { lang: "" };
+    settings.lang = loc
+    await set_settings(settings)
+}
+
+export function save_all(): Promise<void> {
+    return invoke("save_all")
+}
+
+export function choose_locale(locales: Locale[]): Promise<Locale | undefined> {
+    return invoke("choose_locale", { locales: locales })
+}
+
+export function locale_native_name(loc: Locale): string {
+    return new Intl.DisplayNames(loc, { type: "language" }).of(loc) ?? ""
+}
+
+export async function info(): Promise<GameInfo> {
+    let res = await invoke<GameInfo | undefined>("info");
+    return res ?? { title: "", author: "", props: {} }
+}
+
+export function start_new(locale: Locale): Promise<void> {
+    return invoke("start_new", { locale: locale })
+}
+
+export function start_record(locale: Locale, index: number): Promise<void> {
+    return invoke("start_record", { locale: locale, index: index })
+}
+
+export function next_run(): Promise<boolean> {
+    return invoke("next_run")
+}
+
+export function next_back_run(): Promise<boolean> {
+    return invoke("next_back_run")
+}
+
+export function current_run(): Promise<Action | undefined> {
+    return invoke("current_run")
+}
+
+export async function current_visited(): Promise<boolean> {
+    return invoke("current_visited")
+}
+
+export function switch_(i: number): Promise<void> {
+    return invoke("switch", { i: i })
+}
+
+export function history(): Promise<Action[]> {
+    return invoke("history")
+}
+
+export function merge_lines(lines: ActionLine[]): string {
+    let res = ""
+    lines.forEach(s => {
+        res += s.data
+    })
+    return res
+}
diff --git a/bins/ayaka-gui/src/locale/en.json b/bins/ayaka-gui/src/locale/en.json
new file mode 100644
index 00000000..1f39a866
--- /dev/null
+++ b/bins/ayaka-gui/src/locale/en.json
@@ -0,0 +1,15 @@
+{
+    "$schema": "./schema.json",
+    "dialogYes": "Yes",
+    "dialogNo": "No",
+    "dialogOk": "OK",
+    "newGame": "New game",
+    "loadRecords": "Load records",
+    "settings": "Settings",
+    "about": "About",
+    "goHome": "Go home",
+    "goHomeConfirm": "Back to the home page?",
+    "quit": "Quit",
+    "quitConfirm": "Quit the game?",
+    "error": "Error"
+}
\ No newline at end of file
diff --git a/bins/ayaka-gui/src/locale/index.ts b/bins/ayaka-gui/src/locale/index.ts
new file mode 100644
index 00000000..456913c4
--- /dev/null
+++ b/bins/ayaka-gui/src/locale/index.ts
@@ -0,0 +1,7 @@
+import en from './en.json'
+import zh_Hans from './zh_Hans.json'
+import ja from './ja.json'
+
+export default {
+    en, "zh-Hans": zh_Hans, ja
+}
diff --git a/bins/ayaka-gui/src/locale/ja.json b/bins/ayaka-gui/src/locale/ja.json
new file mode 100644
index 00000000..1bb41964
--- /dev/null
+++ b/bins/ayaka-gui/src/locale/ja.json
@@ -0,0 +1,15 @@
+{
+    "$schema": "./schema.json",
+    "dialogYes": "はい",
+    "dialogNo": "いいえ",
+    "dialogOk": "OK",
+    "newGame": "始めから",
+    "loadRecords": "続きから",
+    "settings": "設定",
+    "about": "説明",
+    "goHome": "ホーム",
+    "goHomeConfirm": "ホームに戻りますか？",
+    "quit": "終了する",
+    "quitConfirm": "ゲームを終了しますか？",
+    "error": "エラー"
+}
\ No newline at end of file
diff --git a/bins/ayaka-gui/src/locale/schema.json b/bins/ayaka-gui/src/locale/schema.json
new file mode 100644
index 00000000..4cd2f610
--- /dev/null
+++ b/bins/ayaka-gui/src/locale/schema.json
@@ -0,0 +1,57 @@
+{
+    "$schema": "http://json-schema.org/draft-07/schema#",
+    "title": "LangResources",
+    "description": "A resource file of translation",
+    "type": "object",
+    "properties": {
+        "dialogYes": {
+            "description": "The YES button in dialog",
+            "type": "string"
+        },
+        "dialogNo": {
+            "description": "The NO button in dialog",
+            "type": "string"
+        },
+        "dialogOk": {
+            "description": "The OK button in dialog",
+            "type": "string"
+        },
+        "newGame": {
+            "description": "The new game button at HomeView",
+            "type": "string"
+        },
+        "loadRecords": {
+            "description": "The load records button at HomeView",
+            "type": "string"
+        },
+        "settings": {
+            "description": "The settings button at HomeView, and title at SettingsView",
+            "type": "string"
+        },
+        "about": {
+            "description": "The about button at HomeView",
+            "type": "string"
+        },
+        "goHome": {
+            "description": "The go home button at GameView",
+            "type": "string"
+        },
+        "goHomeConfirm": {
+            "description": "The confirm message in go home confirm dialog",
+            "type": "string"
+        },
+        "quit": {
+            "description": "The quit button at HomeView",
+            "type": "string"
+        },
+        "quitConfirm": {
+            "description": "The confirm message in quit confirm dialog",
+            "type": "string"
+        },
+        "error": {
+            "description": "The error title of dialog",
+            "type": "string"
+        }
+    },
+    "required": []
+}
\ No newline at end of file
diff --git a/bins/ayaka-gui/src/locale/zh_Hans.json b/bins/ayaka-gui/src/locale/zh_Hans.json
new file mode 100644
index 00000000..a18171b8
--- /dev/null
+++ b/bins/ayaka-gui/src/locale/zh_Hans.json
@@ -0,0 +1,15 @@
+{
+    "$schema": "./schema.json",
+    "dialogYes": "是",
+    "dialogNo": "否",
+    "dialogOk": "确定",
+    "newGame": "新游戏",
+    "loadRecords": "加载进度",
+    "settings": "设置",
+    "about": "关于",
+    "goHome": "主页",
+    "goHomeConfirm": "返回主页？",
+    "quit": "退出",
+    "quitConfirm": "退出游戏？",
+    "error": "错误"
+}
\ No newline at end of file
diff --git a/bins/ayaka-gui/src/main.ts b/bins/ayaka-gui/src/main.ts
new file mode 100644
index 00000000..c8d76a3d
--- /dev/null
+++ b/bins/ayaka-gui/src/main.ts
@@ -0,0 +1,26 @@
+import { createApp } from 'vue'
+import App from './App.vue'
+import router from './router'
+import { createI18n } from 'vue-i18n'
+import messages from "./locale"
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faArrowLeft, faBackwardStep, faFileArrowDown, faFileArrowUp, faForward, faForwardStep, faGear, faHouse, faList, faPlay } from '@fortawesome/free-solid-svg-icons'
+import { Ticker } from '@pixi/ticker'
+import { Live2DModel } from 'pixi-live2d-display'
+
+Live2DModel.registerTicker(Ticker)
+
+library.add(faArrowLeft, faFileArrowUp, faFileArrowDown, faList, faBackwardStep, faPlay, faForwardStep, faForward, faGear, faHouse)
+
+const app = createApp(App)
+
+app.use(router)
+
+const i18n = createI18n({
+    locale: 'en',
+    fallbackLocale: 'en',
+    messages
+})
+app.use(i18n)
+
+app.mount('#app')
diff --git a/bins/ayaka-gui/src/router/index.ts b/bins/ayaka-gui/src/router/index.ts
new file mode 100644
index 00000000..2586f4ef
--- /dev/null
+++ b/bins/ayaka-gui/src/router/index.ts
@@ -0,0 +1,45 @@
+import { createRouter, createWebHistory } from 'vue-router'
+import StartView from '../views/StartView.vue'
+
+const router = createRouter({
+  history: createWebHistory(import.meta.env.BASE_URL),
+  routes: [
+    {
+      path: '/',
+      name: 'start',
+      component: StartView
+    },
+    {
+      path: '/home',
+      name: 'home',
+      component: () => import('../views/HomeView.vue')
+    },
+    {
+      path: "/settings",
+      name: "settings",
+      component: () => import('../views/SettingsView.vue')
+    },
+    {
+      path: '/game',
+      name: 'game',
+      component: () => import('../views/GameView.vue')
+    },
+    {
+      path: '/history',
+      name: 'history',
+      component: () => import('../views/HistoryView.vue')
+    },
+    {
+      path: '/records/:op',
+      name: 'records',
+      component: () => import('../views/RecordsView.vue')
+    },
+    {
+      path: '/about',
+      name: 'about',
+      component: () => import('../views/AboutView.vue')
+    }
+  ]
+})
+
+export default router
diff --git a/bins/ayaka-gui/src/views/AboutView.vue b/bins/ayaka-gui/src/views/AboutView.vue
new file mode 100644
index 00000000..0149bc67
--- /dev/null
+++ b/bins/ayaka-gui/src/views/AboutView.vue
@@ -0,0 +1,53 @@
+<script setup lang="ts">
+import { getName, getTauriVersion, getVersion } from '@tauri-apps/api/app'
+import { info, ayaka_version } from '../interop'
+import IconButton from '../components/IconButton.vue';
+</script>
+
+<script lang="ts">
+export default {
+    emits: ["quit"],
+    data() {
+        return {
+            title: "",
+            author: "",
+            app_name: "",
+            app_ver: "",
+            ayaka_ver: "",
+            tauri_ver: ""
+        }
+    },
+    async created() {
+        const res = await info()
+        this.title = res.title
+        this.author = res.author
+        this.app_name = await getName()
+        this.app_ver = await getVersion()
+        this.ayaka_ver = await ayaka_version()
+        this.tauri_ver = await getTauriVersion()
+    }
+}
+</script>
+
+<template>
+    <div class="content">
+        <h1>{{ title }}</h1>
+        <p>Author: {{ author }}</p>
+        <h2>{{ app_name }}</h2>
+        <p>Version {{ app_ver }}</p>
+        <p>This is a sample GUI frontend of Ayaka project.</p>
+        <h2>Ayaka</h2>
+        <p>Version {{ ayaka_ver }}</p>
+        <p>Just Ayaka.</p>
+        <h2>Tauri</h2>
+        <p>Version {{ tauri_ver }}</p>
+        <p>
+            This is an awesome framework to build cross-platform GUI applications,
+            <br />
+            with HTML frontend and Rust backend.
+        </p>
+    </div>
+    <div>
+        <IconButton icon="arrow-left" @click="$router.back()"></IconButton>
+    </div>
+</template>
diff --git a/bins/ayaka-gui/src/views/GameView.vue b/bins/ayaka-gui/src/views/GameView.vue
new file mode 100644
index 00000000..9c679d8a
--- /dev/null
+++ b/bins/ayaka-gui/src/views/GameView.vue
@@ -0,0 +1,377 @@
+<script setup lang="ts">
+import { setTimeout } from 'timers-promises'
+import { Mutex, tryAcquire } from 'async-mutex'
+import ActionCard from '../components/ActionCard.vue'
+import IconButton from '../components/IconButton.vue'
+import { conv_src, current_run, next_run, next_back_run, switch_, merge_lines, Action, ActionLineType, ActionLine, current_visited } from '../interop'
+import { cloneDeep } from 'lodash'
+import Live2D from '../components/Live2D.vue'
+import { Modal } from 'bootstrap'
+</script>
+
+<script lang="ts">
+enum ActionState {
+    Typing,
+    Typed,
+    Switching,
+    Video,
+    End,
+}
+
+enum PlayState {
+    Manual,
+    Auto,
+    FastForward,
+}
+
+function wait_play(e: HTMLAudioElement): Promise<void> {
+    return new Promise<void>((resolve, _) => {
+        e.addEventListener("ended", () => { resolve() }, { once: true })
+    })
+}
+
+function live2d_names(props: any): string[] {
+    return ((props.ch_models ?? "") as string).split(",").filter(s => s.length != 0)
+}
+
+export default {
+    emits: ["quit"],
+    data() {
+        return {
+            action: {
+                line: [],
+                switches: [],
+                props: {},
+            } as Action,
+            type_text: "",
+            type_text_buffer: [] as ActionLine[],
+            state: ActionState.End,
+            play_state: PlayState.Manual,
+            mutex: new Mutex(),
+        }
+    },
+    async mounted() {
+        document.addEventListener('keydown', this.onkeydown)
+        await this.mutex.runExclusive(this.fetch_current_run)
+        this.start_type_anime()
+    },
+    async unmounted() {
+        document.removeEventListener('keydown', this.onkeydown)
+    },
+    methods: {
+        go_home() {
+            let modal = new Modal(this.$refs.homeModal as HTMLElement)
+            modal.show()
+        },
+        async go_home_direct() {
+            await this.$router.replace("/home")
+        },
+        // Should be called in mutex
+        async fetch_current_run() {
+            const res = await current_run()
+            console.info(res)
+            if (res) {
+                const load_new_bgm = (res.props.bgm != this.action.props.bgm);
+                this.action = res
+                if (load_new_bgm) {
+                    (this.$refs.bgm as HTMLAudioElement).load()
+                }
+                if (res.props.efm) {
+                    (this.$refs.efm as HTMLAudioElement).load()
+                }
+                if (res.props.voice) {
+                    (this.$refs.voice as HTMLAudioElement).load()
+                }
+            } else {
+                await this.go_home_direct()
+            }
+        },
+        // Should be called in mutex
+        async fetch_next_run(): Promise<boolean> {
+            const has_next = await next_run()
+            await this.fetch_current_run()
+            return has_next
+        },
+        async fetch_next_back_run(): Promise<boolean> {
+            const has_back = await next_back_run()
+            await this.fetch_current_run()
+            return has_back
+        },
+        end_typing(): boolean {
+            this.type_text = merge_lines(this.action.line)
+            this.type_text_buffer = []
+            if (this.action.switches.length != 0) {
+                this.state = ActionState.Switching
+                return false
+            } else {
+                return this.end_switching()
+            }
+        },
+        end_switching(): boolean {
+            if (this.action.props.video) {
+                this.state = ActionState.Video;
+                let element = this.$refs.video as HTMLVideoElement
+                element.load()
+                element.play()
+                return false
+            } else {
+                return true
+            }
+        },
+        async switch_run(i: number) {
+            await switch_(i)
+            if (this.end_switching()) {
+                await this.mutex.runExclusive(this.fetch_next_run)
+                this.start_type_anime()
+            }
+        },
+        // Shouldn't be called in mutex
+        async start_type_anime(timeout: boolean = false) {
+            this.state = ActionState.Typing
+            let values = timeout ? [setTimeout(3000)] : []
+            if (this.action.props.efm) {
+                let efm = this.$refs.efm as HTMLAudioElement
+                values.push(wait_play(efm))
+                efm.play()
+            }
+            if (this.action.props.voice) {
+                let voice = this.$refs.voice as HTMLAudioElement
+                values.push(wait_play(voice))
+                voice.play()
+            }
+            this.type_text = ""
+            this.type_text_buffer = cloneDeep(this.action.line)
+            while (this.type_text_buffer.length != 0) {
+                if (this.type_text_buffer[0].data.length == 0) {
+                    this.type_text_buffer.shift()
+                    continue
+                }
+                switch (ActionLineType[this.type_text_buffer[0].type]) {
+                    case ActionLineType.Chars:
+                        this.type_text += this.type_text_buffer[0].data[0]
+                        this.type_text_buffer[0].data = this.type_text_buffer[0].data.substring(1)
+                        await setTimeout(10)
+                        break
+                    case ActionLineType.Block:
+                        this.type_text += this.type_text_buffer[0].data
+                        this.type_text_buffer[0].data = ""
+                        break
+                }
+            }
+            await Promise.all(values)
+            this.state = ActionState.Typed
+            if (this.type_text.length == 0) {
+                await this.next()
+            }
+        },
+        async next() {
+            if (this.state != ActionState.Switching) {
+                const new_text = await tryAcquire(this.mutex).runExclusive(async () => {
+                    switch (this.state) {
+                        case ActionState.Typing:
+                        case ActionState.Typed:
+                            return this.end_typing()
+                        case ActionState.Video:
+                            let element = this.$refs.video as HTMLVideoElement
+                            element.pause()
+                            this.state = ActionState.End
+                        case ActionState.End:
+                            return true
+                    }
+                    return false
+                }).catch(_ => { })
+                if (new_text) {
+                    await this.mutex.runExclusive(this.fetch_next_run)
+                    this.start_type_anime()
+                }
+            }
+        },
+        async on_auto_play_click() {
+            if (this.play_state != PlayState.Auto) {
+                this.play_state = PlayState.Auto
+                this.end_typing()
+                while (this.play_state == PlayState.Auto && (this.state != ActionState.Switching && this.state != ActionState.Video)) {
+                    const has_next = await tryAcquire(this.mutex).runExclusive(async () => {
+                        const has_next = await this.fetch_next_run()
+                        await this.start_type_anime(true)
+                        this.end_typing()
+                        return has_next
+                    }).catch(_ => { })
+                    if (!has_next) {
+                        break
+                    }
+                }
+            }
+            this.play_state = PlayState.Manual
+        },
+        async on_fast_forward_click() {
+            if (this.play_state != PlayState.FastForward) {
+                this.play_state = PlayState.FastForward
+                this.end_typing()
+                while (this.play_state == PlayState.FastForward && (this.state != ActionState.Switching && this.state != ActionState.Video)) {
+                    await setTimeout(20)
+                    const has_next = await tryAcquire(this.mutex).runExclusive(async () => {
+                        const has_next = await this.fetch_next_run()
+                        this.end_typing()
+                        return has_next
+                    }).catch(_ => { })
+                    if (!await current_visited()) {
+                        break
+                    }
+                    if (!has_next) {
+                        break
+                    }
+                }
+            }
+            this.play_state = PlayState.Manual
+        },
+        async onkeydown(e: KeyboardEvent) {
+            if (e.key == "Enter" || e.key == " " || e.key == "ArrowDown") {
+                await this.next()
+            }
+        },
+        async onvideoended() {
+            this.state = ActionState.End
+            await this.next()
+        },
+        async next_back() {
+            if (this.state != ActionState.Switching) {
+                await this.mutex.runExclusive(this.fetch_next_back_run)
+                this.start_type_anime()
+            }
+        },
+        async on_history_click() {
+            await this.$router.push("/history")
+        },
+        async on_records_click(op: string) {
+            await this.$router.push("/records/" + op)
+        },
+        async on_settings_click() {
+            await this.$router.push("/settings")
+        }
+    }
+}
+</script>
+
+<template>
+    <audio ref="bgm" :src="conv_src(action.props.bgm)" type="audio/mpeg" autoplay hidden loop></audio>
+    <audio ref="efm" :src="conv_src(action.props.efm)" type="audio/mpeg" hidden></audio>
+    <audio ref="voice" :src="conv_src(action.props.voice)" type="audio/mpeg" hidden></audio>
+    <img class="background" :src="conv_src(action.props.bg)">
+    <Live2D :names="live2d_names(action.props)"></Live2D>
+    <div class="card-lines">
+        <ActionCard :ch="action.character" :line="type_text"></ActionCard>
+    </div>
+    <div>
+        <h4><span class="badge bg-primary">{{ action.para_title }}</span></h4>
+    </div>
+    <div class="logo d-flex align-items-center">
+        <span>Powered by Ayaka.</span>
+    </div>
+    <div class="content-full bg-body" :hidden="state != ActionState.Video">
+        <video ref="video" class="background" @ended="onvideoended" :src="conv_src(action.props.video)"
+            type="video/mp4"></video>
+    </div>
+    <div class="backboard" @click="next"></div>
+    <div class="commands">
+        <div class="btn-group" role="group" :hidden="state == ActionState.Video">
+            <IconButton icon="file-arrow-down" @click='on_records_click("save")'></IconButton>
+            <IconButton icon="file-arrow-up" @click='on_records_click("load")'></IconButton>
+            <IconButton icon="list" @click="on_history_click"></IconButton>
+            <IconButton icon="backward-step" @click="next_back"></IconButton>
+            <IconButton icon="play" :btnclass='play_state == PlayState.Auto ? "active" : ""'
+                @click="on_auto_play_click"></IconButton>
+            <IconButton icon="forward-step" @click="next"></IconButton>
+            <IconButton icon="forward" :btnclass='play_state == PlayState.FastForward ? "active" : ""'
+                @click="on_fast_forward_click"></IconButton>
+            <IconButton icon="gear" @click="on_settings_click"></IconButton>
+            <IconButton icon="house" @click="go_home"></IconButton>
+        </div>
+    </div>
+    <div class="content-full container-switches" :hidden="state != ActionState.Switching">
+        <div class="switches">
+            <div class="switches-center">
+                <div class="d-grid gap-5 col-8 mx-auto">
+                    <button class="btn btn-primary switch" v-for="(s, i) in action.switches" @click="switch_run(i)"
+                        :disabled="!s.enabled">
+                        {{ s.text }}
+                    </button>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <div class="modal fade" ref="homeModal" tabindex="-1">
+        <div class="modal-dialog">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h5 class="modal-title">{{ $t("goHome") }}</h5>
+                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
+                </div>
+                <div class="modal-body">{{ $t("goHomeConfirm") }}</div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-primary" data-bs-dismiss="modal">
+                        {{ $t("dialogNo") }}
+                    </button>
+                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal" @click="go_home_direct">
+                        {{ $t("dialogYes") }}
+                    </button>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<style>
+.backboard {
+    position: absolute;
+    top: 0;
+    left: 0;
+    bottom: 2.5em;
+    right: 0;
+}
+
+.card-lines {
+    position: absolute;
+    bottom: 2.5em;
+    width: 100%;
+    opacity: 0.8;
+}
+
+/* Copied from .h4 */
+.switch {
+    font-size: calc(1.275rem + .3vw);
+}
+
+.logo {
+    position: absolute;
+    top: 100%;
+    left: 0;
+    height: 2.5em;
+    transform: translateY(-100%);
+}
+
+.commands {
+    position: absolute;
+    top: 100%;
+    left: 100%;
+    transform: translate(-100%, -100%);
+}
+
+.container-switches {
+    background-color: #00000077;
+}
+
+.switches {
+    position: absolute;
+    width: 100%;
+    height: calc(100% - 13.5em);
+}
+
+.switches-center {
+    position: absolute;
+    width: 100%;
+    top: 50%;
+    transform: translateY(-50%);
+}
+</style>
diff --git a/bins/ayaka-gui/src/views/HistoryView.vue b/bins/ayaka-gui/src/views/HistoryView.vue
new file mode 100644
index 00000000..b13a8f71
--- /dev/null
+++ b/bins/ayaka-gui/src/views/HistoryView.vue
@@ -0,0 +1,34 @@
+<script setup lang="ts">
+import { merge_lines, history, Action } from '../interop'
+import ActionCard from '../components/ActionCard.vue'
+</script>
+
+<script lang="ts">
+export default {
+    emits: ["quit"],
+    data() {
+        return {
+            records: [] as Action[]
+        }
+    },
+    async mounted() {
+        this.records = await history()
+    }
+}
+</script>
+
+<template>
+    <div class="content-full container-history" @click="$router.back">
+        <ul class="list-group">
+            <li class="list-group-item" v-for="h in records">
+                <ActionCard :ch="h.character" :line="merge_lines(h.line)"></ActionCard>
+            </li>
+        </ul>
+    </div>
+</template>
+
+<style>
+.container-history {
+    overflow-y: scroll;
+}
+</style>
diff --git a/bins/ayaka-gui/src/views/HomeView.vue b/bins/ayaka-gui/src/views/HomeView.vue
new file mode 100644
index 00000000..88b5ae79
--- /dev/null
+++ b/bins/ayaka-gui/src/views/HomeView.vue
@@ -0,0 +1,49 @@
+<script setup lang="ts">
+import { conv_src, info, next_run, start_new } from '../interop'
+</script>
+
+<script lang="ts">
+export default {
+    emits: ["quit"],
+    data() {
+        return {
+            title: "",
+            bg: undefined as string | undefined,
+        }
+    },
+    async created() {
+        const res = await info()
+        this.title = res.title
+        this.bg = res.props.bg
+    },
+    methods: {
+        async new_game() {
+            await start_new(this.$i18n.locale)
+            if (await next_run()) {
+                this.$router.replace("/game")
+            }
+        }
+    }
+}
+</script>
+
+<template>
+    <img class="background" :src="conv_src(bg)">
+    <div class="content-full bg-body backboard-bg"></div>
+    <div class="content">
+        <div class="d-grid gap-4 col-4 mx-auto">
+            <h1>{{ title }}</h1>
+            <button class="btn btn-primary" @click="new_game">{{ $t("newGame") }}</button>
+            <router-link class="btn btn-primary" to="/records/load">{{ $t("loadRecords") }}</router-link>
+            <router-link class="btn btn-primary" to="/settings">{{ $t("settings") }}</router-link>
+            <router-link class="btn btn-primary" to="/about">{{ $t("about") }}</router-link>
+            <button class="btn btn-primary" @click="$emit('quit')">{{ $t("quit") }}</button>
+        </div>
+    </div>
+</template>
+
+<style>
+.backboard-bg {
+    opacity: 0.5;
+}
+</style>
diff --git a/bins/ayaka-gui/src/views/RecordsView.vue b/bins/ayaka-gui/src/views/RecordsView.vue
new file mode 100644
index 00000000..438bf30f
--- /dev/null
+++ b/bins/ayaka-gui/src/views/RecordsView.vue
@@ -0,0 +1,56 @@
+<script setup lang="ts">
+import { RawContext, get_records, start_record, save_record_to, merge_lines } from '../interop'
+import IconButton from '../components/IconButton.vue';
+</script>
+
+<script lang="ts">
+export default {
+    emits: ["quit"],
+    data() {
+        return {
+            op: this.$route.params.op,
+            records: [] as RawContext[],
+        }
+    },
+    async created() {
+        this.records = await get_records()
+    },
+    methods: {
+        async on_record_click(index: number) {
+            if (this.op == "load") {
+                await start_record(this.$i18n.locale, index)
+                await this.$router.replace("/game")
+            } else if (this.op == "save") {
+                await save_record_to(index)
+                await this.$router.back()
+            } else {
+                console.warn("Invalid op: %s", this.op)
+            }
+        }
+    }
+}
+</script>
+
+<template>
+    <div class="content-below-command">
+        <ul class="list-group list-group-flush">
+            <li class="list-group-item list-group-item-action record-item" v-for="(rec, i) in records"
+                @click="on_record_click(i)">
+                <span v-html="merge_lines(rec.history[rec.history.length - 1].line)"></span>
+            </li>
+            <li class="list-group-item list-group-item-action record-item" @click="on_record_click(records.length)"
+                :hidden='op != "save"'>
+                Add new record
+            </li>
+        </ul>
+    </div>
+    <div>
+        <IconButton icon="arrow-left" @click="$router.back()"></IconButton>
+    </div>
+</template>
+
+<style>
+.record-item {
+    cursor: pointer;
+}
+</style>
diff --git a/bins/ayaka-gui/src/views/SettingsView.vue b/bins/ayaka-gui/src/views/SettingsView.vue
new file mode 100644
index 00000000..ef364f53
--- /dev/null
+++ b/bins/ayaka-gui/src/views/SettingsView.vue
@@ -0,0 +1,42 @@
+<script setup lang="ts">
+import { Locale } from 'vue-i18n'
+import { locale_native_name, set_locale } from '../interop'
+import IconButton from '../components/IconButton.vue';
+</script>
+
+<script lang="ts">
+export default {
+    emits: ["quit"],
+    data() {
+        return {
+            locale_names: new Map<Locale, string>(),
+        }
+    },
+    async created() {
+        this.$i18n.availableLocales.forEach(locale => {
+            this.locale_names.set(locale, locale_native_name(locale))
+        })
+    },
+    methods: {
+        async on_locale_select(e: Event) {
+            await set_locale((e.target as HTMLInputElement).value)
+        }
+    }
+}
+</script>
+
+<template>
+    <div class="content">
+        <div class="d-grid gap-4 col-4 mx-auto">
+            <h1>{{ $t("settings") }}</h1>
+            <select class="form-select" v-model="$i18n.locale" @change="on_locale_select">
+                <option v-for="locale in $i18n.availableLocales" :key="`locale-${locale}`" :value="locale">
+                    {{ locale_names.get(locale) ?? locale }}
+                </option>
+            </select>
+        </div>
+    </div>
+    <div>
+        <IconButton icon="arrow-left" @click="$router.back()"></IconButton>
+    </div>
+</template>
diff --git a/bins/ayaka-gui/src/views/StartView.vue b/bins/ayaka-gui/src/views/StartView.vue
new file mode 100644
index 00000000..e00e3111
--- /dev/null
+++ b/bins/ayaka-gui/src/views/StartView.vue
@@ -0,0 +1,150 @@
+<script setup lang="ts">
+import { listen, Event as TauriEvent, UnlistenFn } from '@tauri-apps/api/event';
+import { OpenGameStatus, OpenGameStatusType, open_game, choose_locale, get_settings, set_locale } from '../interop'
+import { appWindow } from '@tauri-apps/api/window'
+import { Modal } from 'bootstrap'
+</script>
+
+<script lang="ts">
+export default {
+    emits: ["quit"],
+    data() {
+        return {
+            text: "",
+            error: "",
+            progress: 0,
+            unlisten_fn: null as UnlistenFn | null
+        }
+    },
+    async mounted() {
+        this.unlisten_fn = await listen('ayaka://open_status', this.on_open_status)
+        try {
+            await open_game()
+        }
+        catch (e) {
+            if (e instanceof Error) {
+                this.error = e.message
+            } else {
+                this.error = JSON.stringify(e)
+            }
+            let modal = new Modal(this.$refs.errorModal as HTMLElement)
+            modal.show()
+        }
+    },
+    unmounted() {
+        if (this.unlisten_fn) {
+            this.unlisten_fn()
+            this.unlisten_fn = null
+        }
+    },
+    methods: {
+        async on_open_status(e: TauriEvent<OpenGameStatus>) {
+            console.log(e.payload)
+            const status = e.payload;
+            [this.text, this.progress] = this.status_to_text(status);
+            let anime = (this.$refs.logo as HTMLElement).animate([
+                { rotate: `${this.rotate_degree()}deg` }
+            ], {
+                duration: 800,
+                fill: "forwards",
+                easing: "ease-out"
+            })
+            anime.onfinish = async () => {
+                switch (OpenGameStatusType[status.t]) {
+                    case OpenGameStatusType.LoadRecords:
+                        await this.process_settings()
+                        break
+                    case OpenGameStatusType.Loaded:
+                        this.$router.replace("/home")
+                        break
+                }
+            }
+        },
+        status_to_text(s: OpenGameStatus): [string, number] {
+            const step = 100 / 7
+            const t = OpenGameStatusType[s.t]
+            switch (t) {
+                case OpenGameStatusType.LoadProfile:
+                    return [`Loading profile "${s.data as unknown as string}"...`, step * (t + 1)]
+                case OpenGameStatusType.CreateRuntime:
+                    return ["Creating runtime...", step * (t + 1)]
+                case OpenGameStatusType.LoadPlugin:
+                    const data = s.data as unknown as [string, number, number]
+                    return [`Loading plugin ${data[0]}...`, step * (t + 1) + data[1] / data[2] * step]
+                case OpenGameStatusType.LoadSettings:
+                    return ["Loading settings...", step * (t + 1)]
+                case OpenGameStatusType.LoadGlobalRecords:
+                    return ["Loading global records...", step * (t + 1)]
+                case OpenGameStatusType.LoadRecords:
+                    return ["Loading records...", step * (t + 1)]
+                case OpenGameStatusType.Loaded:
+                    return ["Loaded.", step * (t + 1)]
+                default:
+                    return ["", 0]
+            }
+        },
+        async process_settings() {
+            const settings = await get_settings()
+            console.log(settings)
+            let loc = settings?.lang
+            if (!loc || !this.$i18n.availableLocales.includes(loc)) {
+                loc = await choose_locale(this.$i18n.availableLocales)
+            }
+            if (loc) {
+                console.log("Set locale to %s", loc)
+                this.$i18n.locale = loc
+                await set_locale(loc)
+            }
+        },
+        rotate_degree() {
+            return this.progress / 100 * 360
+        }
+    }
+}
+</script>
+
+<template>
+    <div class="content-logo">
+        <img ref="logo" src="../assets/logo.png" alt="Logo" />
+        <h1 class="fw-bolder" style="font-size: 300%">Just Ayaka.</h1>
+    </div>
+    <div class="progress progress-bottom">
+        <div class="progress-bar" role="progressbar" :style='`width: ${progress}%`'>{{ text }}</div>
+    </div>
+
+    <div class="modal fade" ref="errorModal" tabindex="-1">
+        <div class="modal-dialog">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h5 class="modal-title">{{ $t("error") }}</h5>
+                </div>
+                <div class="modal-body">{{ error }}</div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-primary" @click="appWindow.close()">
+                        {{ $t("dialogOk") }}
+                    </button>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<style>
+.progress-bottom {
+    position: absolute;
+    top: 100%;
+    width: 100%;
+    transform: translateY(-100%);
+}
+
+.content-logo {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    translate: -50% -50%;
+    width: fit-content;
+    height: fit-content;
+    scale: 70%;
+    text-align: center;
+}
+</style>
diff --git a/bins/ayaka-gui/tsconfig.json b/bins/ayaka-gui/tsconfig.json
new file mode 100644
index 00000000..bcc4abda
--- /dev/null
+++ b/bins/ayaka-gui/tsconfig.json
@@ -0,0 +1,18 @@
+{
+  "compilerOptions": {
+    "target": "esnext",
+    "useDefineForClassFields": true,
+    "module": "esnext",
+    "moduleResolution": "node",
+    "strict": true,
+    "jsx": "preserve",
+    "sourceMap": true,
+    "resolveJsonModule": true,
+    "isolatedModules": true,
+    "esModuleInterop": true,
+    "lib": ["esnext", "dom"],
+    "skipLibCheck": true
+  },
+  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
+  "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/bins/ayaka-gui/tsconfig.node.json b/bins/ayaka-gui/tsconfig.node.json
new file mode 100644
index 00000000..e993792c
--- /dev/null
+++ b/bins/ayaka-gui/tsconfig.node.json
@@ -0,0 +1,8 @@
+{
+  "compilerOptions": {
+    "composite": true,
+    "module": "esnext",
+    "moduleResolution": "node"
+  },
+  "include": ["vite.config.ts"]
+}
diff --git a/bins/ayaka-gui/vite.config.ts b/bins/ayaka-gui/vite.config.ts
new file mode 100644
index 00000000..2aa6d6ef
--- /dev/null
+++ b/bins/ayaka-gui/vite.config.ts
@@ -0,0 +1,21 @@
+import { env } from 'process'
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+  plugins: [vue()],
+  clearScreen: false,
+  envPrefix: ['VITE_', 'TAURI_', 'RUST_'],
+  build: {
+    target: ['es2021', 'chrome97', 'safari13'],
+    minify: !env.TAURI_DEBUG ? 'esbuild' : false,
+    sourcemap: !!env.TAURI_DEBUG,
+    chunkSizeWarningLimit: 1000,
+  },
+  server: {
+    fs: {
+      strict: false
+    }
+  }
+})
diff --git a/bins/ayaka-latex/Cargo.toml b/bins/ayaka-latex/Cargo.toml
new file mode 100644
index 00000000..e2a6588f
--- /dev/null
+++ b/bins/ayaka-latex/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "ayaka-latex"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+ayaka-runtime = { path = "../../utils/ayaka-runtime" }
+tokio = { version = "1", features = ["fs", "io-util", "macros", "rt"] }
+clap = { version = "3.1", features = ["derive"] }
+env_logger = "0.9"
diff --git a/bins/ayaka-latex/src/main.rs b/bins/ayaka-latex/src/main.rs
new file mode 100644
index 00000000..162e41ba
--- /dev/null
+++ b/bins/ayaka-latex/src/main.rs
@@ -0,0 +1,69 @@
+mod writer;
+
+use ayaka_runtime::{anyhow::Result, log::LevelFilter, Context, FrontendType, Locale};
+use clap::Parser;
+use std::ffi::OsString;
+use writer::LaTeXWriter;
+
+#[derive(Debug, Parser)]
+#[clap(about, version, author)]
+pub struct Options {
+    input: OsString,
+    #[clap(short, long)]
+    output: OsString,
+    #[clap(short, long)]
+    locale: Option<Locale>,
+}
+
+#[tokio::main(flavor = "current_thread")]
+async fn main() -> Result<()> {
+    let opts = Options::parse();
+    env_logger::Builder::from_default_env()
+        .filter_module("wasmer", LevelFilter::Warn)
+        .try_init()?;
+    let context = Context::open(&opts.input, FrontendType::Text);
+    let mut ctx = context.await?;
+
+    let output = tokio::fs::File::create(&opts.output).await?;
+    let mut output = LaTeXWriter::new(output);
+    output.command("documentclass", ["ctexart"]).await?;
+    output.command("usepackage", ["lua-ul"]).await?;
+    output.command("title", [&ctx.game.title]).await?;
+    output.command("author", [&ctx.game.author]).await?;
+    output
+        .environment("document", |output| async move {
+            output.command0("maketitle").await?;
+            output.command0("tableofcontents").await?;
+
+            ctx.init_new();
+            ctx.set_locale(opts.locale.unwrap_or_else(Locale::current));
+            while let Some(action) = ctx.next_run() {
+                if let Some(name) = &action.character {
+                    output.command("paragraph", [name]).await?;
+                }
+                for s in action.line {
+                    output.write(s.as_str()).await?;
+                }
+                output.write("\n").await?;
+                if !action.switches.is_empty() {
+                    output
+                        .environment("itemize", |output| async move {
+                            for s in action.switches.iter() {
+                                output.command0("item").await?;
+                                if s.enabled {
+                                    output.write(&s.text).await?;
+                                } else {
+                                    output.command("strikeThrough", [&s.text]).await?;
+                                }
+                                output.write("\n").await?;
+                            }
+                            Ok(output)
+                        })
+                        .await?;
+                }
+            }
+            Ok(output)
+        })
+        .await?;
+    Ok(())
+}
diff --git a/bins/ayaka-latex/src/writer.rs b/bins/ayaka-latex/src/writer.rs
new file mode 100644
index 00000000..4ead6060
--- /dev/null
+++ b/bins/ayaka-latex/src/writer.rs
@@ -0,0 +1,53 @@
+use std::{future::Future, io::Result};
+use tokio::{fs::File, io::AsyncWriteExt};
+
+pub struct LaTeXWriter {
+    file: File,
+    ident: usize,
+}
+
+impl LaTeXWriter {
+    pub fn new(file: File) -> Self {
+        Self { file, ident: 0 }
+    }
+
+    pub async fn write(&mut self, text: impl AsRef<str>) -> Result<&mut Self> {
+        self.file
+            .write_all(" ".repeat(self.ident * 4).as_bytes())
+            .await?;
+        self.file.write_all(text.as_ref().as_bytes()).await?;
+        Ok(self)
+    }
+
+    pub async fn command(
+        &mut self,
+        cmd: impl AsRef<str>,
+        args: impl IntoIterator<Item = impl AsRef<str>>,
+    ) -> Result<&mut Self> {
+        self.write(format!("\\{}{}\n", cmd.as_ref(), unsafe {
+            String::from_utf8_unchecked(
+                args.into_iter()
+                    .map(|arg| format!("{{{}}}", arg.as_ref()))
+                    .flat_map(|s| s.into_bytes())
+                    .collect::<Vec<_>>(),
+            )
+        }))
+        .await
+    }
+
+    pub async fn command0(&mut self, cmd: impl AsRef<str>) -> Result<&mut Self> {
+        self.command(cmd, &[] as &[&str]).await
+    }
+
+    pub async fn environment<'a, F: Future<Output = Result<&'a mut Self>>>(
+        &'a mut self,
+        env: impl AsRef<str>,
+        f: impl FnOnce(&'a mut Self) -> F,
+    ) -> Result<&'a mut Self> {
+        self.command("begin", [env.as_ref()]).await?;
+        self.ident += 1;
+        let this = f(self).await?;
+        this.ident -= 1;
+        this.command("end", [env]).await
+    }
+}
diff --git a/book/.gitignore b/book/.gitignore
new file mode 100644
index 00000000..7585238e
--- /dev/null
+++ b/book/.gitignore
@@ -0,0 +1,1 @@
+book
diff --git a/book/Makefile b/book/Makefile
new file mode 100644
index 00000000..e8cd6131
--- /dev/null
+++ b/book/Makefile
@@ -0,0 +1,7 @@
+.PHONY: build serve test clean
+build:
+	mdbook build
+serve:
+	mdbook serve --open
+clean:
+	mdbook clean
diff --git a/book/book.toml b/book/book.toml
new file mode 100644
index 00000000..fe08077c
--- /dev/null
+++ b/book/book.toml
@@ -0,0 +1,9 @@
+[book]
+authors = ["Berrysoft"]
+language = "en"
+multilingual = false
+src = "src"
+title = "Ayaka Book"
+
+[rust]
+edition = "2021"
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
new file mode 100644
index 00000000..ce5be563
--- /dev/null
+++ b/book/src/SUMMARY.md
@@ -0,0 +1,21 @@
+# Summary
+
+- [Introduction](./intro.md)
+- [Quick start](./quick_start.md)
+- [Config](./config/summary.md)
+    - [File structure](./config/structure.md)
+    - [Specify character](./config/character.md)
+    - [Resources](./config/resources.md)
+    - [Internationalization](./config/i18n.md)
+    - [Switches](./config/switches.md)
+    - [Script](./config/script.md)
+- [Runtime](./runtime/summary.md)
+    - [Run a game](./runtime/run.md)
+- [Plugin](./plugin/summary.md)
+    - [Script plugin](./plugin/script_plugin.md)
+    - [Text plugin](./plugin/text_plugin.md)
+    - [Action plugin](./plugin/action_plugin.md)
+    - [Game plugin](./plugin/game_plugin.md)
+- [GUI](./gui/summary.md)
+    - [Live2D](./gui/live2d.md)
+- [Support platforms](./platforms.md)
diff --git a/book/src/config/character.md b/book/src/config/character.md
new file mode 100644
index 00000000..d6614109
--- /dev/null
+++ b/book/src/config/character.md
@@ -0,0 +1,48 @@
+# Specify character
+The dialogues should be marked with the speaking character.
+We specify a character with `\ch{}{}` command.
+
+## Add the character names
+The character names should be placed in `res` at the front of the game.
+Not only because the character name is too long to type again and again, but also to make i18n easy.
+
+The key of the character name should be prefixed with `ch_`:
+``` yaml
+res:
+  en:
+    ch_foo: A. Foo
+    ch_bar: B. Bar
+```
+You can then specify the character with the command:
+``` yaml
+- \ch{foo}This is the first line.
+- \ch{bar}This is the second line.
+```
+These two lines will output as:
+``` ignore
+_A. Foo_This is the first line.
+_B. Bar_This is the second line.
+```
+
+## Specify the alias of the character
+Sometimes we need a temporary alias of the current character:
+``` yaml
+- \ch{foo}{Person 1st}This is the first line.
+- \ch{bar}{Person 2nd}This is the second line.
+```
+The output will be
+``` ignore
+_Person 1st_This is the first line.
+_Person 2nd_This is the second line.
+```
+
+## Simple grammar
+We provide an easier grammar to specify the character:
+``` yaml
+- /foo//This is the first line.
+- /bar/Person 2nd/This is the second line.
+```
+Note the double slashes in `/foo//` could not be simplified.
+
+## Warning
+The `\ch{}{}` command could be called many times, but only the last one affects.
diff --git a/book/src/config/i18n.md b/book/src/config/i18n.md
new file mode 100644
index 00000000..db8501ec
--- /dev/null
+++ b/book/src/config/i18n.md
@@ -0,0 +1,32 @@
+# Internationalization
+## ICU
+The i18n feature are supported by [ICU4X](https://github.com/unicode-org/icu4x) with [CLDR](https://github.com/unicode-org/cldr) data.
+We use CLDR to choose the best fit locale for current system.
+
+## Simplify translation
+The translation of the texts is always a difficult job. You don't need to copy all commands as is.
+For example, the original text (`ja`)
+``` ignore
+\ch{rd}団長！車の用意できました！
+\switch{おう！}{$end = false}
+\switch{止まるんじゃねぇぞ！}{$end = true}
+\switch{止まれ！}{}{false}
+```
+could be translated as (`zh-Hans`)
+``` ignore
+团长！车已经准备好了！
+\switch{哦！}
+\switch{不要停下来啊！}
+\switch{停下！}
+```
+
+## Fallback
+The resources, commands, and even paragraphs could be fell back, if a translated one is not apparent.
+However, some other ones couldn't be fell back.
+
+### The `\res` and `\exec` commands
+The `\res` and `\exec` commands couldn't be fell back.
+If there's no corresponding commands in the translated lines, they won't be referenced or executed. However, the `\ch` and `\switch` commands could be fell back.
+
+### Fallback with empty text
+However, if a certain translated line is empty, it will fall back to the base language one.
diff --git a/book/src/config/resources.md b/book/src/config/resources.md
new file mode 100644
index 00000000..5c96399e
--- /dev/null
+++ b/book/src/config/resources.md
@@ -0,0 +1,27 @@
+# Resources
+The resources are indexed by locale:
+``` yaml
+res:
+  en:
+    foo: Foo value
+    bar: Bar value
+```
+You can specify other locales, too.
+The keys not specified in other locales will fallback to `base_lang` ones.
+``` yaml
+base_lang: en
+res:
+  en:
+    foo: Foo
+    bar: Bar
+  zh:
+    foo: 天
+    bar: 地
+```
+
+## Reference resources
+You can reference resources in texts with `\res{}` command.
+``` yaml
+- 'The foo value: \res{foo}'
+- 'The bar value: \res{bar}'
+```
diff --git a/book/src/config/script.md b/book/src/config/script.md
new file mode 100644
index 00000000..0ce53b3e
--- /dev/null
+++ b/book/src/config/script.md
@@ -0,0 +1,39 @@
+# Script
+The script we use is dynamic typed.
+The only supported types are unit `~`, boolean, integer, and string.
+``` rust
+pub enum RawValue {
+    Unit,
+    Bool(bool),
+    Num(i64),
+    Str(String),
+}
+```
+## Execute scripts
+Execute a piece of script(we call it *program*) with `\exec{}` command:
+``` yaml
+- 1 + 1 = \exec{1 + 1}
+```
+The output is
+``` ignore
+1 + 1 = 2
+```
+The script `1 + 1` is evaluated, and the result is `2`.
+It is then converted to string and appended to the text.
+
+## Example: Fibonacci
+With the config file, we can even calculate some math problems. For example, Fibonacci:
+``` yaml
+-
+  tag: init
+  texts:
+    - 1
+    - \exec{$n = 50; $a = 1; $b = 1; $i = 1; $b}
+  next: loop
+-
+  tag: loop
+  texts:
+    - \exec{c = $b; $b += $a; $a = c; $i += 1; $b}
+  next: \exec{if($i < $n, "loop")}
+```
+
diff --git a/book/src/config/structure.md b/book/src/config/structure.md
new file mode 100644
index 00000000..a0f3950e
--- /dev/null
+++ b/book/src/config/structure.md
@@ -0,0 +1,59 @@
+# File structure
+
+## Properties
+The total config file is a `Game` object.
+Here shows the properties:
+
+| Property    | Description                                 |
+| ----------- | ------------------------------------------- |
+| `title`     | The title of the game.                      |
+| `base_lang` | The base language.                          |
+| `paras`     | The `Paragraph` objects, indexed by locale. |
+| `author`    | Optional. The author of the game.           |
+| `plugins`   | Optional. The `PluginConfig` object.        |
+| `res`       | Optional. The resources, indexed by locale. |
+| `props`     | Optional. The custom properties.            |
+
+The `PluginConfig` object contains the base directory and the plugin names:
+
+| Property  | Description       |
+| --------- | ----------------- |
+| `dir`     | The directory.    |
+| `modules` | The plugin names. |
+
+A `Paragraph` object is a collection of texts:
+
+| Property | Description                           |
+| -------- | ------------------------------------- |
+| `tag`    | The tag and key of the paragraph.     |
+| `texts`  | The texts.                            |
+| `title`  | Optional. The title of the paragraph. |
+| `next`   | Optional. The next paragraph.         |
+
+## Basic example
+This is a config example, with 2 paragraphs.
+``` yaml
+title: Title
+base_lang: en
+paras:
+  en:
+    -
+      tag: para1
+      texts:
+        - This is the first line.
+        - This is the second line.
+      next: para2
+    -
+      tag: para2
+      texts:
+        - The first line of the second paragraph.
+```
+The output will be
+``` ignore
+This is the first line.
+This is the second line.
+The first line of the second paragraph.
+```
+You can see that the game starts at the first paragraph `para1`,
+and it jumps to `para2` after `para1` ends.
+The game exits after `para2` ends, because it doesn't specify the next paragraph.
diff --git a/book/src/config/summary.md b/book/src/config/summary.md
new file mode 100644
index 00000000..0d0da1a1
--- /dev/null
+++ b/book/src/config/summary.md
@@ -0,0 +1,9 @@
+# Config
+Our config file is based on YAML. The structure is simple to author.
+
+The articles below uses `ayaka-check` to show the example,
+it may behave a little different in GUI.
+To run the example, you need to create a config file with full [structure](./structure.md), go to the `bins` folder and run
+``` bash
+$ cargo run --package ayaka-check -- path/to/config.yaml --auto
+```
diff --git a/book/src/config/switches.md b/book/src/config/switches.md
new file mode 100644
index 00000000..935f3f58
--- /dev/null
+++ b/book/src/config/switches.md
@@ -0,0 +1,16 @@
+# Switches
+The switches could be specified with `\switch{}{}{}` command.
+The `\switch` command in one line of text are in the same series.
+
+The first parameter is the display text;
+the second parameter is the action script;
+the third parameter is a boolean expression of whether the switch is enabled.
+For the second and the third parameter, see [Script](./script.md).
+
+``` yaml
+- |
+  Choose a switch:
+  \switch{Switch 1}{$s = 1}
+  \switch{Switch 2}{$s = 2}
+  \switch{Not enabled}{}{false}
+```
diff --git a/book/src/gui/live2d.md b/book/src/gui/live2d.md
new file mode 100644
index 00000000..277c69ab
--- /dev/null
+++ b/book/src/gui/live2d.md
@@ -0,0 +1,2 @@
+# Live2D
+The Live2D functionality is powered by [`pixi-live2d-display`](https://github.com/guansss/pixi-live2d-display).
diff --git a/book/src/gui/summary.md b/book/src/gui/summary.md
new file mode 100644
index 00000000..ed4de66d
--- /dev/null
+++ b/book/src/gui/summary.md
@@ -0,0 +1,5 @@
+# GUI
+The `ayaka-gui` is a sample GUI frontend.
+It provides basic functionalities, including control flow, multimedia, i18n and Live2D integration.
+
+The frontend is based on [Tauri](https://tauri.app/) with [Vue](https://vuejs.org/).
diff --git a/book/src/intro.md b/book/src/intro.md
new file mode 100644
index 00000000..b2c1d3c0
--- /dev/null
+++ b/book/src/intro.md
@@ -0,0 +1,20 @@
+# Introduction
+Ayaka project is a project for OSPP 2022.
+It is a voice novel engine which aims at 3 goals: simple, free, concentrate.
+
+## Simple
+A voice novel should be easy to author.
+The author need little knowledge of programming.
+We provide a config file format based on YAML and TeX-like commands.
+It is easy to learn and author your own voice novel.
+
+## Free
+You are free to implement anything you'd like with our script and plugin system.
+The script is simple, but also strong with the plugin system.
+The plugin system provides possibility to calculate and hook important parts in the runtime.
+
+## Concentrate
+The project is separated into 4 parts: runtime, plugins, config, frontend.
+You can concentrate at one part without knowing about others.
+If you like, you can write config file only, and author a voice novel.
+You can also write your own fantastic game by customizing the frontend.
diff --git a/book/src/platforms.md b/book/src/platforms.md
new file mode 100644
index 00000000..2a2f4686
--- /dev/null
+++ b/book/src/platforms.md
@@ -0,0 +1,23 @@
+# Supported platforms
+Ayaka is cross-platform, and the triples are supported with 3 tiers.
+
+## Tier 1
+Ensured to work well with these triples:
+
+* x86_64-pc-windows-msvc
+* x86_64-unknown-linux-gnu
+* x86_64-apple-darwin
+
+## Tier 2
+Should work well with these triples, but not tested:
+
+* x86_64-pc-windows-gnu
+* aarch64-unknown-linux-gnu
+* aarch64-apple-darwin
+
+## Tier 3
+May not build or run because of dependencies:
+
+* i686-pc-windows-msvc
+* i686-pc-windows-gnu
+* aarch64-pc-windows-msvc
diff --git a/book/src/plugin/action_plugin.md b/book/src/plugin/action_plugin.md
new file mode 100644
index 00000000..bca455b7
--- /dev/null
+++ b/book/src/plugin/action_plugin.md
@@ -0,0 +1,46 @@
+# Action plugin
+Action plugins deal with the whole action after the text being parsed.
+An action plugin usually modifies the text, for example, parses the Markdown text and output to HTML.
+
+Action plugins could access the last action in the history, will text plugins cannot.
+
+## Simple Markdown plugin
+Action plugins don't need to register anything, but only to specify in the `plugin_type`:
+
+``` rust,ignore
+use ayaka_bindings::*;
+use pulldown_cmark::*;
+
+#[export]
+fn plugin_type() -> PluginType {
+    PluginType::builder().action().build()
+}
+
+#[export]
+fn process_action(mut ctx: ActionProcessContext) -> Action {
+    let line = ctx
+        .action
+        .line
+        .into_iter()
+        .map(|s| s.into_string())
+        .collect::<Vec<_>>()
+        .concat();
+    let parser = Parser::new(&line);
+    let mut html_output = String::new();
+    html::push_html(&mut html_output, parser);
+    ctx.action.line.clear();
+    ctx.action.line.push_back_chars(html_output);
+    ctx.action
+}
+```
+
+Add the plugin to the `modules` list, and all markdown text will be translated to HTML.
+
+You may notice that the HTML tags are treated as `ActionLine::Chars`, which means they will be displayed one by one on GUI frontends. Our existing `markdown` plugin resolves this problem by providing a custom writer.
+
+## Existing plugins
+| Plugin     | Description                                      |
+| ---------- | ------------------------------------------------ |
+| `live2d`   | Inherit models layout and deal with hiding.      |
+| `markdown` | Process Markdown texts.                          |
+| `media`    | Inherit background image and music from history. |
diff --git a/book/src/plugin/game_plugin.md b/book/src/plugin/game_plugin.md
new file mode 100644
index 00000000..d290cc2e
--- /dev/null
+++ b/book/src/plugin/game_plugin.md
@@ -0,0 +1,24 @@
+# Game plugin
+Game plugins adjust some properties of the game before any record starts.
+
+## Insert a global property
+``` rust,ignore
+use ayaka_bindings::*;
+
+#[export]
+fn plugin_type() -> PluginType {
+    PluginType::builder().game().build()
+}
+
+#[export]
+fn process_game(mut ctx: GameProcessContext) -> GameProcessResult {
+    ctx.props.insert("hello".to_string(), "Hello world!".to_string());
+    GameProcessResult { props: ctx.props }
+}
+```
+
+## Existing plugins
+| Plugin   | Description                                   |
+| -------- | --------------------------------------------- |
+| `live2d` | Get correct path of Live2D models.            |
+| `media`  | Get correct path of background image at home. |
diff --git a/book/src/plugin/script_plugin.md b/book/src/plugin/script_plugin.md
new file mode 100644
index 00000000..8866310a
--- /dev/null
+++ b/book/src/plugin/script_plugin.md
@@ -0,0 +1,47 @@
+# Script plugin
+All plugins are script plugins.
+[Scripts](../config/script.md) could call methods in the script plugins.
+
+## Calling methods
+A plugin method is referenced with `<module>.<fn>(...)` grammar.
+If you would like to call the `rnd` function in `random` module,
+``` yaml
+- \exec{random.rnd()}
+```
+Pass the parameters in the brace `()`.
+
+As the scripts are calculated at runtime, if there's no plugin called `random`,
+or no method called `rnd` inside `random`, it will give a warning, and continue with `RawValue::Unit`.
+
+## Author a script plugin
+Here we're going to author a script plugin `meet` to return a string "Hello".
+``` rust,ignore
+use ayaka_bindings::*;
+
+#[export]
+fn plugin_type() -> PluginType {
+    PluginType::default()
+}
+
+#[export]
+fn hello(_args: Vec<RawValue>) -> RawValue {
+    RawValue::Str("Hello".to_string())
+}
+```
+And call the function:
+``` yaml
+- \exec{meet.hello()} from plugin!
+```
+If it builds successfully, and you set the right path to the plugins, it will output:
+``` ignore
+Hello from plugin!
+```
+
+## Existing plugins
+There are some existing script (only) plugins:
+
+| Plugin   | Description              |
+| -------- | ------------------------ |
+| `format` | Format strings.          |
+| `ayalog` | Log to runtime.          |
+| `random` | Generate random numbers. |
diff --git a/book/src/plugin/summary.md b/book/src/plugin/summary.md
new file mode 100644
index 00000000..790257a3
--- /dev/null
+++ b/book/src/plugin/summary.md
@@ -0,0 +1,25 @@
+# Plugin
+All plugins should target WebAssembly.
+We now support `wasm32-unknown-unknown` and `wasm32-wasi` targets.
+
+The plugin runtime is supported by [Wasmer](https://wasmer.io/).
+Our [platform support](../platforms.md) is largely limited by this engine.
+
+We provide a crate `ayaka-bindings` to easily author a plugin in Rust.
+
+## Load plugins
+Specify the plugin directory in the config file:
+``` yaml
+plugins:
+  dir: path/to/plugins
+```
+The runtime will try to load all WebAssembly file in the directory.
+If you want to specify some of them, or specify the load order, specify them in `modules`:
+``` yaml
+plugins:
+  dir: path/to/plugins
+  modules:
+    - foo
+    - bar
+```
+You don't need to specify the extension.
diff --git a/book/src/plugin/text_plugin.md b/book/src/plugin/text_plugin.md
new file mode 100644
index 00000000..f3bec3a9
--- /dev/null
+++ b/book/src/plugin/text_plugin.md
@@ -0,0 +1,41 @@
+# Text plugin
+Text plugins deal with custom TeX-like commands.
+They should register the commands in `text_commands` method.
+
+## Register commands
+Here we will register a command `\hello` and call it in the config file.
+You also need `plugin_type` to specify that it is a text plugin.
+``` rust,ignore
+use ayaka_bindings::*;
+
+#[export]
+fn plugin_type() -> PluginType {
+    PluginType::builder().text(["hello"]).build()
+}
+
+#[export]
+fn hello(_args: Vec<String>, _ctx: TextProcessContext) -> TextProcessResult {
+    let mut res = TextProcessResult::default();
+    res.line.push_back_chars("Hello");
+    res
+}
+```
+
+Call the command in the config file:
+``` yaml
+- \hello world!
+```
+And it outputs:
+``` ignore
+Hello world!
+```
+
+## The process result
+The `TextProcessResult` object is some lines and properties to be added to the current action. `line` will be appended to the current position of the command, and `props` will be set and update.
+
+## Existing plugins
+| Plugin     | Description          |
+| ---------- | -------------------- |
+| `basictex` | Basic TeX commands.  |
+| `live2d`   | Live2D commands.     |
+| `media`    | Multimedia commands. |
diff --git a/book/src/quick_start.md b/book/src/quick_start.md
new file mode 100644
index 00000000..9bed2dd1
--- /dev/null
+++ b/book/src/quick_start.md
@@ -0,0 +1,45 @@
+# Quick start
+
+## Prerequisites
+All platforms need [Rust](https://www.rust-lang.org/) and [Nodejs](https://nodejs.org/) installed.
+* Rust: nightly toolchain.
+* Nodejs: 14.18+/16+ required by [Vite](https://vitejs.dev/).
+
+### Windows
+Windows 10+ is recommended but any Windows that Rust supports is OK.
+
+[WebView2](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) is required by [Tauri](https://tauri.app/). It comes with the latest Edge browser.
+
+To run the Makefile toolchain, you need GNU Make from [MSYS2](https://www.msys2.org/) project, either for Msys2(`make`) or Mingw64(`mingw32-make`).
+
+Note that if you have a WSL `bash.exe` in PATH before MSYS2 one, the `npm` command may fail.
+
+### Linux
+`webkit2gtk` is needed. We only support `webkit2gtk-4.0` required by [Tauri](https://tauri.app/).
+
+### macOS
+Generally we don't need anything more, but you should ensure there a `make`.
+
+## Clone from source
+``` bash
+$ git clone https://github.com/Uni-Gal/Ayaka.git
+$ cd Ayaka
+```
+
+## Test the utilities
+``` bash
+$ make test
+```
+
+## Release build of frontends
+``` bash
+$ make release
+```
+
+## Run examples
+``` bash
+$ # Run Fibonacci2
+$ make example-Fibonacci2
+$ # Run Orga in GUI
+$ make example-Orga-gui
+```
diff --git a/book/src/runtime/run.md b/book/src/runtime/run.md
new file mode 100644
index 00000000..6bc9ad1a
--- /dev/null
+++ b/book/src/runtime/run.md
@@ -0,0 +1,31 @@
+# Run a game
+The CLI tool in `bins/ayaka-check` is a full example to run a game.
+
+## Open a config file
+``` rust,ignore
+use ayaka_runtime::*;
+let mut context = Context::open("../../../examples/Fibonacci/config.yaml", FrontendType::Text).await?;
+```
+The context object should be initialized first to start from an initial record.
+``` rust,ignore
+context.init_new();
+```
+Then you can iterate the actions:
+``` rust,ignore
+while let Some(action) = context.next_run() {
+    //...
+}
+```
+
+## Get the open status
+The `context` also implements `Stream`.
+The `OpenStatus` could be iterated before the future awaited.
+``` rust,ignore
+use ayaka_runtime::*;
+let context = Context::open("../../../examples/Fibonacci/config.yaml", FrontendType::Text);
+pin_mut!(context);
+while let Some(status) = context.next().await {
+    println!("{:?}", status);
+}
+let mut context = context.await?;
+```
diff --git a/book/src/runtime/summary.md b/book/src/runtime/summary.md
new file mode 100644
index 00000000..50df27b6
--- /dev/null
+++ b/book/src/runtime/summary.md
@@ -0,0 +1,3 @@
+# Runtime
+The runtime, aka "backend", is the engine of a game.
+It provides functionality to load config, settings, plugins, and control the full status.
diff --git a/examples/.gitignore b/examples/.gitignore
new file mode 100644
index 00000000..d6ffa030
--- /dev/null
+++ b/examples/.gitignore
@@ -0,0 +1,287 @@
+# resources
+bgs
+bgms
+ch_models
+efms
+voices
+videos
+plugins
+*.tex
+
+## Core latex/pdflatex auxiliary files:
+*.aux
+*.lof
+*.log
+*.lot
+*.fls
+*.out
+*.toc
+*.fmt
+*.fot
+*.cb
+*.cb2
+.*.lb
+
+## Intermediate documents:
+*.dvi
+*.xdv
+*-converted-to.*
+# these rules might exclude image files for figures etc.
+# *.ps
+# *.eps
+# *.pdf
+
+## Generated if empty string is given at "Please type another file name for output:"
+*.pdf
+
+## Bibliography auxiliary files (bibtex/biblatex/biber):
+*.bbl
+*.bcf
+*.blg
+*-blx.aux
+*-blx.bib
+*.run.xml
+
+## Build tool auxiliary files:
+*.fdb_latexmk
+*.synctex
+*.synctex(busy)
+*.synctex.gz
+*.synctex.gz(busy)
+*.pdfsync
+
+## Build tool directories for auxiliary files
+# latexrun
+latex.out/
+
+## Auxiliary and intermediate files from other packages:
+# algorithms
+*.alg
+*.loa
+
+# achemso
+acs-*.bib
+
+# amsthm
+*.thm
+
+# beamer
+*.nav
+*.pre
+*.snm
+*.vrb
+
+# changes
+*.soc
+
+# comment
+*.cut
+
+# cprotect
+*.cpt
+
+# elsarticle (documentclass of Elsevier journals)
+*.spl
+
+# endnotes
+*.ent
+
+# fixme
+*.lox
+
+# feynmf/feynmp
+*.mf
+*.mp
+*.t[1-9]
+*.t[1-9][0-9]
+*.tfm
+
+#(r)(e)ledmac/(r)(e)ledpar
+*.end
+*.?end
+*.[1-9]
+*.[1-9][0-9]
+*.[1-9][0-9][0-9]
+*.[1-9]R
+*.[1-9][0-9]R
+*.[1-9][0-9][0-9]R
+*.eledsec[1-9]
+*.eledsec[1-9]R
+*.eledsec[1-9][0-9]
+*.eledsec[1-9][0-9]R
+*.eledsec[1-9][0-9][0-9]
+*.eledsec[1-9][0-9][0-9]R
+
+# glossaries
+*.acn
+*.acr
+*.glg
+*.glo
+*.gls
+*.glsdefs
+*.lzo
+*.lzs
+
+# uncomment this for glossaries-extra (will ignore makeindex's style files!)
+# *.ist
+
+# gnuplottex
+*-gnuplottex-*
+
+# gregoriotex
+*.gaux
+*.gtex
+
+# htlatex
+*.4ct
+*.4tc
+*.idv
+*.lg
+*.trc
+*.xref
+
+# hyperref
+*.brf
+
+# knitr
+*-concordance.tex
+# TODO Comment the next line if you want to keep your tikz graphics files
+*.tikz
+*-tikzDictionary
+
+# listings
+*.lol
+
+# luatexja-ruby
+*.ltjruby
+
+# makeidx
+*.idx
+*.ilg
+*.ind
+
+# minitoc
+*.maf
+*.mlf
+*.mlt
+*.mtc[0-9]*
+*.slf[0-9]*
+*.slt[0-9]*
+*.stc[0-9]*
+
+# minted
+_minted*
+*.pyg
+
+# morewrites
+*.mw
+
+# nomencl
+*.nlg
+*.nlo
+*.nls
+
+# pax
+*.pax
+
+# pdfpcnotes
+*.pdfpc
+
+# sagetex
+*.sagetex.sage
+*.sagetex.py
+*.sagetex.scmd
+
+# scrwfile
+*.wrt
+
+# sympy
+*.sout
+*.sympy
+sympy-plots-for-*.tex/
+
+# pdfcomment
+*.upa
+*.upb
+
+# pythontex
+*.pytxcode
+pythontex-files-*/
+
+# tcolorbox
+*.listing
+
+# thmtools
+*.loe
+
+# TikZ & PGF
+*.dpth
+*.md5
+*.auxlock
+
+# todonotes
+*.tdo
+
+# vhistory
+*.hst
+*.ver
+
+# easy-todo
+*.lod
+
+# xcolor
+*.xcp
+
+# xmpincl
+*.xmpi
+
+# xindy
+*.xdy
+
+# xypic precompiled matrices and outlines
+*.xyc
+*.xyd
+
+# endfloat
+*.ttt
+*.fff
+
+# Latexian
+TSWLatexianTemp*
+
+## Editors:
+# WinEdt
+*.bak
+*.sav
+
+# Texpad
+.texpadtmp
+
+# LyX
+*.lyx~
+
+# Kile
+*.backup
+
+# gummi
+.*.swp
+
+# KBibTeX
+*~[0-9]*
+
+# TeXnicCenter
+*.tps
+
+# auto folder when using emacs and auctex
+./auto/*
+*.el
+
+# expex forward references with \gathertags
+*-tags.tex
+
+# standalone packages
+*.sta
+
+# Makeindex log files
+*.lpz
+
diff --git a/examples/Fibonacci/config.yaml b/examples/Fibonacci/config.yaml
new file mode 100644
index 00000000..0bdef7bb
--- /dev/null
+++ b/examples/Fibonacci/config.yaml
@@ -0,0 +1,16 @@
+title: Fibonacci
+author: Berrysoft
+base_lang: en
+paras:
+  en:
+    -
+      tag: init
+      texts:
+        - 1
+        - \exec{$n = 50; $a = 1; $b = 1; $i = 1; $b}
+      next: loop
+    -
+      tag: loop
+      texts:
+        - \exec{c = $b; $b += $a; $a = c; $i += 1; $b}
+      next: \exec{if($i < $n, "loop")}
diff --git a/examples/Fibonacci2/config.yaml b/examples/Fibonacci2/config.yaml
new file mode 100644
index 00000000..1ff794fd
--- /dev/null
+++ b/examples/Fibonacci2/config.yaml
@@ -0,0 +1,20 @@
+title: Fibonacci2
+author: Berrysoft
+plugins:
+  dir: ../plugins/
+  modules:
+    - random
+    - format
+base_lang: en
+paras:
+  en:
+    -
+      tag: init
+      texts:
+        - \exec{$n = random.rnd(50); $a = 1; $b = 1; $i = 1; format.fmt("Starting to calculate Fibonacci {}", $n)}
+      next: loop
+    -
+      tag: loop
+      texts:
+        - \exec{a = $a; b = $b; c = $b; $b += $a; $a = c; $i += 1; format.fmt("{:<11} + {:<11} = {:<11}", a, b, $b)}
+      next: \exec{if($i < $n, "loop")}
diff --git a/examples/Gacha/config.yaml b/examples/Gacha/config.yaml
new file mode 100644
index 00000000..94bdde45
--- /dev/null
+++ b/examples/Gacha/config.yaml
@@ -0,0 +1,126 @@
+title: 原神抽卡
+author: Berrysoft
+plugins:
+  dir: ../plugins/
+  modules:
+    - format
+    - ayalog
+    - media
+    - random
+props:
+  videos: videos
+base_lang: zh-Hans
+paras:
+  zh-Hans:
+    -
+      tag: init
+      texts:
+        - \exec{$total = 0; $t3 = 0; $t4 = 0; $t5 = 0; $c4 = 0; $c5 = 0;}
+      next: start
+    -
+      tag: start
+      texts:
+        - |
+          \exec{format.fmt("你共抽了{}次，三星{}个，四星{}个，五星{}个", $total, $t3, $t4, $t5)}
+          \switch{祈愿一次}{$n = 1}
+          \switch{祈愿十次}{$n = 10}
+          \switch{退出}{$n = -1}
+      next: |
+        \exec{
+          $total5 = 0;
+          $total4 = 0;
+          $total3 = 0;
+          $temp5 = $c5;
+          $temp4 = $c4;
+          if($n > 0, "calc")
+        }
+    -
+      tag: calc
+      texts:
+        - |
+          \exec{
+            p = random.rnd(1000);
+            current5 = if($temp5 < 73,
+              p < 6,
+              if($temp5 >= 99,
+                true,
+                p < (6 + 60 * ($temp5 - 73))
+              )
+            );
+            current4 = if($temp4 < 8,
+              p < 51,
+              if($temp4 >= 9,
+                true,
+                p < 561
+              )
+            );
+            if(current5,
+              $total5 += 1,
+              if(current4,
+                $total4 += 1,
+                $total3 += 1
+              )
+            );
+            if(current5,
+              $temp4 += 1,
+              if(current4,
+                $temp4 = 0,
+                $temp4 += 1
+              )
+            );
+            if(current5,
+              $temp5 = 0,
+              $temp5 += 1,
+            );
+            ayalog.info(if(current5, 5, if(current4, 4, 3)), " star");
+          }
+      next: |
+        \exec{
+          $n -= 1;
+          if($n,
+            "calc",
+            if($total3 + $total4 + $total5 == 1,
+              if($total5,
+                "pull2",
+                if($total4,
+                  "pull1",
+                  "pull0"
+                )
+              ),
+              if($total5,
+                "pull4",
+                "pull3"
+              )
+            )
+          )
+        }
+    -
+      tag: pull0
+      texts:
+        - \video{0}\exec{$total += 1;}
+      next: end
+    -
+      tag: pull1
+      texts:
+        - \video{1}\exec{$total += 1;}
+      next: end
+    -
+      tag: pull2
+      texts:
+        - \video{2}\exec{$total += 1;}
+      next: end
+    -
+      tag: pull3
+      texts:
+        - \video{3}\exec{$total += 10;}
+      next: end
+    -
+      tag: pull4
+      texts:
+        - \video{4}\exec{$total += 10;}
+      next: end
+    -
+      tag: end
+      texts:
+        - \exec{$t5 += $total5; $t4 += $total4; $t3 += $total3; $c4 = $temp4; $c5 = $temp5;}
+      next: start
diff --git a/examples/Live2D/config.yaml b/examples/Live2D/config.yaml
new file mode 100644
index 00000000..1f19c1bc
--- /dev/null
+++ b/examples/Live2D/config.yaml
@@ -0,0 +1,29 @@
+title: Live2D
+author: Berrysoft
+props:
+  ch_models: ch_models
+  ch_names: Haru,Hiyori,Mao
+  ch_Haru_scale: 0.25
+  ch_Hiyori_scale: 0.2
+  ch_Mao_scale: 0.1
+res:
+  ja:
+    ch_Haru: はる
+    ch_Hiyori: ひより
+    ch_Mao: まお
+plugins:
+  dir: ../plugins/
+  modules:
+    - live2d
+base_lang: ja
+paras:
+  ja:
+    -
+      tag: show
+      texts:
+        - /Haru//おはよう\show
+        - /Haru//元気ですか
+        - /Hiyori//~~~ヾ(＾∇＾)おはよー♪\show{Haru}{Hiyori}
+        - /Hiyori//今日もよろしく\hide{Haru}
+        - /Mao/？？？/お早う\hide
+        - /Mao//元気？\show
diff --git a/examples/Orga/config.yaml b/examples/Orga/config.yaml
new file mode 100644
index 00000000..fbafd378
--- /dev/null
+++ b/examples/Orga/config.yaml
@@ -0,0 +1,139 @@
+title: 団長の名場面
+author: 冈田麿里
+props:
+  bg: 4
+  bgs: bgs
+  bgms: bgms
+  voices: voices
+res:
+  ja:
+    ch_rd: ライド
+    ch_org: オルガ
+    ch_kdr: クーデリア
+    ch_tkk: タカキ
+    ch_td: チャド
+    ch_ass: 暗殺者
+    ch_mktk: 三日月
+  zh-Hans:
+    ch_rd: 莱德
+    ch_org: 奥尔加
+    ch_kdr: 古荻莉亚
+    ch_tkk: 塔卡基
+    ch_td: 查德
+    ch_ass: 刺客
+plugins:
+  dir: ../plugins/
+  modules:
+    - basictex
+    - media
+base_lang: ja
+paras:
+  ja:
+    -
+      tag: pre_car
+      title: 車の用意し
+      texts:
+        - |
+          \ch{rd}団長！車の用意できました！\bg{0}
+          \switch{おう！}{$end = false}
+          \switch{止まるんじゃねぇぞ！}{$end = true}
+          \switch{止まれ！}{}{false}
+      next: \exec{if($end, "end", "walk")}
+    -
+      tag: walk
+      title: 静かだ
+      texts:
+        - \ch{org}おう！じゃあな。
+        - /kdr//はい、お気をつけて。
+        - |
+          /rd//なんか静かですね。街の中にはギャラルホルンもいないし本部とはえらい違いだ。\bg{1}
+          \switch{安全}{}
+          \switch{気を付け}{}{false}
+        - /org//ああ。火星の戦力は軒並み向こうに回してんのかもな。
+        - /rd//まっそんなのもう関係ないですけどね！
+        - /org//上機嫌だな。
+        - /rd/ガンバラナイト/そりゃそうですよ！みんな助かるし、\res{ch_tkk}も頑張ってたし、俺も\ruby{頑張らないと}{ガンバラナイト}！
+        - /org//ああ。
+        - そうだ。俺たちが今まで積み上げてきたもんは全部無駄じゃなかった。これからも俺たちが立ち止まらないかぎり道は続く。
+      next: gun
+    -
+      tag: gun
+      title: 何やってんだよ
+      texts:
+        - /td//ぐわっ！\bg{2}
+        - /rd//団長？何やってんだよ？団長！
+        - /org//ぐっ！うおぉ～～！
+        - /ass//うおっ！あっ！
+        - /org//はぁはぁはぁ……なんだよ、結構当たんじゃねぇか。ふっ……\bg{3}
+        - /rd//だ……団長……あっ……あぁ……
+        - /org//なんて声出してやがる……ライド。
+        - /rd//だって……だって……\bgm{0}
+        - /org//俺は鉄華団団長オルガ・イツカだぞ。こんくれぇなんてこたぁねぇ。
+        - /rd//そんな……俺なんかのために……
+        - /org//団員を守んのは俺の仕事だ。
+        - /rd//でも！
+        - /org//いいから行くぞ。皆が待ってんだ。それに……。
+        - ミカ、やっと分かったんだ。
+        - 俺たちにはたどりつく場所なんていらねぇ。ただ進み続けるだけでいい。止まんねぇかぎり、道は続く。
+        - /mktk//謝ったら許さない。
+        - /org//ああ分かってる。
+      next: end
+    -
+      tag: end
+      title: 止まるんじゃねぇぞ
+      texts:
+        - /org//俺は止まんねぇからよ、お前らが止まんねぇかぎり、その先に俺はいるぞ！\bgm{0}\bg{4}
+        - /org//だからよ、止まるんじゃねぇぞ……
+  zh-Hans:
+    -
+      tag: pre_car
+      title: 备车
+      texts:
+        - |
+          团长！车已经准备好了！
+          \switch{哦！}
+          \switch{不要停下来啊！}
+          \switch{停下！}
+    -
+      tag: walk
+      title: 安静
+      texts:
+        - 哦！那么我走了。
+        - 好，路上小心。
+        - |
+          感觉真安静啊，街上也没有加拉尔霍恩的人，和总部差别真大啊。
+          \switch{安全}
+          \switch{小心}
+        - 啊，可能是他们把火星的战力都调到那里去了。
+        - 不过这也和我们没关系了。
+        - 心情很愉快啊。
+        - /rd/加把劲骑士/那是当然的了！大家也有救了，{}又那么努力，我也\ruby{要加油了}{是加把劲骑士}！
+        - 啊。
+        - 没错，我们至今为止所做的一切，并不是全部徒劳的。今后也是，只要我们不停下脚步，道路就会不断延伸。
+    -
+      tag: gun
+      title: 你在干什么啊
+      texts:
+        - 咕哇！
+        - 团长，你在干什么啊，团长！
+        - 呃呃啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊！！！
+        - 呜哦！啊！
+        - 哈哈哈……什么嘛，我的枪法还挺准的嘛。呵……
+        - 团……团长……啊……啊……
+        - 你的声音为什么要颤抖，莱德。
+        - 因为……因为……
+        - 我可是铁华团团长奥尔加·伊兹卡啊，这点小伤无关紧要。
+        - 为什么……要为了保护我……
+        - 保护团员就是我的使命。
+        - 但是！
+        - 好了，快走吧！大家都在等着你们。而且……
+        - 三日，我终于明白了。
+        - 我们的目的地根本不重要，只要继续前进就好了，只要不停下脚步，道路就会不断延伸。
+        - 道歉的话我是不会原谅你的。
+        - 啊，我明白。
+    -
+      tag: end
+      title: 不要停下来啊
+      texts:
+        - 我是不会停下来的，只要你们不停下来，那前面就一定有我！
+        - 所以，不要停下来啊……
diff --git a/examples/Styles/config.yaml b/examples/Styles/config.yaml
new file mode 100644
index 00000000..723d808d
--- /dev/null
+++ b/examples/Styles/config.yaml
@@ -0,0 +1,31 @@
+title: Markdown
+author: Berrysoft
+plugins:
+  dir: ../plugins/
+  modules:
+    - basictex
+    - markdown
+base_lang: en
+paras:
+  en:
+    -
+      tag: md
+      texts:
+        - Markdown examples
+        - '# HEAD'
+        - Normal
+        - '*Italic*'
+        - '**Bold**'
+        - '`code`'
+        - Mixed normal *italic* **bold** `code`.
+      next: tex
+    -
+      tag: tex
+      texts:
+        - LaTeX examples
+        - This is the first line.\par This is the second line.
+        - \textrm{Roman}
+        - \textsf{Sans-serif}
+        - \texttt{Monospace}
+        - Mixed \textrm{Roman} \textsf{Sans-serif} \texttt{Monospace}
+        - \ruby{Ruby}{ruby}
\ No newline at end of file
diff --git a/plugins/Cargo.toml b/plugins/Cargo.toml
new file mode 100644
index 00000000..8e88f8a4
--- /dev/null
+++ b/plugins/Cargo.toml
@@ -0,0 +1,14 @@
+[workspace]
+members = [
+    "basictex",
+    "format",
+    "ayalog",
+    "live2d",
+    "markdown",
+    "media",
+    "random",
+]
+
+[profile.release]
+lto = true
+codegen-units = 1
diff --git a/plugins/Makefile b/plugins/Makefile
new file mode 100644
index 00000000..9b553d3d
--- /dev/null
+++ b/plugins/Makefile
@@ -0,0 +1,12 @@
+.PHONY: test clean update
+clean:
+	cargo clean
+update:
+	cargo update
+
+.PHONY: plugins
+plugins:
+	cargo build --release
+	mkdir -p ../examples/plugins
+	cp target/wasm32-wasi/release/*.wasm ../examples/plugins/
+	cp target/wasm32-unknown-unknown/release/*.wasm ../examples/plugins/
diff --git a/plugins/ayalog/Cargo.toml b/plugins/ayalog/Cargo.toml
new file mode 100644
index 00000000..5c58a27d
--- /dev/null
+++ b/plugins/ayalog/Cargo.toml
@@ -0,0 +1,13 @@
+cargo-features = ["per-package-target"]
+
+[package]
+name = "ayalog"
+version = "0.1.0"
+edition = "2021"
+forced-target = "wasm32-unknown-unknown"
+
+[lib]
+crate-type = ["cdylib"]
+
+[dependencies]
+ayaka-bindings = { path = "../../utils/ayaka-bindings" }
diff --git a/plugins/ayalog/src/lib.rs b/plugins/ayalog/src/lib.rs
new file mode 100644
index 00000000..f82771fa
--- /dev/null
+++ b/plugins/ayalog/src/lib.rs
@@ -0,0 +1,40 @@
+use ayaka_bindings::*;
+
+#[export]
+fn plugin_type() -> PluginType {
+    PluginType::default()
+}
+
+fn log_impl(level: log::Level, args: Vec<RawValue>) -> RawValue {
+    let mut buffer = String::new();
+    for arg in args.into_iter() {
+        buffer.push_str(&arg.get_str());
+    }
+    log::log!(level, "{}", buffer);
+    RawValue::Unit
+}
+
+#[export]
+fn error(args: Vec<RawValue>) -> RawValue {
+    log_impl(log::Level::Error, args)
+}
+
+#[export]
+fn warn(args: Vec<RawValue>) -> RawValue {
+    log_impl(log::Level::Warn, args)
+}
+
+#[export]
+fn info(args: Vec<RawValue>) -> RawValue {
+    log_impl(log::Level::Info, args)
+}
+
+#[export]
+fn debug(args: Vec<RawValue>) -> RawValue {
+    log_impl(log::Level::Debug, args)
+}
+
+#[export]
+fn trace(args: Vec<RawValue>) -> RawValue {
+    log_impl(log::Level::Trace, args)
+}
diff --git a/plugins/basictex/Cargo.toml b/plugins/basictex/Cargo.toml
new file mode 100644
index 00000000..ff4daacd
--- /dev/null
+++ b/plugins/basictex/Cargo.toml
@@ -0,0 +1,13 @@
+cargo-features = ["per-package-target"]
+
+[package]
+name = "basictex"
+version = "0.1.0"
+edition = "2021"
+forced-target = "wasm32-unknown-unknown"
+
+[lib]
+crate-type = ["cdylib"]
+
+[dependencies]
+ayaka-bindings = { path = "../../utils/ayaka-bindings" }
diff --git a/plugins/basictex/src/lib.rs b/plugins/basictex/src/lib.rs
new file mode 100644
index 00000000..87ccdb5f
--- /dev/null
+++ b/plugins/basictex/src/lib.rs
@@ -0,0 +1,69 @@
+use ayaka_bindings::*;
+
+#[export]
+fn plugin_type() -> PluginType {
+    PluginType::builder()
+        .text(["par", "textrm", "textsf", "texttt", "ruby"])
+        .build()
+}
+
+#[export]
+fn par(args: Vec<String>, ctx: TextProcessContext) -> TextProcessResult {
+    assert!(args.is_empty());
+    let mut res = TextProcessResult::default();
+    match ctx.frontend {
+        FrontendType::Text => res.line.push_back_chars("\n"),
+        FrontendType::Html => res.line.push_back_chars("<br />"),
+    }
+    res
+}
+
+fn text_font(args: Vec<String>, ctx: TextProcessContext, fonts: &str) -> TextProcessResult {
+    assert_eq!(args.len(), 1);
+    let mut res = TextProcessResult::default();
+    match ctx.frontend {
+        FrontendType::Text => res.line.push_back_chars(&args[0]),
+        FrontendType::Html => {
+            res.line
+                .push_back_block(format!("<font face=\"{}\">", fonts));
+            res.line.push_back_chars(&args[0]);
+            res.line.push_back_block("</font>");
+        }
+    }
+    res
+}
+
+#[export]
+fn textrm(args: Vec<String>, ctx: TextProcessContext) -> TextProcessResult {
+    text_font(args, ctx, "Times New Roman")
+}
+
+#[export]
+fn textsf(args: Vec<String>, ctx: TextProcessContext) -> TextProcessResult {
+    text_font(args, ctx, "Arial")
+}
+
+#[export]
+fn texttt(args: Vec<String>, ctx: TextProcessContext) -> TextProcessResult {
+    text_font(args, ctx, "Courier New")
+}
+
+#[export]
+fn ruby(args: Vec<String>, ctx: TextProcessContext) -> TextProcessResult {
+    assert_eq!(args.len(), 2);
+    let mut res = TextProcessResult::default();
+    match ctx.frontend {
+        FrontendType::Text => res
+            .line
+            .push_back_chars(format!("{}（{}）", args[0], args[1])),
+        FrontendType::Html => {
+            res.line.push_back_block("<ruby>");
+            res.line.push_back_chars(&args[0]);
+            res.line.push_back_block("<rp>（</rp><rt>");
+            res.line.push_back_chars(&args[1]);
+            res.line.push_back_block("</rt><rp>）</rp>");
+            res.line.push_back_block("</ruby>");
+        }
+    }
+    res
+}
diff --git a/plugins/format/Cargo.toml b/plugins/format/Cargo.toml
new file mode 100644
index 00000000..8681ce6d
--- /dev/null
+++ b/plugins/format/Cargo.toml
@@ -0,0 +1,15 @@
+cargo-features = ["per-package-target"]
+
+[package]
+name = "format"
+version = "0.1.0"
+edition = "2021"
+forced-target = "wasm32-unknown-unknown"
+
+[lib]
+crate-type = ["cdylib"]
+
+[dependencies]
+ayaka-script-types = { path = "../../utils/ayaka-script-types", features = ["rt-format"] }
+ayaka-bindings = { path = "../../utils/ayaka-bindings" }
+rt-format = "0.3"
diff --git a/plugins/format/src/lib.rs b/plugins/format/src/lib.rs
new file mode 100644
index 00000000..d79e5fc7
--- /dev/null
+++ b/plugins/format/src/lib.rs
@@ -0,0 +1,28 @@
+use ayaka_bindings::*;
+use log::warn;
+use rt_format::*;
+use std::collections::HashMap;
+
+#[export]
+fn plugin_type() -> PluginType {
+    PluginType::default()
+}
+
+#[export]
+fn fmt(args: Vec<RawValue>) -> RawValue {
+    if args.is_empty() {
+        warn!("Format args is empty.");
+        RawValue::Unit
+    } else {
+        ParsedFormat::parse(
+            &args[0].get_str(),
+            &args[1..],
+            &HashMap::<String, RawValue>::new(),
+        )
+        .map(|r| RawValue::Str(r.to_string()))
+        .unwrap_or_else(|i| {
+            warn!("Format failed, stopped at {}.", i);
+            Default::default()
+        })
+    }
+}
diff --git a/plugins/live2d/Cargo.toml b/plugins/live2d/Cargo.toml
new file mode 100644
index 00000000..276f77c2
--- /dev/null
+++ b/plugins/live2d/Cargo.toml
@@ -0,0 +1,13 @@
+cargo-features = ["per-package-target"]
+
+[package]
+name = "live2d"
+version = "0.1.0"
+edition = "2021"
+forced-target = "wasm32-wasi"
+
+[lib]
+crate-type = ["cdylib"]
+
+[dependencies]
+ayaka-bindings = { path = "../../utils/ayaka-bindings" }
diff --git a/plugins/live2d/src/lib.rs b/plugins/live2d/src/lib.rs
new file mode 100644
index 00000000..20ea5b1c
--- /dev/null
+++ b/plugins/live2d/src/lib.rs
@@ -0,0 +1,117 @@
+use ayaka_bindings::*;
+use std::{
+    collections::{HashMap, HashSet},
+    path::{Path, PathBuf},
+};
+
+#[export]
+fn plugin_type() -> PluginType {
+    PluginType::builder()
+        .action()
+        .text(["show", "hide"])
+        .game()
+        .build()
+}
+
+const CH_DEFAULT: &str = "__ch_default__";
+const CH_ALL: &str = "__ch_all__";
+
+fn find_model(
+    ch: &str,
+    root_path: impl AsRef<Path>,
+    game_props: &HashMap<String, String>,
+) -> Option<PathBuf> {
+    let base_dir = root_path.as_ref().join(
+        game_props
+            .get("ch_models")
+            .map(|s| s.as_str())
+            .unwrap_or(""),
+    );
+    ["model.json", "model3.json"]
+        .iter()
+        .map(|ex| base_dir.join(ch).join(ch).with_extension(ex))
+        .find(|p| p.exists())
+}
+
+#[export]
+fn show(args: Vec<String>, ctx: TextProcessContext) -> TextProcessResult {
+    let models = args
+        .into_iter()
+        .filter(|name| ctx.game_props.contains_key(&format!("ch_{}_model", name)))
+        .collect::<Vec<_>>();
+    let mut res = TextProcessResult::default();
+    res.props.insert(
+        "ch_models".to_string(),
+        if models.is_empty() {
+            CH_DEFAULT.to_string()
+        } else {
+            models.join(",")
+        },
+    );
+    res
+}
+
+#[export]
+fn hide(args: Vec<String>, _ctx: TextProcessContext) -> TextProcessResult {
+    let mut res = TextProcessResult::default();
+    res.props.insert(
+        "ch_hide".to_string(),
+        if args.is_empty() {
+            CH_ALL.to_string()
+        } else {
+            args.join(",")
+        },
+    );
+    res
+}
+
+#[export]
+fn process_action(mut ctx: ActionProcessContext) -> Action {
+    let hide = ctx.action.props.remove("ch_hide");
+    if hide.as_deref() == Some(CH_ALL) {
+        ctx.action.props.remove("ch_models");
+    } else {
+        let hide = hide
+            .as_ref()
+            .map(|hide| hide.split(',').collect::<HashSet<_>>())
+            .unwrap_or_default();
+
+        let models = ctx
+            .action
+            .props
+            .entry("ch_models".to_string())
+            .or_insert_with_key(|key| {
+                ctx.last_action
+                    .and_then(|act| act.props.get(key).cloned())
+                    .unwrap_or_default()
+            });
+
+        if models == CH_DEFAULT {
+            if let Some(ch) = &ctx.action.ch_key {
+                *models = ch.clone()
+            }
+        }
+
+        *models = models
+            .split(',')
+            .filter(|name| !hide.contains(name))
+            .collect::<Vec<_>>()
+            .join(",");
+    }
+    ctx.action
+}
+
+#[export]
+fn process_game(mut ctx: GameProcessContext) -> GameProcessResult {
+    if let Some(names) = ctx.props.remove("ch_names") {
+        for name in names.split(',') {
+            if let Some(path) = find_model(name, &ctx.root_path, &ctx.props) {
+                ctx.props.insert(
+                    format!("ch_{}_model", name),
+                    path.to_string_lossy().into_owned(),
+                );
+            }
+        }
+    }
+    GameProcessResult { props: ctx.props }
+}
diff --git a/plugins/markdown/Cargo.toml b/plugins/markdown/Cargo.toml
new file mode 100644
index 00000000..4ada78ee
--- /dev/null
+++ b/plugins/markdown/Cargo.toml
@@ -0,0 +1,14 @@
+cargo-features = ["per-package-target"]
+
+[package]
+name = "markdown"
+version = "0.1.0"
+edition = "2021"
+forced-target = "wasm32-unknown-unknown"
+
+[lib]
+crate-type = ["cdylib"]
+
+[dependencies]
+ayaka-bindings = { path = "../../utils/ayaka-bindings" }
+pulldown-cmark = "0.9"
diff --git a/plugins/markdown/src/lib.rs b/plugins/markdown/src/lib.rs
new file mode 100644
index 00000000..f6e98a39
--- /dev/null
+++ b/plugins/markdown/src/lib.rs
@@ -0,0 +1,347 @@
+use ayaka_bindings::*;
+use pulldown_cmark::{Event::*, *};
+use std::{borrow::Cow, collections::HashMap};
+
+#[export]
+fn plugin_type() -> PluginType {
+    PluginType::builder().action().build()
+}
+
+#[export]
+fn process_action(mut ctx: ActionProcessContext) -> Action {
+    let line = ctx
+        .action
+        .line
+        .into_iter()
+        .map(|s| s.into_string())
+        .collect::<Vec<_>>()
+        .concat();
+    let parser = Parser::new(&line);
+    let writer = Writer::new(parser);
+    ctx.action.line = match ctx.frontend {
+        FrontendType::Html => writer.run_html().into_lines(),
+        FrontendType::Text => writer.run_text().into_lines(),
+    };
+    ctx.action
+}
+
+// The below code are modified from pulldown_cmark
+
+fn escape_html(s: &str) -> String {
+    let mut buffer = String::new();
+    pulldown_cmark::escape::escape_html(&mut buffer, s).unwrap();
+    buffer
+}
+
+enum TableState {
+    Head,
+    Body,
+}
+
+struct Writer<'a, I> {
+    iter: I,
+    writer: ActionLines,
+    table_state: TableState,
+    table_alignments: Vec<Alignment>,
+    table_cell_index: usize,
+    numbers: HashMap<CowStr<'a>, usize>,
+}
+
+impl<'a, I> Writer<'a, I>
+where
+    I: Iterator<Item = Event<'a>>,
+{
+    fn new(iter: I) -> Self {
+        Self {
+            iter,
+            writer: ActionLines::default(),
+            table_state: TableState::Head,
+            table_alignments: vec![],
+            table_cell_index: 0,
+            numbers: HashMap::new(),
+        }
+    }
+
+    /// Writes a buffer, and tracks whether or not a newline was written.
+    fn write_chars<'s>(&mut self, s: impl Into<Cow<'s, str>>) {
+        self.writer.push_back_chars(s);
+    }
+
+    fn write_block<'s>(&mut self, s: impl Into<Cow<'s, str>>) {
+        self.writer.push_back_block(s);
+    }
+
+    fn run_text(mut self) -> Self {
+        while let Some(event) = self.iter.next() {
+            match event {
+                Text(text) | Code(text) | Html(text) => self.write_chars(text.as_ref()),
+                SoftBreak | HardBreak | Rule => self.write_chars("\n"),
+                _ => {}
+            }
+        }
+        self
+    }
+
+    fn run_html(mut self) -> Self {
+        while let Some(event) = self.iter.next() {
+            match event {
+                Start(tag) => {
+                    self.start_tag(tag);
+                }
+                End(tag) => {
+                    self.end_tag(tag);
+                }
+                Text(text) => {
+                    self.write_chars(escape_html(&text));
+                }
+                Code(text) => {
+                    self.write_block("<code>");
+                    self.write_chars(escape_html(&text));
+                    self.write_block("</code>");
+                }
+                Html(html) => {
+                    self.write_block(html.into_string());
+                }
+                SoftBreak => {
+                    self.write_chars("\n");
+                }
+                HardBreak | Rule => {
+                    self.write_block("<br />");
+                }
+                FootnoteReference(name) => {
+                    let len = self.numbers.len() + 1;
+                    self.write_block("<sup class=\"footnote-reference\"><a href=\"#");
+                    self.write_block(escape_html(&name));
+                    self.write_block("\">");
+                    let number = *self.numbers.entry(name).or_insert(len);
+                    self.write_chars(number.to_string());
+                    self.write_block("</a></sup>");
+                }
+                TaskListMarker(true) => {
+                    self.write_block("<input disabled=\"\" type=\"checkbox\" checked=\"\"/>");
+                }
+                TaskListMarker(false) => {
+                    self.write_block("<input disabled=\"\" type=\"checkbox\"/>");
+                }
+            }
+        }
+        self
+    }
+
+    /// Writes the start of an HTML tag.
+    fn start_tag(&mut self, tag: Tag<'a>) {
+        match tag {
+            Tag::Paragraph => self.write_block("<p>"),
+            Tag::Heading(level, id, classes) => {
+                self.write_block("<");
+                self.write_block(level.to_string());
+                if let Some(id) = id {
+                    self.write_block(" id=\"");
+                    self.write_block(escape_html(id));
+                    self.write_block("\"");
+                }
+                let mut classes = classes.iter();
+                if let Some(class) = classes.next() {
+                    self.write_block(" class=\"");
+                    self.write_block(escape_html(class));
+                    for class in classes {
+                        self.write_block(" ");
+                        self.write_block(escape_html(class));
+                    }
+                    self.write_block("\"");
+                }
+                self.write_block(">")
+            }
+            Tag::Table(alignments) => {
+                self.table_alignments = alignments;
+                self.write_block("<table>")
+            }
+            Tag::TableHead => {
+                self.table_state = TableState::Head;
+                self.table_cell_index = 0;
+                self.write_block("<thead><tr>")
+            }
+            Tag::TableRow => {
+                self.table_cell_index = 0;
+                self.write_block("<tr>")
+            }
+            Tag::TableCell => {
+                match self.table_state {
+                    TableState::Head => {
+                        self.write_block("<th");
+                    }
+                    TableState::Body => {
+                        self.write_block("<td");
+                    }
+                }
+                match self.table_alignments.get(self.table_cell_index) {
+                    Some(&Alignment::Left) => self.write_block(" style=\"text-align: left\">"),
+                    Some(&Alignment::Center) => self.write_block(" style=\"text-align: center\">"),
+                    Some(&Alignment::Right) => self.write_block(" style=\"text-align: right\">"),
+                    _ => self.write_block(">"),
+                }
+            }
+            Tag::BlockQuote => self.write_block("<blockquote>"),
+            Tag::CodeBlock(info) => match info {
+                CodeBlockKind::Fenced(info) => {
+                    let lang = info.split(' ').next().unwrap();
+                    if lang.is_empty() {
+                        self.write_block("<pre><code>")
+                    } else {
+                        self.write_block("<pre><code class=\"language-");
+                        self.write_block(escape_html(lang));
+                        self.write_block("\">")
+                    }
+                }
+                CodeBlockKind::Indented => self.write_block("<pre><code>"),
+            },
+            Tag::List(Some(1)) => self.write_block("<ol>"),
+            Tag::List(Some(start)) => {
+                self.write_block("<ol start=\"");
+                self.write_chars(start.to_string());
+                self.write_block("\">")
+            }
+            Tag::List(None) => self.write_block("<ul>"),
+            Tag::Item => self.write_block("<li>"),
+            Tag::Emphasis => self.write_block("<em>"),
+            Tag::Strong => self.write_block("<strong>"),
+            Tag::Strikethrough => self.write_block("<del>"),
+            Tag::Link(LinkType::Email, dest, title) => {
+                self.write_block("<a href=\"mailto:");
+                self.write_block(escape_html(&dest));
+                if !title.is_empty() {
+                    self.write_block("\" title=\"");
+                    self.write_block(escape_html(&title));
+                }
+                self.write_block("\">")
+            }
+            Tag::Link(_link_type, dest, title) => {
+                self.write_block("<a href=\"");
+                self.write_block(escape_html(&dest));
+                if !title.is_empty() {
+                    self.write_block("\" title=\"");
+                    self.write_block(escape_html(&title));
+                }
+                self.write_block("\">")
+            }
+            Tag::Image(_link_type, dest, title) => {
+                self.write_block("<img src=\"");
+                self.write_block(escape_html(&dest));
+                self.write_block("\" alt=\"");
+                self.raw_text();
+                if !title.is_empty() {
+                    self.write_block("\" title=\"");
+                    self.write_block(escape_html(&title));
+                }
+                self.write_block("\" />")
+            }
+            Tag::FootnoteDefinition(name) => {
+                self.write_block("<div class=\"footnote-definition\" id=\"");
+                self.write_block(escape_html(&name));
+                self.write_block("\"><sup class=\"footnote-definition-label\">");
+                let len = self.numbers.len() + 1;
+                let number = *self.numbers.entry(name).or_insert(len);
+                self.write_chars(number.to_string());
+                self.write_block("</sup>")
+            }
+        }
+    }
+
+    fn end_tag(&mut self, tag: Tag) {
+        match tag {
+            Tag::Paragraph => {
+                self.write_block("</p>");
+            }
+            Tag::Heading(level, _id, _classes) => {
+                self.write_block("</");
+                self.write_block(level.to_string());
+                self.write_block(">");
+            }
+            Tag::Table(_) => {
+                self.write_block("</tbody></table>");
+            }
+            Tag::TableHead => {
+                self.write_block("</tr></thead><tbody>");
+                self.table_state = TableState::Body;
+            }
+            Tag::TableRow => {
+                self.write_block("</tr>");
+            }
+            Tag::TableCell => {
+                match self.table_state {
+                    TableState::Head => {
+                        self.write_block("</th>");
+                    }
+                    TableState::Body => {
+                        self.write_block("</td>");
+                    }
+                }
+                self.table_cell_index += 1;
+            }
+            Tag::BlockQuote => {
+                self.write_block("</blockquote>");
+            }
+            Tag::CodeBlock(_) => {
+                self.write_block("</code></pre>");
+            }
+            Tag::List(Some(_)) => {
+                self.write_block("</ol>");
+            }
+            Tag::List(None) => {
+                self.write_block("</ul>");
+            }
+            Tag::Item => {
+                self.write_block("</li>");
+            }
+            Tag::Emphasis => {
+                self.write_block("</em>");
+            }
+            Tag::Strong => {
+                self.write_block("</strong>");
+            }
+            Tag::Strikethrough => {
+                self.write_block("</del>");
+            }
+            Tag::Link(_, _, _) => {
+                self.write_block("</a>");
+            }
+            Tag::Image(_, _, _) => (), // shouldn't happen, handled in start
+            Tag::FootnoteDefinition(_) => {
+                self.write_block("</div>");
+            }
+        }
+    }
+
+    // run raw text, consuming end tag
+    fn raw_text(&mut self) {
+        let mut nest = 0;
+        while let Some(event) = self.iter.next() {
+            match event {
+                Start(_) => nest += 1,
+                End(_) => {
+                    if nest == 0 {
+                        break;
+                    }
+                    nest -= 1;
+                }
+                Html(text) | Code(text) | Text(text) => {
+                    self.write_chars(escape_html(&text));
+                }
+                SoftBreak | HardBreak | Rule => {
+                    self.write_chars(" ");
+                }
+                FootnoteReference(name) => {
+                    let len = self.numbers.len() + 1;
+                    let number = *self.numbers.entry(name).or_insert(len);
+                    self.write_chars(format!("[{}]", number));
+                }
+                TaskListMarker(true) => self.write_chars("[x]"),
+                TaskListMarker(false) => self.write_chars("[ ]"),
+            }
+        }
+    }
+
+    pub fn into_lines(self) -> ActionLines {
+        self.writer
+    }
+}
diff --git a/plugins/media/Cargo.toml b/plugins/media/Cargo.toml
new file mode 100644
index 00000000..54ee0e16
--- /dev/null
+++ b/plugins/media/Cargo.toml
@@ -0,0 +1,13 @@
+cargo-features = ["per-package-target"]
+
+[package]
+name = "media"
+version = "0.1.0"
+edition = "2021"
+forced-target = "wasm32-wasi"
+
+[lib]
+crate-type = ["cdylib"]
+
+[dependencies]
+ayaka-bindings = { path = "../../utils/ayaka-bindings" }
diff --git a/plugins/media/src/lib.rs b/plugins/media/src/lib.rs
new file mode 100644
index 00000000..8535da72
--- /dev/null
+++ b/plugins/media/src/lib.rs
@@ -0,0 +1,127 @@
+use std::path::{Path, PathBuf};
+
+use ayaka_bindings::*;
+
+#[export]
+fn plugin_type() -> PluginType {
+    PluginType::builder()
+        .action()
+        .text(["bg", "bgm", "efm", "video"])
+        .game()
+        .build()
+}
+
+fn find_exists(name: &str, base_dir: impl AsRef<Path>, exs: &[&str]) -> Option<PathBuf> {
+    let base_dir = base_dir.as_ref();
+    exs.iter()
+        .map(|ex| base_dir.join(name).with_extension(ex))
+        .find(|p| p.exists())
+}
+
+fn file(
+    args: Vec<String>,
+    base_dir: impl AsRef<Path>,
+    prop: &str,
+    exs: &[&str],
+) -> TextProcessResult {
+    assert_eq!(args.len(), 1);
+    let base_dir = base_dir.as_ref();
+    log::debug!(
+        "File {:?}, {:?}, {}, {:?}",
+        args,
+        base_dir.display(),
+        prop,
+        exs
+    );
+    let mut res = TextProcessResult::default();
+    if let Some(path) = find_exists(&args[0], base_dir, exs) {
+        res.props
+            .insert(prop.to_string(), path.to_string_lossy().into_owned());
+    }
+    res
+}
+
+fn file_ctx(
+    args: Vec<String>,
+    ctx: TextProcessContext,
+    game_prop: &str,
+    prop: &str,
+    exs: &[&str],
+) -> TextProcessResult {
+    file(
+        args,
+        ctx.root_path.join(
+            ctx.game_props
+                .get(game_prop)
+                .map(|s| s.as_str())
+                .unwrap_or(""),
+        ),
+        prop,
+        exs,
+    )
+}
+
+#[export]
+fn bg(args: Vec<String>, ctx: TextProcessContext) -> TextProcessResult {
+    file_ctx(args, ctx, "bgs", "bg", &["png", "jpg", "gif"])
+}
+
+#[export]
+fn bgm(args: Vec<String>, ctx: TextProcessContext) -> TextProcessResult {
+    file_ctx(args, ctx, "bgms", "bgm", &["mp3"])
+}
+
+#[export]
+fn efm(args: Vec<String>, ctx: TextProcessContext) -> TextProcessResult {
+    file_ctx(args, ctx, "efms", "efm", &["mp3"])
+}
+
+#[export]
+fn video(args: Vec<String>, ctx: TextProcessContext) -> TextProcessResult {
+    file_ctx(args, ctx, "videos", "video", &["mp4"])
+}
+
+#[export]
+fn process_action(mut ctx: ActionProcessContext) -> Action {
+    if let Some(last_action) = &ctx.last_action {
+        for prop in ["bg", "bgm"] {
+            if let Some(value) = last_action.props.get(prop) {
+                ctx.action
+                    .props
+                    .entry(prop.to_string())
+                    .or_insert_with(|| value.clone());
+            }
+        }
+    }
+    let voice_id = ctx.action.ctx.cur_act.to_string();
+    let res = file(
+        vec![voice_id],
+        ctx.root_path
+            .join(
+                ctx.game_props
+                    .get("voices")
+                    .map(|s| s.as_str())
+                    .unwrap_or(""),
+            )
+            .join(&ctx.action.ctx.cur_para),
+        "voice",
+        &["mp3"],
+    );
+    for (key, value) in res.props.into_iter() {
+        ctx.action.props.insert(key, value);
+    }
+    ctx.action
+}
+
+#[export]
+fn process_game(mut ctx: GameProcessContext) -> GameProcessResult {
+    let base_dir = ctx
+        .root_path
+        .join(ctx.props.get("bgs").map(|s| s.as_str()).unwrap_or(""));
+    if let Some(bg) = ctx.props.get_mut("bg") {
+        if let Some(path) = find_exists(bg, &base_dir, &["png", "jpg", "gif"]) {
+            *bg = path.to_string_lossy().into_owned();
+        }
+    }
+    GameProcessResult { props: ctx.props }
+}
diff --git a/plugins/random/Cargo.toml b/plugins/random/Cargo.toml
new file mode 100644
index 00000000..c7b86696
--- /dev/null
+++ b/plugins/random/Cargo.toml
@@ -0,0 +1,14 @@
+cargo-features = ["per-package-target"]
+
+[package]
+name = "random"
+version = "0.1.0"
+edition = "2021"
+forced-target = "wasm32-wasi"
+
+[lib]
+crate-type = ["cdylib"]
+
+[dependencies]
+ayaka-bindings = { path = "../../utils/ayaka-bindings" }
+rand = "0.8"
diff --git a/plugins/random/src/lib.rs b/plugins/random/src/lib.rs
new file mode 100644
index 00000000..d3a7dc9b
--- /dev/null
+++ b/plugins/random/src/lib.rs
@@ -0,0 +1,28 @@
+#![feature(once_cell)]
+
+use ayaka_bindings::*;
+use log::error;
+use rand::{rngs::StdRng, Rng, SeedableRng};
+use std::sync::{LazyLock, Mutex};
+
+#[export]
+fn plugin_type() -> PluginType {
+    PluginType::default()
+}
+
+static RNG: LazyLock<Mutex<StdRng>> = LazyLock::new(|| Mutex::new(StdRng::from_entropy()));
+
+#[export]
+fn rnd(args: Vec<RawValue>) -> RawValue {
+    if let Ok(mut rng) = RNG.lock() {
+        let res = match args.len() {
+            0 => rng.gen(),
+            1 => rng.gen_range(0..args[0].get_num()),
+            _ => rng.gen_range(args[0].get_num()..args[1].get_num()),
+        };
+        RawValue::Num(res)
+    } else {
+        error!("Cannot get random engine.");
+        RawValue::Unit
+    }
+}
diff --git a/rust-toolchain b/rust-toolchain
new file mode 100644
index 00000000..bf867e0a
--- /dev/null
+++ b/rust-toolchain
@@ -0,0 +1,1 @@
+nightly
diff --git a/utils/Cargo.toml b/utils/Cargo.toml
new file mode 100644
index 00000000..a2643360
--- /dev/null
+++ b/utils/Cargo.toml
@@ -0,0 +1,13 @@
+[workspace]
+members = [
+    "ayaka-bindings-types",
+    "ayaka-script-types",
+    "ayaka-script",
+    "ayaka-runtime",
+]
+
+resolver = "2"
+
+[profile.release]
+lto = true
+codegen-units = 1
diff --git a/utils/Makefile b/utils/Makefile
new file mode 100644
index 00000000..7708e85c
--- /dev/null
+++ b/utils/Makefile
@@ -0,0 +1,11 @@
+.PHONY: test nextest clean update doc
+test:
+	cargo test
+nextest:
+	cargo nextest run
+clean:
+	cargo clean
+update:
+	cargo update
+doc:
+	cargo doc --no-deps
diff --git a/utils/ayaka-bindings-impl/Cargo.toml b/utils/ayaka-bindings-impl/Cargo.toml
new file mode 100644
index 00000000..a6c1a7da
--- /dev/null
+++ b/utils/ayaka-bindings-impl/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "ayaka-bindings-impl"
+version = "0.1.0"
+authors = ["Berrysoft <Strawberry_Str@hotmail.com>"]
+edition = "2021"
+
+[lib]
+proc-macro = true
+
+[dependencies]
+syn = { version = "1.0", features = ["full"] }
+quote = "1.0"
+proc-macro2 = "1.0"
diff --git a/utils/ayaka-bindings-impl/src/lib.rs b/utils/ayaka-bindings-impl/src/lib.rs
new file mode 100644
index 00000000..d7ad8fcc
--- /dev/null
+++ b/utils/ayaka-bindings-impl/src/lib.rs
@@ -0,0 +1,23 @@
+use proc_macro::TokenStream;
+use quote::quote;
+use syn::{parse_macro_input, parse_str, Ident, ItemFn};
+
+#[proc_macro_attribute]
+pub fn export(_attr: TokenStream, input: TokenStream) -> TokenStream {
+    let func = input.clone();
+    let func = parse_macro_input!(func as ItemFn);
+    let name = func.sig.ident;
+    let name_str = name.to_string();
+    let expname = parse_str::<Ident>(&format!("__{}", name_str)).unwrap();
+    let input = proc_macro2::TokenStream::from(input);
+    let export_func = quote! {
+        #[doc(hidden)]
+        #[allow(unsafe_code)]
+        #[export_name = #name_str]
+        unsafe extern "C" fn #expname(len: usize, data: *const u8) -> u64 {
+            ::ayaka_bindings::__export(len, data, #name)
+        }
+        #input
+    };
+    TokenStream::from(export_func)
+}
diff --git a/utils/ayaka-bindings-types/Cargo.toml b/utils/ayaka-bindings-types/Cargo.toml
new file mode 100644
index 00000000..141581ae
--- /dev/null
+++ b/utils/ayaka-bindings-types/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "ayaka-bindings-types"
+version = "0.1.0"
+authors = ["Berrysoft <Strawberry_Str@hotmail.com>"]
+edition = "2021"
+
+[dependencies]
+ayaka-script-types = { path = "../ayaka-script-types" }
+fallback = "0.1"
+serde = { version = "1.0", features = ["derive"] }
+log = { version = "0.4", features = ["serde"] }
+bitflags = "1.3"
diff --git a/utils/ayaka-bindings-types/src/lib.rs b/utils/ayaka-bindings-types/src/lib.rs
new file mode 100644
index 00000000..432b4550
--- /dev/null
+++ b/utils/ayaka-bindings-types/src/lib.rs
@@ -0,0 +1,400 @@
+//! The types used in both runtime and plugins.
+
+#![warn(missing_docs)]
+#![deny(unsafe_code)]
+
+use ayaka_script_types::{Program, RawValue};
+use fallback::{FallbackSpec, IsEmpty2};
+use serde::{Deserialize, Serialize};
+use std::{
+    borrow::Cow,
+    collections::{HashMap, VecDeque},
+    ops::{Deref, DerefMut},
+    path::{Path, PathBuf},
+};
+
+#[doc(hidden)]
+#[derive(Serialize, Deserialize)]
+pub struct Record {
+    pub level: log::Level,
+    pub target: String,
+    pub msg: String,
+    pub module_path: Option<String>,
+    pub file: Option<String>,
+    pub line: Option<u32>,
+}
+
+impl From<&log::Record<'_>> for Record {
+    fn from(r: &log::Record) -> Self {
+        Self {
+            level: r.level(),
+            target: r.target().to_string(),
+            msg: r.args().to_string(),
+            module_path: r.module_path().map(|s| s.to_string()),
+            file: r.file().map(|s| s.to_string()),
+            line: r.line(),
+        }
+    }
+}
+
+/// The bit flags to describe plugin type.
+///
+/// Every plugin should provide a function `plugin_type`,
+/// which returns [`PluginType`].
+///
+/// ```ignore
+/// use ayaka_bindings::*;
+///
+/// #[export]
+/// fn plugin_type() -> PluginType {
+///     PluginType::default()
+/// }
+/// ```
+#[derive(Debug, Default, Clone, Serialize, Deserialize)]
+pub struct PluginType {
+    /// The action plugin.
+    /// This plugin processes the action after they are parsed.
+    pub action: bool,
+    /// The text plugin.
+    /// The custom text commands are dealt with this type of plugin.
+    pub text: Vec<String>,
+    /// The game plugin.
+    /// This plugin processes the game properties after it is loaded.
+    pub game: bool,
+}
+
+impl PluginType {
+    /// Creates a [`PluginTypeBuilder`] instance to build a [`PluginType`].
+    pub fn builder() -> PluginTypeBuilder {
+        PluginTypeBuilder {
+            data: Self::default(),
+        }
+    }
+}
+
+/// The builder of [`PluginType`].
+pub struct PluginTypeBuilder {
+    data: PluginType,
+}
+
+impl PluginTypeBuilder {
+    /// An action plugin.
+    pub fn action(mut self) -> Self {
+        self.data.action = true;
+        self
+    }
+
+    /// A text plugin, which provides commands.
+    pub fn text(mut self, cmds: impl IntoIterator<Item = impl Into<String>>) -> Self {
+        self.data.text = cmds.into_iter().map(|s| s.into()).collect();
+        self
+    }
+
+    /// A game plugin.
+    pub fn game(mut self) -> Self {
+        self.data.game = true;
+        self
+    }
+
+    /// Build a [`PluginType`].
+    pub fn build(self) -> PluginType {
+        self.data
+    }
+}
+
+/// The type of current frontend.
+#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
+pub enum FrontendType {
+    /// The frontend only accepts raw texts.
+    Text,
+    /// The frontend renders HTML.
+    Html,
+}
+
+/// The unit of one line in an action.
+///
+/// If a frontend supports animation,
+/// the characters in [`ActionLine::Chars`] should be printed one by one,
+/// while the characters in [`ActionLine::Block`] should be printed together.
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[serde(tag = "type", content = "data")]
+pub enum ActionLine {
+    /// Characters printed one by one.
+    /// Usually they are meaningful texts.
+    Chars(String),
+    /// Characters printed together.
+    /// Usually they are HTML tags or other control characters.
+    Block(String),
+}
+
+impl ActionLine {
+    /// Creates [`ActionLine::Chars`].
+    pub fn chars(s: impl Into<String>) -> Self {
+        Self::Chars(s.into())
+    }
+
+    /// Creates [`ActionLine::Block`].
+    pub fn block(s: impl Into<String>) -> Self {
+        Self::Block(s.into())
+    }
+
+    /// Gets a reference of [`str`].
+    pub fn as_str(&self) -> &str {
+        match self {
+            Self::Chars(s) | Self::Block(s) => s,
+        }
+    }
+
+    /// Gets the inner [`String`].
+    pub fn into_string(self) -> String {
+        match self {
+            Self::Chars(s) | Self::Block(s) => s,
+        }
+    }
+}
+
+/// A collection of [`ActionLine`].
+///
+/// Internally it is a [`VecDeque<ActionLine>`].
+/// The [`ActionLine`] could be pushed and poped at front or back.
+///
+/// Generally, you should avoid using `push_back` directly.
+/// To reduce allocations in serialization, you should use
+/// `push_back_chars` and `push_back_block`.
+///
+/// ```
+/// # use ayaka_bindings_types::*;
+/// let mut lines = ActionLines::default();
+/// lines.push_back_chars("Hello ");
+/// assert_eq!(lines[0], ActionLine::chars("Hello "));
+/// lines.push_back_chars("world!");
+/// assert_eq!(lines[0], ActionLine::chars("Hello world!"));
+/// ```
+#[derive(Debug, Default, Clone, Serialize, Deserialize)]
+#[serde(transparent)]
+pub struct ActionLines(VecDeque<ActionLine>);
+
+impl Deref for ActionLines {
+    type Target = VecDeque<ActionLine>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl DerefMut for ActionLines {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.0
+    }
+}
+
+impl IntoIterator for ActionLines {
+    type Item = ActionLine;
+
+    type IntoIter = <VecDeque<ActionLine> as IntoIterator>::IntoIter;
+
+    fn into_iter(self) -> Self::IntoIter {
+        self.0.into_iter()
+    }
+}
+
+impl ActionLines {
+    /// Push the string as [`ActionLine::Chars`] to the back.
+    /// If the back element is also [`ActionLine::Chars`], the string is appended.
+    pub fn push_back_chars<'a>(&mut self, s: impl Into<Cow<'a, str>>) {
+        let s = s.into();
+        if let Some(ActionLine::Chars(text)) = self.back_mut() {
+            text.push_str(&s);
+        } else {
+            self.push_back(ActionLine::chars(s));
+        }
+    }
+
+    /// Push the string as [`ActionLine::Block`] to the back.
+    /// If the back element is also [`ActionLine::Block`], the string is appended.
+    pub fn push_back_block<'a>(&mut self, s: impl Into<Cow<'a, str>>) {
+        let s = s.into();
+        if let Some(ActionLine::Block(text)) = self.back_mut() {
+            text.push_str(&s);
+        } else {
+            self.push_back(ActionLine::block(s));
+        }
+    }
+}
+
+impl IsEmpty2 for ActionLines {
+    fn is_empty2(&self) -> bool {
+        self.0.is_empty()
+    }
+}
+
+/// A map from variable name to [`RawValue`].
+pub type VarMap = HashMap<String, RawValue>;
+
+/// The serializable context.
+#[derive(Debug, Default, Clone, Deserialize, Serialize)]
+pub struct RawContext {
+    /// Current paragraph tag.
+    pub cur_para: String,
+    /// Current text index.
+    pub cur_act: usize,
+    /// Current local variables.
+    pub locals: VarMap,
+}
+
+/// The full action information in one line of config.
+/// It provides the full texts and other properties exacted from [`ayaka_script::Text`].
+#[derive(Debug, Default, Clone, Serialize, Deserialize, FallbackSpec)]
+pub struct Action {
+    /// The context snapshot.
+    pub ctx: RawContext,
+    /// The full texts.
+    pub line: ActionLines,
+    #[doc(hidden)]
+    pub line_params: Vec<RawValue>,
+    /// The key of current character.
+    pub ch_key: Option<String>,
+    /// The current character.
+    pub character: Option<String>,
+    /// The title of current paragraph.
+    pub para_title: Option<String>,
+    /// The switches.
+    pub switches: Vec<Switch>,
+    /// The other custom properties.
+    pub props: HashMap<String, String>,
+}
+
+/// One switch in the switches of an [`Action`].
+#[derive(Debug, Default, Clone, Serialize, Deserialize, FallbackSpec)]
+pub struct Switch {
+    /// The switch text.
+    pub text: String,
+    /// The action of this switch after chosen.
+    pub action: Program,
+    /// Whether the switch is enabled.
+    pub enabled: bool,
+}
+
+/// The argument to action plugin.
+///
+/// Every action plugin should implement `process_action`:
+/// ```ignore
+/// use ayaka_bindings::*;
+///
+/// #[export]
+/// fn process_action(mut ctx: ActionProcessContext) -> Action {
+///     // Process the action...
+///     ctx.action
+/// }
+/// ```
+#[derive(Debug, Serialize, Deserialize)]
+pub struct ActionProcessContext {
+    /// The root path of the game profile.
+    pub root_path: PathBuf,
+    /// The global properties of the game profile.
+    pub game_props: HashMap<String, String>,
+    /// The frontend type.
+    pub frontend: FrontendType,
+    /// The previous action in the history.
+    /// It is used if some properties need to inherit.
+    pub last_action: Option<Action>,
+    /// The current action.
+    pub action: Action,
+}
+
+#[derive(Debug, Serialize)]
+#[doc(hidden)]
+pub struct ActionProcessContextRef<'a> {
+    pub root_path: &'a Path,
+    pub game_props: &'a HashMap<String, String>,
+    pub frontend: FrontendType,
+    pub last_action: Option<&'a Action>,
+    pub action: &'a Action,
+}
+
+/// The argument to text plugin.
+///
+/// Every text plugin should implement `text_commands` and the specified function:
+/// ```ignore
+/// use ayaka_bindings::*;
+///
+/// #[export]
+/// fn text_commands() -> &'static [&'static str] {
+///     &["hello"]
+/// }
+///
+/// #[export]
+/// fn hello(_args: Vec<String>, _ctx: TextProcessContext) -> TextProcessResult {
+///     let mut res = TextProcessResult::default();
+///     res.line.push_back_chars("hello");
+///     res
+/// }
+/// ```
+#[derive(Debug, Serialize, Deserialize)]
+pub struct TextProcessContext {
+    /// The root path of the game profile.
+    pub root_path: PathBuf,
+    /// The global properties of the game profile.
+    pub game_props: HashMap<String, String>,
+    /// The frontend type.
+    pub frontend: FrontendType,
+}
+
+#[derive(Debug, Serialize)]
+#[doc(hidden)]
+pub struct TextProcessContextRef<'a> {
+    pub root_path: &'a Path,
+    pub game_props: &'a HashMap<String, String>,
+    pub frontend: FrontendType,
+}
+
+/// The result of commands in text plugins.
+/// See examples at [`TextProcessContext`].
+#[derive(Debug, Default, Serialize, Deserialize)]
+pub struct TextProcessResult {
+    /// The lines to append.
+    pub line: ActionLines,
+    /// The custom properties to update.
+    pub props: HashMap<String, String>,
+}
+
+/// The argument to game plugin.
+///
+/// Every game plugin should implement `process_game`:
+/// ```ignore
+/// use ayaka_bindings::*;
+///
+/// #[export]
+/// fn process_game(mut ctx: GameProcessContext) -> GameProcessResult {
+///     // Process the game...
+///     GameProcessResult { props: ctx.props }
+/// }
+/// ```
+#[derive(Debug, Serialize, Deserialize)]
+pub struct GameProcessContext {
+    /// The title of the game.
+    pub title: String,
+    /// The author of the game.
+    pub author: String,
+    /// The root path of the game profile.
+    pub root_path: PathBuf,
+    /// The global properties of the game.
+    pub props: HashMap<String, String>,
+}
+
+#[derive(Debug, Serialize)]
+#[doc(hidden)]
+pub struct GameProcessContextRef<'a> {
+    pub title: &'a str,
+    pub author: &'a str,
+    pub root_path: &'a Path,
+    pub props: &'a HashMap<String, String>,
+}
+
+/// The result of game plugins.
+/// See examples at [`GameProcessContext`].
+#[derive(Debug, Serialize, Deserialize)]
+pub struct GameProcessResult {
+    /// The updated properties.
+    pub props: HashMap<String, String>,
+}
diff --git a/utils/ayaka-bindings/Cargo.toml b/utils/ayaka-bindings/Cargo.toml
new file mode 100644
index 00000000..a0ff94a7
--- /dev/null
+++ b/utils/ayaka-bindings/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "ayaka-bindings"
+version = "0.1.0"
+authors = ["Berrysoft <Strawberry_Str@hotmail.com>"]
+edition = "2021"
+
+[dependencies]
+ayaka-script-types = { path = "../ayaka-script-types" }
+ayaka-bindings-types = { path = "../ayaka-bindings-types" }
+ayaka-bindings-impl = { path = "../ayaka-bindings-impl" }
+serde = "1.0"
+rmp-serde = "1.1"
+log = "0.4"
diff --git a/utils/ayaka-bindings/src/lib.rs b/utils/ayaka-bindings/src/lib.rs
new file mode 100644
index 00000000..efd22626
--- /dev/null
+++ b/utils/ayaka-bindings/src/lib.rs
@@ -0,0 +1,62 @@
+#![feature(fn_traits)]
+#![feature(unboxed_closures)]
+
+#[doc(no_inline)]
+pub use ayaka_bindings_types::*;
+#[doc(no_inline)]
+pub use ayaka_script_types::{RawValue, ValueType};
+#[doc(no_inline)]
+pub use log;
+
+mod logger;
+
+use serde::{de::DeserializeOwned, Serialize};
+use std::alloc::{self, Layout};
+
+const ABI_ALIGN: usize = 8;
+
+#[no_mangle]
+unsafe extern "C" fn __abi_alloc(len: usize) -> *mut u8 {
+    if len == 0 {
+        return ABI_ALIGN as *mut u8;
+    }
+    let layout = Layout::from_size_align_unchecked(len, ABI_ALIGN);
+    let ptr = alloc::alloc(layout);
+    if ptr.is_null() {
+        alloc::handle_alloc_error(layout);
+    }
+    return ptr;
+}
+
+#[no_mangle]
+unsafe extern "C" fn __abi_free(ptr: *mut u8, len: usize) {
+    if len == 0 {
+        return;
+    }
+    let layout = Layout::from_size_align_unchecked(len, ABI_ALIGN);
+    alloc::dealloc(ptr, layout);
+}
+
+unsafe fn __abi_alloc_from(data: &[u8]) -> (*mut u8, usize) {
+    let ptr = __abi_alloc(data.len());
+    let slice = std::slice::from_raw_parts_mut(ptr, data.len());
+    slice.copy_from_slice(data);
+    (slice.as_mut_ptr(), slice.len())
+}
+
+#[doc(hidden)]
+pub unsafe fn __export<Params: DeserializeOwned, Res: Serialize>(
+    len: usize,
+    data: *const u8,
+    f: impl FnOnce<Params, Output = Res>,
+) -> u64 {
+    logger::PluginLogger::init();
+    let data = std::slice::from_raw_parts(data, len);
+    let data = rmp_serde::from_slice(data).unwrap();
+    let res = f.call_once(data);
+    let data = rmp_serde::to_vec(&res).unwrap();
+    let (ptr, len) = __abi_alloc_from(&data);
+    ((len as u64) << 32) | (ptr as u64)
+}
+
+pub use ayaka_bindings_impl::export;
diff --git a/utils/ayaka-bindings/src/logger.rs b/utils/ayaka-bindings/src/logger.rs
new file mode 100644
index 00000000..5442d421
--- /dev/null
+++ b/utils/ayaka-bindings/src/logger.rs
@@ -0,0 +1,47 @@
+use log::Log;
+
+#[cfg(target_arch = "wasm32")]
+#[link(wasm_import_module = "log")]
+extern "C" {
+    fn __log(len: usize, data: *const u8);
+    fn __log_flush();
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+unsafe fn __log(_len: usize, _data: *const u8) {}
+
+#[cfg(not(target_arch = "wasm32"))]
+unsafe fn __log_flush() {}
+
+pub struct PluginLogger;
+
+impl PluginLogger {
+    pub fn init() {
+        use std::sync::Once;
+        static INIT: Once = Once::new();
+
+        INIT.call_once(|| {
+            let r = log::set_logger(&PluginLogger);
+            if r.is_ok() {
+                log::set_max_level(log::LevelFilter::Trace);
+            }
+            r.unwrap();
+        });
+    }
+}
+
+impl Log for PluginLogger {
+    fn enabled(&self, _metadata: &log::Metadata) -> bool {
+        true
+    }
+
+    fn log(&self, record: &log::Record) {
+        let record: ayaka_bindings_types::Record = record.into();
+        let data = rmp_serde::to_vec(&record).unwrap();
+        unsafe { __log(data.len(), data.as_ptr()) }
+    }
+
+    fn flush(&self) {
+        unsafe { __log_flush() }
+    }
+}
diff --git a/utils/ayaka-runtime/Cargo.toml b/utils/ayaka-runtime/Cargo.toml
new file mode 100644
index 00000000..e26394de
--- /dev/null
+++ b/utils/ayaka-runtime/Cargo.toml
@@ -0,0 +1,31 @@
+[package]
+name = "ayaka-runtime"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+ayaka-bindings-types = { path = "../ayaka-bindings-types" }
+ayaka-script-types = { path = "../ayaka-script-types", features = ["rt-format"] }
+ayaka-script = { path = "../ayaka-script" }
+fallback = "0.1"
+language-matcher = "0.1"
+icu_locid = { version = "1.0.0-beta1", features = ["std"] }
+sys-locale = "0.2"
+serde = { version = "1.0", features = ["derive"] }
+serde_yaml = "0.9"
+serde_json = "1.0"
+rmp-serde = "1.1"
+anyhow = "1.0"
+wasmer = "2.3"
+wasmer-wasi = "2.3"
+unicode-width = "0.1"
+rt-format = "0.3"
+tokio = { version = "1", features = ["fs", "macros"] }
+tokio-stream = { version = "0.1", features = ["fs"] }
+stream-future = "0.3"
+futures-util = "0.3"
+dirs = "4.0"
+scopeguard = "1.1"
+
+[dev-dependencies]
+tokio = { version = "1", features = ["parking_lot", "rt"] }
diff --git a/utils/ayaka-runtime/src/config.rs b/utils/ayaka-runtime/src/config.rs
new file mode 100644
index 00000000..6fceae39
--- /dev/null
+++ b/utils/ayaka-runtime/src/config.rs
@@ -0,0 +1,110 @@
+#[doc(no_inline)]
+pub use ayaka_bindings_types::{Action, Switch};
+#[doc(no_inline)]
+pub use fallback::Fallback;
+
+use crate::*;
+use serde::Deserialize;
+use std::{collections::HashMap, path::PathBuf};
+
+/// The paragraph in a game config.
+#[derive(Debug, Deserialize)]
+pub struct Paragraph {
+    /// The tag and key of a paragraph.
+    /// They are referenced in `next`.
+    pub tag: String,
+    /// The title of a paragraph.
+    /// It can be [`None`], but better with a human-readable one.
+    pub title: Option<String>,
+    /// The texts.
+    /// They will be parsed into [`ayaka_script::Text`] later.
+    pub texts: Vec<String>,
+    /// The next paragraph.
+    /// If [`None`], the game meets the end.
+    pub next: Option<String>,
+}
+
+/// The ayaka-game config.
+/// It should be deserialized from a YAML file.
+#[derive(Debug, Default, Deserialize)]
+pub struct Game {
+    /// The title of the game.
+    pub title: String,
+    /// The author of the game.
+    #[serde(default)]
+    pub author: String,
+    /// The paragraphs, indexed by locale.
+    pub paras: HashMap<Locale, Vec<Paragraph>>,
+    /// The plugin config.
+    #[serde(default)]
+    pub plugins: PluginConfig,
+    /// The global game properties.
+    #[serde(default)]
+    pub props: HashMap<String, String>,
+    /// The resources, indexed by locale.
+    #[serde(default)]
+    pub res: HashMap<Locale, VarMap>,
+    /// The base language.
+    /// If the runtime fails to choose a best match,
+    /// it fallbacks to this one.
+    pub base_lang: Locale,
+}
+
+/// The plugin config.
+#[derive(Debug, Default, Deserialize)]
+pub struct PluginConfig {
+    /// The directory of the plugins.
+    pub dir: PathBuf,
+    /// The names of the plugins, without extension.
+    #[serde(default)]
+    pub modules: Vec<String>,
+}
+
+impl Game {
+    fn choose_from_keys<'a, V>(&'a self, loc: &Locale, map: &'a HashMap<Locale, V>) -> &'a Locale {
+        loc.choose_from(map.keys()).unwrap_or(&self.base_lang)
+    }
+
+    fn find_para(&self, loc: &Locale, tag: &str) -> Option<&Paragraph> {
+        if let Some(paras) = self.paras.get(loc) {
+            for p in paras {
+                if p.tag == tag {
+                    return Some(p);
+                }
+            }
+        }
+        None
+    }
+
+    /// Find a paragraph by tag, with specified locale.
+    pub fn find_para_fallback(&self, loc: &Locale, tag: &str) -> Fallback<&Paragraph> {
+        let key = self.choose_from_keys(loc, &self.paras);
+        let base_key = self.choose_from_keys(&self.base_lang, &self.paras);
+        Fallback::new(
+            if key == base_key {
+                None
+            } else {
+                self.find_para(key, tag)
+            },
+            self.find_para(base_key, tag),
+        )
+    }
+
+    fn find_res(&self, loc: &Locale) -> Option<&VarMap> {
+        self.res.get(loc)
+    }
+
+    /// Find the resource map with specified locale.
+    pub fn find_res_fallback(&self, loc: &Locale) -> Fallback<&VarMap> {
+        let key = self.choose_from_keys(loc, &self.res);
+        let base_key = self.choose_from_keys(&self.base_lang, &self.res);
+        Fallback::new(
+            if key == base_key {
+                None
+            } else {
+                self.find_res(key)
+            },
+            self.find_res(base_key),
+        )
+    }
+}
diff --git a/utils/ayaka-runtime/src/context.rs b/utils/ayaka-runtime/src/context.rs
new file mode 100644
index 00000000..8592b78a
--- /dev/null
+++ b/utils/ayaka-runtime/src/context.rs
@@ -0,0 +1,489 @@
+#[doc(no_inline)]
+pub use ayaka_bindings_types::{FrontendType, RawContext};
+
+use crate::{
+    plugin::{LoadStatus, Runtime},
+    *,
+};
+use anyhow::{anyhow, bail, Result};
+use ayaka_bindings_types::{
+    ActionLine, ActionLines, ActionProcessContextRef, GameProcessContextRef, TextProcessContextRef,
+};
+use ayaka_script::{Loc, ParseError, TextParser};
+use ayaka_script_types::{Command, Line, Program, Text};
+use log::error;
+use script::*;
+use std::{
+    collections::HashMap,
+    path::{Path, PathBuf},
+};
+use stream_future::stream;
+use unicode_width::UnicodeWidthStr;
+
+/// The game running context.
+pub struct Context {
+    /// The inner [`Game`] object.
+    pub game: Game,
+    frontend: FrontendType,
+    root_path: PathBuf,
+    runtime: Runtime,
+    settings: Settings,
+    global_record: GlobalRecord,
+    /// The inner raw context.
+    pub ctx: RawContext,
+    /// The inner record.
+    pub record: ActionRecord,
+}
+
+/// The open status when creating [`Context`].
+#[derive(Debug, Clone)]
+pub enum OpenStatus {
+    /// Start loading config file.
+    LoadProfile,
+    /// Start creating plugin runtime.
+    CreateRuntime,
+    /// Loading the plugin.
+    LoadPlugin(String, usize, usize),
+}
+
+impl Context {
+    /// Open a config file with frontend type.
+    #[stream(OpenStatus, lifetime = "'a")]
+    pub async fn open<'a>(path: impl AsRef<Path> + 'a, frontend: FrontendType) -> Result<Self> {
+        yield OpenStatus::LoadProfile;
+        let file = tokio::fs::read(&path).await?;
+        let mut game: Game = serde_yaml::from_slice(&file)?;
+        let root_path = path
+            .as_ref()
+            .parent()
+            .ok_or_else(|| anyhow!("Cannot get parent from input path."))?;
+        let root_path = std::path::absolute(root_path)?;
+        let runtime = {
+            let runtime = Runtime::load(&game.plugins.dir, &root_path, &game.plugins.modules);
+            pin_mut!(runtime);
+            while let Some(load_status) = runtime.next().await {
+                match load_status {
+                    LoadStatus::CreateEngine => yield OpenStatus::CreateRuntime,
+                    LoadStatus::LoadPlugin(name, i, len) => {
+                        yield OpenStatus::LoadPlugin(name, i, len)
+                    }
+                };
+            }
+            runtime.await?
+        };
+        for m in &runtime.game_modules {
+            let module = &runtime.modules[m];
+            let ctx = GameProcessContextRef {
+                title: &game.title,
+                author: &game.author,
+                root_path: &root_path,
+                props: &game.props,
+            };
+            let res = module.process_game(ctx)?;
+            for (key, value) in res.props {
+                game.props.insert(key, value);
+            }
+        }
+        Ok(Self {
+            game,
+            frontend,
+            root_path,
+            runtime,
+            settings: Settings::new(),
+            global_record: GlobalRecord::default(),
+            ctx: RawContext::default(),
+            record: ActionRecord::default(),
+        })
+    }
+
+    /// Initialize the [`RawContext`] to the start of the game.
+    pub fn init_new(&mut self) {
+        self.init_context(ActionRecord { history: vec![] })
+    }
+
+    /// Initialize the [`ActionRecord`] with given record.
+    pub fn init_context(&mut self, record: ActionRecord) {
+        self.ctx = record.last_ctx_with_game(&self.game);
+        self.record = record;
+        if !self.record.history.is_empty() {
+            // If the record is not empty,
+            // we need to set current context to the next one.
+            self.ctx.cur_act += 1;
+        }
+    }
+
+    fn table(&mut self) -> VarTable {
+        VarTable::new(
+            &self.runtime,
+            self.game.find_res_fallback(self.locale()),
+            &mut self.ctx.locals,
+        )
+    }
+
+    fn current_paragraph(&self) -> Fallback<&Paragraph> {
+        self.game
+            .find_para_fallback(self.locale(), &self.ctx.cur_para)
+    }
+
+    fn current_text(&self) -> Fallback<&String> {
+        self.current_paragraph()
+            .map(|p| {
+                p.texts.get(self.ctx.cur_act).and_then(|s| {
+                    if s.is_empty() || s == "~" {
+                        None
+                    } else {
+                        Some(s)
+                    }
+                })
+            })
+            .flatten()
+    }
+
+    /// Set the current locale.
+    pub fn set_locale(&mut self, loc: impl Into<Locale>) {
+        self.settings.lang = loc.into();
+    }
+
+    /// Get the current locale.
+    pub fn locale(&self) -> &Locale {
+        &self.settings.lang
+    }
+
+    /// Set all settings.
+    pub fn set_settings(&mut self, s: Settings) {
+        self.settings = s;
+    }
+
+    /// Get all settings.
+    pub fn settings(&self) -> &Settings {
+        &self.settings
+    }
+
+    /// Set global record.
+    pub fn set_global_record(&mut self, r: GlobalRecord) {
+        self.global_record = r;
+    }
+
+    /// Get global record.
+    pub fn global_record(&self) -> &GlobalRecord {
+        &self.global_record
+    }
+
+    /// Determine if an [`Action`] has been visited,
+    /// by the paragraph tag and action index.
+    pub fn visited(&self, action: &Action) -> bool {
+        if let Some(max_act) = self.global_record.record.get(&action.ctx.cur_para) {
+            log::debug!("Test act: {}, max act: {}", action.ctx.cur_act, max_act);
+            *max_act >= action.ctx.cur_act
+        } else {
+            false
+        }
+    }
+
+    /// Call the part of script with this context.
+    pub fn call(&mut self, expr: &impl Callable) -> RawValue {
+        self.table().call(expr)
+    }
+
+    fn rich_error(&self, text: &str, e: &ParseError) -> String {
+        use std::iter::repeat;
+        const FREE_LEN: usize = 20;
+
+        let loc = e.loc();
+        let loc = Loc(
+            text.floor_char_boundary(loc.0),
+            text.ceil_char_boundary(loc.1),
+        );
+        let pre = text.floor_char_boundary(loc.0 - loc.0.min(FREE_LEN));
+        let post = text.ceil_char_boundary(loc.1 + (text.len() - loc.1).min(FREE_LEN));
+
+        let para_name = self
+            .current_paragraph()
+            .and_then(|p| p.title.as_ref())
+            .map(|s| s.escape_default().to_string())
+            .unwrap_or_default();
+        let act_num = self.ctx.cur_act + 1;
+        let show_code = &text[pre..post];
+        let pre_code = &text[pre..loc.0];
+        let error_code = &text[loc.0..loc.1];
+        format!(
+            "Parse error on paragraph \"{para_name}\", act {act_num}:\n    {show_code}\n    {}\n{e}\n",
+            repeat(' ')
+                .take(UnicodeWidthStr::width_cjk(pre_code))
+                .chain(repeat('^').take(UnicodeWidthStr::width_cjk(error_code)))
+                .collect::<String>(),
+        )
+    }
+
+    fn exact_text(&mut self, para_title: Option<String>, t: Text) -> Result<Action> {
+        let mut action_line = ActionLines::default();
+        let mut action_line_params = vec![];
+        let mut chkey = None;
+        let mut chname = None;
+        let mut switches = vec![];
+        let mut props = HashMap::new();
+        for line in t.0.into_iter() {
+            match line {
+                Line::Str(s) => action_line.push_back_chars(s),
+                Line::Cmd(cmd) => match cmd {
+                    Command::Character(key, alter) => {
+                        // TODO: reduce allocation
+                        chkey = Some(key.clone());
+                        chname = if alter.is_empty() {
+                            let res_key = format!("ch_{}", key);
+                            self.game
+                                .find_res_fallback(self.locale())
+                                .and_then(|map| map.get(&res_key))
+                                .map(|v| v.get_str().into_owned())
+                        } else {
+                            Some(alter)
+                        }
+                    }
+                    Command::Exec(p) => {
+                        let param = self.call(&p);
+                        action_line.push_back_chars(format!("{{{}}}", action_line_params.len()));
+                        action_line_params.push(param);
+                    }
+                    Command::Switch {
+                        text,
+                        action,
+                        enabled,
+                    } => {
+                        // unwrap: when enabled is None, it means true.
+                        let enabled = enabled.map(|p| self.call(&p).get_bool()).unwrap_or(true);
+                        switches.push(Switch {
+                            text,
+                            action,
+                            enabled,
+                        });
+                    }
+                    Command::Other(name, args) => {
+                        if let Some(m) = self.runtime.text_modules.get(&name) {
+                            let game_context = TextProcessContextRef {
+                                root_path: &self.root_path,
+                                game_props: &self.game.props,
+                                frontend: self.frontend,
+                            };
+                            let mut res = self.runtime.modules.get(m).unwrap().dispatch_command(
+                                &name,
+                                &args,
+                                game_context,
+                            )?;
+                            action_line.append(&mut res.line);
+                            for (key, value) in res.props.into_iter() {
+                                props.insert(key, value);
+                            }
+                        } else {
+                            bail!("Invalid command {}", name);
+                        }
+                    }
+                },
+            }
+        }
+        Ok(Action {
+            ctx: self.ctx.clone(),
+            line: action_line,
+            line_params: action_line_params,
+            ch_key: chkey,
+            character: chname,
+            para_title,
+            switches,
+            props,
+        })
+    }
+
+    fn merge_action(&self, actions: Fallback<Action>) -> Option<Action> {
+        if actions.is_some() {
+            let actions = actions.spec();
+
+            let ctx = actions.ctx.fallback().unwrap_or_default();
+            let line = actions.line.and_any().unwrap_or_default();
+            let line_params = actions.line_params.and_any().unwrap_or_default();
+            let ch_key = actions.ch_key.flatten().and_any();
+            let character = actions.character.flatten().and_any();
+            let para_title = actions.para_title.flatten().and_any();
+            let switches = actions
+                .switches
+                .into_iter()
+                .map(|s| {
+                    let s = s.spec();
+                    let text = s.text.and_any().unwrap_or_default();
+                    let action = s
+                        .action
+                        .map(|p| p.0)
+                        .and_any()
+                        .map(Program)
+                        .unwrap_or_default();
+                    let (enabled, base_enabled) = s.enabled.unzip();
+                    let enabled = base_enabled.or(enabled).unwrap_or(true);
+                    Switch {
+                        text,
+                        action,
+                        enabled,
+                    }
+                })
+                .collect();
+            let (props, base_props) = actions.props.unzip();
+            let (mut props, base_props) =
+                (props.unwrap_or_default(), base_props.unwrap_or_default());
+            for (key, value) in base_props.into_iter() {
+                props.entry(key).or_insert(value);
+            }
+            Some(Action {
+                ctx,
+                line,
+                line_params,
+                ch_key,
+                character,
+                para_title,
+                switches,
+                props,
+            })
+        } else {
+            None
+        }
+    }
+
+    fn process_action(&mut self, mut action: Action) -> Result<Action> {
+        {
+            let params = std::mem::take(&mut action.line_params);
+            let named = HashMap::<String, RawValue>::new();
+            for line in action.line.iter_mut() {
+                match line {
+                    ActionLine::Chars(s) | ActionLine::Block(s) => {
+                        *s = rt_format::ParsedFormat::parse(s, &params, &named)
+                            .map_err(|id| anyhow!("Format error at {}", id))?
+                            .to_string();
+                    }
+                }
+            }
+        }
+        let last_action = self.record.history.last();
+        for action_module in &self.runtime.action_modules {
+            let module = &self.runtime.modules[action_module];
+            let ctx = ActionProcessContextRef {
+                root_path: &self.root_path,
+                game_props: &self.game.props,
+                frontend: self.frontend,
+                last_action,
+                action: &action,
+            };
+            action = module.process_action(ctx)?;
+        }
+        while let Some(act) = action.line.back() {
+            if act.as_str().trim().is_empty() {
+                action.line.pop_back();
+            } else {
+                break;
+            }
+        }
+        while let Some(act) = action.line.front() {
+            if act.as_str().trim().is_empty() {
+                action.line.pop_front();
+            } else {
+                break;
+            }
+        }
+        if !action.line.is_empty() || action.character.is_some() {
+            self.record.history.push(action.clone());
+        }
+        Ok(action)
+    }
+
+    fn parse_text_rich_error(&self, text: &str) -> Text {
+        match TextParser::new(text).parse() {
+            Ok(t) => t,
+            Err(e) => {
+                error!("{}", self.rich_error(text, &e));
+                Text::default()
+            }
+        }
+    }
+
+    fn check_text_rich_error(&self, text: &str) -> bool {
+        if let Err(e) = TextParser::new(text).parse() {
+            eprintln!("{}", self.rich_error(text, &e));
+            false
+        } else {
+            true
+        }
+    }
+
+    /// Step to next line.
+    pub fn next_run(&mut self) -> Option<Action> {
+        if let Some(action) = self.record.history.last() {
+            self.global_record
+                .record
+                .entry(action.ctx.cur_para.clone())
+                .and_modify(|act| *act = (*act).max(action.ctx.cur_act))
+                .or_insert(action.ctx.cur_act);
+        }
+        let cur_para = self.current_paragraph();
+        if cur_para.is_some() {
+            let cur_text = self.current_text();
+            if cur_text.is_some() {
+                let text = cur_text.map(|act| self.parse_text_rich_error(act));
+                let para_title = cur_para.and_then(|p| p.title.as_ref()).cloned();
+                let actions = text.map(|t| {
+                    self.exact_text(para_title.clone(), t).unwrap_or_else(|e| {
+                        error!("Exact text error: {}", e);
+                        Action::default()
+                    })
+                });
+                let res = self.merge_action(actions).map(|act| {
+                    self.process_action(act).unwrap_or_else(|e| {
+                        error!("Error when processing action: {}", e);
+                        Action::default()
+                    })
+                });
+                self.ctx.cur_act += 1;
+                res
+            } else {
+                self.ctx.cur_para = cur_para
+                    .and_then(|p| p.next.as_ref())
+                    .map(|next| self.parse_text_rich_error(next))
+                    .map(|text| self.call(&text).into_str())
+                    .unwrap_or_default();
+                self.ctx.cur_act = 0;
+                self.next_run()
+            }
+        } else {
+            None
+        }
+    }
+
+    /// Step back to the last run.
+    pub fn next_back_run(&mut self) -> Option<Action> {
+        if self.record.history.len() <= 1 {
+            None
+        } else {
+            if let Some(last_action) = self.record.history.pop() {
+                self.ctx = last_action.ctx;
+                log::debug!(
+                    "Back to para {}, act {}",
+                    self.ctx.cur_para,
+                    self.ctx.cur_act
+                );
+            }
+            self.record.history.last().cloned()
+        }
+    }
+
+    /// Check all paragraphs to find grammer errors.
+    pub fn check(&mut self) -> bool {
+        let mut succeed = true;
+        for paras in self.game.paras.values() {
+            for para in paras {
+                self.ctx.cur_para = para.tag.clone();
+                for (index, act) in para.texts.iter().enumerate() {
+                    self.ctx.cur_act = index;
+                    succeed &= self.check_text_rich_error(act);
+                }
+                if let Some(next) = &para.next {
+                    succeed &= self.check_text_rich_error(next);
+                }
+            }
+        }
+        succeed
+    }
+}
diff --git a/utils/ayaka-runtime/src/lib.rs b/utils/ayaka-runtime/src/lib.rs
new file mode 100644
index 00000000..01e59cba
--- /dev/null
+++ b/utils/ayaka-runtime/src/lib.rs
@@ -0,0 +1,39 @@
+//! The runtime of Ayaka project.
+//!
+//! This runtime provides the game config, running context,
+//! plugin system and settings system.
+//! It can be treated as the "backend" of the game engine.
+
+#![warn(missing_docs)]
+#![deny(unsafe_code)]
+#![feature(absolute_path)]
+#![feature(generators)]
+#![feature(once_cell)]
+#![feature(round_char_boundary)]
+
+mod config;
+mod context;
+mod locale;
+pub mod plugin;
+pub mod script;
+mod settings;
+
+#[doc(no_inline)]
+pub use anyhow;
+#[doc(no_inline)]
+pub use ayaka_script::log;
+#[doc(no_inline)]
+pub use ayaka_script_types::RawValue;
+pub use config::*;
+pub use context::*;
+#[doc(no_inline)]
+pub use futures_util::{pin_mut, StreamExt, TryStreamExt};
+#[doc(no_inline)]
+pub use locale::*;
+pub use settings::*;
+
+/// Get the version of Ayaka runtime.
+/// This version string is exacted from `CARGO_PKG_VERSION`.
+pub fn version() -> &'static str {
+    env!("CARGO_PKG_VERSION")
+}
diff --git a/utils/ayaka-runtime/src/locale.rs b/utils/ayaka-runtime/src/locale.rs
new file mode 100644
index 00000000..d8427c08
--- /dev/null
+++ b/utils/ayaka-runtime/src/locale.rs
@@ -0,0 +1,121 @@
+use icu_locid::{LanguageIdentifier, ParserError};
+use language_matcher::LanguageMatcher;
+use serde::{Deserialize, Serialize};
+use std::{fmt::Display, str::FromStr, sync::LazyLock};
+use sys_locale::get_locale;
+
+static MATCHER: LazyLock<LanguageMatcher> = LazyLock::new(LanguageMatcher::new);
+
+/// Representation of a language identifier.
+#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[repr(transparent)]
+pub struct Locale(pub LanguageIdentifier);
+
+impl Locale {
+    /// Get the current locale of the system.
+    /// Internally it calles [`sys_locale::get_locale`].
+    ///
+    /// ```
+    /// # use ayaka_runtime::Locale;
+    /// println!("Current locale: {}", Locale::current());
+    /// ```
+    pub fn current() -> Self {
+        get_locale()
+            .and_then(|loc| loc.parse().ok())
+            .unwrap_or_default()
+    }
+
+    /// Choose the best match from the provided locales.
+    ///
+    /// Returns [`None`] if it cannot choose a best match.
+    ///
+    /// ```
+    /// # use ayaka_runtime::locale;
+    /// let current = locale!("zh-CN");
+    /// let accepts = [
+    ///     locale!("en"),
+    ///     locale!("ja"),
+    ///     locale!("zh-Hans"),
+    ///     locale!("zh-Hant"),
+    /// ];
+    /// assert_eq!(
+    ///     current.choose_from(&accepts),
+    ///     Some(&locale!("zh-Hans")),
+    /// );
+    /// ```
+    pub fn choose_from<'a>(
+        &self,
+        locales: impl IntoIterator<Item = impl Into<&'a Locale>>,
+    ) -> Option<&'a Locale> {
+        MATCHER
+            .matches(self.0.clone(), locales.into_iter().map(|loc| loc.into()))
+            .map(|(lang, _)| lang)
+    }
+}
+
+impl Display for Locale {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+impl FromStr for Locale {
+    type Err = ParserError;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        Ok(Self(s.parse()?))
+    }
+}
+
+impl AsRef<LanguageIdentifier> for Locale {
+    fn as_ref(&self) -> &LanguageIdentifier {
+        &self.0
+    }
+}
+
+#[doc(hidden)]
+pub use icu_locid::langid as __icu_langid;
+
+/// A macro allowing for compile-time construction of valid [`Locale`].
+/// See [`icu_locid::langid!`].
+///
+/// ```
+/// # use ayaka_runtime::{locale, Locale};
+/// const ZH_CN: Locale = locale!("zh_CN");
+/// let zh_cn: Locale = "zh_CN".parse().unwrap();
+/// assert_eq!(ZH_CN, zh_cn);
+/// ```
+#[macro_export]
+macro_rules! locale {
+    ($langid:literal) => {
+        $crate::Locale($crate::__icu_langid!($langid))
+    };
+}
+
+#[cfg(test)]
+mod test {
+    use crate::locale;
+
+    #[test]
+    fn parse() {
+        assert_eq!(locale!("zh-Hans").to_string(), "zh-Hans");
+    }
+
+    #[test]
+    fn accept() {
+        let accepts = [
+            locale!("en"),
+            locale!("ja"),
+            locale!("zh-Hans"),
+            locale!("zh-Hant"),
+        ];
+        assert_eq!(
+            locale!("zh-CN").choose_from(&accepts),
+            Some(&locale!("zh-Hans"))
+        );
+        assert_eq!(
+            locale!("zh-TW").choose_from(&accepts),
+            Some(&locale!("zh-Hant"))
+        );
+    }
+}
diff --git a/utils/ayaka-runtime/src/plugin.rs b/utils/ayaka-runtime/src/plugin.rs
new file mode 100644
index 00000000..0bbf5599
--- /dev/null
+++ b/utils/ayaka-runtime/src/plugin.rs
@@ -0,0 +1,265 @@
+//! The plugin utilities.
+
+#![allow(unsafe_code)]
+#![allow(clippy::mut_from_ref)]
+
+use crate::*;
+use anyhow::Result;
+use ayaka_bindings_types::*;
+use futures_util::TryStreamExt;
+use log::warn;
+use scopeguard::defer;
+use serde::{de::DeserializeOwned, Serialize};
+use std::{collections::HashMap, path::Path};
+use stream_future::stream;
+use tokio_stream::wrappers::ReadDirStream;
+use wasmer::*;
+use wasmer_wasi::*;
+
+/// An instance of a WASM plugin module.
+pub struct Host {
+    abi_free: NativeFunc<(i32, i32), ()>,
+    abi_alloc: NativeFunc<i32, i32>,
+    instance: Instance,
+}
+
+unsafe fn mem_slice(memory: &Memory, start: i32, len: i32) -> &[u8] {
+    memory
+        .data_unchecked()
+        .get_unchecked(start as usize..)
+        .get_unchecked(..len as usize)
+}
+
+unsafe fn mem_slice_mut(memory: &Memory, start: i32, len: i32) -> &mut [u8] {
+    memory
+        .data_unchecked_mut()
+        .get_unchecked_mut(start as usize..)
+        .get_unchecked_mut(..len as usize)
+}
+
+impl Host {
+    /// Loads the WASM [`Module`], with some imports.
+    pub fn new(module: &Module, resolver: &(dyn Resolver + Send + Sync)) -> Result<Self> {
+        let instance = Instance::new(module, resolver)?;
+        let abi_free = instance.exports.get_native_function("__abi_free")?;
+        let abi_alloc = instance.exports.get_native_function("__abi_alloc")?;
+        Ok(Self {
+            abi_free,
+            abi_alloc,
+            instance,
+        })
+    }
+
+    /// Calls a method by name.
+    ///
+    /// The args and returns are passed by MessagePack with [`rmp_serde`].
+    pub fn call<Params: Serialize, Res: DeserializeOwned>(
+        &self,
+        name: &str,
+        args: Params,
+    ) -> Result<Res> {
+        let memory = self.instance.exports.get_memory("memory")?;
+        let func = self
+            .instance
+            .exports
+            .get_native_function::<(i32, i32), u64>(name)?;
+
+        let data = rmp_serde::to_vec(&args)?;
+
+        let ptr = self.abi_alloc.call(data.len() as i32)?;
+        defer! { self.abi_free.call(ptr, data.len() as i32).unwrap(); }
+        unsafe { mem_slice_mut(memory, ptr, data.len() as i32) }.copy_from_slice(&data);
+
+        let res = func.call(data.len() as i32, ptr)?;
+        let (len, res) = ((res >> 32) as i32, (res & 0xFFFFFFFF) as i32);
+        defer! { self.abi_free.call(res, len).unwrap(); }
+
+        let res_data = unsafe { mem_slice(memory, res, len) };
+        let res_data = rmp_serde::from_slice(res_data)?;
+        Ok(res_data)
+    }
+
+    /// Calls a script plugin method by name.
+    pub fn dispatch_method(&self, name: &str, args: &[RawValue]) -> Result<RawValue> {
+        self.call(name, (args,))
+    }
+
+    /// Gets the [`PluginType`].
+    pub fn plugin_type(&self) -> Result<PluginType> {
+        self.call("plugin_type", ())
+    }
+
+    /// Processes [`Action`] in action plugin.
+    pub fn process_action(&self, ctx: ActionProcessContextRef) -> Result<Action> {
+        self.call("process_action", (ctx,))
+    }
+
+    /// Gets registered TeX commands of a text plugin.
+    pub fn text_commands(&self) -> Result<Vec<String>> {
+        self.call("text_commands", ())
+    }
+
+    /// Calls a custom command in the text plugin.
+    pub fn dispatch_command(
+        &self,
+        name: &str,
+        args: &[String],
+        ctx: TextProcessContextRef,
+    ) -> Result<TextProcessResult> {
+        self.call(name, (args, ctx))
+    }
+
+    /// Processes [`Game`] when opening the config file.
+    pub fn process_game(&self, ctx: GameProcessContextRef) -> Result<GameProcessResult> {
+        self.call("process_game", (ctx,))
+    }
+}
+
+/// The plugin runtime.
+pub struct Runtime {
+    /// The plugins map by name.
+    pub modules: HashMap<String, Host>,
+    /// The action plugins.
+    pub action_modules: Vec<String>,
+    /// The text plugins by command name.
+    pub text_modules: HashMap<String, String>,
+    /// The game plugins.
+    pub game_modules: Vec<String>,
+}
+
+/// The load status of [`Runtime`].
+#[derive(Debug, Clone)]
+pub enum LoadStatus {
+    /// Start creating the engine.
+    CreateEngine,
+    /// Loading the plugin.
+    LoadPlugin(String, usize, usize),
+}
+
+#[derive(Default, Clone, WasmerEnv)]
+struct RuntimeInstanceData {
+    #[wasmer(export)]
+    memory: LazyInit<Memory>,
+}
+
+impl Runtime {
+    fn imports(store: &Store) -> Result<Box<dyn NamedResolver + Send + Sync>> {
+        let log_func = Function::new_native_with_env(
+            store,
+            RuntimeInstanceData::default(),
+            |env_data: &RuntimeInstanceData, len: i32, data: i32| {
+                let memory = unsafe { env_data.memory.get_unchecked() };
+                let data = unsafe { mem_slice(memory, data, len) };
+                let data: Record = rmp_serde::from_slice(data).unwrap();
+                log::logger().log(
+                    &log::Record::builder()
+                        .level(data.level)
+                        .target(&data.target)
+                        .args(format_args!("{}", data.msg))
+                        .module_path(data.module_path.as_deref())
+                        .file(data.file.as_deref())
+                        .line(data.line)
+                        .build(),
+                );
+            },
+        );
+        let log_flush_func = Function::new_native(store, || log::logger().flush());
+        let import_object = imports! {
+            "log" => {
+                "__log" => log_func,
+                "__log_flush" => log_flush_func,
+            }
+        };
+        let wasi_env = WasiState::new("ayaka-runtime")
+            .preopen_dir("/")?
+            .finalize()?;
+        let wasi_import = generate_import_object_from_env(store, wasi_env, WasiVersion::Latest);
+        Ok(Box::new(import_object.chain_front(wasi_import)))
+    }
+
+    /// Load plugins from specific directory and plugin names.
+    ///
+    /// The actual load folder will be `rel_to.join(dir)`.
+    ///
+    /// If `names` is empty, all WASM files will be loaded.
+    #[stream(LoadStatus, lifetime = "'a")]
+    pub async fn load<'a>(
+        dir: impl AsRef<Path> + 'a,
+        rel_to: impl AsRef<Path> + 'a,
+        names: &'a [impl AsRef<str>],
+    ) -> Result<Self> {
+        let path = rel_to.as_ref().join(dir);
+        yield LoadStatus::CreateEngine;
+        let store = Store::default();
+        let import_object = Self::imports(&store)?;
+        let mut modules = HashMap::new();
+        let mut action_modules = vec![];
+        let mut text_modules = HashMap::new();
+        let mut game_modules = vec![];
+        let paths = if names.is_empty() {
+            ReadDirStream::new(tokio::fs::read_dir(path).await?)
+                .try_filter_map(|f| async move {
+                    let p = f.path();
+                    if p.extension()
+                        .map(|s| s.to_string_lossy())
+                        .unwrap_or_default()
+                        == "wasm"
+                    {
+                        let name = p
+                            .file_stem()
+                            .map(|s| s.to_string_lossy())
+                            .unwrap_or_default()
+                            .into_owned();
+                        Ok(Some((name, p)))
+                    } else {
+                        Ok(None)
+                    }
+                })
+                .try_collect::<Vec<_>>()
+                .await?
+        } else {
+            names
+                .iter()
+                .filter_map(|name| {
+                    let name = name.as_ref();
+                    let p = path.join(name).with_extension("wasm");
+                    if p.exists() {
+                        Some((name.to_string(), p))
+                    } else {
+                        None
+                    }
+                })
+                .collect::<Vec<_>>()
+        };
+        let total_len = paths.len();
+        for (i, (name, p)) in paths.into_iter().enumerate() {
+            yield LoadStatus::LoadPlugin(name.clone(), i, total_len);
+            let buf = tokio::fs::read(p).await?;
+            let module = Module::from_binary(&store, &buf)?;
+            let runtime = Host::new(&module, &import_object)?;
+            let plugin_type = runtime.plugin_type()?;
+            if plugin_type.action {
+                action_modules.push(name.clone());
+            }
+            for cmd in plugin_type.text {
+                let res = text_modules.insert(cmd.clone(), name.clone());
+                if let Some(old_module) = res {
+                    warn!(
+                        "Command `{}` is overrided by \"{}\" over \"{}\"",
+                        cmd, name, old_module
+                    );
+                }
+            }
+            if plugin_type.game {
+                game_modules.push(name.clone());
+            }
+            modules.insert(name, runtime);
+        }
+        Ok(Self {
+            modules,
+            action_modules,
+            text_modules,
+            game_modules,
+        })
+    }
+}
diff --git a/utils/ayaka-runtime/src/script.rs b/utils/ayaka-runtime/src/script.rs
new file mode 100644
index 00000000..fecb36aa
--- /dev/null
+++ b/utils/ayaka-runtime/src/script.rs
@@ -0,0 +1,390 @@
+//! The script interpreter.
+
+use crate::{plugin::Runtime, *};
+use ayaka_script_types::*;
+use fallback::Fallback;
+use log::{error, warn};
+
+/// The variable table in scripts.
+pub struct VarTable<'a> {
+    /// The plugin runtime.
+    pub runtime: &'a Runtime,
+    /// The resource map.
+    pub res: Fallback<&'a VarMap>,
+    /// The context variables.
+    pub locals: &'a mut VarMap,
+    /// The locale variables.
+    pub vars: VarMap,
+}
+
+impl<'a> VarTable<'a> {
+    /// Creates a new [`VarTable`].
+    pub fn new(runtime: &'a Runtime, res: Fallback<&'a VarMap>, locals: &'a mut VarMap) -> Self {
+        Self {
+            runtime,
+            res,
+            locals,
+            vars: VarMap::default(),
+        }
+    }
+
+    /// Calls a [`Callable`] object.
+    pub fn call(&mut self, c: &impl Callable) -> RawValue {
+        c.call(self)
+    }
+}
+
+/// Represents a callable part of a script.
+pub trait Callable {
+    /// Calls the part with the [`VarTable`].
+    fn call(&self, ctx: &mut VarTable) -> RawValue;
+}
+
+impl<T: Callable> Callable for &T {
+    fn call(&self, ctx: &mut VarTable) -> RawValue {
+        (*self).call(ctx)
+    }
+}
+
+impl<T: Callable> Callable for Option<T> {
+    fn call(&self, ctx: &mut VarTable) -> RawValue {
+        match self {
+            Some(c) => c.call(ctx),
+            None => RawValue::Unit,
+        }
+    }
+}
+
+impl Callable for Program {
+    fn call(&self, ctx: &mut VarTable) -> RawValue {
+        ctx.vars.clear();
+        let mut res = RawValue::Unit;
+        for expr in &self.0 {
+            res = expr.call(ctx);
+        }
+        res
+    }
+}
+
+impl Callable for Expr {
+    fn call(&self, ctx: &mut VarTable) -> RawValue {
+        match self {
+            Self::Ref(r) => r.call(ctx),
+            Self::Const(c) => c.clone(),
+            Self::Unary(op, e) => match op {
+                UnaryOp::Positive => RawValue::Num(e.call(ctx).get_num()),
+                UnaryOp::Negative => RawValue::Num(-e.call(ctx).get_num()),
+                UnaryOp::Not => match e.call(ctx) {
+                    RawValue::Unit => RawValue::Unit,
+                    RawValue::Bool(b) => RawValue::Bool(!b),
+                    RawValue::Num(i) => RawValue::Num(!i),
+                    RawValue::Str(_) => RawValue::Str(String::new()),
+                },
+            },
+            Self::Binary(lhs, op, rhs) => match op {
+                BinaryOp::Val(op) => bin_val(ctx, lhs, op, rhs),
+                BinaryOp::Logic(op) => bin_logic(ctx, lhs, op, rhs),
+                BinaryOp::Assign => {
+                    let val = rhs.call(ctx);
+                    assign(ctx, lhs, val)
+                }
+                BinaryOp::Inplace(op) => {
+                    let val = bin_val(ctx, lhs, op, rhs);
+                    assign(ctx, lhs, val)
+                }
+            },
+            Self::Call(ns, name, args) => call(ctx, ns, name, args),
+        }
+    }
+}
+
+fn bin_val(ctx: &mut VarTable, lhs: &Expr, op: &ValBinaryOp, rhs: &Expr) -> RawValue {
+    let lhs = lhs.call(ctx);
+    let rhs = rhs.call(ctx);
+    let t = lhs.get_type().max(rhs.get_type());
+    match t {
+        ValueType::Unit => RawValue::Unit,
+        ValueType::Bool => bin_bool_val(lhs.get_bool(), op, rhs.get_bool()),
+        ValueType::Num => RawValue::Num(bin_num_val(lhs.get_num(), op, rhs.get_num())),
+        ValueType::Str => bin_str_val(lhs, op, rhs),
+    }
+}
+
+fn bin_bool_val(lhs: bool, op: &ValBinaryOp, rhs: bool) -> RawValue {
+    match op {
+        ValBinaryOp::Add
+        | ValBinaryOp::Minus
+        | ValBinaryOp::Mul
+        | ValBinaryOp::Div
+        | ValBinaryOp::Mod => RawValue::Num(bin_num_val(lhs as i64, op, rhs as i64)),
+        ValBinaryOp::And => RawValue::Bool(lhs && rhs),
+        ValBinaryOp::Or => RawValue::Bool(lhs || rhs),
+        ValBinaryOp::Xor => RawValue::Bool(lhs ^ rhs),
+    }
+}
+
+fn bin_num_val(lhs: i64, op: &ValBinaryOp, rhs: i64) -> i64 {
+    match op {
+        ValBinaryOp::Add => lhs + rhs,
+        ValBinaryOp::Minus => lhs - rhs,
+        ValBinaryOp::Mul => lhs * rhs,
+        ValBinaryOp::Div => lhs / rhs,
+        ValBinaryOp::Mod => lhs % rhs,
+        ValBinaryOp::And => lhs & rhs,
+        ValBinaryOp::Or => lhs | rhs,
+        ValBinaryOp::Xor => lhs ^ rhs,
+    }
+}
+
+fn bin_str_val(lhs: RawValue, op: &ValBinaryOp, rhs: RawValue) -> RawValue {
+    match op {
+        ValBinaryOp::Add => RawValue::Str((lhs.get_str() + rhs.get_str()).into()),
+        ValBinaryOp::Mul => match (
+            lhs.get_type().max(ValueType::Num),
+            rhs.get_type().max(ValueType::Num),
+        ) {
+            (ValueType::Str, ValueType::Str) => unimplemented!(),
+            (ValueType::Num, ValueType::Str) => {
+                RawValue::Str(rhs.get_str().repeat(lhs.get_num() as usize))
+            }
+            (ValueType::Str, ValueType::Num) => {
+                RawValue::Str(lhs.get_str().repeat(rhs.get_num() as usize))
+            }
+            _ => unreachable!(),
+        },
+        _ => unimplemented!(),
+    }
+}
+
+fn bin_logic(ctx: &mut VarTable, lhs: &Expr, op: &LogicBinaryOp, rhs: &Expr) -> RawValue {
+    let res = match op {
+        LogicBinaryOp::And => lhs.call(ctx).get_bool() && rhs.call(ctx).get_bool(),
+        LogicBinaryOp::Or => lhs.call(ctx).get_bool() || rhs.call(ctx).get_bool(),
+        op => {
+            let lhs = lhs.call(ctx);
+            let rhs = rhs.call(ctx);
+            let t = lhs.get_type().max(rhs.get_type());
+            match t {
+                ValueType::Unit => false,
+                ValueType::Bool => bin_ord_logic(&lhs.get_bool(), op, &rhs.get_bool()),
+                ValueType::Num => bin_ord_logic(&lhs.get_num(), op, &rhs.get_num()),
+                ValueType::Str => bin_ord_logic(&lhs.get_str(), op, &rhs.get_str()),
+            }
+        }
+    };
+    RawValue::Bool(res)
+}
+
+fn bin_ord_logic<T: Ord>(lhs: &T, op: &LogicBinaryOp, rhs: &T) -> bool {
+    match op {
+        LogicBinaryOp::Eq => lhs == rhs,
+        LogicBinaryOp::Neq => lhs != rhs,
+        LogicBinaryOp::Lt => lhs < rhs,
+        LogicBinaryOp::Le => lhs <= rhs,
+        LogicBinaryOp::Gt => lhs > rhs,
+        LogicBinaryOp::Ge => lhs >= rhs,
+        _ => unreachable!(),
+    }
+}
+
+fn assign(ctx: &mut VarTable, e: &Expr, val: RawValue) -> RawValue {
+    match e {
+        Expr::Ref(r) => match r {
+            Ref::Var(n) => ctx.vars.insert(n.into(), val),
+            Ref::Ctx(n) => ctx.locals.insert(n.into(), val),
+            Ref::Res(_) => unimplemented!("Resources"),
+        },
+        _ => unreachable!(),
+    };
+    RawValue::Unit
+}
+
+fn call(ctx: &mut VarTable, ns: &str, name: &str, args: &[Expr]) -> RawValue {
+    if ns.is_empty() {
+        match name {
+            "if" => if args.get(0).call(ctx).get_bool() {
+                args.get(1)
+            } else {
+                args.get(2)
+            }
+            .call(ctx),
+            _ => unimplemented!("intrinstics"),
+        }
+    } else {
+        let args = args.iter().map(|e| e.call(ctx)).collect::<Vec<_>>();
+        if let Some(runtime) = ctx.runtime.modules.get(ns) {
+            match runtime.dispatch_method(name, &args) {
+                Ok(res) => res,
+                Err(e) => {
+                    error!("Calling `{}.{}` error: {}", ns, name, e);
+                    RawValue::Unit
+                }
+            }
+        } else {
+            error!("Cannot find namespace `{}`.", ns);
+            RawValue::Unit
+        }
+    }
+}
+
+impl Callable for Ref {
+    fn call(&self, ctx: &mut VarTable) -> RawValue {
+        match self {
+            Self::Var(n) => ctx.vars.get(n).cloned().unwrap_or_else(|| {
+                warn!("Cannot find variable `{}`.", n);
+                Default::default()
+            }),
+            Self::Ctx(n) => ctx.locals.get(n).cloned().unwrap_or_else(|| {
+                warn!("Cannot find context variable `{}`.", n);
+                Default::default()
+            }),
+            Self::Res(n) => ctx
+                .res
+                .as_ref()
+                .and_then(|map| map.get(n))
+                .cloned()
+                .unwrap_or_else(|| {
+                    warn!("Cannot find resource `{}`.", n);
+                    Default::default()
+                }),
+        }
+    }
+}
+
+impl Callable for Text {
+    fn call(&self, ctx: &mut VarTable) -> RawValue {
+        let mut str = String::new();
+        for line in &self.0 {
+            match line {
+                Line::Str(s) => str.push_str(s),
+                Line::Cmd(c) => {
+                    if let Command::Exec(p) = c {
+                        str.push_str(&p.call(ctx).get_str())
+                    }
+                }
+            }
+        }
+        RawValue::Str(str.trim().to_string())
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use crate::{plugin::Runtime, script::*};
+    use ayaka_script::*;
+    use tokio::sync::OnceCell;
+
+    static RUNTIME: OnceCell<Runtime> = OnceCell::const_new();
+
+    async fn with_ctx(f: impl FnOnce(&mut VarTable)) {
+        let runtime = RUNTIME
+            .get_or_init(|| async {
+                let runtime = Runtime::load(
+                    "../../examples/plugins",
+                    env!("CARGO_MANIFEST_DIR"),
+                    &["format"],
+                );
+                runtime.await.unwrap()
+            })
+            .await;
+        let mut locals = VarMap::default();
+        let mut ctx = VarTable::new(runtime, Fallback::new(None, None), &mut locals);
+        f(&mut ctx);
+    }
+
+    #[tokio::test]
+    async fn vars() {
+        with_ctx(|ctx| {
+            assert_eq!(
+                ProgramParser::new()
+                    .parse(
+                        "
+                            a = 0;
+                            a += 1;
+                            a += a;
+                            a
+                        "
+                    )
+                    .ok()
+                    .call(ctx),
+                RawValue::Num(2)
+            );
+
+            assert_eq!(
+                ProgramParser::new().parse("a").ok().call(ctx),
+                RawValue::Unit
+            );
+
+            assert_eq!(
+                ProgramParser::new()
+                    .parse(
+                        "
+                            $a = 0;
+                            $a += 1;
+                            $a += a;
+                            $a
+                        "
+                    )
+                    .ok()
+                    .call(ctx),
+                RawValue::Num(1)
+            );
+
+            assert_eq!(
+                ProgramParser::new().parse("$a").ok().call(ctx),
+                RawValue::Num(1)
+            );
+        })
+        .await;
+    }
+
+    #[tokio::test]
+    async fn if_test() {
+        with_ctx(|ctx| {
+            assert_eq!(
+                ProgramParser::new()
+                    .parse(
+                        r##"
+                            if(1 + 1 + 4 + 5 + 1 + 4 == 16, "sodayo", ~)
+                        "##
+                    )
+                    .ok()
+                    .call(ctx)
+                    .get_num(),
+                6
+            );
+            assert_eq!(
+                ProgramParser::new()
+                    .parse(
+                        r##"
+                            if(true, "sodayo")
+                        "##
+                    )
+                    .ok()
+                    .call(ctx)
+                    .get_str(),
+                "sodayo"
+            );
+        })
+        .await;
+    }
+
+    #[tokio::test]
+    async fn format() {
+        with_ctx(|ctx| {
+            assert_eq!(
+                ProgramParser::new()
+                    .parse(
+                        r##"
+                            format.fmt("Hello {}!", 114514)
+                        "##
+                    )
+                    .ok()
+                    .call(ctx)
+                    .get_str(),
+                "Hello 114514!"
+            )
+        })
+        .await;
+    }
+}
diff --git a/utils/ayaka-runtime/src/settings.rs b/utils/ayaka-runtime/src/settings.rs
new file mode 100644
index 00000000..89e2af7f
--- /dev/null
+++ b/utils/ayaka-runtime/src/settings.rs
@@ -0,0 +1,160 @@
+#[doc(no_inline)]
+pub use ayaka_bindings_types::VarMap;
+
+use crate::*;
+use anyhow::{anyhow, Result};
+use dirs::{config_dir, data_local_dir};
+use futures_util::TryStreamExt;
+use serde::{de::DeserializeOwned, Deserialize, Serialize};
+use std::{
+    collections::HashMap,
+    path::{Path, PathBuf},
+};
+use tokio_stream::wrappers::ReadDirStream;
+
+/// The settings of the game.
+#[derive(Debug, Default, Clone, Deserialize, Serialize)]
+pub struct Settings {
+    /// The display language.
+    pub lang: Locale,
+}
+
+impl Settings {
+    /// Creates [`Settings`] object with current locale.
+    pub fn new() -> Self {
+        Self {
+            lang: Locale::default(),
+        }
+    }
+}
+
+/// The global record.
+#[derive(Debug, Default, Clone, Deserialize, Serialize)]
+pub struct GlobalRecord {
+    /// The key is the tag of paragraphs,
+    /// the value is the maximum text index.
+    pub record: HashMap<String, usize>,
+}
+
+/// The specific record.
+#[derive(Debug, Default, Clone, Deserialize, Serialize)]
+pub struct ActionRecord {
+    /// The history actions.
+    pub history: Vec<Action>,
+}
+
+impl ActionRecord {
+    /// Get the [`RawContext`] object from the last [`Action`] in the history.
+    pub fn last_ctx(&self) -> Option<&RawContext> {
+        self.history.last().map(|act| &act.ctx)
+    }
+
+    /// Get the [`RawContext`] object from the last [`Action`] in the history,
+    /// and if the history is empty, create a new [`RawContext`] from the game.
+    pub fn last_ctx_with_game(&self, game: &Game) -> RawContext {
+        self.last_ctx().cloned().unwrap_or_else(|| RawContext {
+            cur_para: game
+                .paras
+                .get(&game.base_lang)
+                .and_then(|paras| paras.first().map(|p| p.tag.clone()))
+                .unwrap_or_else(|| {
+                    log::warn!("There is no paragraph in the game.");
+                    Default::default()
+                }),
+            ..Default::default()
+        })
+    }
+}
+
+async fn load_file<T: DeserializeOwned>(path: impl AsRef<Path>) -> Result<T> {
+    let buffer = tokio::fs::read(path).await?;
+    Ok(serde_json::from_slice(&buffer)?)
+}
+
+async fn save_file<T: Serialize>(data: &T, path: impl AsRef<Path>, pretty: bool) -> Result<()> {
+    let path = path.as_ref();
+    if let Some(parent) = path.parent() {
+        tokio::fs::create_dir_all(parent).await?;
+    }
+    let buffer = if pretty {
+        serde_json::to_vec_pretty(data)
+    } else {
+        serde_json::to_vec(data)
+    }?;
+    tokio::fs::write(path, &buffer).await?;
+    Ok(())
+}
+
+fn settings_path(ident: &str) -> Result<PathBuf> {
+    let path = config_dir().ok_or_else(|| anyhow!("Cannot find config path"))?;
+    Ok(path.join(ident).join("settings.json"))
+}
+
+/// Load settings from JSON file.
+pub async fn load_settings(ident: &str) -> Result<Settings> {
+    load_file(settings_path(ident)?).await
+}
+
+/// Save settings into pretty JSON file.
+pub async fn save_settings(ident: &str, data: &Settings) -> Result<()> {
+    save_file(data, settings_path(ident)?, true).await
+}
+
+fn records_path(ident: &str, game: &str) -> Result<PathBuf> {
+    let path = data_local_dir().ok_or_else(|| anyhow!("Cannot find config path"))?;
+    Ok(path.join(ident).join("save").join(game))
+}
+
+fn global_record_path(ident: &str, game: &str) -> Result<PathBuf> {
+    Ok(records_path(ident, game)?.join("global.json"))
+}
+
+/// Load [`GlobalRecord`] from the records folder.
+pub async fn load_global_record(ident: &str, game: &str) -> Result<GlobalRecord> {
+    load_file(global_record_path(ident, game)?).await
+}
+
+/// Save [`GlobalRecord`] into the records folder.
+pub async fn save_global_record(ident: &str, game: &str, data: &GlobalRecord) -> Result<()> {
+    save_file(data, global_record_path(ident, game)?, false).await
+}
+
+/// Load all [`ActionRecord`] from the records folder.
+pub async fn load_records(ident: &str, game: &str) -> Result<Vec<ActionRecord>> {
+    let ctx_path = records_path(ident, game)?;
+    let contexts = ReadDirStream::new(tokio::fs::read_dir(ctx_path).await?)
+        .map_err(anyhow::Error::from)
+        .try_filter_map(|entry| async move {
+            let p = entry.path();
+            if p.extension()
+                .map(|s| s.to_string_lossy())
+                .unwrap_or_default()
+                == "json"
+                && p.file_stem()
+                    .map(|s| s.to_string_lossy())
+                    .unwrap_or_default()
+                    != "global"
+            {
+                Ok(Some(load_file(&p).await?))
+            } else {
+                Ok(None)
+            }
+        })
+        .try_collect()
+        .await?;
+    Ok(contexts)
+}
+
+/// Save all [`ActionRecord`] into the records folder.
+pub async fn save_records(ident: &str, game: &str, contexts: &[ActionRecord]) -> Result<()> {
+    let ctx_path = records_path(ident, game)?;
+    for (i, ctx) in contexts.iter().enumerate() {
+        save_file(
+            ctx,
+            ctx_path.join(i.to_string()).with_extension("json"),
+            false,
+        )
+        .await?;
+    }
+    Ok(())
+}
diff --git a/utils/ayaka-script-types/Cargo.toml b/utils/ayaka-script-types/Cargo.toml
new file mode 100644
index 00000000..0bac3d1c
--- /dev/null
+++ b/utils/ayaka-script-types/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "ayaka-script-types"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+serde = { version = "1.0", features = ["derive"] }
+rt-format = { version = "0.3", optional = true }
+
+[dev-dependencies]
+serde_yaml = "0.9"
+
+[features]
+default = []
diff --git a/utils/ayaka-script-types/src/exec.rs b/utils/ayaka-script-types/src/exec.rs
new file mode 100644
index 00000000..122bfa79
--- /dev/null
+++ b/utils/ayaka-script-types/src/exec.rs
@@ -0,0 +1,106 @@
+use crate::*;
+use serde::{Deserialize, Serialize};
+
+/// A full script, a collection of expressions.
+///
+/// The last expression is the final value of the script.
+#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq)]
+pub struct Program(pub Vec<Expr>);
+
+/// An expression.
+///
+/// Two expressions should be splited with `;`.
+#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
+pub enum Expr {
+    /// A reference to a variable.
+    Ref(Ref),
+    /// A const value.
+    Const(RawValue),
+    /// A unary operation.
+    Unary(UnaryOp, Box<Expr>),
+    /// A binary operation.
+    Binary(Box<Expr>, BinaryOp, Box<Expr>),
+    /// A call to a function.
+    Call(String, String, Vec<Expr>),
+}
+
+/// Unary operations.
+#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)]
+pub enum UnaryOp {
+    /// `+`
+    Positive,
+    /// `-`
+    Negative,
+    /// `!`
+    Not,
+}
+
+/// Binary operations.
+#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)]
+pub enum BinaryOp {
+    /// Value operations.
+    Val(ValBinaryOp),
+    /// Logical operations.
+    Logic(LogicBinaryOp),
+    /// Assignment.
+    Assign,
+    /// Inplace value operations.
+    Inplace(ValBinaryOp),
+}
+
+/// Value binary operations.
+#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)]
+pub enum ValBinaryOp {
+    /// `+`
+    Add,
+    /// `-`
+    Minus,
+    /// `*`
+    Mul,
+    /// `/`
+    Div,
+    /// `%`
+    Mod,
+    /// `&`
+    And,
+    /// `|`
+    Or,
+    /// `^`
+    Xor,
+}
+
+/// Logical operations.
+#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)]
+pub enum LogicBinaryOp {
+    /// `&&`
+    And,
+    /// `||`
+    Or,
+    /// `==`
+    Eq,
+    /// `!=`
+    Neq,
+    /// `<`
+    Lt,
+    /// `<=`
+    Le,
+    /// `>`
+    Gt,
+    /// `>=`
+    Ge,
+}
+
+/// Reference of a variable.
+#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
+pub enum Ref {
+    /// A local variable.
+    /// It is only accessible in current program.
+    Var(String),
+    /// A context variable.
+    /// It is stored in the context.
+    /// The variable name is prefixed with `$`.
+    Ctx(String),
+    /// A resource constant.
+    /// The constant name is prefixed with `#`.
+    Res(String),
+}
diff --git a/utils/ayaka-script-types/src/lib.rs b/utils/ayaka-script-types/src/lib.rs
new file mode 100644
index 00000000..f285e15c
--- /dev/null
+++ b/utils/ayaka-script-types/src/lib.rs
@@ -0,0 +1,12 @@
+//! The types used by script and text parsers.
+
+#![warn(missing_docs)]
+#![deny(unsafe_code)]
+
+mod exec;
+mod primitive;
+mod text;
+
+pub use exec::*;
+pub use primitive::*;
+pub use text::*;
diff --git a/utils/ayaka-script-types/src/primitive.rs b/utils/ayaka-script-types/src/primitive.rs
new file mode 100644
index 00000000..dcf37e41
--- /dev/null
+++ b/utils/ayaka-script-types/src/primitive.rs
@@ -0,0 +1,341 @@
+use serde::{Deserialize, Serialize};
+use std::borrow::Cow;
+
+/// The basic and only type used in scripts.
+/// ```
+/// # use ayaka_script_types::RawValue;
+/// assert_eq!(serde_yaml::from_str::<RawValue>("~").unwrap(), RawValue::Unit);
+/// assert_eq!(serde_yaml::from_str::<RawValue>("true").unwrap(), RawValue::Bool(true));
+/// assert_eq!(serde_yaml::from_str::<RawValue>("123").unwrap(), RawValue::Num(123));
+/// assert_eq!(serde_yaml::from_str::<RawValue>("\"hello\"").unwrap(), RawValue::Str("hello".to_string()));
+/// ```
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum RawValue {
+    /// The unit type. It is empty, just like [`None`] or [`()`] in Rust.
+    Unit,
+    /// The boolean type.
+    Bool(bool),
+    /// The number type. It's [`i64`].
+    Num(i64),
+    /// The string type.
+    Str(String),
+}
+
+/// Represents the type of [`RawValue`].
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+pub enum ValueType {
+    /// The unit type.
+    Unit,
+    /// The boolean type.
+    Bool,
+    /// The number type.
+    Num,
+    /// The string type.
+    Str,
+}
+
+impl Default for RawValue {
+    fn default() -> Self {
+        Self::Unit
+    }
+}
+
+impl RawValue {
+    /// Gets [`ValueType`].
+    pub fn get_type(&self) -> ValueType {
+        match self {
+            Self::Unit => ValueType::Unit,
+            Self::Bool(_) => ValueType::Bool,
+            Self::Num(_) => ValueType::Num,
+            Self::Str(_) => ValueType::Str,
+        }
+    }
+
+    /// Gets a boolean from the value:
+    /// * A [`RawValue::Unit`] converts to `false`.
+    /// * A [`RawValue::Num`] converts to `false` if and only if it's zero.
+    /// * A [`RawValue::Str`] converts to `false` if and only if it's empty.
+    ///
+    /// ```
+    /// # use ayaka_script_types::RawValue;
+    /// let unit_value = RawValue::Unit;
+    /// assert!(!unit_value.get_bool());
+    /// let num_value = RawValue::Num(123);
+    /// assert!(num_value.get_bool());
+    /// let str_value = RawValue::Str("hello".to_string());
+    /// assert!(str_value.get_bool());
+    /// let empty_str_value = RawValue::Str(String::default());
+    /// assert!(!empty_str_value.get_bool());
+    /// ```
+    pub fn get_bool(&self) -> bool {
+        match self {
+            Self::Unit => false,
+            Self::Bool(b) => *b,
+            Self::Num(i) => *i != 0,
+            Self::Str(s) => !s.is_empty(),
+        }
+    }
+
+    /// Gets a number from the value:
+    /// * A [`RawValue::Unit`] converts to 0.
+    /// * A [`RawValue::Bool`] converts `false` to 0 and `true` to 1.
+    /// * A [`RawValue::Str`] converts to the length of the string.
+    ///
+    /// ```
+    /// # use ayaka_script_types::RawValue;
+    /// let unit_value = RawValue::Unit;
+    /// assert_eq!(unit_value.get_num(), 0);
+    /// let bool_value = RawValue::Bool(true);
+    /// assert_eq!(bool_value.get_num(), 1);
+    /// let str_value = RawValue::Str("hello".to_string());
+    /// assert_eq!(str_value.get_num(), 5);
+    /// ```
+    pub fn get_num(&self) -> i64 {
+        match self {
+            Self::Unit => 0,
+            Self::Bool(b) => *b as i64,
+            Self::Num(i) => *i,
+            Self::Str(s) => s.len() as i64,
+        }
+    }
+
+    /// Gets a string from the value:
+    /// * A [`RawValue::Unit`] converts to empty string.
+    /// * A [`RawValue::Bool`] converts to "false" or "true".
+    /// * A [`RawValue::Num`] converts to the string representation of the number.\
+    ///
+    /// Be careful to use `get_str().into_owned()`, if possible, use `into_str()` instead.
+    ///
+    /// ```
+    /// # use ayaka_script_types::RawValue;
+    /// let unit_value = RawValue::Unit;
+    /// assert_eq!(unit_value.get_str(), "");
+    /// let bool_value = RawValue::Bool(true);
+    /// assert_eq!(bool_value.get_str(), "true");
+    /// let num_value = RawValue::Num(123);
+    /// assert_eq!(num_value.get_str(), "123");
+    /// ```
+    pub fn get_str(&self) -> Cow<str> {
+        match self {
+            Self::Unit => Cow::default(),
+            Self::Bool(b) => b.to_string().into(),
+            Self::Num(i) => i.to_string().into(),
+            Self::Str(s) => s.as_str().into(),
+        }
+    }
+
+    /// Gets a string from the value:
+    /// * A [`RawValue::Unit`] converts to empty string.
+    /// * A [`RawValue::Bool`] converts to "false" or "true".
+    /// * A [`RawValue::Num`] converts to the string representation of the number.
+    pub fn into_str(self) -> String {
+        match self {
+            Self::Unit => String::default(),
+            Self::Bool(b) => b.to_string(),
+            Self::Num(i) => i.to_string(),
+            Self::Str(s) => s,
+        }
+    }
+}
+
+impl<'de> Deserialize<'de> for RawValue {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: serde::Deserializer<'de>,
+    {
+        use serde::de::Error;
+
+        struct ValueVisitor;
+
+        impl<'de> serde::de::Visitor<'de> for ValueVisitor {
+            type Value = RawValue;
+
+            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
+                formatter.write_str("a unit, boolean, integer, string value")
+            }
+
+            fn visit_unit<E>(self) -> Result<Self::Value, E>
+            where
+                E: Error,
+            {
+                Ok(RawValue::Unit)
+            }
+
+            fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
+            where
+                E: Error,
+            {
+                Ok(RawValue::Bool(v))
+            }
+
+            fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
+            where
+                E: Error,
+            {
+                Ok(RawValue::Num(v))
+            }
+
+            fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
+            where
+                E: Error,
+            {
+                Ok(RawValue::Num(v as i64))
+            }
+
+            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
+            where
+                E: Error,
+            {
+                Ok(RawValue::Str(v.into()))
+            }
+        }
+        deserializer.deserialize_any(ValueVisitor)
+    }
+}
+
+impl Serialize for RawValue {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: serde::Serializer,
+    {
+        match self {
+            Self::Unit => serializer.serialize_unit(),
+            Self::Bool(b) => serializer.serialize_bool(*b),
+            Self::Num(n) => serializer.serialize_i64(*n),
+            Self::Str(s) => serializer.serialize_str(s),
+        }
+    }
+}
+
+#[cfg(feature = "rt-format")]
+use rt_format::{Format, FormatArgument, Specifier};
+
+#[cfg(feature = "rt-format")]
+impl FormatArgument for RawValue {
+    fn supports_format(&self, specifier: &Specifier) -> bool {
+        match self {
+            RawValue::Unit | RawValue::Bool(_) | RawValue::Str(_) => {
+                matches!(specifier.format, Format::Debug | Format::Display)
+            }
+            RawValue::Num(_) => true,
+        }
+    }
+
+    fn fmt_display(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        use std::fmt::Display;
+        match self {
+            RawValue::Unit => Ok(()),
+            RawValue::Bool(b) => b.fmt(f),
+            RawValue::Num(n) => n.fmt(f),
+            RawValue::Str(s) => s.fmt(f),
+        }
+    }
+
+    fn fmt_debug(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        use std::fmt::Debug;
+        self.fmt(f)
+    }
+
+    fn fmt_octal(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        match self {
+            RawValue::Num(n) => std::fmt::Octal::fmt(n, f),
+            _ => Err(std::fmt::Error),
+        }
+    }
+
+    fn fmt_lower_hex(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        match self {
+            RawValue::Num(n) => std::fmt::LowerHex::fmt(n, f),
+            _ => Err(std::fmt::Error),
+        }
+    }
+
+    fn fmt_upper_hex(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        match self {
+            RawValue::Num(n) => std::fmt::UpperHex::fmt(n, f),
+            _ => Err(std::fmt::Error),
+        }
+    }
+
+    fn fmt_binary(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        match self {
+            RawValue::Num(n) => std::fmt::Binary::fmt(n, f),
+            _ => Err(std::fmt::Error),
+        }
+    }
+
+    fn fmt_lower_exp(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        match self {
+            RawValue::Num(n) => std::fmt::LowerExp::fmt(n, f),
+            _ => Err(std::fmt::Error),
+        }
+    }
+
+    fn fmt_upper_exp(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        match self {
+            RawValue::Num(n) => std::fmt::UpperExp::fmt(n, f),
+            _ => Err(std::fmt::Error),
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use crate::*;
+
+    #[test]
+    fn serde_value() {
+        assert_eq!(
+            serde_yaml::from_str::<RawValue>("~").unwrap(),
+            RawValue::Unit
+        );
+
+        assert_eq!(
+            serde_yaml::from_str::<RawValue>("true").unwrap(),
+            RawValue::Bool(true)
+        );
+        assert_eq!(
+            serde_yaml::from_str::<RawValue>("false").unwrap(),
+            RawValue::Bool(false)
+        );
+
+        assert_eq!(
+            serde_yaml::from_str::<RawValue>("114514").unwrap(),
+            RawValue::Num(114514)
+        );
+        assert_eq!(
+            serde_yaml::from_str::<RawValue>("-1919810").unwrap(),
+            RawValue::Num(-1919810)
+        );
+
+        assert_eq!(
+            serde_yaml::from_str::<RawValue>("\"Hello world!\"").unwrap(),
+            RawValue::Str("Hello world!".into())
+        );
+
+        assert_eq!(serde_yaml::to_string(&RawValue::Unit).unwrap(), "null\n");
+
+        assert_eq!(
+            serde_yaml::to_string(&RawValue::Bool(true)).unwrap(),
+            "true\n"
+        );
+        assert_eq!(
+            serde_yaml::to_string(&RawValue::Bool(false)).unwrap(),
+            "false\n"
+        );
+
+        assert_eq!(
+            serde_yaml::to_string(&RawValue::Num(114514)).unwrap(),
+            "114514\n"
+        );
+        assert_eq!(
+            serde_yaml::to_string(&RawValue::Num(-1919)).unwrap(),
+            "-1919\n"
+        );
+
+        assert_eq!(
+            serde_yaml::to_string(&RawValue::Str("aaa".into())).unwrap(),
+            "aaa\n"
+        );
+    }
+}
diff --git a/utils/ayaka-script-types/src/text.rs b/utils/ayaka-script-types/src/text.rs
new file mode 100644
index 00000000..923c78ae
--- /dev/null
+++ b/utils/ayaka-script-types/src/text.rs
@@ -0,0 +1,40 @@
+use crate::*;
+
+/// A collection of [`Line`].
+#[derive(Debug, Default, PartialEq, Eq)]
+pub struct Text(pub Vec<Line>);
+
+/// A part of a line, either some texts or a command.
+#[derive(Debug, PartialEq, Eq)]
+pub enum Line {
+    /// Raw texts.
+    Str(String),
+    /// A command. See [`Command`].
+    Cmd(Command),
+}
+
+/// A TeX-like command in the text.
+#[derive(Debug, PartialEq, Eq)]
+pub enum Command {
+    /// `\ch{}{}`
+    ///
+    /// Controls the current character.
+    Character(String, String),
+    /// `\exec{}`
+    ///
+    /// Executes a program and calculates the return value into text.
+    Exec(Program),
+    /// `\switch{}{}{}`
+    ///
+    /// A switch.
+    Switch {
+        /// The text of the switch.
+        text: String,
+        /// The action after choosing the switch,
+        action: Program,
+        /// The expression determines whether the switch is enabled.
+        enabled: Option<Program>,
+    },
+    /// Other custom commands.
+    Other(String, Vec<String>),
+}
diff --git a/utils/ayaka-script/Cargo.toml b/utils/ayaka-script/Cargo.toml
new file mode 100644
index 00000000..504dce20
--- /dev/null
+++ b/utils/ayaka-script/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "ayaka-script"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+ayaka-script-types = { path = "../ayaka-script-types" }
+lalrpop-util = { version = "0.19", features = ["lexer"] }
+regex = "1"
+log = "0.4"
+
+[build-dependencies]
+lalrpop = "0.19"
diff --git a/utils/ayaka-script/build.rs b/utils/ayaka-script/build.rs
new file mode 100644
index 00000000..ca5c2836
--- /dev/null
+++ b/utils/ayaka-script/build.rs
@@ -0,0 +1,3 @@
+fn main() {
+    lalrpop::process_root().unwrap();
+}
diff --git a/utils/ayaka-script/src/exec/grammer.lalrpop b/utils/ayaka-script/src/exec/grammer.lalrpop
new file mode 100644
index 00000000..2969ab2b
--- /dev/null
+++ b/utils/ayaka-script/src/exec/grammer.lalrpop
@@ -0,0 +1,126 @@
+use super::*;
+use log::warn;
+use std::str::FromStr;
+
+grammar;
+
+Delimiter<T, D>: Vec<T> = {
+    <mut v:(<T> D)*> <e:T?> => match e {
+        None => v,
+        Some(e) => {
+            v.push(e);
+            v
+        }
+    }
+};
+
+pub Program: Program = Delimiter<Expr, ";"> => Program(<>);
+
+Exprs: Vec<Expr> = Delimiter<Expr, ",">;
+
+FuncName: (String, String) = {
+    <i:Id> => (String::default(), i),
+    <ns:Id> "." <name:Id> => (ns, name),
+}
+
+UnaryOp: UnaryOp = {
+    "+" => UnaryOp::Positive,
+    "-" => UnaryOp::Negative,
+    "!" => UnaryOp::Not,
+}
+
+// To make sure the full expr in parens.
+FullExpr: Expr = Expr;
+
+pub Expr: Expr = {
+    #[precedence(level="1")]
+    <r:Ref> => Expr::Ref(r),
+    <c:Const> => Expr::Const(c),
+    "(" <e:FullExpr> ")" => e,
+    <i:FuncName> "(" <a:Exprs> ")" => Expr::Call(i.0, i.1, a),
+    <o:UnaryOp> <e:Expr> => Expr::Unary(o, Box::new(e)),
+    #[precedence(level="2")]
+    #[assoc(side="left")]
+    <le:Expr> "*" <re:Expr> => Expr::Binary(Box::new(le), BinaryOp::Val(ValBinaryOp::Mul), Box::new(re)),
+    #[assoc(side="left")]
+    <le:Expr> "/" <re:Expr> => Expr::Binary(Box::new(le), BinaryOp::Val(ValBinaryOp::Div), Box::new(re)),
+    #[assoc(side="left")]
+    <le:Expr> "%" <re:Expr> => Expr::Binary(Box::new(le), BinaryOp::Val(ValBinaryOp::Mod), Box::new(re)),
+    #[precedence(level="3")]
+    #[assoc(side="left")]
+    <le:Expr> "+" <re:Expr> => Expr::Binary(Box::new(le), BinaryOp::Val(ValBinaryOp::Add), Box::new(re)),
+    #[assoc(side="left")]
+    <le:Expr> "-" <re:Expr> => Expr::Binary(Box::new(le), BinaryOp::Val(ValBinaryOp::Minus), Box::new(re)),
+    #[precedence(level="4")]
+    #[assoc(side="left")]
+    <le:Expr> "<" <re:Expr> => Expr::Binary(Box::new(le), BinaryOp::Logic(LogicBinaryOp::Lt), Box::new(re)),
+    #[assoc(side="left")]
+    <le:Expr> "<=" <re:Expr> => Expr::Binary(Box::new(le), BinaryOp::Logic(LogicBinaryOp::Le), Box::new(re)),
+    #[assoc(side="left")]
+    <le:Expr> ">" <re:Expr> => Expr::Binary(Box::new(le), BinaryOp::Logic(LogicBinaryOp::Gt), Box::new(re)),
+    #[assoc(side="left")]
+    <le:Expr> ">=" <re:Expr> => Expr::Binary(Box::new(le), BinaryOp::Logic(LogicBinaryOp::Ge), Box::new(re)),
+    #[precedence(level="5")]
+    #[assoc(side="left")]
+    <le:Expr> "==" <re:Expr> => Expr::Binary(Box::new(le), BinaryOp::Logic(LogicBinaryOp::Eq), Box::new(re)),
+    #[assoc(side="left")]
+    <le:Expr> "!=" <re:Expr> => Expr::Binary(Box::new(le), BinaryOp::Logic(LogicBinaryOp::Neq), Box::new(re)),
+    #[precedence(level="6")]
+    #[assoc(side="left")]
+    <le:Expr> "&" <re:Expr> => Expr::Binary(Box::new(le), BinaryOp::Val(ValBinaryOp::And), Box::new(re)),
+    #[precedence(level="7")]
+    #[assoc(side="left")]
+    <le:Expr> "^" <re:Expr> => Expr::Binary(Box::new(le), BinaryOp::Val(ValBinaryOp::Xor), Box::new(re)),
+    #[precedence(level="8")]
+    #[assoc(side="left")]
+    <le:Expr> "|" <re:Expr> => Expr::Binary(Box::new(le), BinaryOp::Val(ValBinaryOp::Or), Box::new(re)),
+    #[precedence(level="9")]
+    #[assoc(side="left")]
+    <le:Expr> "&&" <re:Expr> => Expr::Binary(Box::new(le), BinaryOp::Logic(LogicBinaryOp::And), Box::new(re)),
+    #[precedence(level="10")]
+    #[assoc(side="left")]
+    <le:Expr> "||" <re:Expr> => Expr::Binary(Box::new(le), BinaryOp::Logic(LogicBinaryOp::Or), Box::new(re)),
+    #[precedence(level="11")]
+    #[assoc(side="left")]
+    <r:Ref> <o:AssignOp> <e:Expr> => Expr::Binary(Box::new(Expr::Ref(r)), o, Box::new(e)),
+}
+
+AssignOp: BinaryOp = {
+    "=" => BinaryOp::Assign,
+    "+=" => BinaryOp::Inplace(ValBinaryOp::Add),
+    "-=" => BinaryOp::Inplace(ValBinaryOp::Minus),
+    "*=" => BinaryOp::Inplace(ValBinaryOp::Mul),
+    "/=" => BinaryOp::Inplace(ValBinaryOp::Div),
+    "%=" => BinaryOp::Inplace(ValBinaryOp::Mod),
+    "&=" => BinaryOp::Inplace(ValBinaryOp::And),
+    "|=" => BinaryOp::Inplace(ValBinaryOp::Or),
+    "^=" => BinaryOp::Inplace(ValBinaryOp::Xor),
+}
+
+pub Ref: Ref = {
+    <i:Id> => Ref::Var(i),
+    "$" <i:Id> => Ref::Ctx(i),
+    "#" <i:Id> => Ref::Res(i),
+}
+
+Id: String = <s:r"[A-Za-z]\w*"> => s.into();
+
+pub Const: RawValue = {
+    "~" => RawValue::Unit,
+    "null" => RawValue::Unit,
+    <b:Bool> => RawValue::Bool(b),
+    <n:Num> => RawValue::Num(n),
+    <s:Str> => RawValue::Str(s),
+}
+
+Bool: bool = {
+    "true" => true,
+    "false" => false,
+}
+
+Num: i64 = <s:r"[0-9]+"> => i64::from_str(s).unwrap_or_else(|e| {
+    warn!("{}", e);
+    0
+});
+
+Str: String = <s:r##""[^"\\]*(\\.[^"\\]*)*""##> => s[1..s.len() - 1].into();
diff --git a/utils/ayaka-script/src/exec/mod.rs b/utils/ayaka-script/src/exec/mod.rs
new file mode 100644
index 00000000..da96152a
--- /dev/null
+++ b/utils/ayaka-script/src/exec/mod.rs
@@ -0,0 +1,114 @@
+//! The script parser.
+
+use crate::*;
+use ayaka_script_types::*;
+use lalrpop_util::lalrpop_mod;
+
+lalrpop_mod!(
+    #[allow(missing_docs)]
+    #[allow(dead_code)]
+    grammer,
+    "/exec/grammer.rs"
+);
+
+pub use grammer::{ConstParser, ExprParser, ProgramParser, RefParser};
+
+#[cfg(test)]
+mod test {
+    use crate::exec::*;
+
+    fn var(s: &str) -> Expr {
+        Expr::Ref(Ref::Var(s.into()))
+    }
+
+    #[test]
+    fn program() {
+        assert_eq!(
+            ProgramParser::new()
+                .parse(
+                    "foo(a);
+                    foo.bar(a, b)"
+                )
+                .unwrap(),
+            Program(vec![
+                Expr::Call(String::default(), "foo".into(), vec![var("a")]),
+                Expr::Call("foo".into(), "bar".into(), vec![var("a"), var("b")])
+            ])
+        );
+    }
+
+    #[test]
+    fn expr() {
+        assert_eq!(ExprParser::new().parse("a").unwrap(), var("a"));
+        assert_eq!(
+            ExprParser::new().parse("!(a && b || c)").unwrap(),
+            Expr::Unary(
+                UnaryOp::Not,
+                Box::new(Expr::Binary(
+                    Box::new(Expr::Binary(
+                        Box::new(var("a")),
+                        BinaryOp::Logic(LogicBinaryOp::And),
+                        Box::new(var("b"))
+                    )),
+                    BinaryOp::Logic(LogicBinaryOp::Or),
+                    Box::new(var("c"))
+                ))
+            )
+        );
+        assert_eq!(
+            ExprParser::new().parse("foo(a)").unwrap(),
+            Expr::Call(String::default(), "foo".into(), vec![var("a")])
+        );
+        assert_eq!(
+            ExprParser::new().parse("foo.bar(a, b)").unwrap(),
+            Expr::Call("foo".into(), "bar".into(), vec![var("a"), var("b")])
+        );
+        assert_eq!(
+            ExprParser::new().parse("a + (b * (c & d))").unwrap(),
+            Expr::Binary(
+                Box::new(var("a")),
+                BinaryOp::Val(ValBinaryOp::Add),
+                Box::new(Expr::Binary(
+                    Box::new(var("b")),
+                    BinaryOp::Val(ValBinaryOp::Mul),
+                    Box::new(Expr::Binary(
+                        Box::new(var("c")),
+                        BinaryOp::Val(ValBinaryOp::And),
+                        Box::new(var("d"))
+                    ))
+                ))
+            )
+        );
+    }
+
+    #[test]
+    fn r#const() {
+        assert_eq!(ConstParser::new().parse("~").unwrap(), RawValue::Unit);
+
+        assert_eq!(
+            ConstParser::new().parse("true").unwrap(),
+            RawValue::Bool(true)
+        );
+        assert_eq!(
+            ConstParser::new().parse("false").unwrap(),
+            RawValue::Bool(false)
+        );
+
+        assert_eq!(
+            ConstParser::new().parse("114514").unwrap(),
+            RawValue::Num(114514.into())
+        );
+
+        assert_eq!(
+            ConstParser::new().parse("\"Hello world!\"").unwrap(),
+            RawValue::Str("Hello world!".into())
+        );
+    }
+
+    #[test]
+    fn r#ref() {
+        assert_eq!(RefParser::new().parse("a").unwrap(), Ref::Var("a".into()));
+        assert_eq!(RefParser::new().parse("$a").unwrap(), Ref::Ctx("a".into()));
+        assert_eq!(RefParser::new().parse("#a").unwrap(), Ref::Res("a".into()));
+    }
+}
diff --git a/utils/ayaka-script/src/lib.rs b/utils/ayaka-script/src/lib.rs
new file mode 100644
index 00000000..7db7c35b
--- /dev/null
+++ b/utils/ayaka-script/src/lib.rs
@@ -0,0 +1,14 @@
+//! The script and text parsers.
+
+#![warn(missing_docs)]
+#![deny(unsafe_code)]
+#![feature(iterator_try_collect)]
+#![feature(once_cell)]
+
+mod exec;
+mod text;
+
+pub use exec::*;
+#[doc(no_inline)]
+pub use log;
+pub use text::*;
diff --git a/utils/ayaka-script/src/text.rs b/utils/ayaka-script/src/text.rs
new file mode 100644
index 00000000..1d1de14f
--- /dev/null
+++ b/utils/ayaka-script/src/text.rs
@@ -0,0 +1,750 @@
+//! The text parser.
+
+use crate::*;
+use ayaka_script_types::*;
+use regex::Regex;
+use std::{error::Error, fmt::Display, iter::Peekable, str::CharIndices, sync::LazyLock};
+
+static SPACE_REGEX: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"(\s+)").unwrap());
+
+/// The location of a token.
+/// The `Loc(start, end)` means the location `[start, end)`.
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
+pub struct Loc(pub usize, pub usize);
+
+impl Loc {
+    /// Combines a series of [`Loc`].
+    ///
+    /// ```
+    /// # use ayaka_script::Loc;
+    /// let full_loc = Loc::from_locs([Loc(1, 2), Loc(4, 6), Loc(5, 8)]);
+    /// assert_eq!(full_loc, Loc(1, 8));
+    /// ```
+    pub fn from_locs(locs: impl IntoIterator<Item = Loc>) -> Self {
+        let mut start = usize::MAX;
+        let mut end = 0;
+        for loc in locs.into_iter() {
+            start = loc.0.min(start);
+            end = loc.1.max(end);
+        }
+        Self(start, end)
+    }
+}
+
+#[derive(Debug, PartialEq, Eq)]
+struct Token<'a> {
+    loc: Loc,
+    tok: TokenType<'a>,
+}
+
+#[derive(Debug, PartialEq, Eq)]
+enum TokenType<'a> {
+    Space,
+    SpecChar(char),
+    Text(&'a str),
+}
+
+impl<'a> Token<'a> {
+    pub fn space(loc: Loc) -> Self {
+        Self {
+            loc,
+            tok: TokenType::Space,
+        }
+    }
+
+    pub fn spec_char(loc: Loc, c: char) -> Self {
+        Self {
+            loc,
+            tok: TokenType::SpecChar(c),
+        }
+    }
+
+    pub fn text(loc: Loc, s: &'a str) -> Self {
+        Self {
+            loc,
+            tok: TokenType::Text(s),
+        }
+    }
+}
+
+#[derive(Debug, PartialEq, Eq)]
+struct RichToken<'a> {
+    loc: Loc,
+    tok: RichTokenType<'a>,
+}
+
+#[derive(Debug, PartialEq, Eq)]
+enum RichTokenType<'a> {
+    Char(char),
+    Text(&'a str),
+    Character(&'a str, &'a str),
+    Command(&'a str, Vec<Vec<RichToken<'a>>>),
+}
+
+impl<'a> RichToken<'a> {
+    pub fn char(loc: Loc, c: char) -> Self {
+        Self {
+            loc,
+            tok: RichTokenType::Char(c),
+        }
+    }
+
+    pub fn text(loc: Loc, s: &'a str) -> Self {
+        Self {
+            loc,
+            tok: RichTokenType::Text(s),
+        }
+    }
+
+    pub fn character(loc: Loc, s: &'a str, a: &'a str) -> Self {
+        Self {
+            loc,
+            tok: RichTokenType::Character(s, a),
+        }
+    }
+
+    pub fn command(loc: Loc, n: &'a str, params: Vec<Vec<RichToken<'a>>>) -> Self {
+        Self {
+            loc,
+            tok: RichTokenType::Command(n, params),
+        }
+    }
+}
+
+/// The error when parsing [`Text`].
+#[derive(Debug, PartialEq, Eq)]
+pub struct ParseError {
+    loc: Loc,
+    err: ParseErrorType,
+}
+
+impl ParseError {
+    pub(crate) fn new(loc: Loc, err: ParseErrorType) -> Self {
+        Self { loc, err }
+    }
+
+    /// The error location.
+    pub fn loc(&self) -> Loc {
+        self.loc
+    }
+
+    /// The error type.
+    pub fn error(&self) -> &ParseErrorType {
+        &self.err
+    }
+}
+
+fn parse_error<T>(loc: Loc, err: ParseErrorType) -> ParseResult<T> {
+    Err(ParseError::new(loc, err))
+}
+
+impl Display for ParseError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        self.err.fmt(f)
+    }
+}
+
+impl Error for ParseError {}
+
+/// The type of [`ParseError`].
+#[derive(Debug, PartialEq, Eq)]
+pub enum ParseErrorType {
+    /// Illegal char.
+    /// Usually unexcepted char after `\`,
+    /// or redundant `/`.
+    IllegalChar(char),
+    /// Illegal space.
+    /// The name in `\ch` command cannot contain spaces.
+    IllegalSpace,
+    /// No command name found after `\`.
+    CmdNotFound,
+    /// We don't support embedded command inside parameters.
+    CmdInCmd,
+    /// The builtin commands check the parameters count.
+    InvalidParamsCount(String, usize),
+    /// An error occurred when parsing [`Program`].
+    InvalidProgram(String),
+}
+
+impl Display for ParseErrorType {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            Self::IllegalChar(c) => write!(f, "Illegal char \"{}\".", c.escape_default())?,
+            Self::IllegalSpace => write!(f, "Illegal space.")?,
+            Self::CmdNotFound => write!(f, "Command not found after \"\\\".")?,
+            Self::CmdInCmd => write!(f, "Embedded command is not supported.")?,
+            Self::InvalidParamsCount(name, count) => write!(
+                f,
+                "Invalid params count {} for \"{}\"",
+                count,
+                name.escape_default()
+            )?,
+            Self::InvalidProgram(err) => write!(f, "Program parse error: {}", err)?,
+        }
+        Ok(())
+    }
+}
+
+/// The [`std::result::Result`] when parsing [`Text`].
+pub type ParseResult<T> = std::result::Result<T, ParseError>;
+
+const fn is_special_char(c: char) -> bool {
+    matches!(c, '\\' | '{' | '}' | '/')
+}
+
+struct TextLexer<'a> {
+    text: &'a str,
+    chars: Peekable<CharIndices<'a>>,
+}
+
+impl<'a> TextLexer<'a> {
+    pub fn new(text: &'a str) -> Self {
+        Self {
+            text,
+            chars: text.char_indices().peekable(),
+        }
+    }
+
+    fn peek_char(&mut self) -> Option<char> {
+        self.chars.peek().map(|(_, c)| *c)
+    }
+
+    fn next_char(&mut self) -> Option<char> {
+        self.chars.next().map(|(_, c)| c)
+    }
+
+    fn offset(&mut self) -> usize {
+        self.chars
+            .peek()
+            .map(|(offset, _)| *offset)
+            .unwrap_or_else(|| self.text.len())
+    }
+}
+
+impl<'a> Iterator for TextLexer<'a> {
+    type Item = Token<'a>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let cur = self.offset();
+        let mut has_whitespace = false;
+        while let Some(c) = self.peek_char() {
+            if c.is_whitespace() {
+                self.next_char();
+                has_whitespace = true;
+            } else {
+                break;
+            }
+        }
+        if has_whitespace {
+            return Some(Token::space(Loc(cur, self.offset())));
+        }
+        let cur = self.offset();
+        while let Some(c) = self.peek_char() {
+            if is_special_char(c) {
+                if self.offset() - cur > 0 {
+                    break;
+                } else {
+                    self.next_char();
+                    return Some(Token::spec_char(Loc(self.offset() - 1, self.offset()), c));
+                }
+            } else if c.is_whitespace() {
+                if self.offset() - cur > 0 {
+                    break;
+                } else {
+                    return self.next();
+                }
+            } else {
+                self.next_char();
+            }
+        }
+        if self.offset() - cur > 0 {
+            Some(Token::text(
+                Loc(cur, self.offset()),
+                &self.text[cur..self.offset()],
+            ))
+        } else {
+            None
+        }
+    }
+}
+
+struct TextRichLexer<'a> {
+    lexer: Peekable<TextLexer<'a>>,
+    in_param: usize,
+}
+
+impl<'a> TextRichLexer<'a> {
+    pub fn new(text: &'a str) -> Self {
+        Self {
+            lexer: TextLexer::new(text).peekable(),
+            in_param: 0,
+        }
+    }
+
+    fn parse_spec_char(&mut self, loc: Loc, c: char) -> ParseResult<RichToken<'a>> {
+        match c {
+            '\\' => self.parse_escape_or_command(loc),
+            '{' | '}' /*if self.in_param > 0*/ => Ok(RichToken::char(loc, c)),
+            '/' => self.parse_character(loc),
+            _ => parse_error(loc, ParseErrorType::IllegalChar(c)),
+        }
+    }
+
+    fn parse_character(&mut self, prev_loc: Loc) -> ParseResult<RichToken<'a>> {
+        let (name, mid_loc) = self.parse_character_name(prev_loc)?;
+        let (alias, last_loc) = self.parse_character_name(mid_loc)?;
+        Ok(RichToken::character(
+            Loc::from_locs([prev_loc, last_loc].into_iter()),
+            name,
+            alias,
+        ))
+    }
+
+    fn parse_character_name(&mut self, prev_loc: Loc) -> ParseResult<(&'a str, Loc)> {
+        let name = if let Some(tok) = self.lexer.next() {
+            match tok.tok {
+                TokenType::Space => parse_error(tok.loc, ParseErrorType::IllegalSpace),
+                TokenType::SpecChar(c) => match c {
+                    '/' => Ok(""),
+                    _ => parse_error(tok.loc, ParseErrorType::IllegalChar(c)),
+                },
+                TokenType::Text(name) => Ok(name),
+            }
+        } else {
+            parse_error(prev_loc, ParseErrorType::IllegalChar('/'))
+        }?;
+        let last_loc = if !name.is_empty() {
+            match self.lexer.next() {
+                Some(tok) => match tok.tok {
+                    TokenType::SpecChar('/') => Ok(tok.loc),
+                    _ => parse_error(prev_loc, ParseErrorType::IllegalChar('/')),
+                },
+                None => parse_error(prev_loc, ParseErrorType::IllegalChar('/')),
+            }
+        } else {
+            Ok(Loc(prev_loc.0 + 1, prev_loc.1 + 1))
+        }?;
+        Ok((name, last_loc))
+    }
+
+    fn parse_escape_or_command(&mut self, prev_loc: Loc) -> ParseResult<RichToken<'a>> {
+        if let Some(tok) = self.lexer.next() {
+            match tok.tok {
+                TokenType::Space => Ok(RichToken::char(tok.loc, ' ')),
+                TokenType::SpecChar(c) => Ok(RichToken::char(tok.loc, c)),
+                TokenType::Text(name) => {
+                    if self.in_param > 0 {
+                        parse_error(tok.loc, ParseErrorType::CmdInCmd)
+                    } else {
+                        self.parse_params(Loc::from_locs([prev_loc, tok.loc].into_iter()), name)
+                    }
+                }
+            }
+        } else {
+            parse_error(prev_loc, ParseErrorType::CmdNotFound)
+        }
+    }
+
+    fn parse_params(&mut self, prev_loc: Loc, name: &'a str) -> ParseResult<RichToken<'a>> {
+        if let Some(tok) = self.lexer.peek() {
+            let loc = tok.loc;
+            match &tok.tok {
+                TokenType::Space => {
+                    self.lexer.next();
+                    Ok(RichToken::command(prev_loc, name, vec![]))
+                }
+                &TokenType::SpecChar(c) => match c {
+                    '\\' => Ok(RichToken::command(prev_loc, name, vec![])),
+                    '{' => {
+                        let mut params = vec![];
+                        while let Some(tok) = self.lexer.peek() {
+                            if tok.tok == TokenType::SpecChar('{') {
+                                self.lexer.next();
+                                let param = self.parse_param()?;
+                                params.push(param);
+                            } else {
+                                break;
+                            }
+                        }
+                        Ok(RichToken::command(prev_loc, name, params))
+                    }
+                    _ => parse_error(loc, ParseErrorType::IllegalChar(c)),
+                },
+                TokenType::Text(_) => parse_error(loc, ParseErrorType::CmdNotFound),
+            }
+        } else {
+            Ok(RichToken::command(prev_loc, name, vec![]))
+        }
+    }
+
+    fn parse_param(&mut self) -> ParseResult<Vec<RichToken<'a>>> {
+        self.in_param += 1;
+        let mut tokens = vec![];
+        while let Some(tok) = self.lexer.next() {
+            match tok.tok {
+                TokenType::Space => tokens.push(RichToken::char(tok.loc, ' ')),
+                TokenType::SpecChar(c) => {
+                    match c {
+                        '{' => self.in_param += 1,
+                        '}' => {
+                            self.in_param -= 1;
+                            if self.in_param == 0 {
+                                break;
+                            }
+                        }
+                        _ => {}
+                    };
+                    tokens.push(self.parse_spec_char(tok.loc, c)?);
+                }
+                TokenType::Text(s) => tokens.push(RichToken::text(tok.loc, s)),
+            }
+        }
+        Ok(tokens)
+    }
+}
+
+impl<'a> Iterator for TextRichLexer<'a> {
+    type Item = ParseResult<RichToken<'a>>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if let Some(tok) = self.lexer.next() {
+            match tok.tok {
+                TokenType::Space => Some(Ok(RichToken::char(tok.loc, ' '))),
+                TokenType::SpecChar(c) => Some(self.parse_spec_char(tok.loc, c)),
+                TokenType::Text(s) => Some(Ok(RichToken::text(tok.loc, s))),
+            }
+        } else {
+            None
+        }
+    }
+}
+
+/// The parser of [`Text`].
+pub struct TextParser<'a> {
+    lexer: Peekable<TextRichLexer<'a>>,
+}
+
+impl<'a> TextParser<'a> {
+    /// Create a new [`TextParser`] from a string.
+    pub fn new(text: &'a str) -> Self {
+        Self {
+            lexer: TextRichLexer::new(text).peekable(),
+        }
+    }
+
+    /// Parse into [`Text`].
+    pub fn parse(mut self) -> ParseResult<Text> {
+        Ok(Text(self.try_collect()?))
+    }
+
+    fn parse_next(&mut self) -> ParseResult<Option<Line>> {
+        let mut str = String::new();
+        while let Some(tok) = self.lexer.peek() {
+            match tok {
+                Ok(tok) => match &tok.tok {
+                    RichTokenType::Char(c) => {
+                        str.push(*c);
+                        self.lexer.next();
+                    }
+                    RichTokenType::Text(s) => {
+                        str.push_str(s);
+                        self.lexer.next();
+                    }
+                    RichTokenType::Character(name, alias) => {
+                        if str.is_empty() {
+                            let name = name.to_string();
+                            let alias = alias.to_string();
+                            self.lexer.next();
+                            return Ok(Some(Line::Cmd(Command::Character(name, alias))));
+                        } else {
+                            break;
+                        }
+                    }
+                    RichTokenType::Command(name, params) => {
+                        if str.is_empty() {
+                            let res = Self::parse_command(tok.loc, name, params)?;
+                            self.lexer.next();
+                            return Ok(Some(res));
+                        } else {
+                            break;
+                        }
+                    }
+                },
+                Err(_) => {
+                    // unwrap: peek succeeded.
+                    self.lexer.next().unwrap()?;
+                }
+            }
+        }
+        if !str.is_empty() {
+            let trimmed_str = SPACE_REGEX.replace_all(&str, " ");
+            Ok(Some(Line::Str(trimmed_str.into_owned())))
+        } else {
+            Ok(None)
+        }
+    }
+
+    fn concat_params(toks: &[RichToken]) -> ParseResult<String> {
+        let mut str = String::new();
+        for tok in toks {
+            match &tok.tok {
+                RichTokenType::Char(c) => str.push(*c),
+                RichTokenType::Text(s) => str.push_str(s),
+                RichTokenType::Character(_, _) => parse_error(tok.loc, ParseErrorType::CmdInCmd)?,
+                RichTokenType::Command(_, _) => parse_error(tok.loc, ParseErrorType::CmdInCmd)?,
+            }
+        }
+        Ok(str)
+    }
+
+    fn parse_program(toks: &[RichToken]) -> ParseResult<Program> {
+        let program = Self::concat_params(toks)?;
+        match ProgramParser::new().parse(&program) {
+            Ok(p) => Ok(p),
+            Err(e) => {
+                use lalrpop_util::ParseError as ExecParseError;
+
+                let loc = Loc::from_locs(toks.iter().map(|tok| tok.loc));
+                let loc = match &e {
+                    ExecParseError::InvalidToken { location } => {
+                        Loc(loc.0 + location, loc.0 + location + 1)
+                    }
+                    ExecParseError::UnrecognizedEOF {
+                        location: _,
+                        expected: _,
+                    } => Loc(loc.1, loc.1 + 1),
+                    ExecParseError::UnrecognizedToken { token, expected: _ }
+                    | ExecParseError::ExtraToken { token } => Loc(loc.0 + token.0, loc.0 + token.2),
+                    ExecParseError::User { error: _ } => loc,
+                };
+                parse_error(loc, ParseErrorType::InvalidProgram(e.to_string()))
+            }
+        }
+    }
+
+    fn check_params_count(
+        count: usize,
+        min: usize,
+        max: usize,
+        loc: Loc,
+        name: &str,
+    ) -> ParseResult<()> {
+        if count < min || count > max {
+            parse_error(
+                loc,
+                ParseErrorType::InvalidParamsCount(name.to_string(), count),
+            )
+        } else {
+            Ok(())
+        }
+    }
+
+    fn parse_command(loc: Loc, name: &str, params: &[Vec<RichToken>]) -> ParseResult<Line> {
+        let params_count = params.len();
+        let cmd = match name {
+            "res" => {
+                Self::check_params_count(params_count, 1, 1, loc, name)?;
+                // Construct a simple program to get the resource.
+                // We don't expose this command to the front end.
+                Command::Exec(Program(vec![Expr::Ref(Ref::Res(Self::concat_params(
+                    &params[0],
+                )?))]))
+            }
+            "ch" => {
+                Self::check_params_count(params_count, 1, 2, loc, name)?;
+                Command::Character(
+                    Self::concat_params(&params[0])?,
+                    Self::concat_params(
+                        params.get(1).map(|slice| slice.as_slice()).unwrap_or(&[]),
+                    )?,
+                )
+            }
+            "exec" => {
+                Self::check_params_count(params_count, 1, 1, loc, name)?;
+                Command::Exec(Self::parse_program(&params[0])?)
+            }
+            "switch" => {
+                Self::check_params_count(params_count, 1, 3, loc, name)?;
+                let enabled = match params.get(2) {
+                    Some(toks) => Some(Self::parse_program(toks)?),
+                    None => None,
+                };
+                Command::Switch {
+                    text: Self::concat_params(&params[0])?,
+                    action: if let Some(toks) = params.get(1) {
+                        Self::parse_program(toks)?
+                    } else {
+                        Program::default()
+                    },
+                    enabled,
+                }
+            }
+            name => {
+                let mut args = vec![];
+                for p in params.iter() {
+                    args.push(Self::concat_params(p)?);
+                }
+                Command::Other(name.to_string(), args)
+            }
+        };
+        Ok(Line::Cmd(cmd))
+    }
+}
+
+impl<'a> Iterator for TextParser<'a> {
+    type Item = ParseResult<Line>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match self.parse_next() {
+            Ok(Some(res)) => Some(Ok(res)),
+            Ok(None) => None,
+            Err(e) => Some(Err(e)),
+        }
+    }
+}
+
+#[cfg(test)]
+mod test_lexer {
+    use crate::text::*;
+
+    #[test]
+    fn basic() {
+        let lexer = TextLexer::new("\\par text");
+        let res = lexer.collect::<Vec<_>>();
+        assert_eq!(res.len(), 4);
+        assert_eq!(res[0].tok, TokenType::SpecChar('\\'));
+        assert_eq!(res[1].tok, TokenType::Text("par"));
+        assert_eq!(res[2].tok, TokenType::Space);
+        assert_eq!(res[3].tok, TokenType::Text("text"));
+    }
+
+    #[test]
+    fn space() {
+        let lexer = TextLexer::new("text \\par");
+        let res = lexer.collect::<Vec<_>>();
+        assert_eq!(res.len(), 4);
+        assert_eq!(res[0].tok, TokenType::Text("text"));
+        assert_eq!(res[1].tok, TokenType::Space);
+        assert_eq!(res[2].tok, TokenType::SpecChar('\\'));
+        assert_eq!(res[3].tok, TokenType::Text("par"));
+    }
+}
+
+#[cfg(test)]
+mod test_rich_lexer {
+    use crate::text::*;
+
+    #[test]
+    fn space() {
+        let mut lexer = TextRichLexer::new("\\cmd{123} \\cmd{123}");
+        let res = lexer.try_collect::<Vec<_>>().unwrap();
+        assert_eq!(res.len(), 3);
+        assert_eq!(res[1].tok, RichTokenType::Char(' '));
+    }
+}
+
+#[cfg(test)]
+mod test_parser {
+    use crate::text::*;
+
+    #[test]
+    fn basic() {
+        assert_eq!(
+            TextParser::new("\\\\").parse().unwrap(),
+            Text(vec![Line::Str("\\".to_string())])
+        );
+        assert_eq!(
+            TextParser::new("\\{").parse().unwrap(),
+            Text(vec![Line::Str("{".to_string())])
+        );
+    }
+
+    #[test]
+    fn space() {
+        assert_eq!(
+            TextParser::new("\\cmd{123} \\cmd{123}").parse().unwrap(),
+            Text(vec![
+                Line::Cmd(Command::Other("cmd".to_string(), vec!["123".to_string()])),
+                Line::Str(" ".to_string()),
+                Line::Cmd(Command::Other("cmd".to_string(), vec!["123".to_string()])),
+            ])
+        );
+    }
+
+    #[test]
+    fn exec() {
+        assert_eq!(
+            TextParser::new(r##"\exec{"Hello world!"}"##)
+                .parse()
+                .unwrap(),
+            Text(vec![Line::Cmd(Command::Exec(Program(vec![Expr::Const(
+                RawValue::Str("Hello world!".to_string())
+            )])))])
+        );
+        assert_eq!(
+            TextParser::new(r##"\exec{"Hello world!{}"}"##)
+                .parse()
+                .unwrap(),
+            Text(vec![Line::Cmd(Command::Exec(Program(vec![Expr::Const(
+                RawValue::Str("Hello world!{}".to_string())
+            )])))])
+        );
+        TextParser::new(r##"\exec{format.fmt("Hello {}", "world!")}"##)
+            .parse()
+            .unwrap();
+    }
+
+    #[test]
+    fn switch() {
+        assert_eq!(
+            TextParser::new(r##"\switch{hello}{"Hello world!"}"##)
+                .parse()
+                .unwrap(),
+            Text(vec![Line::Cmd(Command::Switch {
+                text: "hello".to_string(),
+                action: Program(vec![Expr::Const(RawValue::Str("Hello world!".to_string()))]),
+                enabled: None
+            })])
+        );
+
+        TextParser::new(r##"\switch{hello}{$s = 2}{a == b}"##)
+            .parse()
+            .unwrap();
+    }
+
+    #[test]
+    fn error() {
+        assert_eq!(
+            TextParser::new(r##"\switch{\exec{114514}}"##).parse(),
+            Err(ParseError::new(Loc(9, 13), ParseErrorType::CmdInCmd))
+        );
+    }
+
+    #[test]
+    fn lf() {
+        assert_eq!(
+            TextParser::new(" ").parse().unwrap(),
+            Text(vec![Line::Str(" ".to_string())])
+        );
+        assert_eq!(
+            TextParser::new("  ").parse().unwrap(),
+            Text(vec![Line::Str(" ".to_string())])
+        );
+        assert_eq!(
+            TextParser::new(" \n ").parse().unwrap(),
+            Text(vec![Line::Str(" ".to_string())])
+        );
+        assert_eq!(
+            TextParser::new(" 123 ").parse().unwrap(),
+            Text(vec![Line::Str(" 123 ".to_string())])
+        );
+        assert_eq!(
+            TextParser::new(" \n123\t ").parse().unwrap(),
+            Text(vec![Line::Str(" 123 ".to_string())])
+        );
+        assert_eq!(
+            TextParser::new("123").parse().unwrap(),
+            Text(vec![Line::Str("123".to_string())])
+        );
+    }
+}


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 00000000..e0a4885a
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,23 @@
+name: Test
+on:
+  push:
+    branches: ["master"]
+  pull_request:
+    branches: ["master"]
+jobs:
+  Test:
+    strategy:
+      matrix:
+        os: [ubuntu-latest, windows-latest, macos-latest]
+    runs-on: ${{ matrix.os }}
+    steps:
+      - uses: actions/checkout@v2
+      - name: Install dependencies
+        run: sudo apt-get install -y libwebkit2gtk-4.0-dev
+        if: matrix.os == 'ubuntu-latest'
+      - name: Install targets
+        run: |
+          rustup target add wasm32-unknown-unknown
+          rustup target add wasm32-wasi
+      - name: Test
+        run: make test